database timestamp fixup
[lhc/web/wiklou.git] / includes / SpecialAsksql.php
1 <?php
2 #
3 # If enabled through $wgAllowSysopQueries = true, this class
4 # let users with sysop right the possibility to make sql queries
5 # against the cur table.
6 # Heavy queries could slow down the database specially for the
7 # biggest wikis.
8
9 function wfSpecialAsksql()
10 {
11 global $wgUser, $wgOut, $wgRequest, $wgAllowSysopQueries;
12
13 if( !$wgAllowSysopQueries ) {
14 $wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
15 return;
16 }
17 if( !$wgUser->isSysop() ) {
18 $wgOut->sysopRequired();
19 return;
20 }
21
22 if( $wgRequest->wasPosted() ) {
23 $query = $wgRequest->getVal( 'wpSqlQuery' );
24 $action = $wgRequest->getVal( 'action' );
25 } else {
26 $query = "";
27 $action = "";
28 }
29 $f = new SqlQueryForm( $query);
30
31 if ( "submit" == $action ) {
32 $f->doSubmit();
33 } else {
34 $f->showForm( "" );
35 }
36 }
37
38 class SqlQueryForm {
39 var $query = "";
40
41 function SqlQueryForm( $query ) {
42 $this->query = $query;
43 }
44
45 function showForm( $err )
46 {
47 global $wgOut, $wgUser, $wgLang;
48 global $wgLogQueries;
49
50 $wgOut->setPagetitle( wfMsg( "asksql" ) );
51 $note = wfMsg( "asksqltext" );
52 if($wgLogQueries)
53 $note .= " " . wfMsg( "sqlislogged" );
54 $wgOut->addWikiText( $note );
55
56 if ( "" != $err ) {
57 $wgOut->addHTML( "<p><font color='red' size='+1'>" . htmlspecialchars($err) . "</font>\n" );
58 }
59 if ( ! $this->query ) { $this->query = "SELECT ... FROM ... WHERE ..."; }
60 $q = wfMsg( "sqlquery" );
61 $qb = wfMsg( "querybtn" );
62 $titleObj = Title::makeTitle( NS_SPECIAL, "Asksql" );
63 $action = $titleObj->escapeLocalURL( "action=submit" );
64
65 $wgOut->addHTML( "<p>
66 <form id=\"asksql\" method=\"post\" action=\"{$action}\">
67 <table border=0><tr>
68 <td align=right>{$q}:</td>
69 <td align=left>
70 <textarea name=\"wpSqlQuery\" cols=80 rows=4 wrap=\"virtual\">"
71 . htmlspecialchars($this->query) ."
72 </textarea>
73 </td>
74 </tr><tr>
75 <td>&nbsp;</td><td align=\"left\">
76 <input type=submit name=\"wpQueryBtn\" value=\"{$qb}\">
77 </td></tr></table>
78 </form>\n" );
79
80 }
81
82 function doSubmit()
83 {
84 global $wgOut, $wgUser, $wgServer, $wgScript, $wgArticlePath, $wgLang;
85 global $wgDBserver, $wgDBsqluser, $wgDBsqlpassword, $wgDBname, $wgSqlTimeout;
86
87 # Use a limit, folks!
88 $this->query = trim( $this->query );
89 if( preg_match( "/^SELECT/i", $this->query )
90 and !preg_match( "/LIMIT/i", $this->query ) ) {
91 $this->query .= " LIMIT 100";
92 }
93 $conn = Database::newFromParams( $wgDBserver, $wgDBsqluser, $wgDBsqlpassword, $wgDBname );
94
95 $this->logQuery( $this->query );
96
97 # Start timer, will kill the DB thread in $wgSqlTimeout seconds
98 $conn->startTimer( $wgSqlTimeout );
99 $res = $conn->query( $this->query, "SpecialAsksql::doSubmit" );
100 $conn->stopTimer();
101 $this->logFinishedQuery();
102
103 $n = 0;
104 @$n = $conn->numFields( $res );
105 $titleList = false;
106
107 if ( $n ) {
108 $k = array();
109 for ( $x = 0; $x < $n; ++$x ) {
110 array_push( $k, $conn->fieldName( $res, $x ) );
111 }
112
113 if ( $n == 2 && in_array( "cur_title", $k ) && in_array( "cur_namespace", $k ) ) {
114 $titleList = true;
115 }
116
117 $a = array();
118 while ( $s = $conn->fetchObject( $res ) ) {
119 array_push( $a, $s );
120 }
121 $conn->freeResult( $res );
122
123 if ( $titleList ) {
124 $r = "";
125 foreach ( $a as $y ) {
126 $sTitle = htmlspecialchars( $y->cur_title );
127 if ( $y->cur_namespace ) {
128 $sNamespace = $wgLang->getNsText( $y->cur_namespace );
129 $link = "$sNamespace:$sTitle";
130 } else {
131 $link = "$sTitle";
132 }
133 $skin = $wgUser->getSkin();
134 $link = $skin->makeLink( $link );
135 $r .= "* [[$link]]<br>\n";
136 }
137 } else {
138
139 $r = "<table border=1 bordercolor=black cellspacing=0 " .
140 "cellpadding=2><tr>\n";
141 foreach ( $k as $x ) $r .= "<th>" . htmlspecialchars( $x ) . "</th>";
142 $r .= "</tr>\n";
143
144 foreach ( $a as $y ) {
145 $r .= "<tr>";
146 foreach ( $k as $x ) {
147 $o = $y->$x ;
148 if ( $x == "cur_title" or $x == "old_title" or $x == "rc_title") {
149 $namespace = 0;
150 if( $x == "cur_title" ) $namespace = $y->cur_namespace;
151 if( $x == "old_title" ) $namespace = $y->old_namespace;
152 if( $x == "rc_title" ) $namespace = $y->rc_namespace;
153 if( $namespace ) $o = $wgLang->getNsText( $namespace ) . ":" . $o;
154 $o = "<a href=\"" . wfLocalUrlE($o) . "\" class='internal'>" .
155 htmlspecialchars( $y->$x ) . "</a>" ;
156 } else {
157 $o = htmlspecialchars( $o );
158 }
159 $r .= "<td>" . $o . "</td>\n";
160 }
161 $r .= "</tr>\n";
162 }
163 $r .= "</table>\n";
164 }
165 }
166 $this->showForm( wfMsg( "querysuccessful" ) );
167 $wgOut->addHTML( "<hr>{$r}\n" );
168 }
169
170 function logQuery( $q ) {
171 global $wgSqlLogFile, $wgLogQueries, $wgUser;
172 if(!$wgLogQueries) return;
173
174 $f = fopen( $wgSqlLogFile, "a" );
175 fputs( $f, "\n\n" . wfTimestampNow() .
176 " query by " . $wgUser->getName() .
177 ":\n$q\n" );
178 fclose( $f );
179 $this->starttime = wfTime();
180 }
181
182 function logFinishedQuery() {
183 global $wgSqlLogFile, $wgLogQueries;
184 if(!$wgLogQueries) return;
185
186 $interval = wfTime() - $this->starttime;
187
188 $f = fopen( $wgSqlLogFile, "a" );
189 fputs( $f, "finished at " . wfTimestampNow() . "; took $interval secs\n" );
190 fclose( $f );
191 }
192
193 }
194
195 ?>