· 6 years ago · Jan 09, 2020, 06:24 PM
1<?php
2
3/*
4 SQLyog
5 Copyright 2003-2006, Webyog
6 http://www.webyog.com
7
8 HTTP Tunneling Page
9
10 This page exposes the MySQL API as a set of web-services which is consumed by SQLyog - the most popular GUI to MySQL.
11
12 This page allows SQLyog to manage MySQL even if the MySQL port is blocked or remote access to MySQL is not allowed.
13*/
14
15/*Wrapper Functions for PHP-MYSQL and PHP-MYSQLI*/
16
17function yog_mysql_connect ($host, $port, $username, $password, $db_name="")
18{
19 $username = utf8_decode($username);
20 $ret=0;
21 switch (DB_EXTENSION)
22 {
23 case "mysql":
24 $ret = mysql_connect ($host.':'.$port, $username, $password);
25 if (strlen ($db_name)!=0){
26 mysql_select_db("$db_name");
27 }
28 break;
29 case "mysqli":
30 $port=(int)$port;
31 $GLOBALS["___mysqli_ston"] = mysqli_connect($host, $username, $password,$db_name, $port);
32 $ret=$GLOBALS["___mysqli_ston"];
33 break;
34 }
35 return $ret;
36}
37
38
39function yog_mysql_field_type ( $result, $offset )
40{
41 //Get the type of the specified field in a result
42
43 $ret=0;
44 switch (DB_EXTENSION)
45 {
46 case "mysql":
47 $ret = mysql_field_type ( $result, $offset );
48 break;
49 case "mysqli":
50 $tmp=mysqli_fetch_field_direct ( $result, $offset);
51 $ret = GetCorrectDataTypeMySQLI($tmp->type);
52 break;
53 }
54 return $ret;
55}
56
57
58function yog_mysql_field_len ( $result, $offset )
59{
60 //Returns the length of the specified field
61
62 $ret=0;
63 switch (DB_EXTENSION)
64 {
65 case "mysql":
66 $ret = mysql_field_len ($result,$offset );
67 break;
68 case "mysqli":
69 $tmp=mysqli_fetch_field_direct ( $result, $offset);
70 $ret = $tmp->length;
71 break;
72 }
73 return $ret;
74}
75
76
77function yog_mysql_field_flags ($result, $offset)
78{
79 //Get the flags associated with the specified field in a result
80
81 $ret=0;
82 switch (DB_EXTENSION)
83 {
84 case "mysql":
85 $ret = mysql_field_flags ($result,$offset);
86 break;
87 case "mysqli":
88 $___mysqli_obj = (mysqli_fetch_field_direct($result, $offset));
89 $___mysqli_tmp = $___mysqli_obj->flags;
90 $ret=($___mysqli_tmp? (string)(substr((($___mysqli_tmp & MYSQLI_NOT_NULL_FLAG) ? "not_null " : "") . (($___mysqli_tmp & MYSQLI_PRI_KEY_FLAG) ? "primary_key " : "") . (($___mysqli_tmp & MYSQLI_UNIQUE_KEY_FLAG) ? "unique_key " : "") . (($___mysqli_tmp & MYSQLI_MULTIPLE_KEY_FLAG) ? "unique_key " : "") . (($___mysqli_tmp & MYSQLI_BLOB_FLAG) ? "blob " : "") . (($___mysqli_tmp & MYSQLI_UNSIGNED_FLAG) ? "unsigned " : "") . (($___mysqli_tmp & MYSQLI_ZEROFILL_FLAG) ? "zerofill " : "") . (($___mysqli_tmp & 128) ? "binary " : "") . (($___mysqli_tmp & 256) ? "enum " : "") . (($___mysqli_tmp & MYSQLI_AUTO_INCREMENT_FLAG) ? "auto_increment " : "") . (($___mysqli_tmp & MYSQLI_TIMESTAMP_FLAG) ? "timestamp " : "") . (($___mysqli_tmp & MYSQLI_SET_FLAG) ? "set " : ""), 0, -1)) : false);
91 break;
92 }
93 return $ret;
94}
95
96
97function yog_mysql_get_server_info ($db_link)
98{
99 //Get MySQL server info
100
101 $ret=0;
102 switch (DB_EXTENSION)
103 {
104 case "mysql":
105 $ret = mysql_get_server_info ($db_link);
106 break;
107 case "mysqli":
108 $ret = mysqli_get_server_info ($db_link);
109 break;
110 }
111 return $ret;
112}
113
114
115function yog_mysql_affected_rows ( $db_link )
116{
117 //Get number of affected rows in previous MySQL operation
118
119 $ret=0;
120 switch (DB_EXTENSION)
121 {
122 case "mysql":
123 $ret = mysql_affected_rows($db_link);
124 break;
125 case "mysqli":
126 $ret = mysqli_affected_rows($db_link);
127 break;
128 }
129 return $ret;
130}
131
132
133function yog_mysql_insert_id ( $db_link )
134{
135 //Get the ID generated from the previous INSERT operation
136
137 $ret=0;
138 switch (DB_EXTENSION)
139 {
140 case "mysql":
141 $ret = mysql_insert_id($db_link);
142 break;
143 case "mysqli":
144 $ret = mysqli_insert_id($db_link);
145 break;
146 }
147 return $ret;
148}
149
150
151function yog_mysql_query ( $query, $db_link )
152{
153 //Send a MySQL query
154 $ret=array();
155 switch (DB_EXTENSION)
156 {
157 case "mysql":
158 $result = mysql_query ($query, $db_link);
159 /**********************/
160
161 if (yog_mysql_errno($db_link)!=0) {
162 $temp_ar= array("result"=>-1, "ar"=>mysql_affected_rows($db_link));
163 array_push($ret, $temp_ar);
164 }
165 elseif ($result===FALSE) {
166
167 $temp_ar= array("result"=>1, "ar"=>mysql_affected_rows($db_link));
168 array_push($ret, $temp_ar);
169 }
170 else {
171 $temp_ar= array("result"=>$result, "ar"=>mysql_affected_rows($db_link));
172 array_push($ret, $temp_ar);
173 }
174
175 /**********************/
176 break;
177 case "mysqli":
178 $ret = get_array_from_query($query, $db_link);
179 break;
180 }
181 return $ret;
182}
183
184function get_array_from_query($query, $db_link)
185{
186 $ret=array();
187 $bool = mysqli_real_query ( $db_link, $query )or yog_mysql_error($db_link);
188
189 if (yog_mysql_errno($db_link)!=0) {
190
191 $temp_ar= array("result"=>-1, "ar"=>0);
192 array_push($ret, $temp_ar);
193
194 }
195
196 elseif ($bool) {
197 do {
198 /* store first result set */
199 $result = mysqli_store_result($db_link);
200 $num_ar= mysqli_affected_rows($db_link);
201
202 if ($result===FALSE && yog_mysql_errno($db_link)!=0) {
203 $temp_ar= array("result"=>-1, "ar"=>$num_ar);
204 array_push($ret, $temp_ar);
205 break;
206 }
207 elseif ($result===FALSE) {
208 $temp_ar= array("result"=>1, "ar"=>$num_ar);
209 array_push($ret, $temp_ar);
210 }
211 else {
212 $temp_ar= array("result"=>$result, "ar"=>$num_ar);
213 array_push($ret, $temp_ar);
214 }
215 } while (mysqli_next_result($db_link));
216
217 if (yog_mysql_errno($db_link)!=0) {
218 $temp_ar= array("result"=>-1, "ar"=>$num_ar);
219 array_push($ret, $temp_ar);
220 }
221 }
222 return $ret;
223}
224
225
226
227function yog_mysql_errno($db_link)
228{
229 //Returns the numerical value of the error message from previous MySQL operation
230
231 $ret=0;
232 switch (DB_EXTENSION)
233 {
234 case "mysql":
235 $ret = mysql_errno($db_link);
236 break;
237 case "mysqli":
238 $ret = mysqli_errno($db_link);
239 break;
240 }
241 return $ret;
242}
243
244
245function yog_mysql_error($db_link)
246{
247 //Returns the text of the error message from previous MySQL operation
248
249 $ret=0;
250 switch (DB_EXTENSION)
251 {
252 case "mysql":
253 $ret = mysql_error ($db_link);
254 break;
255 case "mysqli":
256 $ret = mysqli_error ($db_link);
257 break;
258 }
259 return $ret;
260}
261
262
263function yog_mysql_num_rows ( $result )
264{
265 //Get number of rows in result
266 $ret=0;
267 switch (DB_EXTENSION)
268 {
269 case "mysql":
270 $ret = mysql_num_rows ($result);
271 break;
272 case "mysqli":
273 $ret = mysqli_num_rows ($result);
274 break;
275 }
276 return $ret;
277}
278
279
280function yog_mysql_num_fields ( $result )
281{
282 //Get number of fields in result
283 $ret=0;
284 switch (DB_EXTENSION)
285 {
286 case "mysql":
287 $ret = mysql_num_fields ($result);
288 break;
289 case "mysqli":
290 $ret = mysqli_num_fields ($result);
291 break;
292 }
293 return $ret;
294}
295
296
297function yog_mysql_fetch_field($result)
298{
299 //Get column information from a result and return as an object
300 $ret=0;
301 switch (DB_EXTENSION)
302 {
303 case "mysql":
304 $ret = mysql_fetch_field ($result);
305 break;
306 case "mysqli":
307 $ret = mysqli_fetch_field ($result);
308 break;
309 }
310 return $ret;
311}
312
313
314function yog_mysql_fetch_array ( $result)
315{
316 //Fetch a result row as an associative array, a numeric array, or both
317 $ret=0;
318 switch (DB_EXTENSION)
319 {
320 case "mysql":
321 $ret=mysql_fetch_array ( $result);
322 break;
323 case "mysqli":
324 $ret=mysqli_fetch_array ( $result);
325 break;
326 }
327 return $ret;
328}
329
330
331function yog_mysql_fetch_lengths ( $result )
332{
333 //Get the length of each output in a result
334 $ret=array();
335 switch (DB_EXTENSION)
336 {
337 case "mysql":
338 $ret = mysql_fetch_lengths ($result);
339 break;
340 case "mysqli":
341 $ret = mysqli_fetch_lengths ($result);
342 break;
343 }
344 return $ret;
345}
346
347
348function yog_mysql_free_result ( $result )
349{
350 //Free result memory
351 $ret=0;
352 switch (DB_EXTENSION)
353 {
354 case "mysql":
355 $ret = mysql_free_result ($result);
356 break;
357 case "mysqli":
358 $ret = mysqli_free_result ($result);
359 break;
360 }
361 return $ret;
362}
363
364
365function yog_mysql_select_db ( $db_name, $db_link )
366{
367 //Select a MySQL database
368 $ret=0;
369 switch (DB_EXTENSION)
370 {
371 case "mysql":
372 $ret = mysql_select_db ($db_name, $db_link);
373 break;
374 case "mysqli":
375 $ret = mysqli_select_db ($db_link, $db_name);
376 break;
377 }
378 return $ret;
379}
380
381
382function yog_mysql_close ( $db_link )
383{
384 //Close MySQL connection
385 $ret=0;
386 switch (DB_EXTENSION)
387 {
388 case "mysql":
389 $ret = mysql_close ( $db_link );
390 break;
391 case "mysqli":
392 $ret = mysqli_close ( $db_link );
393 break;
394 }
395 return $ret;
396}
397
398function yog_mysql_connect_errno()
399{
400 $ret=0;
401 switch (DB_EXTENSION)
402 {
403 case "mysqli":
404 $ret=mysqli_connect_errno ();
405 break;
406 case "mysql":
407 $ret=mysql_errno ();
408 break;
409 }
410 return $ret;
411}
412
413
414function yog_mysql_connect_error()
415{
416 $ret=0;
417 switch (DB_EXTENSION)
418 {
419 case "mysqli":
420 $ret=mysqli_connect_error ();
421 break;
422 case "mysql":
423 $ret=mysql_error ();
424 break;
425 }
426 return $ret;
427}
428
429
430
431function GetCorrectDataTypeMySQLI( $type )
432{
433 switch($type)
434 {
435 case MYSQLI_TYPE_TINY:
436 $data = "tinyint";
437 break;
438 case MYSQLI_TYPE_SHORT:
439 $data = "int";
440 break;
441 case MYSQLI_TYPE_LONG:
442 $data = "int";
443 break;
444 case MYSQLI_TYPE_FLOAT:
445 $data = "float";
446 break;
447 case MYSQLI_TYPE_DOUBLE:
448 $data = "double";
449 break;
450 case MYSQLI_TYPE_NULL:
451 $data = "default null";
452 break;
453 case MYSQLI_TYPE_TIMESTAMP:
454 $data = "timestamp" ;
455 break;
456 case MYSQLI_TYPE_BIT:
457 $data = "bit" ;
458 break;
459 case MYSQLI_TYPE_LONGLONG:
460 $data = "bigint";
461 break;
462 case MYSQLI_TYPE_INT24:
463 $data = "mediumint";
464 break;
465 case MYSQLI_TYPE_DATE:
466 $data = "date";
467 break;
468 case MYSQLI_TYPE_TIME:
469 $data = "time";
470 break;
471 case MYSQLI_TYPE_DATETIME:
472 $data = "datetime";
473 break;
474 case MYSQLI_TYPE_YEAR:
475 $data = "year";
476 break;
477 case MYSQLI_TYPE_NEWDATE:
478 $data = "date";
479 break;
480 case MYSQLI_TYPE_ENUM:
481 $data = "enum";
482 break;
483 case MYSQLI_TYPE_SET:
484 $data = "set";
485 break;
486 case MYSQLI_TYPE_TINY_BLOB:
487 $data = "tinyblob";
488 break;
489 case MYSQLI_TYPE_MEDIUM_BLOB:
490 $data = "mediumblob";
491 break;
492 case MYSQLI_TYPE_LONG_BLOB:
493 $data = "longblob";
494 break;
495 case MYSQLI_TYPE_BLOB:
496 $data = "blob";
497 break;
498 case MYSQLI_TYPE_VAR_STRING:
499 $data = "varchar";
500 break;
501 case MYSQLI_TYPE_STRING:
502 $data = "char";
503 break;
504 case MYSQLI_TYPE_GEOMETRY:
505 $data = "geometry";
506 break;
507
508 }
509 return ($data);
510}
511/* function finds and returns the correct type understood by MySQL C API() */
512
513function GetCorrectDataType ( $result, $j )
514{
515 $data = NULL;
516
517 WriteLog ( "Enter GetCorrectDataType" );
518
519 switch( yog_mysql_field_type ( $result, $j ) )
520 {
521 case "int":
522 if ( yog_mysql_field_len ( $result, $j ) <= 4 )
523 {
524 $data = "smallint";
525 }
526 elseif ( yog_mysql_field_len ( $result, $j ) <= 9 )
527 {
528 $data = "mediumint";
529 }
530 else
531 {
532 $data = "int";
533 }
534 break;
535
536 case "real":
537 if (yog_mysql_field_len($result,$j) <= 10 )
538 {
539 $data = "float";
540 }
541 else
542 {
543 $data = "double";
544 }
545 break;
546
547 case "string":
548 $data = "varchar";
549 break;
550
551 case "blob":
552 $textblob = "TEXT";
553 if ( strpos ( yog_mysql_field_flags ($result,$j),"binary") )
554 {
555 $textblob = "BLOB";
556 }
557 if (yog_mysql_field_len($result,$j) <= 255)
558 {
559 if ( $textblob == "TEXT" )
560 {
561 $data = "tinytext";
562 }
563 else
564 {
565 $data = "tinyblob";
566 }
567 }
568 elseif (yog_mysql_field_len($result, $j) <= 65535 )
569 {
570 if ( $textblob == "TEXT" ) {
571 $data = "mediumtext";
572 }
573 else
574 {
575 $data = "mediumblob";
576 }
577 }
578 else
579 {
580 if ( $textblob == "TEXT" ) {
581 $data = "longtext";
582 }
583 else
584 {
585 $data = "longblob";
586 }
587 }
588 break;
589
590 case "date":
591 $data = "date";
592 break;
593
594 case "time":
595 $data = "time";
596 break;
597
598 case "datetime":
599 $data = "datetime";
600 break;
601 }
602
603 WriteLog ( "Exit GetCorrectDataType" );
604
605 return (convertxmlchars($data));
606}
607
608/* Output extra info used by SQLyog internally */
609
610function HandleExtraInfo ( $mysql, $value )
611{
612
613 WriteLog ( "Enter HandleExtraInfo" );
614
615 echo "<s_v>" . yog_mysql_get_server_info ( $mysql ) . "</s_v>";
616 echo "<m_i></m_i>";
617 echo "<a_r>" . $value['ar'] . "</a_r>";
618 echo "<i_i>" . yog_mysql_insert_id ( $mysql ) . "</i_i>";
619
620 WriteLog ( "Exit HandleExtraInfo" );
621
622}
623
624
625/* Process when only a single query is called. */
626
627function ExecuteSingleQuery ( $mysql, $query )
628{
629 WriteLog ( "Enter ExecuteSingleQuery" );
630
631 $result = yog_mysql_query ( $query, $mysql );
632 foreach ($result as $key => $value)
633 {
634 //$value['result'],$value['ar'];
635
636 if ( $value['result']=== -1 ) {
637 HandleError ( yog_mysql_errno($mysql), yog_mysql_error($mysql) );
638 return;
639 }
640
641 /* free the result */
642 CreateXMLFromResult ($mysql, $value);
643
644 if ($value['result']!==1) {
645 yog_mysql_free_result ( $value['result'] );
646 }
647 }
648
649 WriteLog ( "Exit ExecuteSingleQuery" );
650}
651
652
653function CreateXMLFromResult ($mysql, $value)
654{
655 // $value['result'], $value['ar']
656 /* query execute was successful so we need to echo the correct xml */
657 /* the query may or may not return any result */
658 WriteLog ( "yog_mysql_num_rows in ExecuteSingleQuery" );
659
660 // check if the query is not a result returning query
661 $isNotResultQuery=0;
662 if ( DB_EXTENSION=="mysqli") {
663 ($value['result'] ===1)?$isNotResultQuery=1:$isNotResultQuery=0;
664 }
665 else{
666 ($value['result'] ==1)?$isNotResultQuery=1:$isNotResultQuery=0;
667 }
668
669 $numrows=0;
670 $numfields=0;
671
672 if (!is_int($value['result'])) {
673 $numrows=yog_mysql_num_rows ( $value['result'] );
674 $numfields=yog_mysql_num_fields ( $value['result'] );
675 }
676
677 if ( $isNotResultQuery || (!$numrows && !$numfields ))//
678 {
679 /* is a non-result query */
680 echo "<result v=\"" . tunnelversion . "\">";
681 echo "<e_i></e_i>";
682 HandleExtraInfo ( $mysql, $value );
683 echo "<f_i c=\"0\"></f_i><r_i></r_i></result>";
684 return;
685 }
686
687 /* handle result query like SELECT,SHOW,EXPLAIN or DESCRIBE */
688 echo '<result v="' . tunnelversion . '">';
689 echo "<e_i></e_i>";
690
691 /* add some extra info */
692 HandleExtraInfo ( $mysql, $value );
693
694 /* add the field count information */
695 $fieldcount = yog_mysql_num_fields ( $value['result'] );
696 print ( $fieldcount );
697 echo "<f_i c=\"$fieldcount\">";
698
699 /* retrieve information about each fields */
700 $i = 0;
701 while ($i < $fieldcount )
702 {
703 $meta = yog_mysql_fetch_field($value['result']);
704
705 echo "<f>";
706 echo "<n>" . convertxmlchars($meta->name) . "</n>";
707 echo "<t>" . convertxmlchars($meta->table) . "</t>";
708 echo "<m>" . convertxmlchars($meta->max_length) . "</m>";
709 echo "<d></d>";
710 switch (DB_EXTENSION)
711 {
712 case "mysql":
713 echo "<ty>" . GetCorrectDataType ( $value['result'], $i ) . "</ty>";
714 break;
715 case "mysqli":
716 echo "<ty>" . yog_mysql_field_type( $value['result'], $i ) . "</ty>";
717 break;
718 }
719
720 echo "</f>";
721
722 $i++;
723 }
724
725 /* end field informations */
726 echo "</f_i>";
727
728 /* get information about number of rows in the resultset */
729
730 echo "<r_i c=\"$numrows\">";
731 /* add up each row information */
732 while ( $row = yog_mysql_fetch_array ( $value['result'] ) )
733 {
734 $lengths = yog_mysql_fetch_lengths ( $value['result'] );
735
736 /* start of a row */
737 echo "<r>";
738
739 for ( $i=0; $i < $fieldcount; $i++ )
740 {
741 /* start of a col */
742 echo "<c l=\"$lengths[$i]\">";
743 if ( !isset($row[$i]) /*== NULL*/ )
744 {
745 echo "(NULL)";
746 }
747 else
748 {
749 if ( $lengths[$i] == 0 )
750 {
751 echo "_";
752 }
753 else
754 {
755 echo convertxmlchars ( base64_encode ( $row[$i] ) );
756 }
757 }
758
759 /* end of a col */
760 echo "</c>";
761 }
762
763 /* end of a row */
764 echo "</r>";
765 }
766
767 /* close the xml output */
768 echo "</r_i></result>";
769}
770
771
772/* implementation of my_strtok() in PHP */
773
774/*
775 * Description: string my_strtok(string $string, string $delimiter).
776 *
777 * Function my_strtok() splits a string ($string) into smaller
778 * strings (tokens), with each token being delimited by the delimiter
779 * string ($delimiter), considering string variables and comments
780 * in the $string argument. Note that the comparision is case-insensitive.
781 *
782 * Returns FALSE if there are no tokens left.
783 * Does not return empty tokens.
784 * Does not return the "delimiter" command as a token.
785 *
786 * Usage:
787 * The first call to my_strtok() uses the $string and $delimiter arguments.
788 * Every subsequent call to my_strtok() needs no arguments at all, or only
789 * the $delimiter argument to use, as it keeps track of where it is in the
790 * current string. To start over, or to tokenize a new string you simply
791 * call my_strtok() with the both arguments again to initialize it.
792 * The delimiter can be changed by the command "delimiter new_delimiter" in
793 * the $string argument (the command is case-insensitive).
794 *
795 * Example:
796 * $res = my_strtok($query, $delimiter);
797 * while ($res) {
798 * echo "token = $res<br>";
799 * $res = my_strtok();
800 * }
801 *
802 * Author: Andrey Adaikin, IVA Team, <IVATeam@gmail.com>
803 * @version $Revision: 1.3 $, $Date: 2005/09/28 $
804 */
805
806function my_strtok($string = NULL, $delimiter = NULL) {
807
808 static $str; // lower case $string (equals to strtolower($string))
809 static $str_original; // stores $string argument
810 static $len; // length of the $string
811 static $curr_pos; // current position in the $string
812 static $match_pos; // position where the $delimiter is a substring of the $string
813 static $delim; // lower case $delimiter (equals to strtolower($delimiter))
814
815 WriteLog ( "Enter my_strtok" );
816
817 if (NULL === $delimiter)
818 {
819 if (NULL !== $string)
820 {
821 $delim = strtolower($string);
822 $match_pos = -1;
823 }
824 }
825 else
826 {
827 if (!is_string($string) || !is_string($delimiter))
828 {
829 return FALSE;
830 }
831 $str_original = $string;
832 $str = strtolower($str_original);
833 $len = strlen($str);
834 $curr_pos = 0;
835 $match_pos = -1;
836 $delim = strtolower($delimiter);
837 }
838
839 if ($curr_pos >= $len)
840 {
841 return FALSE;
842 }
843
844 if ("" == $delim)
845 {
846 $delim = ";";
847 $match_pos = -1;
848 }
849
850 $dlen = strlen($delim);
851 $result = FALSE;
852
853 for ($i = $curr_pos; $i < $len; ++$i)
854 {
855 if ($match_pos < $i)
856 {
857 $match_pos = strpos($str, $delim, $i);
858 if (FALSE === $match_pos)
859 {
860 $match_pos = $len;
861 }
862 }
863
864 if ($i == $match_pos)
865 {
866 if ($i != $curr_pos)
867 {
868 $result = trim(substr($str_original, $curr_pos, $i - $curr_pos));
869 if (strncasecmp($result, 'delimiter', 9) == 0 && (strlen($result) == 9 || FALSE !== strpos(" \t", $result{9})))
870 {
871 $delim = trim(strtolower(substr($result, 10)));
872 if ("" == $delim) { $delim = ";"; }
873 $match_pos = -1;
874 $result = FALSE;
875 }
876 }
877 $i += $dlen;
878 if ($match_pos < 0)
879 {
880 $dlen = strlen($delim);
881 }
882 $curr_pos = $i--;
883 if ("" === $result)
884 {
885 $result = FALSE;
886 }
887 if (FALSE !== $result)
888 {
889 break;
890 }
891 } else if ($str{$i} == "'") {
892 for ($j = $i+1; $j < $len; ++$j) {
893 if ($str{$j} == "\\") ++$j;
894 else if ($str{$j} == "'") break;
895 }
896 $i = $j;
897 } else if ($str{$i} == "\"") {
898 for ($j = $i+1; $j < $len; ++$j) {
899 if ($str{$j} == "\\") ++$j;
900 else if ($str{$j} == "\"") break;
901 }
902 $i = $j;
903 } else if ($i < $len-1 && $str{$i} == "/" && $str{$i+1} == "*") {
904 $j = $i+2;
905 while ($j) {
906 $j = strpos($str, "*/", $j);
907 if (!$j || $str{$j-1} != "\\") { break; }
908 ++$j;
909 }
910 if (!$j) { break; }
911 $i = $j+1;
912 } else if ($str{$i} == "#") {
913 $j = strpos($str, "\n", $i+1) or strpos($str, "\r", $i+1);
914 if (!$j) { break; }
915 $i = $j;
916 } else if ($i < $len-2 && $str{$i} == "-" && $str{$i+1} == "-" && FALSE !== strpos(" \t", $str{$i+2})) {
917 $j = strpos($str, "\n", $i+3) or strpos($str, "\r", $i+1);
918 if (!$j) { break; }
919 $i = $j;
920 } else if ($str{$i} == "\\") {
921 ++$i;
922 }
923 }
924
925 if (FALSE === $result && $curr_pos < $len) {
926 $result = trim(substr($str_original, $curr_pos));
927 if (strncasecmp($result, 'delimiter', 9) == 0 && (strlen($result) == 9 || FALSE !== strpos(" \t", $result{9}))) {
928 $delim = trim(strtolower(substr($result, 10)));
929 if ("" == $delim) { $delim = ";"; }
930 $match_pos = -1;
931 $dlen = strlen($delim);
932 $result = FALSE;
933 }
934 $curr_pos = $len;
935 if ("" === $result) {
936 $result = FALSE;
937 }
938 }
939
940 WriteLog ( "Exit my_strtok" );
941
942 return $result;
943}
944
945
946/* Processes a set of queries. The queries are delimited with ;. Will return result for the last query only. */
947/* If it encounters any error in between will return error values for that query */
948
949function ExecuteBatchQuery ( $mysql, $query )
950{
951
952 WriteLog ( "Enter ExecuteBatchQuery" );
953
954 $prev = FALSE;
955 $token = my_strtok ( $query, ";" );
956
957 while ( $token )
958 {
959 $prev = $token;
960
961 $token = my_strtok();
962
963 if ( !$token )
964 {
965 return ExecuteSingleQuery ( $mysql, $prev );
966 }
967
968 $result = yog_mysql_query ( $prev, $mysql );
969
970 foreach ($result as $key => $value)
971 {
972 //$value['result'], $value['ar']
973 if ( $value['result']===-1 ) {
974 HandleError ( yog_mysql_errno($mysql), yog_mysql_error($mysql) );
975 return;
976 }
977
978 /* free the result */
979 if (!is_int($value['result'])) {
980 yog_mysql_free_result ( $value['result'] );
981 }
982
983 }
984 }
985
986 WriteLog ( "Exit ExecuteBatchQuery" );
987
988 return;
989}
990
991
992/* Function sets the MySQL server to non-strict mode as SQLyog is designed to work in non-strict mode */
993function SetNonStrictMode ( $mysql )
994{
995
996 WriteLog ( "Enter SetNonStrictMode" );
997
998 /* like SQLyog app we dont check the MySQL version. We just execute the statement and ignore the error if any */
999 $query = "set sql_mode=''";
1000 $result = yog_mysql_query ( $query, $mysql );
1001
1002 WriteLog ( "Exit SetNonStrictMode" );
1003
1004 return;
1005}
1006
1007
1008/* Starting from SQLyog v5.1, we dont take the charset info from the server, instead SQLyog send the info
1009 in the posted XML */
1010
1011function SetName ( $mysql )
1012{
1013
1014 global $charset;
1015
1016 WriteLog ( "Enter SetName" );
1017
1018 if ( $charset === NULL )
1019 return;
1020
1021 $query = 'SET NAMES ' . $charset;
1022 if ($charset!="[default]") {
1023 yog_mysql_query ( $query, $mysql );
1024 }
1025
1026 WriteLog ( "Exit SetName" );
1027
1028 return;
1029}
1030
1031/* Start element handler for the parser */
1032
1033function startElement ( $parser, $name, $attrs )
1034{
1035 global $xml_state;
1036 global $host;
1037 global $port;
1038 global $db;
1039 global $username;
1040 global $pwd;
1041 global $batch;
1042 global $query;
1043 global $base;
1044 global $libxml2_is_base64;
1045
1046 WriteLog ( "Enter startelement" );
1047
1048 //Done for bug in PHP 5.2.6 and libXML 2.7,2.
1049 // Special HTML characters were being dropped. So, now we provide to send always as base 64 encoded data.
1050
1051 $base = 0;
1052 if(isset($attrs['E']))
1053 {
1054 $base = (( $attrs['E'] == '1' )?(1):(0));
1055 }
1056
1057 switch ( strtolower ( $name ) )
1058 {
1059
1060 case "host":
1061 $xml_state = XML_HOST;
1062 break;
1063 case "db":
1064 $xml_state = XML_DB;
1065 break;
1066 case "charset":
1067 WriteLog ( 'Got charset' );
1068 $xml_state = XML_CHARSET;
1069 break;
1070 case "user":
1071 $xml_state = XML_USER;
1072 break;
1073 case "password":
1074 $xml_state = XML_PWD;
1075 break;
1076 case "port":
1077 $xml_state = XML_PORT;
1078 //This is an assumption that, if port is sent as base64 encoded
1079 //the "Always Use Base64 Encoding For Data Stream is checked."
1080 if($base == 1)
1081 {
1082 $libxml2_is_base64 = 1;
1083 }
1084 break;
1085 case "query":
1086 $xml_state = XML_QUERY;
1087 /* track whether the query(s) has to be processed in batch mode */
1088 $batch = (( $attrs['B'] == '1' )?(1):(0));
1089 break;
1090 case "libxml2_test_query":
1091 $xml_state = XML_LIBXML2_TEST_QUERY;
1092 break;
1093 }
1094 WriteLog ( "Exit startelement" );
1095}
1096
1097/* End element handler for the XML parser */
1098
1099function endElement ( $parser, $name )
1100{
1101 WriteLog ( "Enter endElement" );
1102
1103 global $xml_state;
1104
1105 $xml_state = XML_NOSTATE;
1106
1107 WriteLog ( "Exit endElement" );
1108}
1109
1110/* Character data handler for the parser */
1111
1112function charHandler ( $parser, $data )
1113{
1114
1115 global $xml_state;
1116 global $host;
1117 global $port;
1118 global $db;
1119 global $username;
1120 global $pwd;
1121 global $batch;
1122 global $query;
1123 global $base;
1124 global $charset;
1125 global $libxml2_test_query;
1126
1127 WriteLog ( "Enter charhandler" );
1128
1129 //Done for bug in PHP 5.2.6 and libXML 2.7,2.
1130 // Special HTML characters were being dropped. So, now we provide to send always as base 64 encoded data.
1131 if ( $base )
1132 {
1133 $data = base64_decode ( $data );
1134 }
1135
1136 if ( $xml_state == XML_HOST )
1137 {
1138 $host .= $data;
1139 }
1140 else if ( $xml_state == XML_DB )
1141 {
1142 $db .= $data;
1143 }
1144 else if ( $xml_state == XML_CHARSET )
1145 {
1146 $charset .= $data;
1147 }
1148 else if ( $xml_state == XML_USER )
1149 {
1150 $username .= $data;
1151 }
1152 else if ( $xml_state == XML_PWD )
1153 {
1154 $pwd .= $data;
1155 }
1156 else if ( $xml_state == XML_PORT )
1157 {
1158 $port .= $data;
1159 }
1160 else if ( $xml_state == XML_QUERY )
1161 {
1162 $query .= $data;
1163 }
1164 else if ( $xml_state == XML_LIBXML2_TEST_QUERY )
1165 {
1166 $libxml2_test_query .= $data;
1167 }
1168
1169 WriteLog ( "Exit charhandler" );
1170}
1171
1172
1173/* Convert special characters such as <,>,&, /,\, to equivalent xmlor html characters*/
1174function convertxmlchars ( $string,$called_by="" )
1175{
1176 WriteLog ( "Enter convertxmlchars, called by".$called_by );
1177 WriteLog ( "Input: " . $string );
1178
1179 $result = $string;
1180
1181 $result = eregi_replace('&', '&', $result);
1182 $result = eregi_replace('<', '<', $result);
1183 $result = eregi_replace('>', '>', $result);
1184 $result = eregi_replace('\'', ''', $result);
1185 $result = eregi_replace('\"', '"', $result);
1186
1187 WriteLog ( "Output: " . $result );
1188 WriteLog ( "Exit convertxmlchars" );
1189
1190 return $result;
1191}
1192
1193/* Function writes down the correct XML for handling mysql_pconnect() error */
1194
1195function HandleError ( $errno, $error )
1196{
1197
1198 WriteLog ( "Enter handleerror" );
1199
1200 echo "<result v=\"" . tunnelversion . "\"><e_i><e_n>$errno</e_n><e_d>" . convertxmlchars($error) . "</e_d></e_i></result>";
1201
1202 WriteLog ( "Exit handleerror" );
1203}
1204
1205
1206/* Parses the XML received and stores information into the variables passed as parameter */
1207
1208function GetDetailsFromPostedXML ( $xmlrecvd )
1209{
1210
1211 WriteLog ( "Enter getdetailsfrompostedxml" );
1212
1213 $xml_parser = xml_parser_create ();
1214 xml_set_element_handler($xml_parser, "startElement", "endElement");
1215 xml_set_character_data_handler ( $xml_parser, "charHandler" );
1216
1217 WriteLog ("Starting to parse:");
1218 WriteLog($xmlrecvd);
1219 $ret = xml_parse ( $xml_parser, $xmlrecvd );
1220
1221
1222 if ( !$ret )
1223 {
1224 HandleError ( xml_get_error_code ( $xml_parser ), xml_error_string ( xml_get_error_code ( $xml_parser ) ) );
1225 return FALSE;
1226 }
1227
1228 xml_parser_free($xml_parser);
1229
1230 WriteLog ( "Exit getdetailsfrompostedxml" );
1231
1232 return TRUE;
1233}
1234
1235
1236/* we dont allow an user to connect directly to this page from a browser. It can only be accessed using SQLyog */
1237
1238function ShowAccessError ( $extra = "" )
1239{
1240
1241 WriteLog ( "Enter showaccesserror" );
1242
1243 $errmsg = '<div align="justify"><p><b>Tunnel version: ' . tunnelversion . '</b>.<p>This PHP page exposes the MySQL API as a set of webservices.<br><br>This page allows SQLyog to manage a MySQL server even if the MySQL port is blocked or remote access to MySQL is not allowed.<br><br>Visit <a href ="http://www.webyog.com">Webyog</a> to get more details about SQLyog.';
1244
1245 echo ( '<html><head><title>SQLyog HTTP Tunneling</title></head>'.
1246 '<body leftmargin="0" topmargin="0">'.
1247 '<p align="center"><img src="http://www.webyog.com/images/header.jpg" alt="Webyog"><p>'
1248 );
1249 echo ( '<table align="center" width="60%" cellpadding="3" border="0">'.
1250 '<tr><td><font face="Verdana" size="2">' . $errmsg .
1251 '</td</tr></table>' );
1252
1253 /* we show PHP version error also if required */
1254 if ( CheckPHPVersion() == FALSE ) {
1255 echo ( '<table width="100%" cellpadding="3" border="0"><tr><td><font face="Verdana" size="2"><p><b>Error: </b>SQLyog HTTP Tunnel feature requires PHP version > 4.3.0</td></tr></table>' );
1256 }
1257
1258 if ($extra != "" ) {
1259 echo ( '<table width="100%" cellpadding="3" border="0"><tr><td><font face="Verdana" size="2"><p><b>Error!' . $extra . '</td></tr></table>' );
1260 }
1261
1262 echo ( '</body></html>' );
1263
1264 WriteLog ( "Exit showaccesserror" );
1265}
1266
1267
1268/* Check PHP version compatibility*/
1269function CheckPHPVersion()
1270{
1271
1272 $phpversionstr = phpversion();
1273 $versionarry = explode(".", $phpversionstr, 2);
1274
1275 /* We dont support v4.3.0 */
1276 if ( (integer)$versionarry[0] < 4 ||
1277 ((integer)$versionarry[0] == 4 && (integer)$versionarry[1] < 3 ))
1278 {
1279 return FALSE;
1280 }
1281 else
1282 {
1283 return TRUE;
1284 }
1285
1286 return TRUE;
1287}
1288
1289
1290
1291
1292/* function checks if a required module is installed or not */
1293
1294function AreModulesInstalled ()
1295{
1296 WriteLog ( "Enter aremodulesinstalled" );
1297
1298 $modules = get_loaded_extensions();
1299 $modulenotfound = '';
1300
1301 $thisExtension="";
1302 if ( extension_loaded ( "xml" ) != TRUE )
1303 {
1304 $modulenotfound = 'XML';
1305 $thisExtension="this extension";
1306 } else if ( DB_EXTENSION=="-1")
1307 {
1308 $modulenotfound = 'php_mysqli or php_mysql';
1309 $thisExtension="one of these these extensions";
1310 }
1311 else
1312 {
1313 WriteLog ( "Exit aremodulesinstalled" );
1314 // if correct modules are found - exit IMMEDIATELY
1315 return TRUE;
1316 }
1317
1318 if(isset($_GET['app'])) // from SQLyog - just indicate to SQLyog that SOME modules are not installed
1319 {
1320 echo(tunnelversionstring);
1321 echo(phpmoduleerror);
1322 WriteLog ( "Exit aremodulesinstalled" );
1323 return FALSE;
1324 }
1325
1326 // It will come here only when its called from a browser
1327 $errmsg = '<font color="#FF0000"><b>Error:</b> </font>Extension <b>' . $modulenotfound . '</b> was not found compiled and loaded in the PHP interpreter. SQLyog requires '.$thisExtension .' to work properly.';
1328 $errmsg .= '<p><b>Tunnel version: ' . tunnelversion . '</b>.<p>This PHP page exposes the MySQL API as a set of webservices.<br><br>This page allows SQLyog to manage a MySQL server even if the MySQL port is blocked or remote access to MySQL is not allowed.<br><br>Visit <a href ="http://www.webyog.com">Webyog</a> to get more details about SQLyog.';
1329
1330 echo ( '<html><head><title>SQLyog HTTP Tunneling</title></head><body leftmargin="0" topmargin="0"><div align=center><img src="http://www.webyog.com/images/header.jpg" alt="Webyog"><p>' );
1331 echo ( '<table align=center width="60%" cellpadding="3" border="0"><tr><td><font face="Verdana" size="2">' . $errmsg . '</td</tr></table>' );
1332 echo ( '</body></html>' );
1333
1334 WriteLog ( "Exit aremodulesinstalled" );
1335}
1336
1337
1338/**
1339 * checks if the XML stream is base 64 encoded
1340 *
1341 * @return bool If stream is encoded, return true. Else false;
1342 *
1343 */
1344function LibXml2IsBase64Encoded()
1345{
1346 global $libxml2_is_base64;
1347 if ($libxml2_is_base64 == 0){
1348 return false;
1349 }
1350 return true;
1351}
1352
1353/** Detect if the user's PHP/LibXML is affected by the following bug: -
1354 * http://bugs.php.net/bug.php?id=45996
1355*/
1356function LibXml2IsBuggy()
1357{
1358 global $libxml2_test_query;
1359 $libxml2_test_query = '';
1360
1361 $testxml = '<xml><libxml2_test_query>select 'a'</libxml2_test_query></xml>';
1362
1363 GetDetailsFromPostedXML ($testxml);
1364
1365 if(strcasecmp($libxml2_test_query, 'select a') == 0)
1366 {
1367 //This PHP/LibXML is buggy!
1368 return true;
1369 }
1370
1371 //Not buggy!
1372 return false;
1373}
1374
1375
1376/* we can now use SQLyogTunnel.php to log debug informations, which will help us to point out the error */
1377function WriteLog ( $loginfo )
1378{
1379 if ( defined("DEBUG") )
1380 {
1381 $fp = fopen ( "yogtunnel.log", "a" );
1382
1383 if ( $fp == FALSE )
1384 return;
1385
1386 fwrite ( $fp, $loginfo . "\r\n" ); // MY_CHANGE: Because below it was
1387 // printing 'Enter' instead of new line
1388 fclose ( $fp );
1389 }
1390}
1391
1392function WriteLogTemp ( $loginfo )
1393{
1394 if ( defined("DEBUG") )
1395 {
1396 $fp = fopen ( "sabya.log", "a" );
1397
1398 if ( $fp == FALSE )
1399 return;
1400
1401 fwrite ( $fp, $loginfo . "\r\n" ); // MY_CHANGE: Because below it was
1402 // printing 'Enter' instead of new line
1403 fclose ( $fp );
1404 }
1405}
1406
1407/* Process the query*/
1408function ProcessQuery ()
1409{
1410 WriteLog ( "Enter processquery" );
1411
1412 if ( CheckPHPVersion() == FALSE )
1413 {
1414 /* now the call can be of three types
1415 1.) Specific to check tunnel version
1416 2.) Normal where it is expected that the PHP page is 4.3.0
1417 3.) From browser
1418
1419 We check this by checking the query string which is sent if just a check is done by SQLyog */
1420
1421 WriteLog ( "CheckPHPVersion is FALSE" );
1422 if(isset($_GET['app']))
1423 {
1424 echo(tunnelversionstring);
1425 echo(phpversionerror);
1426 }
1427 else
1428 {
1429 WriteLog ( "CheckPHPVersion is FALSE and app query string not set" );
1430 ShowAccessError();
1431 }
1432
1433 return;
1434
1435 }
1436
1437 /* in special case, sqlyog just sends garbage data with query string to check for tunnel version. we need to process that now */
1438 if(isset($_GET['app']))
1439 {
1440 WriteLog ( "app query string not set" );
1441 echo(tunnelversionstring);
1442 echo(tunnelversion);
1443 return;
1444 }
1445
1446 /* Starting from 5.1 BETA 4, we dont get the data as URL encoded POST data, we just get it as raw data */
1447 WriteLog ( "Trying to get php://input" );
1448 $xmlrecvd = file_get_contents("php://input");
1449 WriteLog ( "Got php://input!" );
1450
1451 if ( strlen ( $xmlrecvd ) == 0 )
1452 {
1453 WriteLog ( "Called from browser." );
1454 ShowAccessError ();
1455 WriteLog ( "xmlrecvd is blank" );
1456 return;
1457 }
1458
1459 WriteLog ( $xmlrecvd );
1460
1461 global $host;
1462 global $port;
1463 global $username;
1464 global $pwd;
1465 global $db;
1466 global $batch;
1467 global $query;
1468 global $base;
1469
1470 $ret = GetDetailsFromPostedXML ( $xmlrecvd );
1471
1472 if ( $ret == FALSE )
1473 return;
1474
1475 /* Wrap result in <XML> tag */
1476 echo "<xml>";
1477
1478 //If the stream is not base-64 encoded and the PHP has the libxml2 bug display extra error.
1479 if(LibXml2IsBase64Encoded() == false && LibXml2IsBuggy() == true)
1480 {
1481 $extra_msg =
1482 'Your PHP/libxml version is affected by a bug. ' .
1483 'Please check "Always Use Base64 Encoding For Data Stream" in "Advanced" section of HTTP tab.'
1484 ;
1485 HandleError (4, $extra_msg);
1486 WriteLog ('libxml2 error');
1487 echo "</xml>";
1488 return;
1489 }
1490
1491 /* connect to the mysql server */
1492 WriteLog ( "Trying to connect" );
1493 $mysql = yog_mysql_connect ( $host,$port, $username, $pwd );
1494 if ( !$mysql )
1495 {
1496 HandleError ( yog_mysql_connect_errno(), yog_mysql_connect_error() );
1497 WriteLog ( yog_mysql_connect_error() );
1498 echo "</xml>";
1499 return;
1500 }
1501
1502 WriteLog ( "Connected" );
1503
1504 /* Function will execute setnames in the server as it does in SQLyog client */
1505 SetName ( $mysql );
1506
1507 yog_mysql_select_db ( str_replace ( '`', '', $db ), $mysql );
1508
1509 /* set sql_mode to zero */
1510 SetNonStrictMode ( $mysql );
1511
1512 if ( $batch ) {
1513 ExecuteBatchQuery ( $mysql, $query );
1514 }
1515 else
1516 ExecuteSingleQuery ( $mysql, $query );
1517
1518 yog_mysql_close ( $mysql );
1519
1520 echo "</xml>";
1521
1522 WriteLog ( "Exit processquery" );
1523}
1524
1525
1526
1527/*********** Global Section **********/
1528
1529define ( "COMMENT_OFF", 0 );
1530define ( "COMMENT_HASH", 1 );
1531define ( "COMMENT_DASH", 2 );
1532define ( "COMMENT_START", 0 );
1533
1534/* current element state while parsing XML received as post */
1535
1536define ( "XML_NOSTATE", 0 );
1537define ( "XML_HOST", 1 );
1538define ( "XML_USER", 2 );
1539define ( "XML_DB", 3 );
1540define ( "XML_PWD", 4 );
1541define ( "XML_PORT", 5 );
1542define ( "XML_QUERY", 6 );
1543define ( "XML_CHARSET", 7 );
1544
1545define ( "XML_LIBXML2_TEST_QUERY", 8);
1546/* uncomment this line to create a debug log */
1547//define ( "DEBUG", 1 );
1548
1549/* version constant */
1550/* You will need to change the version in processquery method too, where it shows: $versionheader = 'TunnelVersion:5.13.1' */
1551
1552define ( "tunnelversion", '8.05');
1553define ( "tunnelversionstring", 'TunnelVersion:' );
1554define ( "phpversionerror", 'PHP_VERSION_ERROR' );
1555define ( "phpmoduleerror", 'PHP_MODULE_NOT_INSTALLED' );
1556
1557if (!defined("MYSQLI_TYPE_BIT")) {
1558 define ( "MYSQLI_TYPE_BIT", 16);
1559}
1560
1561/* current character in the query */
1562$curpos = 0;
1563
1564//ini_set("display_errors",0);
1565
1566/* check whether global variables are registered or not */
1567if (!get_cfg_var("register_globals"))
1568{
1569 extract($_REQUEST);
1570}
1571
1572/* we have to set the value to be off during runtime coz it does not work when magic_quotes_runtime = On is setin Php.ini */
1573set_magic_quotes_runtime (0);
1574
1575
1576/* Check for the PHP_MYSQL/PHP_MYSQLI extension loaded */
1577
1578if (extension_loaded('mysqli'))
1579{
1580 define ("DB_EXTENSION", "mysqli");
1581}
1582elseif (extension_loaded('mysql'))
1583{
1584 define ("DB_EXTENSION", "mysql");
1585}
1586else
1587{
1588 define ("DB_EXTENSION", "-1");
1589}
1590
1591
1592
1593
1594/* global variable to keep the state of current XML element */
1595$xml_state = XML_NOSTATE;
1596
1597/* global variables to track various informations about the query */
1598
1599$host = NULL;
1600$port = NULL;
1601$db = NULL;
1602$username = NULL;
1603$pwd = NULL;
1604$charset = NULL;
1605$batch = 0;
1606$base = 0;
1607$query = NULL;
1608$libxml2_test_query = NULL;
1609$libxml2_is_base64 = 0;
1610
1611
1612/* we stop all error reporting as we check for all sort of errors */
1613WriteLog ( "" );
1614if ( defined("DEBUG") )
1615 error_reporting ( E_ALL );
1616else
1617 error_reporting ( 0 );
1618
1619set_time_limit ( 0 );
1620
1621
1622/* we check if all the external libraries support i.e. expat and mysql in our case is built in or not */
1623/* if any of the libraries are not found then we show a warning and exit */
1624
1625if ( AreModulesInstalled () == TRUE )
1626{
1627
1628 ProcessQuery ();
1629
1630}
1631?>