Make WordPress Core

Ticket #2023: classes.php

File classes.php, 39.1 KB (added by shovel, 19 years ago)

The new classes.php with appended fix.

Line 
1<?php
2
3class WP_Query {
4        var $query;
5        var $query_vars;
6        var $queried_object;
7        var $queried_object_id;
8
9        var $posts;
10        var $post_count = 0;
11        var $current_post = -1;
12        var $post;
13
14        var $is_single = false;
15        var $is_page = false;
16        var $is_archive = false;
17        var $is_date = false;
18        var $is_year = false;
19        var $is_month = false;
20        var $is_day = false;
21        var $is_time = false;
22        var $is_author = false;
23        var $is_category = false;
24        var $is_search = false;
25        var $is_feed = false;
26        var $is_trackback = false;
27        var $is_home = false;
28        var $is_404 = false;
29        var $is_comments_popup = false;
30        var $is_admin = false;
31
32        function init () {
33                $this->is_single = false;
34                $this->is_page = false;
35                $this->is_archive = false;
36                $this->is_date = false;
37                $this->is_year = false;
38                $this->is_month = false;
39                $this->is_day = false;
40                $this->is_time = false;
41                $this->is_author = false;
42                $this->is_category = false;
43                $this->is_search = false;
44                $this->is_feed = false;
45                $this->is_trackback = false;
46                $this->is_home = false;
47                $this->is_404 = false;
48                $this->is_paged = false;
49                $this->is_admin = false;
50
51                unset($this->posts);
52                unset($this->query);
53                unset($this->query_vars);
54                unset($this->queried_object);
55                unset($this->queried_object_id);
56                $this->post_count = 0;
57                $this->current_post = -1;
58        }
59
60        // Reparse the query vars.
61        function parse_query_vars() {
62                $this->parse_query('');
63        }
64
65        // Parse a query string and set query type booleans.
66        function parse_query ($query) {
67                if ( !empty($query) || !isset($this->query) ) {
68                        $this->init();
69                        parse_str($query, $qv);
70                        $this->query = $query;
71                        $this->query_vars = $qv;
72                }
73
74                $qv['m'] =  (int) $qv['m'];
75                $qv['p'] =  (int) $qv['p'];
76
77                if ('' != $qv['name']) {
78                        $this->is_single = true;
79                } elseif ( $qv['p'] ) {
80                        $this->is_single = true;
81                } elseif (('' != $qv['hour']) && ('' != $qv['minute']) &&('' != $qv['second']) && ('' != $qv['year']) && ('' != $qv['monthnum']) && ('' != $qv['day'])) {
82                        // If year, month, day, hour, minute, and second are set, a single
83                  // post is being queried.       
84                        $this->is_single = true;
85                } elseif ('' != $qv['static'] || '' != $qv['pagename'] || '' != $qv['page_id']) {
86                        $this->is_page = true;
87                        $this->is_single = false;
88                } elseif (!empty($qv['s'])) {
89                        $this->is_search = true;
90                } else {
91                // Look for archive queries.  Dates, categories, authors.
92
93                        if ( (int) $qv['second']) {
94                                $this->is_time = true;
95                                $this->is_date = true;
96                        }
97
98                        if ( (int) $qv['minute']) {
99                                $this->is_time = true;
100                                $this->is_date = true;
101                        }
102
103                        if ( (int) $qv['hour']) {
104                                $this->is_time = true;
105                                $this->is_date = true;
106                        }
107
108                        if ( (int) $qv['day']) {
109                                if (! $this->is_date) {
110                                        $this->is_day = true;
111                                        $this->is_date = true;
112                                }
113                        }
114
115                        if ( (int)  $qv['monthnum']) {
116                                if (! $this->is_date) {
117                                        $this->is_month = true;
118                                        $this->is_date = true;
119                                }
120                        }
121
122                        if ( (int)  $qv['year']) {
123                                if (! $this->is_date) {
124                                        $this->is_year = true;
125                                        $this->is_date = true;
126                                }
127                        }
128
129                        if ( (int)  $qv['m']) {
130                                $this->is_date = true;
131                                if (strlen($qv['m']) > 9) {
132                                        $this->is_time = true;
133                                } else if (strlen($qv['m']) > 7) {
134                                        $this->is_day = true;
135                                } else if (strlen($qv['m']) > 5) {
136                                        $this->is_month = true;
137                                } else {
138                                        $this->is_year = true;
139                                }
140                        }
141
142                        if ('' != $qv['w']) {
143                                $this->is_date = true;
144                        }
145
146                        if (empty($qv['cat']) || ($qv['cat'] == '0')) {
147                                $this->is_category = false;
148                        } else {
149                                if (stristr($qv['cat'],'-')) {
150                                        $this->is_category = false;
151                                } else {
152                                        $this->is_category = true;
153                                }
154                        }
155
156                        if ('' != $qv['category_name']) {
157                                $this->is_category = true;
158                        }
159           
160                        if ((empty($qv['author'])) || ($qv['author'] == '0')) {
161                                $this->is_author = false;
162                        } else {
163                                $this->is_author = true;
164                        }
165
166                        if ('' != $qv['author_name']) {
167                                $this->is_author = true;
168                        }
169
170                        if ( ($this->is_date || $this->is_author || $this->is_category)) {
171                                $this->is_archive = true;
172                        }
173                }
174
175                if ('' != $qv['feed']) {
176                        $this->is_feed = true;
177                }
178
179                if ('' != $qv['tb']) {
180                        $this->is_trackback = true;
181                }
182
183                if ('404' == $qv['error']) {
184                        $this->is_404 = true;
185                }
186
187                if ('' != $qv['paged']) {
188                        $this->is_paged = true;
189                }
190
191                if ('' != $qv['comments_popup']) {
192                        $this->is_comments_popup = true;
193                }
194
195                if (strstr($_SERVER['PHP_SELF'], 'wp-admin/')) {
196                        $this->is_admin = true;
197                }
198
199                if ( ! ($this->is_archive || $this->is_single || $this->is_page || $this->is_search || $this->is_feed || $this->is_trackback || $this->is_404 || $this->is_admin || $this->is_comments_popup)) {
200                        $this->is_home = true;
201                }
202
203                if ( !empty($query) ) {
204                        do_action('parse_query', array(&$this));
205                }
206        }
207
208        function get($query_var) {
209                if (isset($this->query_vars[$query_var])) {
210                        return $this->query_vars[$query_var];
211                }
212
213                return '';
214        }
215
216        function set($query_var, $value) {
217                $this->query_vars[$query_var] = $value;
218        }
219
220        function &get_posts() {
221                global $wpdb, $pagenow, $request, $user_ID;
222
223                // Shorthand.
224                $q = $this->query_vars; 
225
226                // First let's clear some variables
227                $whichcat = '';
228                $whichauthor = '';
229                $result = '';
230                $where = '';
231                $limits = '';
232                $distinct = '';
233                $join = '';
234
235                if ( !isset($q['posts_per_page']) || $q['posts_per_page'] == 0 )
236                        $q['posts_per_page'] = get_settings('posts_per_page');
237                if ( !isset($q['what_to_show']) )
238                        $q['what_to_show'] = get_settings('what_to_show');
239                if ( isset($q['showposts']) && $q['showposts'] ) {
240                        $q['showposts'] = (int) $q['showposts'];
241                        $q['posts_per_page'] = $q['showposts'];
242                }
243                if ( (isset($q['posts_per_archive_page']) && $q['posts_per_archive_page'] != 0) && ($this->is_archive || $this->is_search) )
244                        $q['posts_per_page'] = $q['posts_per_archive_page'];
245                if ( !isset($q['nopaging']) ) {
246                        if ($q['posts_per_page'] == -1) {
247                                $q['nopaging'] = true;
248                        } else {
249                                $q['nopaging'] = false;
250                        }
251                }
252                if ( $this->is_feed ) {
253                        $q['posts_per_page'] = get_settings('posts_per_rss');
254                        $q['what_to_show'] = 'posts';
255                }
256
257                if (isset($q['page'])) {
258                        $q['page'] = trim($q['page'], '/');
259                        $q['page'] = (int) $q['page'];
260                }
261       
262                $add_hours = intval(get_settings('gmt_offset'));
263                $add_minutes = intval(60 * (get_settings('gmt_offset') - $add_hours));
264                $wp_posts_post_date_field = "post_date"; // "DATE_ADD(post_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)";
265
266                // If a month is specified in the querystring, load that month
267                if ( (int) $q['m'] ) {
268                        $q['m'] = '' . preg_replace('|[^0-9]|', '', $q['m']);
269                        $where .= ' AND YEAR(post_date)=' . substr($q['m'], 0, 4);
270                        if (strlen($q['m'])>5)
271                                $where .= ' AND MONTH(post_date)=' . substr($q['m'], 4, 2);
272                        if (strlen($q['m'])>7)
273                                $where .= ' AND DAYOFMONTH(post_date)=' . substr($q['m'], 6, 2);
274                        if (strlen($q['m'])>9)
275                                $where .= ' AND HOUR(post_date)=' . substr($q['m'], 8, 2);
276                        if (strlen($q['m'])>11)
277                                $where .= ' AND MINUTE(post_date)=' . substr($q['m'], 10, 2);
278                        if (strlen($q['m'])>13)
279                                $where .= ' AND SECOND(post_date)=' . substr($q['m'], 12, 2);
280                }
281
282                if ( (int) $q['hour'] ) {
283                        $q['hour'] = '' . intval($q['hour']);
284                        $where .= " AND HOUR(post_date)='" . $q['hour'] . "'";
285                }
286
287                if ( (int) $q['minute'] ) {
288                        $q['minute'] = '' . intval($q['minute']);
289                        $where .= " AND MINUTE(post_date)='" . $q['minute'] . "'";
290                }
291
292                if ( (int) $q['second'] ) {
293                        $q['second'] = '' . intval($q['second']);
294                        $where .= " AND SECOND(post_date)='" . $q['second'] . "'";
295                }
296
297                if ( (int) $q['year'] ) {
298                        $q['year'] = '' . intval($q['year']);
299                        $where .= " AND YEAR(post_date)='" . $q['year'] . "'";
300                }
301
302                if ( (int) $q['monthnum'] ) {
303                        $q['monthnum'] = '' . intval($q['monthnum']);
304                        $where .= " AND MONTH(post_date)='" . $q['monthnum'] . "'";
305                }
306
307                if ( (int) $q['day'] ) {
308                        $q['day'] = '' . intval($q['day']);
309                        $where .= " AND DAYOFMONTH(post_date)='" . $q['day'] . "'";
310                }
311
312                if ('' != $q['name']) {
313                        $q['name'] = sanitize_title($q['name']);
314                        $where .= " AND post_name = '" . $q['name'] . "'";
315                } else if ('' != $q['pagename']) {
316                        $q['pagename'] = sanitize_title(basename(str_replace('%2F', '/', urlencode($q['pagename']))));
317                        $q['name'] = $q['pagename'];
318                        $where .= " AND post_name = '" . $q['pagename'] . "'";
319                }
320
321
322                if ( (int) $q['w'] ) {
323                        $q['w'] = ''.intval($q['w']);
324                        $where .= " AND WEEK(post_date, 1)='" . $q['w'] . "'";
325                }
326
327                if ( intval($q['comments_popup']) )
328                        $q['p'] = intval($q['comments_popup']);
329
330                // If a post number is specified, load that post
331                if (($q['p'] != '') && intval($q['p']) != 0) {
332                        $q['p'] =  (int) $q['p'];
333                        $where = ' AND ID = ' . $q['p'];
334                }
335
336                if (($q['page_id'] != '') && (intval($q['page_id']) != 0)) {
337                        $q['page_id'] = intval($q['page_id']);
338                        $q['p'] = $q['page_id'];
339                        $where = ' AND ID = '.$q['page_id'];
340                }
341
342                // If a search pattern is specified, load the posts that match
343                if (!empty($q['s'])) {
344                        $q['s'] = addslashes_gpc($q['s']);
345                        $search = ' AND (';
346                        //$q['s'] = preg_replace('#(&\#x*)([0-9A-F]+);*#iu', ' ', $q['s']);
347                        //$q['s'] = str_replace(',', ' ', $q['s']);
348                        //$q['s'] = str_replace('"', ' ', $q['s']);
349                        //$q['s'] = trim($q['s']);
350                 
351                  // -- BEGIN Anthony White's (firespade@gmail.com) XSS Patch v1.0.1 -- //
352                  $tonystr = array ('@<script[^>]*?>.*?</script>@si', // kill js
353                                    '@<[\/\!]*?[^<>]*?>@si',          // kill html
354                                              '@([\r\n])[\s]+@',                // trim whitespace
355                                              '@&(quot|#34);@i',               
356                                              '@&(amp|#38);@i',
357                                              '@&(lt|#60);@i',
358                                              '@&(gt|#62);@i',
359                                              '@&(nbsp|#160);@i',
360                                              '@&(iexcl|#161);@i',
361                                              '@&(cent|#162);@i',
362                                              '@&(pound|#163);@i',
363                                              '@&(copy|#169);@i',
364                                              '@&#(\d+);@e');
365                  // -- replacements
366                  $replace = array ('',
367                                    '',
368                                    '\1',
369                                    '"',
370                                    '&',
371                                    '<',
372                                    '>',
373                                    ' ',
374                                    chr(161),
375                                    chr(162),
376                                    chr(163),
377                                    chr(169),
378                                    'chr(\1)');
379                  // -- new preg_replace()
380                  $q['s'] = preg_replace($tonystr, $replace, $q['s']);
381                  // -- END Anthony White's (firespade@gmail.com) XSS Patch v1.0.1 -- //
382
383                        if ($q['exact']) {
384                                $n = '';
385                        } else {
386                                $n = '%';
387                        }
388                        if (!$q['sentence']) {
389                                $s_array = explode(' ',$q['s']);
390                                $q['search_terms'] = $s_array;
391                                $search .= '((post_title LIKE \''.$n.$s_array[0].$n.'\') OR (post_content LIKE \''.$n.$s_array[0].$n.'\'))';
392                                for ( $i = 1; $i < count($s_array); $i = $i + 1) {
393                                        $search .= ' AND ((post_title LIKE \''.$n.$s_array[$i].$n.'\') OR (post_content LIKE \''.$n.$s_array[$i].$n.'\'))';
394                                }
395                                $search .= ' OR (post_title LIKE \''.$n.$q['s'].$n.'\') OR (post_content LIKE \''.$n.$q['s'].$n.'\')';
396                                $search .= ')';
397                        } else {
398                                $search = ' AND ((post_title LIKE \''.$n.$q['s'].$n.'\') OR (post_content LIKE \''.$n.$q['s'].$n.'\'))';
399                        }
400                }
401
402                // Category stuff
403
404                if ((empty($q['cat'])) || ($q['cat'] == '0') || 
405                                // Bypass cat checks if fetching specific posts
406                                ( $this->is_single || $this->is_page )) {
407                        $whichcat='';
408                } else {
409                        $q['cat'] = ''.urldecode($q['cat']).'';
410                        $q['cat'] = addslashes_gpc($q['cat']);
411                        if (stristr($q['cat'],'-')) {
412                                // Note: if we have a negative, we ignore all the positives. It must
413                                // always mean 'everything /except/ this one'. We should be able to do
414                                // multiple negatives but we don't :-(
415                                $eq = '!=';
416                                $andor = 'AND';
417                                $q['cat'] = explode('-',$q['cat']);
418                                $q['cat'] = intval($q['cat'][1]);
419                        } else {
420                                $eq = '=';
421                                $andor = 'OR';
422                        }
423                        $join = " LEFT JOIN $wpdb->post2cat ON ($wpdb->posts.ID = $wpdb->post2cat.post_id) ";
424                        $cat_array = preg_split('/[,\s]+/', $q['cat']);
425                        $whichcat .= ' AND (category_id '.$eq.' '.intval($cat_array[0]);
426                        $whichcat .= get_category_children($cat_array[0], ' '.$andor.' category_id '.$eq.' ');
427                        for ($i = 1; $i < (count($cat_array)); $i = $i + 1) {
428                                $whichcat .= ' '.$andor.' category_id '.$eq.' '.intval($cat_array[$i]);
429                                $whichcat .= get_category_children($cat_array[$i], ' '.$andor.' category_id '.$eq.' ');
430                        }
431                        $whichcat .= ')';
432                        if ($eq == '!=') {
433                                $q['cat'] = '-'.$q['cat']; // Put back the knowledge that we are excluding a category.
434                        }
435                }
436
437                // Category stuff for nice URIs
438
439                if ('' != $q['category_name']) {
440                        if (stristr($q['category_name'],'/')) {
441                                $q['category_name'] = explode('/',$q['category_name']);
442                                if ($q['category_name'][count($q['category_name'])-1]) {
443                                        $q['category_name'] = $q['category_name'][count($q['category_name'])-1]; // no trailing slash
444                                } else {
445                                        $q['category_name'] = $q['category_name'][count($q['category_name'])-2]; // there was a trailling slash
446                                }
447                        }
448                        $q['category_name'] = sanitize_title($q['category_name']);
449                        $tables = ", $wpdb->post2cat, $wpdb->categories";
450                        $join = " LEFT JOIN $wpdb->post2cat ON ($wpdb->posts.ID = $wpdb->post2cat.post_id) LEFT JOIN $wpdb->categories ON ($wpdb->post2cat.category_id = $wpdb->categories.cat_ID) ";
451                        $whichcat = " AND (category_nicename = '" . $q['category_name'] . "'";
452                        $q['cat'] = $wpdb->get_var("SELECT cat_ID FROM $wpdb->categories WHERE category_nicename = '" . $q['category_name'] . "'");
453                        $whichcat .= get_category_children($q['cat'], " OR category_id = ");
454                        $whichcat .= ")";
455                }
456
457                // Author/user stuff
458
459                if ((empty($q['author'])) || ($q['author'] == '0')) {
460                        $whichauthor='';
461                } else {
462                        $q['author'] = ''.urldecode($q['author']).'';
463                        $q['author'] = addslashes_gpc($q['author']);
464                        if (stristr($q['author'], '-')) {
465                                $eq = '!=';
466                                $andor = 'AND';
467                                $q['author'] = explode('-', $q['author']);
468                                $q['author'] = ''.intval($q['author'][1]);
469                        } else {
470                                $eq = '=';
471                                $andor = 'OR';
472                        }
473                        $author_array = preg_split('/[,\s]+/', $q['author']);
474                        $whichauthor .= ' AND (post_author '.$eq.' '.intval($author_array[0]);
475                        for ($i = 1; $i < (count($author_array)); $i = $i + 1) {
476                                $whichauthor .= ' '.$andor.' post_author '.$eq.' '.intval($author_array[$i]);
477                        }
478                        $whichauthor .= ')';
479                }
480
481                // Author stuff for nice URIs
482
483                if ('' != $q['author_name']) {
484                        if (stristr($q['author_name'],'/')) {
485                                $q['author_name'] = explode('/',$q['author_name']);
486                                if ($q['author_name'][count($q['author_name'])-1]) {
487                                        $q['author_name'] = $q['author_name'][count($q['author_name'])-1];#no trailing slash
488                                } else {
489                                        $q['author_name'] = $q['author_name'][count($q['author_name'])-2];#there was a trailling slash
490                                }
491                        }
492                        $q['author_name'] = sanitize_title($q['author_name']);
493                        $q['author'] = $wpdb->get_var("SELECT ID FROM $wpdb->users WHERE user_nicename='".$q['author_name']."'");
494                        $whichauthor .= ' AND (post_author = '.intval($q['author']).')';
495                }
496
497                $where .= $search.$whichcat.$whichauthor;
498
499                if ((empty($q['order'])) || ((strtoupper($q['order']) != 'ASC') && (strtoupper($q['order']) != 'DESC'))) {
500                        $q['order']='DESC';
501                }
502
503                // Order by
504                if (empty($q['orderby'])) {
505                        $q['orderby']='date '.$q['order'];
506                } else {
507                        // Used to filter values
508                        $allowed_keys = array('author','date','category','title');
509                        $q['orderby'] = urldecode($q['orderby']);
510                        $q['orderby'] = addslashes_gpc($q['orderby']);
511                        $orderby_array = explode(' ',$q['orderby']);
512                        if (!in_array($orderby_array[0],$allowed_keys)) {
513                                $orderby_array[0] = 'date';
514                        }
515                        $q['orderby'] = $orderby_array[0].' '.$q['order'];
516                        if (count($orderby_array)>1) {
517                                for ($i = 1; $i < (count($orderby_array)); $i = $i + 1) {
518                                        // Only allow certain values for safety
519                                        if (in_array($orderby_array[$i],$allowed_keys)) {
520                                                $q['orderby'] .= ',post_'.$orderby_array[$i].' '.$q['order'];
521                                        }
522                                }
523                        }
524                }
525
526                $now = gmdate('Y-m-d H:i:59');
527
528                if ($pagenow != 'post.php' && $pagenow != 'edit.php') {
529                        $where .= " AND post_date_gmt <= '$now'";
530                        $distinct = 'DISTINCT';
531                }
532
533                if ($this->is_page) {
534                        $where .= ' AND (post_status = "static")';
535                } elseif ($this->is_single) {
536                        $where .= ' AND (post_status != "static")';
537                } else {
538                        $where .= ' AND (post_status = "publish"';
539
540                        if (isset($user_ID) && ('' != intval($user_ID)))
541                                $where .= " OR post_author = $user_ID AND post_status != 'draft' AND post_status != 'static')";
542                        else
543                                $where .= ')';                         
544                }
545
546                // Apply filters on where and join prior to paging so that any
547                // manipulations to them are reflected in the paging by day queries.
548                $where = apply_filters('posts_where', $where);
549                $join = apply_filters('posts_join', $join);
550
551                // Paging
552                if (empty($q['nopaging']) && ! $this->is_single) {
553                        $page = $q['paged'];
554                        if (empty($page)) {
555                                $page = 1;
556                        }
557
558                        if (($q['what_to_show'] == 'posts')) {
559                                $pgstrt = '';
560                                $pgstrt = (intval($page) -1) * $q['posts_per_page'] . ', ';
561                                $limits = 'LIMIT '.$pgstrt.$q['posts_per_page'];
562                        } elseif ($q['what_to_show'] == 'days') {
563                                $startrow = $q['posts_per_page'] * (intval($page)-1);
564                                $start_date = $wpdb->get_var("SELECT max(post_date) FROM $wpdb->posts $join WHERE (1=1) $where GROUP BY year(post_date), month(post_date), dayofmonth(post_date) ORDER BY post_date DESC LIMIT $startrow,1");
565                                $endrow = $startrow + $q['posts_per_page'] - 1;
566                                $end_date = $wpdb->get_var("SELECT min(post_date) FROM $wpdb->posts $join WHERE (1=1) $where GROUP BY year(post_date), month(post_date), dayofmonth(post_date) ORDER BY post_date DESC LIMIT $endrow,1");
567
568                                if ($page > 1) {
569                                        $where .= " AND post_date >= '$end_date' AND post_date <= '$start_date'";
570                                } else {
571                                        $where .= " AND post_date >= '$end_date'";
572                                }
573                        }
574                }
575
576                // Apply post-paging filters on where and join.  Only plugins that
577                // manipulate paging queries should use these hooks.
578                $where = apply_filters('posts_where_paged', $where);
579                $where .= " GROUP BY $wpdb->posts.ID";
580                $join = apply_filters('posts_join_paged', $join);
581                $orderby = "post_" . $q['orderby'];
582                $orderby = apply_filters('posts_orderby', $orderby); 
583                $request = " SELECT $distinct * FROM $wpdb->posts $join WHERE 1=1".$where." ORDER BY " . $orderby . " $limits";
584
585                $this->posts = $wpdb->get_results($request);
586
587                // Check post status to determine if post should be displayed.
588                if ($this->is_single) {
589                        if ('publish' != $this->posts[0]->post_status) {
590                                if ( ! (isset($user_ID) && ('' != intval($user_ID))) ) {
591                                        // User must be logged in to view unpublished posts.
592                                        $this->posts = array();
593                                } else {
594                                        if ('draft' == $this->posts[0]->post_status) {
595                                                // User must have edit permissions on the draft to preview.
596                                                if (! user_can_edit_post($user_ID, $this->posts[0]->ID))
597                                                        $this->posts = array();
598                                        } elseif ('private' == $this->posts[0]->post_status) {
599                                                if ($this->posts[0]->post_author != $user_ID)
600                                                        $this->posts = array();
601                                        }
602                                }
603                        }
604                }
605
606                $this->posts = apply_filters('the_posts', $this->posts);
607                $this->post_count = count($this->posts);
608                if ($this->post_count > 0) {
609                        $this->post = $this->posts[0];
610                }
611
612                update_post_caches($this->posts);
613               
614                // Save any changes made to the query vars.
615                $this->query_vars = $q;
616                return $this->posts;
617        }
618
619        function next_post() {
620       
621                $this->current_post++;
622
623                $this->post = $this->posts[$this->current_post];
624                return $this->post;
625        }
626
627        function the_post() {
628                global $post;
629                $post = $this->next_post();
630                setup_postdata($post);
631        }
632
633        function have_posts() {
634                if ($this->current_post + 1 < $this->post_count) {
635                        return true;
636                }
637
638                return false;
639        }
640
641        function rewind_posts() {
642                $this->current_post = -1;
643                if ($this->post_count > 0) {
644                        $this->post = $this->posts[0];
645                }
646        }
647   
648        function &query($query) {
649                $this->parse_query($query);
650                return $this->get_posts();
651        }
652
653        function get_queried_object() {
654                if (isset($this->queried_object)) {
655                        return $this->queried_object;
656                }
657
658                $this->queried_object = NULL;
659                $this->queried_object_id = 0;
660
661                if ($this->is_category) {
662                        $category = &get_category($this->get('cat'));
663                        $this->queried_object = &$category;
664                        $this->queried_object_id = $this->get('cat');
665                } else if ($this->is_single) {
666                        $this->queried_object = $this->post;
667                        $this->queried_object_id = $this->post->ID;
668                } else if ($this->is_page) {
669                        $this->queried_object = $this->post;
670                        $this->queried_object_id = $this->post->ID;
671                } else if ($this->is_author) {
672                        global $cache_userdata;
673                        if (isset($cache_userdata[$this->get('author')])) {
674                                $this->queried_object = $cache_userdata[$this->get('author')];
675                                $this->queried_object_id = $this->get('author');
676                        }
677                }
678
679                return $this->queried_object;
680        }
681
682        function get_queried_object_id() {
683                $this->get_queried_object();
684
685                if (isset($this->queried_object_id)) {
686                        return $this->queried_object_id;
687                }
688
689                return 0;
690        }
691
692        function WP_Query ($query = '') {
693                if (! empty($query)) {
694                        $this->query($query);
695                }
696        }
697}
698
699// Make a global instance.
700if (! isset($wp_query)) {
701    $wp_query = new WP_Query();
702}
703
704class retrospam_mgr {
705        var $spam_words;
706        var $comments_list;
707        var $found_comments;
708
709        function retrospam_mgr() {
710                global $wpdb;
711
712                $list = explode("\n", get_settings('moderation_keys') );
713                $list = array_unique( $list );
714                $this->spam_words = $list;
715
716                $this->comment_list = $wpdb->get_results("SELECT comment_ID AS ID, comment_content AS text, comment_approved AS approved, comment_author_url AS url, comment_author_ip AS ip, comment_author_email AS email FROM $wpdb->comments ORDER BY comment_ID ASC");
717        }       // End of class constructor
718
719        function move_spam( $id_list ) {
720                global $wpdb;
721                $cnt = 0;
722                $id_list = explode( ',', $id_list );
723
724                foreach ( $id_list as $comment ) {
725                        if ( $wpdb->query("update $wpdb->comments set comment_approved = '0' where comment_ID = '$comment'") ) {
726                                $cnt++;
727                        }
728                }
729                echo "<div class='updated'><p>$cnt comment";
730                if ($cnt != 1 ) echo "s";
731                echo " moved to the moderation queue.</p></div>\n";
732        }       // End function move_spam
733
734        function find_spam() {
735                $in_queue = 0;
736
737                foreach( $this->comment_list as $comment ) {
738                        if( $comment->approved == 1 ) {
739                                foreach( $this->spam_words as $word ) {
740                                        if ( empty( $word ) )
741                                                continue;
742                                        $fulltext = strtolower($comment->email.' '.$comment->url.' '.$comment->ip.' '.$comment->text);
743                                        if( strpos( $fulltext, strtolower(trim($word)) ) != FALSE ) {
744                                                $this->found_comments[] = $comment->ID;
745                                                break;
746                                        }
747                                }
748                        } else {
749                                $in_queue++;
750                        }
751                }
752                return array( 'found' => $this->found_comments, 'in_queue' => $in_queue );
753        }       // End function find_spam
754
755        function display_edit_form( $counters ) {
756                $numfound = count($counters[found]);
757                $numqueue = $counters[in_queue];
758
759                $body = '<p>' . sprintf(__('Suspected spam comments: <strong>%s</strong>'), $numfound) . '</p>';
760
761                if ( count($counters[found]) > 0 ) {
762                        $id_list = implode( ',', $counters[found] );
763                        $body .= '<p><a href="options-discussion.php?action=retrospam&amp;move=true&amp;ids='.$id_list.'">'. __('Move suspect comments to moderation queue &raquo;') . '</a></p>';
764
765                }
766                $head = '<div class="wrap"><h2>' . __('Check Comments Results:') . '</h2>';
767
768                $foot .= '<p><a href="options-discussion.php">' . __('&laquo; Return to Discussion Options page.') . '</a></p></div>';
769               
770                return $head . $body . $foot;
771        }       // End function display_edit_form
772
773}
774
775class WP_Rewrite {
776        var $permalink_structure;
777        var $category_base;
778        var $category_structure;
779        var $author_base = 'author';
780        var $author_structure;
781        var $date_structure;
782        var $page_structure;
783        var $search_base = 'search';
784        var $search_structure;
785        var $comments_base = 'comments';
786        var $feed_base = 'feed';
787        var $comments_feed_structure;
788        var $feed_structure;
789        var $front;
790        var $root = '';
791        var $index = 'index.php';
792        var $matches = '';
793        var $rules;
794        var $rewritecode = 
795                array(
796                                        '%year%',
797                                        '%monthnum%',
798                                        '%day%',
799                                        '%hour%',
800                                        '%minute%',
801                                        '%second%',
802                                        '%postname%',
803                                        '%post_id%',
804                                        '%category%',
805                                        '%author%',
806                                        '%pagename%',
807                                        '%search%'
808                                        );
809
810        var $rewritereplace = 
811                array(
812                                        '([0-9]{4})',
813                                        '([0-9]{1,2})',
814                                        '([0-9]{1,2})',
815                                        '([0-9]{1,2})',
816                                        '([0-9]{1,2})',
817                                        '([0-9]{1,2})',
818                                        '([^/]+)',
819                                        '([0-9]+)',
820                                        '(.+?)',
821                                        '([^/]+)',
822                                        '([^/]+)',
823                                        '(.+)'
824                                        );
825
826        var $queryreplace = 
827                array (
828                                         'year=',
829                                         'monthnum=',
830                                         'day=',
831                                         'hour=',
832                                         'minute=',
833                                         'second=',
834                                         'name=',
835                                         'p=',
836                                         'category_name=',
837                                         'author_name=',
838                                         'pagename=',
839                                         's='
840                                         );
841
842        var $feeds = array ('feed', 'rdf', 'rss', 'rss2', 'atom');
843
844        function using_permalinks() {
845                if (empty($this->permalink_structure))
846                        return false;
847                else
848                        return true;
849        }                                       
850
851        function using_index_permalinks() {
852    if (empty($this->permalink_structure)) {
853                        return false;
854    }
855
856    // If the index is not in the permalink, we're using mod_rewrite.
857    if (preg_match('#^/*' . $this->index . '#', $this->permalink_structure)) {
858      return true;
859    }
860   
861    return false;
862        }
863
864        function using_mod_rewrite_permalinks() {
865                if ( $this->using_permalinks() && ! $this->using_index_permalinks())
866                        return true;
867                else
868                        return false;
869        }                                       
870
871        function preg_index($number) {
872    $match_prefix = '$';
873    $match_suffix = '';
874   
875    if (! empty($this->matches)) {
876                        $match_prefix = '$' . $this->matches . '['; 
877                        $match_suffix = ']';
878    }       
879   
880    return "$match_prefix$number$match_suffix";       
881        }
882
883        function page_rewrite_rules() {
884                $uris = get_settings('page_uris');
885
886                $rewrite_rules = array();
887                $page_structure = $this->get_page_permastruct();
888                if( is_array( $uris ) )
889                        {
890                                foreach ($uris as $uri => $pagename) {
891                                        $this->add_rewrite_tag('%pagename%', "($uri)", 'pagename=');
892                                        $rewrite_rules += $this->generate_rewrite_rules($page_structure);
893                                }
894                        }
895
896                return $rewrite_rules;
897        }
898
899        function get_date_permastruct() {
900                if (isset($this->date_structure)) {
901                        return $this->date_structure;
902                }
903
904    if (empty($this->permalink_structure)) {
905                        $this->date_structure = '';
906                        return false;
907                }
908               
909                // The date permalink must have year, month, and day separated by slashes.
910                $endians = array('%year%/%monthnum%/%day%', '%day%/%monthnum%/%year%', '%monthnum%/%day%/%year%');
911
912                $this->date_structure = '';
913                $date_endian = '';
914
915                foreach ($endians as $endian) {
916                        if (false !== strpos($this->permalink_structure, $endian)) {
917                                $date_endian= $endian;
918                                break;
919                        }
920                } 
921
922                if ( empty($date_endian) )
923                        $date_endian = '%year%/%monthnum%/%day%';
924
925                // Do not allow the date tags and %post_id% to overlap in the permalink
926                // structure. If they do, move the date tags to $front/date/. 
927                $front = $this->front;
928                preg_match_all('/%.+?%/', $this->permalink_structure, $tokens);
929                $tok_index = 1;
930                foreach ($tokens[0] as $token) {
931                        if ( ($token == '%post_id%') && ($tok_index <= 3) ) {
932                                $front = $front . 'date/';
933                                break;
934                        }
935                }
936
937                $this->date_structure = $front . $date_endian;
938
939                return $this->date_structure;
940        }
941
942        function get_year_permastruct() {
943                $structure = $this->get_date_permastruct($permalink_structure);
944
945                if (empty($structure)) {
946                        return false;
947                }
948
949                $structure = str_replace('%monthnum%', '', $structure);
950                $structure = str_replace('%day%', '', $structure);
951
952                $structure = preg_replace('#/+#', '/', $structure);
953
954                return $structure;
955        }
956
957        function get_month_permastruct() {
958                $structure = $this->get_date_permastruct($permalink_structure);
959
960                if (empty($structure)) {
961                        return false;
962                }
963
964                $structure = str_replace('%day%', '', $structure);
965
966                $structure = preg_replace('#/+#', '/', $structure);
967
968                return $structure;
969        }
970
971        function get_day_permastruct() {
972                return $this->get_date_permastruct($permalink_structure);
973        }
974
975        function get_category_permastruct() {
976                if (isset($this->category_structure)) {
977                        return $this->category_structure;
978                }
979
980    if (empty($this->permalink_structure)) {
981                        $this->category_structure = '';
982                        return false;
983                }
984
985                if (empty($this->category_base))
986                        $this->category_structure = $this->front . 'category/';
987                else
988                        $this->category_structure = $this->category_base . '/';
989
990                $this->category_structure .= '%category%';
991               
992                return $this->category_structure;
993        }
994
995        function get_author_permastruct() {
996                if (isset($this->author_structure)) {
997                        return $this->author_structure;
998                }
999
1000    if (empty($this->permalink_structure)) {
1001                        $this->author_structure = '';
1002                        return false;
1003                }
1004
1005                $this->author_structure = $this->front . $this->author_base . '/%author%';
1006
1007                return $this->author_structure;
1008        }
1009
1010        function get_search_permastruct() {
1011                if (isset($this->search_structure)) {
1012                        return $this->search_structure;
1013                }
1014
1015    if (empty($this->permalink_structure)) {
1016                        $this->search_structure = '';
1017                        return false;
1018                }
1019
1020                $this->search_structure = $this->root . $this->search_base . '/%search%';
1021
1022                return $this->search_structure;
1023        }
1024
1025        function get_page_permastruct() {
1026                if (isset($this->page_structure)) {
1027                        return $this->page_structure;
1028                }
1029
1030    if (empty($this->permalink_structure)) {
1031                        $this->page_structure = '';
1032                        return false;
1033                }
1034
1035                $this->page_structure = $this->root . '%pagename%';
1036
1037                return $this->page_structure;
1038        }
1039
1040        function get_feed_permastruct() {
1041                if (isset($this->feed_structure)) {
1042                        return $this->feed_structure;
1043                }
1044
1045    if (empty($this->permalink_structure)) {
1046                        $this->feed_structure = '';
1047                        return false;
1048                }
1049
1050                $this->feed_structure = $this->root . $this->feed_base . '/%feed%';
1051
1052                return $this->feed_structure;
1053        }
1054
1055        function get_comment_feed_permastruct() {
1056                if (isset($this->comment_feed_structure)) {
1057                        return $this->comment_feed_structure;
1058                }
1059
1060    if (empty($this->permalink_structure)) {
1061                        $this->comment_feed_structure = '';
1062                        return false;
1063                }
1064
1065                $this->comment_feed_structure = $this->root . $this->comments_base . '/' . $this->feed_base . '/%feed%';
1066
1067                return $this->comment_feed_structure;
1068        }
1069
1070        function add_rewrite_tag($tag, $pattern, $query) {
1071                // If the tag already exists, replace the existing pattern and query for
1072                // that tag, otherwise add the new tag, pattern, and query to the end of
1073                // the arrays.
1074                $position = array_search($tag, $this->rewritecode);             
1075                if (FALSE !== $position && NULL !== $position) {
1076                        $this->rewritereplace[$position] = $pattern;
1077                        $this->queryreplace[$position] = $query;                       
1078                } else {
1079                        $this->rewritecode[] = $tag;
1080                        $this->rewritereplace[] = $pattern;
1081                        $this->queryreplace[] = $query;
1082                }
1083        }
1084
1085        function generate_rewrite_rules($permalink_structure, $page = true, $feed = true, $forcomments = false, $walk_dirs = true) {
1086                $feedregex2 = '';
1087                foreach ($this->feeds as $feed_name) {
1088                        $feedregex2 .= $feed_name . '|';
1089                }
1090                $feedregex2 = '(' . trim($feedregex2, '|') .  ')/?$';
1091                $feedregex = $this->feed_base  . '/' . $feedregex2;
1092
1093                $trackbackregex = 'trackback/?$';
1094                $pageregex = 'page/?([0-9]{1,})/?$';
1095               
1096                $front = substr($permalink_structure, 0, strpos($permalink_structure, '%'));
1097                preg_match_all('/%.+?%/', $permalink_structure, $tokens);
1098
1099                $num_tokens = count($tokens[0]);
1100
1101                $index = $this->index;
1102                $feedindex = $index;
1103                $trackbackindex = $index;
1104                for ($i = 0; $i < $num_tokens; ++$i) {
1105                        if (0 < $i) {
1106                                $queries[$i] = $queries[$i - 1] . '&';
1107                        }
1108             
1109                        $query_token = str_replace($this->rewritecode, $this->queryreplace, $tokens[0][$i]) . $this->preg_index($i+1);
1110                        $queries[$i] .= $query_token;
1111                }
1112
1113                $structure = $permalink_structure;
1114                if ($front != '/') {
1115                        $structure = str_replace($front, '', $structure);
1116                }
1117                $structure = trim($structure, '/');
1118                if ($walk_dirs) {
1119                        $dirs = explode('/', $structure);
1120                } else {
1121                        $dirs[] = $structure;
1122                }
1123                $num_dirs = count($dirs);
1124
1125                $front = preg_replace('|^/+|', '', $front);
1126
1127                $post_rewrite = array();
1128                $struct = $front;
1129                for ($j = 0; $j < $num_dirs; ++$j) {
1130                        $struct .= $dirs[$j] . '/';
1131                        $struct = ltrim($struct, '/');
1132                        $match = str_replace($this->rewritecode, $this->rewritereplace, $struct);
1133                        $num_toks = preg_match_all('/%.+?%/', $struct, $toks);
1134                        $query = $queries[$num_toks - 1];
1135
1136                        $pagematch = $match . $pageregex;
1137                        $pagequery = $index . '?' . $query . '&paged=' . $this->preg_index($num_toks + 1);
1138
1139                        $feedmatch = $match . $feedregex;
1140                        $feedquery = $feedindex . '?' . $query . '&feed=' . $this->preg_index($num_toks + 1);
1141
1142                        $feedmatch2 = $match . $feedregex2;
1143                        $feedquery2 = $feedindex . '?' . $query . '&feed=' . $this->preg_index($num_toks + 1);
1144
1145                        if ($forcomments) {
1146                                $feedquery .= '&withcomments=1';
1147                                $feedquery2 .= '&withcomments=1';
1148                        }
1149
1150                        $rewrite = array();
1151                        if ($feed) 
1152                                $rewrite = array($feedmatch => $feedquery, $feedmatch2 => $feedquery2);
1153                        if ($page)
1154                                $rewrite = $rewrite + array($pagematch => $pagequery);
1155
1156                        if ($num_toks) {
1157                                $post = 0;
1158                                if (strstr($struct, '%postname%') || strstr($struct, '%post_id%')
1159                                                || strstr($struct, '%pagename%')
1160                                                || (strstr($struct, '%year%') &&  strstr($struct, '%monthnum%') && strstr($struct, '%day%') && strstr($struct, '%hour%') && strstr($struct, '%minute') && strstr($struct, '%second%'))) {
1161                                        $post = 1;
1162                                        $trackbackmatch = $match . $trackbackregex;
1163                                        $trackbackquery = $trackbackindex . '?' . $query . '&tb=1';
1164                                        $match = rtrim($match, '/');
1165                                        $match = $match . '(/[0-9]+)?/?$';
1166                                        $query = $index . '?' . $query . '&page=' . $this->preg_index($num_toks + 1);
1167                                } else {
1168                                        $match .= '?$';
1169                                        $query = $index . '?' . $query;
1170                                }
1171                                       
1172                                $rewrite = $rewrite + array($match => $query);
1173
1174                                if ($post) {
1175                                        $rewrite = array($trackbackmatch => $trackbackquery) + $rewrite;
1176                                }
1177                        }
1178
1179                        $post_rewrite = $rewrite + $post_rewrite;
1180                }
1181
1182                return $post_rewrite;
1183        }
1184
1185        function generate_rewrite_rule($permalink_structure, $walk_dirs = false) {
1186                return $this->generate_rewrite_rules($permalink_structure, false, false, false, $walk_dirs);
1187        }
1188
1189        /* rewrite_rules
1190         * Construct rewrite matches and queries from permalink structure.
1191         * Returns an associate array of matches and queries.
1192         */
1193        function rewrite_rules() {
1194                $rewrite = array();
1195
1196                if (empty($this->permalink_structure)) {
1197                        return $rewrite;
1198                }
1199
1200                // Post
1201                $post_rewrite = $this->generate_rewrite_rules($this->permalink_structure);
1202                $post_rewrite = apply_filters('post_rewrite_rules', $post_rewrite);
1203
1204                // Date
1205                $date_rewrite = $this->generate_rewrite_rules($this->get_date_permastruct());
1206                $date_rewrite = apply_filters('date_rewrite_rules', $date_rewrite);
1207               
1208                // Root
1209                $root_rewrite = $this->generate_rewrite_rules($this->root . '/');
1210                $root_rewrite = apply_filters('root_rewrite_rules', $root_rewrite);
1211
1212                // Comments
1213                $comments_rewrite = $this->generate_rewrite_rules($this->root . $this->comments_base, true, true, true);
1214                $comments_rewrite = apply_filters('comments_rewrite_rules', $comments_rewrite);
1215
1216                // Search
1217                $search_structure = $this->get_search_permastruct();
1218                $search_rewrite = $this->generate_rewrite_rules($search_structure);
1219                $search_rewrite = apply_filters('search_rewrite_rules', $search_rewrite);
1220
1221                // Categories
1222                $category_rewrite = $this->generate_rewrite_rules($this->get_category_permastruct());
1223                $category_rewrite = apply_filters('category_rewrite_rules', $category_rewrite);
1224
1225                // Authors
1226                $author_rewrite = $this->generate_rewrite_rules($this->get_author_permastruct());
1227                $author_rewrite = apply_filters('author_rewrite_rules', $author_rewrite);
1228
1229                // Pages
1230                $page_rewrite = $this->page_rewrite_rules();
1231                $page_rewrite = apply_filters('page_rewrite_rules', $page_rewrite);
1232
1233                // Put them together.
1234                $this->rules = $page_rewrite + $root_rewrite + $comments_rewrite + $search_rewrite + $category_rewrite + $author_rewrite + $date_rewrite + $post_rewrite;
1235
1236                do_action('generate_rewrite_rules', array(&$this));
1237                $this->rules = apply_filters('rewrite_rules_array', $this->rules);
1238                return $this->rules;
1239        }
1240
1241        function wp_rewrite_rules() {
1242                $this->matches = 'matches';
1243                return $this->rewrite_rules();
1244        }
1245
1246        function mod_rewrite_rules() {
1247                if ( ! $this->using_permalinks()) {
1248                        return '';
1249                }
1250
1251                $site_root = parse_url(get_settings('siteurl'));
1252                $site_root = trailingslashit($site_root['path']);
1253
1254                $home_root = parse_url(get_settings('home'));
1255                $home_root = trailingslashit($home_root['path']);
1256   
1257                $rules = "<IfModule mod_rewrite.c>\n";
1258                $rules .= "RewriteEngine On\n";
1259                $rules .= "RewriteBase $home_root\n";
1260                $this->matches = '';
1261                $rewrite = $this->rewrite_rules();
1262                $num_rules = count($rewrite);
1263                $rules .= "RewriteCond %{REQUEST_FILENAME} -f [OR]\n" .
1264                        "RewriteCond %{REQUEST_FILENAME} -d\n" .
1265                        "RewriteRule ^.*$ - [S=$num_rules]\n";
1266
1267                foreach ($rewrite as $match => $query) {
1268                        // Apache 1.3 does not support the reluctant (non-greedy) modifier.
1269                        $match = str_replace('.+?', '.+', $match);
1270
1271                        // If the match is unanchored and greedy, prepend rewrite conditions
1272                        // to avoid infinite redirects and eclipsing of real files.
1273                        if ($match == '(.+)/?$' || $match == '([^/]+)/?$' ) {
1274                                //nada.
1275                        }
1276
1277                        if (strstr($query, $this->index)) {
1278                                $rules .= 'RewriteRule ^' . $match . ' ' . $home_root . $query . " [QSA,L]\n";
1279                        } else {
1280                                $rules .= 'RewriteRule ^' . $match . ' ' . $site_root . $query . " [QSA,L]\n";
1281                        }
1282                }
1283                $rules .= "</IfModule>\n";
1284
1285                $rules = apply_filters('mod_rewrite_rules', $rules);
1286                $rules = apply_filters('rewrite_rules', $rules);  // Deprecated
1287
1288                return $rules;
1289        }
1290
1291        function init() {
1292                $this->permalink_structure = get_settings('permalink_structure');
1293                $this->front = substr($this->permalink_structure, 0, strpos($this->permalink_structure, '%'));         
1294                $this->root = '';
1295                if ($this->using_index_permalinks()) {
1296                        $this->root = $this->index . '/';
1297                }
1298                $this->category_base = get_settings('category_base');
1299                unset($this->category_structure);
1300                unset($this->author_structure);
1301                unset($this->date_structure);
1302                unset($this->page_structure);
1303                unset($this->search_structure);
1304                unset($this->feed_structure);
1305                unset($this->comment_feed_structure);
1306        }
1307
1308        function set_permalink_structure($permalink_structure) {
1309                if ($permalink_structure != $this->permalink_structure) {
1310                        update_option('permalink_structure', $permalink_structure);
1311                        $this->init();
1312                }
1313        }
1314
1315        function set_category_base($category_base) {
1316                if ($category_base != $this->category_base) {
1317                        update_option('category_base', $category_base);
1318                        $this->init();
1319                }
1320        }
1321
1322        function WP_Rewrite() {
1323                $this->init();
1324        }
1325}
1326
1327// Make a global instance.
1328if (! isset($wp_rewrite)) {
1329    $wp_rewrite = new WP_Rewrite();
1330}
1331
1332?>