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