root/branches/multiuser/feed.php

Revision 1759, 49.1 kB (checked in by mdodoo, 11 months ago)

Lots of things are still not working, but I think this code is better than what was currently committed ([1639]
should have been reverted, and the person who committed should have had their SVN access pulled, for example).
Created this by grabbing the trunk code and then manually inserting the MU branch's changes in. This is probably
not usable in an actual installation (no support for creating new user accounts yet, for example), but patches are
welcome.

Not sure why I write so much here - I am not sure anyone other than my fellow devs actually read them...

  • Property svn:eol-style set to native
  • Property svn:eolstyle set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2###############################################################################
3# Gregarius - A PHP based RSS aggregator.
4# Copyright (C) 2003 - 2006 Marco Bonetti
5#
6###############################################################################
7# This program is free software and open source software; you can redistribute
8# it and/or modify it under the terms of the GNU General Public License as
9# published by the Free Software Foundation; either version 2 of the License,
10# or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful, but WITHOUT
13# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15# more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program; if not, write to the Free Software Foundation, Inc.,
19# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  or visit
20# http://www.gnu.org/licenses/gpl.html
21#
22###############################################################################
23# E-mail:      mbonetti at gmail dot com
24# Web page:    http://gregarius.net/
25#
26###############################################################################
27
28
29
30require_once('init.php');
31rss_require('extlib/rss_fetch.inc');
32
33define ('ACT_NAV_PREV_PREFIX','&larr;&nbsp;');
34define ('ACT_NAV_SUCC_POSTFIX','&nbsp;&rarr;');
35
36
37
38
39// Show unread items on the front page?
40// default to the config value, user can override this via a cookie
41$show_what = (getConfig('rss.output.frontpage.mixeditems') ?
42        SHOW_READ_AND_UNREAD : SHOW_UNREAD_ONLY);
43
44if (array_key_exists(SHOW_WHAT,$_POST)) {
45    $show_what = $_POST[SHOW_WHAT];
46    $period = time()+COOKIE_LIFESPAN;
47    setcookie(SHOW_WHAT, $show_what , $period, getPath());
48}
49elseif (array_key_exists(SHOW_WHAT,$_COOKIE)) {
50    $show_what = $_COOKIE[SHOW_WHAT];
51}
52
53
54
55$y=$m=$d=0;
56if (
57    getConfig('rss.output.usemodrewrite')
58    && array_key_exists('channel',$_REQUEST)
59    // this is nasty because a numeric feed title could break it
60    && !is_numeric($_REQUEST['channel'])
61) {
62        $sqlid = preg_replace('#'.RSS_URI_SEPARATOR.'#','_',
63                sanitize($_REQUEST['channel'] , RSS_SANITIZER_SIMPLE_SQL )
64                );
65
66    $sql = "select c.id from " . getTable("channels") 
67      . " c left join " .getTable('channels2user') 
68      ." c2u on (c.id=c2u.fkcid) where title like '$sqlid'";
69    if (hidePrivate()) {
70        $sql .=" and c2u.flgprivate=0 ";
71    }
72    // don't hide deprecated items becuase we want items of deprecated feeds to be accessible
73    // $sql .= " and c2u.flgdeleted=0 ";
74
75    $res =  rss_query( $sql );
76    //echo $sql;
77    if ( rss_num_rows ( $res ) >= 1) {
78        list($cid) = rss_fetch_row($res);
79    } else {
80        $cid = "";
81
82        // is this a folder?
83        $sql = "select c.id, c.parent from ". getTable('channels')." c left join "
84          . getTable('channels2user') . " c2u on (c.id=c2u.fkcid) "
85          ." inner join " . getTable('folders') . " f on f.id = c.parent "
86          ." where f.name like '$sqlid' and f.id > 0";
87
88        if (hidePrivate()) {
89            $sql .=" and c2u.flgprivate=0 ";
90        }
91        $sql .= " and c2u.flgdeleted=0 ";
92
93        $res = rss_query( $sql );
94        if ( rss_num_rows ( $res ) > 0) {
95            $cids = array();
96            while (list ($cid__,$fid__) = rss_fetch_row($res)) {
97                $cids[] = $cid__;
98                $fid = $fid__;
99            }
100        } else {
101            // maybe it's a virtual folder?
102            $sql = "select c.id, m.tid from ". getTable('channels')." c "
103                   . "inner join " . getTable('metatag') . " m on m.fid = c.id " 
104                   . "inner join " . getTable('tag') . " t on m.tid = t.id "
105                   . "where m.ttype = 'channel' and t.tag like '$sqlid'";
106
107            if (hidePrivate()) {
108                $sql .=" and not(c.mode & " . RSS_MODE_PRIVATE_STATE .") ";
109            }
110            $sql .= " and not(c.mode & " .  RSS_MODE_DELETED_STATE .") ";
111
112            $res = rss_query( $sql );
113            if ( rss_num_rows ( $res ) > 0) {
114                $cids = array();
115                while (list ($cid__,$vfid__) = rss_fetch_row($res)) {
116                    $cids[] = $cid__;
117                    $vfid = $vfid__;
118                }
119            }
120        }
121    }
122
123    // date ?
124    if ($cid != ""
125            && array_key_exists('y',$_REQUEST) && $_REQUEST['y'] != "" && is_numeric($_REQUEST['y'])
126            && array_key_exists('m',$_REQUEST) && $_REQUEST['m'] != "" && is_numeric($_REQUEST['m'])) {
127        $y = (int) $_REQUEST['y'];
128        if ($y < 1000)
129            $y+=2000;
130
131        $m =  (int)$_REQUEST['m'];
132        if ($m > 12) {
133            $m = date("m");
134        }
135
136        $d =  (int)$_REQUEST['d'];
137        if ($d > 31) {
138            $d = date("d");
139        }
140    }
141
142
143
144    // lets see if theres an item id as well
145    $iid = "";
146    if ($cid != "" && array_key_exists('iid',$_REQUEST) && $_REQUEST['iid'] != "") {
147        $sqlid =  preg_replace("/[^A-Za-z0-9\.]/","%",$_REQUEST['iid']);
148        $sql = "select id from " .getTable("item") ." i where i.title like '$sqlid' and i.cid=$cid";
149        if ($m > 0 && $y > 0) {
150            $sql .= " and month(ifnull(i.pubdate,i.added))= $m "
151                    ." and year(ifnull(i.pubdate, i.added))= $y ";
152
153            if ($d > 0) {
154                $sql .= " and dayofmonth(ifnull(i.pubdate,i.added))= $d ";
155            }
156
157        }
158
159        if (hidePrivate()) {
160            $sql .=" and not(i.unread & " . RSS_MODE_PRIVATE_STATE .") ";
161        }
162
163        $sql .=" and not(i.unread & " . RSS_MODE_DELETED_STATE  .") ";
164        $sql .=" order by i.added desc, i.id asc";
165
166        $res =  rss_query( $sql );
167
168        if ( rss_num_rows ( $res ) >0) {
169            list($iid) = rss_fetch_row($res);
170        }
171    }
172    // no mod rewrite: ugly but effective
173}
174elseif (array_key_exists('channel',$_REQUEST) || array_key_exists('folder',$_REQUEST) || array_key_exists('vfolder',$_REQUEST)) {
175    $cid= (array_key_exists('channel',$_REQUEST))?sanitize($_REQUEST['channel'],RSS_SANITIZER_NUMERIC):"";
176    $iid= (array_key_exists('iid',$_REQUEST))?sanitize($_REQUEST['iid'],RSS_SANITIZER_NUMERIC):"";
177    $fid= (array_key_exists('folder',$_REQUEST))?sanitize($_REQUEST['folder'],RSS_SANITIZER_NUMERIC):"";
178    $vfid= (array_key_exists('vfolder',$_REQUEST))?sanitize($_REQUEST['vfolder'],RSS_SANITIZER_NUMERIC):"";
179       
180    $y= (array_key_exists('y',$_REQUEST))?sanitize($_REQUEST['y'],RSS_SANITIZER_NUMERIC):"0";
181    $m= (array_key_exists('m',$_REQUEST))?sanitize($_REQUEST['m'],RSS_SANITIZER_NUMERIC):"0";
182    $d= (array_key_exists('d',$_REQUEST))?sanitize($_REQUEST['d'],RSS_SANITIZER_NUMERIC):"0";
183
184    if ($fid) {
185        $sql = "select c.id from ". getTable('channels')." c "
186               ." where c.parent=$fid and c.parent > 0";
187        $sql .= " and not(c.mode & " .  RSS_MODE_DELETED_STATE .") ";
188
189        if (hidePrivate()) {
190            $sql .=" and not(c.mode & " . RSS_MODE_PRIVATE_STATE .") ";
191        }
192        $res = rss_query( $sql );
193
194        if ( rss_num_rows ( $res ) > 0) {
195            $cids = array();
196            while (list ($cid__) = rss_fetch_row($res)) {
197                $cids[] = $cid__;
198            }
199        }
200    }
201    elseif ($vfid) {
202        $sql = "select c.id, m.tid from ". getTable('channels')." c "
203               . "inner join " . getTable('metatag') . " m on c.id = m.fid "
204               . "inner join " . getTable('tag') . " t on m.tid = t.id "
205               . "where m.ttype = 'channel' ";
206        // $vfid can be numeric (t.id) or alphabetic (t.tag)
207        if(is_numeric($vfid)) {
208            $sql .= "and t.id = $vfid";
209        } else {
210            $sql .= "and t.tag like '$vfid'";
211        }
212        $sql .= " and not(c.mode & " .  RSS_MODE_DELETED_STATE .") ";
213
214        if (hidePrivate()) {
215            $sql .=" and not(c.mode & " . RSS_MODE_PRIVATE_STATE .") ";
216        }
217        $res = rss_query( $sql );
218
219        if ( rss_num_rows ( $res ) > 0) {
220            $cids = array();
221            while (list ($cid__,$vfid__) = rss_fetch_row($res)) {
222                $cids[] = $cid__;
223                $vfid = $vfid__;
224            }
225        }
226    }
227    elseif ($cid) {
228        if (hidePrivate()) {
229            $sql = "select id from ". getTable('channels')." where id=$cid ";
230            $sql .=" and not(mode & " . RSS_MODE_PRIVATE_STATE .") ";
231            list ($cid) = rss_fetch_row(rss_query($sql));
232        }
233    }
234}
235elseif (
236    array_key_exists('y',$_REQUEST) && $_REQUEST['y'] != "" && is_numeric($_REQUEST['y'])
237    && array_key_exists('m',$_REQUEST) && $_REQUEST['m'] != "" && is_numeric($_REQUEST['m'])
238    && array_key_exists('d',$_REQUEST) && $_REQUEST['d'] != "" && is_numeric($_REQUEST['d'])
239)   {
240
241    $y = (int) sanitize($_REQUEST['y'],RSS_SANITIZER_NUMERIC);
242    if ($y < 1000)
243        $y+=2000;
244
245    $m =  (int) sanitize($_REQUEST['m'],RSS_SANITIZER_NUMERIC);
246    if ($m > 12) {
247        $m = date("m");
248    }
249
250    $d =  (int) sanitize($_REQUEST['d'],RSS_SANITIZER_NUMERIC);
251    if ($d > 31) {
252        $d = date("d");
253    }
254    $iid = $cid  = null;
255}
256
257
258
259
260// If we have no channel-id something went terribly wrong.
261// Send a 404.
262if (
263    // channel id:
264    (
265        // not set
266        !isset($cid)    ||
267        // ...or empty
268        $cid == ""              ||
269        // or not numeric while mod_rewrite is off
270        (
271            !getConfig('rss.output.usemodrewrite') && !is_numeric($cid)
272        )
273    )
274
275    &&
276    // folder id
277    (
278        // not set
279        !isset($cids) ||
280        // not an array of ids
281        !is_array($cids) ||
282        // zero elements
283        !count($cids)
284    )
285
286    &&
287    // virtual folder id
288    (!isset($vfid))
289
290    &&
291    // date?
292    ($d == 0 && $m == 0 && $y == 0)
293) {
294        rss_404();
295        exit;
296}
297//echo ("cid=".(isset($cid)?"$cid":"") . " fid=" . (isset($fid)?"$fid":""));
298
299if (!hidePrivate() && array_key_exists ('metaaction', $_REQUEST)) {
300
301    if (array_key_exists('markreadids',$_POST)) {
302        $IdsToMarkAsRead = explode(",",rss_real_escape_string($_POST['markreadids']));
303        //var_dump($IdsToMarkAsRead);
304    } else {
305        $IdsToMarkAsRead = array();
306    }
307    switch ($_REQUEST['metaaction']) {
308
309    case  'ACT_MARK_CHANNEL_READ':
310
311        /** mark channel as read **/
312        $sql = "update " .getTable("i2u")
313               ." set flgunread = 0 where i2u.fkcid=$cid";
314        if (hidePrivate()) {
315            $sql .= " and i2u.flgprivate =0";
316        }
317        if (count($IdsToMarkAsRead)) {
318            $sql .= " and id in (" . implode(',',$IdsToMarkAsRead) .")";
319        }
320        rss_query($sql);
321
322        rss_invalidate_cache();
323
324        /* Redirect! If this feed has more unread items, self-redirect */
325
326        $sql = "select count(*) from " .getTable("item2user") . " i2u "
327                ." where i2u.flgunread=1 "
328                ." and i2u.fkcid=$cid"
329                ." and i2u.flgdeleted=0 ";
330        if (hidePrivate()) {
331            $sql .=" and i2u.flgprivate =0";
332        }
333        list($hasMoreUnreads) = rss_fetch_row(rss_query($sql));
334
335
336        //more unread items in this feed?
337        if ($hasMoreUnreads) {
338            $next_unread_id=$cid;
339
340        } else {
341
342            /*
343                Find where we should redirect
344                 - The next feed in the list with unread items, or, failing that:
345                 - The first feed in the list with unread items, or, faling that:
346                 - The main page
347            */
348
349            // 1: build a list of all feeds:
350            $feeds = array();
351            $sql = "select c.id from " . getTable('channels') . " c "
352                   . "inner join " . getTable('folders') . " f on c.parent=f.id "
353                   ." where not (c.mode & " . RSS_MODE_DELETED_STATE .") "
354                   ;
355            if (hidePrivate()) {
356                $sql .= " and not (c.mode & " . RSS_MODE_PRIVATE_STATE . ") ";
357            }
358            if (getConfig('rss.config.absoluteordering')) {
359                $sql .= " order by f.position asc, c.position asc";
360            } else {
361                $sql .=" order by f.name asc, c.title asc";
362            }
363            $res = rss_query($sql);
364            while (list($cid__) = rss_fetch_row($res)) {
365                $feeds[$cid__] = 0;
366            }
367
368            // 2: Get the unread count for each feed:
369            $sql = "select fkcid, count(*) from " .getTable('item2user')
370                   ." i2u where i2u.flgunread=1 "
371                   ." and i2u.flgdeletd=0";
372            if (hidePrivate()) {
373                $sql .= " and i2u.flgprivate=0 ";
374            }
375            $sql .= " group by i2u.fkcid";
376            $res = rss_query($sql);
377            while (list($cid__,$uc__) = rss_fetch_row($res)) {
378                // this makes sure only the feeds that were gathered in the
379                // last query are put into this array.. fixes #305
380                if(array_key_exists($cid__, $feeds)) {
381                    $feeds[$cid__] = $uc__;
382                }
383            }
384
385            // 3: iterate over the feeds and see where we should redirect.
386            $found = false;
387            $first_unread_id = $next_unread_id = 0;
388            foreach($feeds as $cid__ => $cnt) {
389                // reached the feed we're coming from?
390                if ($cid == $cid__) {
391                    $found = true;
392                }
393                // if not yet, get a hold of the first in the list with unread items
394                if ($cnt && !$first_unread_id) {
395                    $first_unread_id = $cid__;
396                }
397
398                // passed the previous feed? We got a winner!
399                if ($cnt && $found) {
400                    $next_unread_id = $cid__;
401                    break;
402                }
403            }
404
405            // found none after the previous feed, but there is on on top
406            if (!$next_unread_id && $first_unread_id) {
407                $next_unread_id = $first_unread_id;
408            }
409        }
410
411        //redirect
412        if (!$next_unread_id) {
413            rss_redirect();
414        } else {
415            $cid = $next_unread_id;
416        }
417
418        break;
419
420        // folder
421    case 'ACT_MARK_FOLDER_READ':
422        $fid = sanitize($_REQUEST['folder'],RSS_SANITIZER_NUMERIC);
423        $rs  = rss_query("select id from " .getTable('channels') . " where parent=$fid");
424        $cids_ = array();
425        while(list($cid_) = rss_fetch_row($rs)) {
426                $cids_[]=$cid_;
427        }
428       
429       
430        $sql = "update " .getTable('item2user')
431               . " set unread = 0 "
432               . " where fkcid  in (" .implode(',', $cids_) . ") ";
433                  unset($cids_);
434        if (count($IdsToMarkAsRead)) {
435            $sql .= " and fkiid in (" . implode(',',$IdsToMarkAsRead) .")";
436        }
437
438        //die($sql);
439        rss_query($sql);
440
441        rss_invalidate_cache();
442
443        $next_fid = $first_fid = 0;
444        $found = false;
445        $res = rss_query( " select id from " .getTable('folders') ." f order by "
446                          .(getConfig('rss.config.absoluteordering')?" f.position asc":"f.name asc")
447                        );
448
449        while (list($fid__) = rss_fetch_row($res)) {
450            if($fid__ == $fid) {
451                $found = true;
452            }
453                       
454                        if( $found || !$first_fid ) {
455                                $sql = "select count(*) from " . getTable('item2user') . " i2u "
456                                           . "inner join ". getTable('channels') ." c on i2u.fkcid = c.id"
457                                           ." where i2u.flgunread=1 and c.parent = $fid__"
458                                           ." and i2u.fkuid=" . rss_user_id();
459                                if (hidePrivate()) {
460                                        $sql .= " and i2u.flgprivate=0 ";
461                                }
462       
463                                list($c) = rss_fetch_row(rss_query($sql));
464                                //echo "$fid__ -> $c\n";
465
466                                if ($c > 0) {
467                                        if (!$first_fid)
468                                                $first_fid = $fid__;
469                                        if ($found) {
470                                                $next_fid = $fid__;
471                                                break;
472                                        }
473                                }
474                        }
475        }
476               
477                if( !$next_fid && $first_fid )
478                        $next_fid = $first_fid;
479
480        if ( $next_fid ) {
481            $fid = $next_fid;
482            $sql = "select id from " . getTable('channels') ." where parent=$fid";
483            $res = rss_query($sql);
484            $cids = array();
485            while ( list($cid__) = rss_fetch_row($res)) {
486                $cids[] = $cid__;
487            }
488        } else {
489            rss_redirect();
490        }
491        break;
492        // virtual folder - code extremely similar to __('Mark These Items as Read')
493    case 'ACT_MARK_VFOLDER_READ':
494        $vfid = sanitize($_REQUEST['vfolder'],RSS_SANITIZER_NUMERIC);
495       
496        $rs  = rss_query(
497                "select fid from " .getTable('metatag') . "m  "
498                ." where m.ttype = 'channel' and m.tid = $vfid");
499        $fids_ = array();
500        while(list($fid_) = rss_fetch_row($rs)) {
501                $fids_[]=$fid_;
502        }
503       
504        $sql = "update " .getTable('item2user') 
505          . " set unread = 0 "
506          . " where fkcid in (" .implode(',',$fids_). ")"
507          . " and fkuid=". rss_user_id();
508         
509
510        if (count($IdsToMarkAsRead)) {
511            $sql .= " and fkiid in (" . implode(',',$IdsToMarkAsRead) .")";
512        }
513
514        rss_query($sql);
515
516        rss_invalidate_cache();
517
518        // find next virtual folder to redirect to
519        $next_vfid = $first_vfid = 0;
520        $found = false;
521        $res = rss_query("select distinct tid from " .getTable('metatag') ." m "
522                                . "inner join" . getTable('tag') ."t on m.tid = t.id order by t.tag asc");
523        while (list($tid__) = rss_fetch_row($res)) {
524            if ($tid__ == $vfid) {
525                $found = true;
526            }
527                       
528                        if( $found || !$first_vfid ) {
529                                // check for unread items in next virtual folder
530                                $sql = "select count(distinct(i.fkiid)) as cnt from "
531                                           .getTable('metatag') ." left join "
532                                           .getTable('item2user') . "i2u on (i2u.fkcid=fid) "
533                                           ."where tid = $tid__ and ttype = 'channel' "
534                                           ." and i2u.flgunread=1 "
535                                           ." and i2u.fkuid=" .rss_user_id()
536                                           ." and i2u.flgdeleted=0 ";
537                                if (hidePrivate()) {
538                                        $sql .= " and i2u.flgprivate=0 ";
539                                }
540                                list($c) = rss_fetch_row(rss_query($sql));
541                                if ($c > 0) {
542                                        if (!$first_vfid)
543                                                $first_vfid = $tid__;
544                                        if ($found) {
545                                                $next_vfid = $tid__;
546                                                break;
547                                        }
548                                }
549                        }
550        }
551               
552                if( !$next_vfid && $first_vfid )
553                        $next_vfid = $first_vfid;
554
555        if($next_vfid) {
556            $vfid = $next_vfid;
557            $sql = "select distinct(fid) from " . getTable('metatag') . " where tid = $vfid";
558            $res = rss_query($sql);
559            $cids = array();
560            while(list($cid__) = rss_fetch_row($res)) {
561                $cids[] = $cid__;
562            }
563        } else {
564            rss_redirect();
565        }
566        break;
567    }
568
569        if( array_key_exists ('redirectto', $_REQUEST)) {
570                header("Location: " .
571                           $_REQUEST['redirectto']);
572                exit();
573        }
574}
575//echo ("cid=".(isset($cid)?"$cid":"") . " fid=" . (isset($fid)?"$fid":""));
576assert(
577    (isset($cid) && is_numeric($cid)) ||
578    (isset($fid) && isset($cids) && is_array($cids) && count($cids)) ||
579    (isset($vfid) && isset($cids) && is_array($cids) && count($cids)) ||
580    (!isset($cid) && ($y || $m))
581);
582
583$itemFound = true;
584if ($iid != "" && !is_numeric($iid)) {
585    //item was deleted
586    $itemFound = false;
587    $iid = "";
588}
589
590// make sure the variables passed to makeName are initialized
591if (!isset($fid)) {
592    $fid=null;
593}
594if (!isset($vfid)) {
595    $vfid=null;
596}
597if (!isset($cids)) {
598    $cids=null;
599}
600//precompute the navigation hints, which will be passed to the header as <link>s
601$links = NULL;
602if (($cid || $fid || $vfid || ($y && $m && $d)) &&