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