]> git.wh0rd.org Git - tt-rss.git/blob - functions.php
deprecate RSS_BACKEND_TYPE
[tt-rss.git] / functions.php
1 <?php
2
3 /*      if ($_GET["debug"]) {
4                 define('DEFAULT_ERROR_LEVEL', E_ALL);
5         } else {
6                 define('DEFAULT_ERROR_LEVEL', E_ERROR | E_WARNING | E_PARSE);
7         } */
8
9         require_once 'config.php';
10         require_once 'db-prefs.php';
11         require_once 'compat.php';
12         require_once 'errors.php';
13         require_once 'version.php';
14
15         define('MAGPIE_USER_AGENT_EXT', ' (Tiny Tiny RSS/' . VERSION . ')');
16         define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');
17
18         require_once "magpierss/rss_fetch.inc";
19         require_once 'magpierss/rss_utils.inc';
20
21         function purge_feed($link, $feed_id, $purge_interval, $debug = false) {
22
23                 $rows = -1;
24
25                 if (DB_TYPE == "pgsql") {
26 /*                      $result = db_query($link, "DELETE FROM ttrss_user_entries WHERE
27                                 marked = false AND feed_id = '$feed_id' AND
28                                 (SELECT date_entered FROM ttrss_entries WHERE
29                                         id = ref_id) < NOW() - INTERVAL '$purge_interval days'"); */
30
31                         $pg_version = get_pgsql_version($link);
32
33                         if (preg_match("/^7\./", $pg_version) || preg_match("/^8\.0/", $pg_version)) {
34
35                                 $result = db_query($link, "DELETE FROM ttrss_user_entries WHERE 
36                                         ttrss_entries.id = ref_id AND 
37                                         marked = false AND 
38                                         feed_id = '$feed_id' AND 
39                                         ttrss_entries.date_entered < NOW() - INTERVAL '$purge_interval days'");
40
41                         } else {
42
43                                 $result = db_query($link, "DELETE FROM ttrss_user_entries 
44                                         USING ttrss_entries 
45                                         WHERE ttrss_entries.id = ref_id AND 
46                                         marked = false AND 
47                                         feed_id = '$feed_id' AND 
48                                         ttrss_entries.date_entered < NOW() - INTERVAL '$purge_interval days'");
49                         }
50
51                         $rows = pg_affected_rows($result);
52                         
53                 } else {
54                 
55 /*                      $result = db_query($link, "DELETE FROM ttrss_user_entries WHERE
56                                 marked = false AND feed_id = '$feed_id' AND
57                                 (SELECT date_entered FROM ttrss_entries WHERE 
58                                         id = ref_id) < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)"); */
59
60                         $result = db_query($link, "DELETE FROM ttrss_user_entries 
61                                 USING ttrss_user_entries, ttrss_entries 
62                                 WHERE ttrss_entries.id = ref_id AND 
63                                 marked = false AND 
64                                 feed_id = '$feed_id' AND 
65                                 ttrss_entries.date_entered < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)");
66                                         
67                         $rows = mysql_affected_rows($link);
68
69                 }
70
71                 if ($debug) {
72                         print "Purged feed $feed_id ($purge_interval): deleted $rows articles\n";
73                 }
74         }
75
76         function global_purge_old_posts($link, $do_output = false, $limit = false) {
77
78                 $random_qpart = sql_random_function();
79
80                 if ($limit) {
81                         $limit_qpart = "LIMIT $limit";
82                 } else {
83                         $limit_qpart = "";
84                 }
85                 
86                 $result = db_query($link, 
87                         "SELECT id,purge_interval,owner_uid FROM ttrss_feeds 
88                                 ORDER BY $random_qpart $limit_qpart");
89
90                 while ($line = db_fetch_assoc($result)) {
91
92                         $feed_id = $line["id"];
93                         $purge_interval = $line["purge_interval"];
94                         $owner_uid = $line["owner_uid"];
95
96                         if ($purge_interval == 0) {
97                         
98                                 $tmp_result = db_query($link, 
99                                         "SELECT value FROM ttrss_user_prefs WHERE
100                                                 pref_name = 'PURGE_OLD_DAYS' AND owner_uid = '$owner_uid'");
101
102                                 if (db_num_rows($tmp_result) != 0) {                    
103                                         $purge_interval = db_fetch_result($tmp_result, 0, "value");
104                                 }
105                         }
106
107                         if ($do_output) {
108 //                              print "Feed $feed_id: purge interval = $purge_interval\n";
109                         }
110
111                         if ($purge_interval > 0) {
112                                 purge_feed($link, $feed_id, $purge_interval, $do_output);
113                         }
114                 }       
115
116                 // purge orphaned posts in main content table
117                 db_query($link, "DELETE FROM ttrss_entries WHERE 
118                         (SELECT COUNT(int_id) FROM ttrss_user_entries WHERE ref_id = id) = 0");
119
120         }
121
122         function purge_old_posts($link) {
123
124                 $user_id = $_SESSION["uid"];
125         
126                 $result = db_query($link, "SELECT id,purge_interval FROM ttrss_feeds 
127                         WHERE owner_uid = '$user_id'");
128
129                 while ($line = db_fetch_assoc($result)) {
130
131                         $feed_id = $line["id"];
132                         $purge_interval = $line["purge_interval"];
133
134                         if ($purge_interval == 0) $purge_interval = get_pref($link, 'PURGE_OLD_DAYS');
135
136                         if ($purge_interval > 0) {
137                                 purge_feed($link, $feed_id, $purge_interval);
138                         }
139                 }       
140
141                 // purge orphaned posts in main content table
142                 db_query($link, "DELETE FROM ttrss_entries WHERE 
143                         (SELECT COUNT(int_id) FROM ttrss_user_entries WHERE ref_id = id) = 0");
144         }
145
146         function update_all_feeds($link, $fetch, $user_id = false, $force_daemon = false) {
147
148                 if (WEB_DEMO_MODE) return;
149
150                 if (!$user_id) {
151                         $user_id = $_SESSION["uid"];
152                         purge_old_posts($link);
153                 }
154
155 //              db_query($link, "BEGIN");
156
157                 if (MAX_UPDATE_TIME > 0) {
158                         if (DB_TYPE == "mysql") {
159                                 $q_order = "RAND()";
160                         } else {
161                                 $q_order = "RANDOM()";
162                         }
163                 } else {
164                         $q_order = "last_updated DESC";
165                 }
166
167                 $result = db_query($link, "SELECT feed_url,id,
168                         SUBSTRING(last_updated,1,19) AS last_updated,
169                         update_interval FROM ttrss_feeds WHERE owner_uid = '$user_id'
170                         ORDER BY $q_order");
171
172                 $upd_start = time();
173
174                 while ($line = db_fetch_assoc($result)) {
175                         $upd_intl = $line["update_interval"];
176
177                         if (!$upd_intl || $upd_intl == 0) {
178                                 $upd_intl = get_pref($link, 'DEFAULT_UPDATE_INTERVAL', $user_id, false);
179                         }
180
181                         if ($upd_intl < 0) { 
182                                 // Updates for this feed are disabled
183                                 continue; 
184                         }
185
186                         if ($fetch || (!$line["last_updated"] || 
187                                 time() - strtotime($line["last_updated"]) > ($upd_intl * 60))) {
188
189 //                              print "<!-- feed: ".$line["feed_url"]." -->";
190
191                                 update_rss_feed($link, $line["feed_url"], $line["id"], $force_daemon);
192
193                                 $upd_elapsed = time() - $upd_start;
194
195                                 if (MAX_UPDATE_TIME > 0 && $upd_elapsed > MAX_UPDATE_TIME) {
196                                         return;
197                                 }
198                         }
199                 }
200
201 //              db_query($link, "COMMIT");
202
203         }
204
205         function fetch_file_contents($url) {
206                 if (USE_CURL_FOR_ICONS) {
207                         $tmpfile = tempnam(TMP_DIRECTORY, "ttrss-tmp");
208
209                         $ch = curl_init($url);
210                         $fp = fopen($tmpfile, "w");
211
212                         if ($fp) {
213                                 curl_setopt($ch, CURLOPT_FILE, $fp);
214                                 curl_exec($ch);
215                                 curl_close($ch);
216                                 fclose($fp);                                    
217                         }
218
219                         $contents =  file_get_contents($tmpfile);
220                         unlink($tmpfile);
221
222                         return $contents;
223
224                 } else {
225                         return file_get_contents($url);
226                 }
227
228         }
229
230         // adapted from wordpress favicon plugin by Jeff Minard (http://thecodepro.com/)
231         // http://dev.wp-plugins.org/file/favatars/trunk/favatars.php
232
233         function get_favicon_url($url) {
234
235                 if ($html = @fetch_file_contents($url)) {
236
237                         if ( preg_match('/<link[^>]+rel="(?:shortcut )?icon"[^>]+?href="([^"]+?)"/si', $html, $matches)) {
238                                 // Attempt to grab a favicon link from their webpage url
239                                 $linkUrl = html_entity_decode($matches[1]);
240
241                                 if (substr($linkUrl, 0, 1) == '/') {
242                                         $urlParts = parse_url($url);
243                                         $faviconURL = $urlParts['scheme'].'://'.$urlParts['host'].$linkUrl;
244                                 } else if (substr($linkUrl, 0, 7) == 'http://') {
245                                         $faviconURL = $linkUrl;
246                                 } else if (substr($url, -1, 1) == '/') {
247                                         $faviconURL = $url.$linkUrl;
248                                 } else {
249                                         $faviconURL = $url.'/'.$linkUrl;
250                                 }
251
252                         } else {
253                                 // If unsuccessful, attempt to "guess" the favicon location
254                                 $urlParts = parse_url($url);
255                                 $faviconURL = $urlParts['scheme'].'://'.$urlParts['host'].'/favicon.ico';
256                         }
257                 }
258
259                 // Run a test to see if what we have attempted to get actually exists.
260                 if(USE_CURL_FOR_ICONS || url_validate($faviconURL)) {
261                         return $faviconURL;
262                 } else {
263                         return false;
264                 }
265         }
266
267         function url_validate($link) {
268                 
269                 $url_parts = @parse_url($link);
270
271                 if ( empty( $url_parts["host"] ) )
272                                 return false;
273
274                 if ( !empty( $url_parts["path"] ) ) {
275                                 $documentpath = $url_parts["path"];
276                 } else {
277                                 $documentpath = "/";
278                 }
279
280                 if ( !empty( $url_parts["query"] ) )
281                                 $documentpath .= "?" . $url_parts["query"];
282
283                 $host = $url_parts["host"];
284                 $port = $url_parts["port"];
285                 
286                 if ( empty($port) )
287                                 $port = "80";
288
289                 $socket = @fsockopen( $host, $port, $errno, $errstr, 30 );
290                 
291                 if ( !$socket )
292                                 return false;
293                                 
294                 fwrite ($socket, "HEAD ".$documentpath." HTTP/1.0\r\nHost: $host\r\n\r\n");
295
296                 $http_response = fgets( $socket, 22 );
297
298                 $responses = "/(200 OK)|(30[0-9] Moved)/";
299                 if ( preg_match($responses, $http_response) ) {
300                                 fclose($socket);
301                                 return true;
302                 } else {
303                                 return false;
304                 }
305
306         } 
307
308         function check_feed_favicon($site_url, $feed, $link) {
309                 $favicon_url = get_favicon_url($site_url);
310
311 #               print "FAVICON [$site_url]: $favicon_url\n";
312
313                 error_reporting(0);
314
315                 $icon_file = ICONS_DIR . "/$feed.ico";
316
317                 if ($favicon_url && !file_exists($icon_file)) {
318                         $contents = fetch_file_contents($favicon_url);
319
320                         $fp = fopen($icon_file, "w");
321
322                         if ($fp) {
323                                 fwrite($fp, $contents);
324                                 fclose($fp);
325                                 chmod($icon_file, 0644);
326                         }
327                 }
328
329                 error_reporting(DEFAULT_ERROR_LEVEL);
330
331         }
332
333         function update_rss_feed($link, $feed_url, $feed, $ignore_daemon = false) {
334
335                 if (DAEMON_REFRESH_ONLY && !$_GET["daemon"] && !$ignore_daemon) {
336                         return;                 
337                 }
338
339                 $result = db_query($link, "SELECT update_interval,auth_login,auth_pass  
340                         FROM ttrss_feeds WHERE id = '$feed'");
341
342                 $auth_login = db_unescape_string(db_fetch_result($result, 0, "auth_login"));
343                 $auth_pass = db_unescape_string(db_fetch_result($result, 0, "auth_pass"));
344
345                 $update_interval = db_fetch_result($result, 0, "update_interval");
346
347                 if ($update_interval < 0) { return; }
348
349                 $feed = db_escape_string($feed);
350
351                 $fetch_url = $feed_url;
352
353                 if ($auth_login && $auth_pass) {
354                         $url_parts = array();
355                         preg_match("/(^[^:]*):\/\/(.*)/", $fetch_url, $url_parts);
356
357                         if ($url_parts[1] && $url_parts[2]) {
358                                 $fetch_url = $url_parts[1] . "://$auth_login:$auth_pass@" . $url_parts[2];
359                         }
360
361                 }
362
363                 error_reporting(0);
364                 $rss = fetch_rss($fetch_url);
365                 error_reporting (DEFAULT_ERROR_LEVEL);
366                 
367                 $feed = db_escape_string($feed);
368
369                 if ($rss) {
370                         
371 //                      db_query($link, "BEGIN");
372
373                         $result = db_query($link, "SELECT title,icon_url,site_url,owner_uid
374                                 FROM ttrss_feeds WHERE id = '$feed'");
375
376                         $registered_title = db_fetch_result($result, 0, "title");
377                         $orig_icon_url = db_fetch_result($result, 0, "icon_url");
378                         $orig_site_url = db_fetch_result($result, 0, "site_url");
379
380                         $owner_uid = db_fetch_result($result, 0, "owner_uid");
381
382                         if (get_pref($link, 'ENABLE_FEED_ICONS', $owner_uid, false)) {  
383                                 check_feed_favicon($rss->channel["link"], $feed, $link);
384                         }
385
386                         if (!$registered_title || $registered_title == "[Unknown]") {
387                         
388                                 $feed_title = db_escape_string($rss->channel["title"]);
389                                 
390                                 db_query($link, "UPDATE ttrss_feeds SET 
391                                         title = '$feed_title' WHERE id = '$feed'");
392                         }
393
394                         $site_url = $rss->channel["link"];
395                         // weird, weird Magpie
396                         if (!$site_url) $site_url = db_escape_string($rss->channel["link_"]);
397
398                         if ($site_url && $orig_site_url != db_escape_string($site_url)) {
399                                 db_query($link, "UPDATE ttrss_feeds SET 
400                                         site_url = '$site_url' WHERE id = '$feed'");
401                         }
402
403 //                      print "I: " . $rss->channel["image"]["url"];
404
405                         $icon_url = $rss->image["url"];
406
407                         if ($icon_url && !$orig_icon_url != db_escape_string($icon_url)) {
408                                 $icon_url = db_escape_string($icon_url);
409                                 db_query($link, "UPDATE ttrss_feeds SET icon_url = '$icon_url' WHERE id = '$feed'");
410                         }
411
412
413                         $filters = array();
414
415                         $result = db_query($link, "SELECT reg_exp,
416                                 ttrss_filter_types.name AS name,
417                                 ttrss_filter_actions.name AS action,
418                                 action_param
419                                 FROM ttrss_filters,ttrss_filter_types,ttrss_filter_actions WHERE                                        
420                                         enabled = true AND
421                                         owner_uid = $owner_uid AND
422                                         ttrss_filter_types.id = filter_type AND
423                                         ttrss_filter_actions.id = action_id AND
424                                 (feed_id IS NULL OR feed_id = '$feed')");
425
426                         while ($line = db_fetch_assoc($result)) {
427                                 if (!$filters[$line["name"]]) $filters[$line["name"]] = array();
428
429                                 $filter["reg_exp"] = $line["reg_exp"];
430                                 $filter["action"] = $line["action"];
431                                 $filter["action_param"] = $line["action_param"];
432                         
433                                 array_push($filters[$line["name"]], $filter);
434                         }
435
436                         $iterator = $rss->items;
437
438                         if (!$iterator || !is_array($iterator)) $iterator = $rss->entries;
439                         if (!$iterator || !is_array($iterator)) $iterator = $rss;
440
441                         if (!is_array($iterator)) {
442                                 /* db_query($link, "UPDATE ttrss_feeds 
443                                         SET last_error = 'Parse error: can\'t find any articles.'
444                                                 WHERE id = '$feed'"); */
445                                 return; // WTF?
446                         }
447
448                         foreach ($iterator as $item) {
449
450                                 $entry_guid = $item["id"];
451         
452                                 if (!$entry_guid) $entry_guid = $item["guid"];
453                                 if (!$entry_guid) $entry_guid = $item["link"];
454                                 if (!$entry_guid) $entry_guid = make_guid_from_title($item["title"]);
455
456                                 if (!$entry_guid) continue;
457
458                                 $entry_timestamp = "";
459
460                                 $rss_2_date = $item['pubdate'];
461                                 $rss_1_date = $item['dc']['date'];
462                                 $atom_date = $item['issued'];
463                                 if (!$atom_date) $atom_date = $item['updated'];
464                         
465                                 if ($atom_date != "") $entry_timestamp = parse_w3cdtf($atom_date);
466                                 if ($rss_1_date != "") $entry_timestamp = parse_w3cdtf($rss_1_date);
467                                 if ($rss_2_date != "") $entry_timestamp = strtotime($rss_2_date);
468                                 
469                                 if ($entry_timestamp == "") {
470                                         $entry_timestamp = time();
471                                         $no_orig_date = 'true';
472                                 } else {
473                                         $no_orig_date = 'false';
474                                 }
475
476                                 $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
477
478                                 $entry_title = trim(strip_tags($item["title"]));
479
480                                 // strange Magpie workaround
481                                 $entry_link = $item["link_"];
482                                 if (!$entry_link) $entry_link = $item["link"];
483
484                                 if (!$entry_title) continue;
485 #                                       if (!$entry_link) continue;
486
487                                 $entry_link = strip_tags($entry_link);
488
489                                 $entry_content = $item["content:escaped"];
490
491                                 if (!$entry_content) $entry_content = $item["content:encoded"];
492                                 if (!$entry_content) $entry_content = $item["content"];
493                                 if (!$entry_content) $entry_content = $item["atom_content"];
494                                 if (!$entry_content) $entry_content = $item["summary"];
495                                 if (!$entry_content) $entry_content = $item["description"];
496
497 //                              if (!$entry_content) continue;
498
499                                 // WTF
500                                 if (is_array($entry_content)) {
501                                         $entry_content = $entry_content["encoded"];
502                                         if (!$entry_content) $entry_content = $entry_content["escaped"];
503                                 }
504
505 //                              print_r($item);
506 //                              print_r(htmlspecialchars($entry_content));
507 //                              print "<br>";
508
509                                 $entry_content_unescaped = $entry_content;
510                                 $content_hash = "SHA1:" . sha1(strip_tags($entry_content));
511
512                                 $entry_comments = strip_tags($item["comments"]);
513
514                                 $entry_author = db_escape_string(strip_tags($item['dc']['creator']));
515
516                                 if (!$entry_author) {
517                                         $entry_author = db_escape_string(strip_tags($item['author']));
518                                 }
519
520                                 $entry_guid = db_escape_string(strip_tags($entry_guid));
521
522                                 $result = db_query($link, "SELECT id FROM       ttrss_entries 
523                                         WHERE guid = '$entry_guid'");
524
525                                 $entry_content = db_escape_string($entry_content);
526                                 $entry_title = db_escape_string($entry_title);
527                                 $entry_link = db_escape_string($entry_link);
528                                 $entry_comments = db_escape_string($entry_comments);
529
530                                 $num_comments = db_escape_string($item["slash"]["comments"]);
531
532                                 if (!$num_comments) $num_comments = 0;
533
534                                 $dc_subject = $item['dc']['subject'];
535
536                                 $subject_tags = false;
537
538                                 if (is_array($dc_subject)) {
539                                         $subject_tags = $dc_subject;
540                                 } else if ($dc_subject) {
541                                         $subject_tags = array($dc_subject);
542                                 }
543
544                                 # sanitize content
545                                 
546                                 $entry_content = sanitize_rss($entry_content);
547
548                                 db_query($link, "BEGIN");
549
550                                 if (db_num_rows($result) == 0) {
551
552                                         // base post entry does not exist, create it
553
554                                         $result = db_query($link,
555                                                 "INSERT INTO ttrss_entries 
556                                                         (title,
557                                                         guid,
558                                                         link,
559                                                         updated,
560                                                         content,
561                                                         content_hash,
562                                                         no_orig_date,
563                                                         date_entered,
564                                                         comments,
565                                                         num_comments,
566                                                         author)
567                                                 VALUES
568                                                         ('$entry_title', 
569                                                         '$entry_guid', 
570                                                         '$entry_link',
571                                                         '$entry_timestamp_fmt', 
572                                                         '$entry_content', 
573                                                         '$content_hash',
574                                                         $no_orig_date, 
575                                                         NOW(), 
576                                                         '$entry_comments',
577                                                         '$num_comments',
578                                                         '$entry_author')");
579                                 } else {
580                                         // we keep encountering the entry in feeds, so we need to
581                                         // update date_entered column so that we don't get horrible
582                                         // dupes when the entry gets purged and reinserted again e.g.
583                                         // in the case of SLOW SLOW OMG SLOW updating feeds
584
585                                         $base_entry_id = db_fetch_result($result, 0, "id");
586
587                                         db_query($link, "UPDATE ttrss_entries SET date_entered = NOW()
588                                                 WHERE id = '$base_entry_id'");
589                                 }
590
591                                 // now it should exist, if not - bad luck then
592
593                                 $result = db_query($link, "SELECT 
594                                                 id,content_hash,no_orig_date,title,
595                                                 substring(date_entered,1,19) as date_entered,
596                                                 substring(updated,1,19) as updated,
597                                                 num_comments
598                                         FROM 
599                                                 ttrss_entries 
600                                         WHERE guid = '$entry_guid'");
601
602                                 if (db_num_rows($result) == 1) {
603
604                                         // this will be used below in update handler
605                                         $orig_content_hash = db_fetch_result($result, 0, "content_hash");
606                                         $orig_title = db_fetch_result($result, 0, "title");
607                                         $orig_num_comments = db_fetch_result($result, 0, "num_comments");
608                                         $orig_date_entered = strtotime(db_fetch_result($result, 
609                                                 0, "date_entered"));
610
611                                         $ref_id = db_fetch_result($result, 0, "id");
612
613                                         // check for user post link to main table
614
615                                         // do we allow duplicate posts with same GUID in different feeds?
616                                         if (get_pref($link, "ALLOW_DUPLICATE_POSTS", $owner_uid, false)) {
617                                                 $dupcheck_qpart = "AND feed_id = '$feed'";
618                                         } else { 
619                                                 $dupcheck_qpart = "";
620                                         }
621
622 //                                      error_reporting(0);
623
624                                         $tuple = get_filter_name($entry_title, $entry_content, 
625                                                 $entry_link, $filters);
626
627                                         $filter_name = $tuple[0];
628                                         $filter_param = $tuple[1];
629
630                                         if ($filter_name == "filter") {
631                                                 continue;
632                                         }
633
634 //                                      error_reporting (DEFAULT_ERROR_LEVEL);
635
636                                         $result = db_query($link,
637                                                 "SELECT ref_id FROM ttrss_user_entries WHERE
638                                                         ref_id = '$ref_id' AND owner_uid = '$owner_uid'
639                                                         $dupcheck_qpart");
640                                                         
641                                         // okay it doesn't exist - create user entry
642                                         if (db_num_rows($result) == 0) {
643
644                                                 if ($filter_name != 'catchup') {
645                                                         $unread = 'true';
646                                                         $last_read_qpart = 'NULL';
647                                                 } else {
648                                                         $unread = 'false';
649                                                         $last_read_qpart = 'NOW()';
650                                                 }                                               
651
652                                                 if ($filter_name == 'mark') {
653                                                         $marked = 'true';
654                                                 } else {
655                                                         $marked = 'false';
656                                                 }
657                                                 
658                                                 $result = db_query($link,
659                                                         "INSERT INTO ttrss_user_entries 
660                                                                 (ref_id, owner_uid, feed_id, unread, last_read, marked) 
661                                                         VALUES ('$ref_id', '$owner_uid', '$feed', $unread,
662                                                                 $last_read_qpart, $marked)");
663                                         }
664                                         
665                                         $post_needs_update = false;
666
667                                         if (get_pref($link, "UPDATE_POST_ON_CHECKSUM_CHANGE", $owner_uid, false) &&
668                                                 ($content_hash != $orig_content_hash)) {
669                                                 $post_needs_update = true;
670                                         }
671
672                                         if ($orig_title != $entry_title) {
673                                                 $post_needs_update = true;
674                                         }
675
676                                         if ($orig_num_comments != $num_comments) {
677                                                 $post_needs_update = true;
678                                         }
679
680 //                                      this doesn't seem to be very reliable
681 //
682 //                                      if ($orig_timestamp != $entry_timestamp && !$orig_no_orig_date) {
683 //                                              $post_needs_update = true;
684 //                                      }
685
686                                         // if post needs update, update it and mark all user entries 
687                                         // linking to this post as updated                                      
688                                         if ($post_needs_update) {
689
690 //                                              print "<!-- post $orig_title needs update : $post_needs_update -->";
691
692                                                 db_query($link, "UPDATE ttrss_entries 
693                                                         SET title = '$entry_title', content = '$entry_content',
694                                                                 num_comments = '$num_comments'
695                                                         WHERE id = '$ref_id'");
696
697                                                 if (get_pref($link, "MARK_UNREAD_ON_UPDATE", $owner_uid, false)) {
698                                                         db_query($link, "UPDATE ttrss_user_entries 
699                                                                 SET last_read = null, unread = true WHERE ref_id = '$ref_id'");
700                                                 } else {
701                                                         db_query($link, "UPDATE ttrss_user_entries 
702                                                                 SET last_read = null WHERE ref_id = '$ref_id' AND unread = false");
703                                                 }
704
705                                         }
706                                 }
707
708                                 db_query($link, "COMMIT");
709
710                                 /* taaaags */
711                                 // <a href="http://technorati.com/tag/Xorg" rel="tag">Xorg</a>, //
712
713                                 $entry_tags = null;
714
715                                 preg_match_all("/<a.*?href=.http:\/\/.*?technorati.com\/tag\/([^\"\'>]+)/i", 
716                                         $entry_content_unescaped, $entry_tags);
717
718 //                              print "<br>$entry_title : $entry_content_unescaped<br>";
719 //                              print_r($entry_tags);
720 //                              print "<br>";
721
722                                 $entry_tags = $entry_tags[1];
723
724                                 # check for manual tags
725
726                                 if ($filter_name == "tag") {
727
728                                         $manual_tags = trim_array(split(",", $filter_param));
729
730                                         foreach ($manual_tags as $tag) {                                        
731                                                 if (tag_is_valid($tag)) {
732                                                         array_push($entry_tags, $tag);
733                                                 }
734                                         }
735                                 }
736
737                                 if ($subject_tags) {
738                                         foreach ($subject_tags as $tag) {
739                                                 if (tag_is_valid($tag)) {
740                                                         array_push($entry_tags, $tag);
741                                                 }
742                                         }
743                                 }
744
745                                 if (count($entry_tags) > 0) {
746                                 
747                                         db_query($link, "BEGIN");
748                         
749                                         $result = db_query($link, "SELECT id,int_id 
750                                                 FROM ttrss_entries,ttrss_user_entries 
751                                                 WHERE guid = '$entry_guid' 
752                                                 AND feed_id = '$feed' AND ref_id = id
753                                                 AND owner_uid = '$owner_uid'");
754
755                                         if (db_num_rows($result) == 1) {
756
757                                                 $entry_id = db_fetch_result($result, 0, "id");
758                                                 $entry_int_id = db_fetch_result($result, 0, "int_id");
759                                                 
760                                                 foreach ($entry_tags as $tag) {
761                                                         $tag = db_escape_string(strtolower($tag));
762
763                                                         $tag = str_replace("+", " ", $tag);     
764                                                         $tag = str_replace("technorati tag: ", "", $tag);
765         
766                                                         $result = db_query($link, "SELECT id FROM ttrss_tags            
767                                                                 WHERE tag_name = '$tag' AND post_int_id = '$entry_int_id' AND 
768                                                                 owner_uid = '$owner_uid' LIMIT 1");
769         
770         //                                              print db_fetch_result($result, 0, "id");
771         
772                                                         if ($result && db_num_rows($result) == 0) {
773                                                                 
774         //                                                      print "tagging $entry_id as $tag<br>";
775         
776                                                                 db_query($link, "INSERT INTO ttrss_tags 
777                                                                         (owner_uid,tag_name,post_int_id)
778                                                                         VALUES ('$owner_uid','$tag', '$entry_int_id')");
779                                                         }                                                       
780                                                 }
781                                         }
782                                         db_query($link, "COMMIT");
783                                 } 
784                         } 
785
786                         db_query($link, "UPDATE ttrss_feeds 
787                                 SET last_updated = NOW(), last_error = '' WHERE id = '$feed'");
788
789 //                      db_query($link, "COMMIT");
790
791                 } else {
792                         $error_msg = db_escape_string(magpie_error());
793                         db_query($link, 
794                                 "UPDATE ttrss_feeds SET last_error = '$error_msg', 
795                                         last_updated = NOW() WHERE id = '$feed'");
796                 }
797
798         }
799
800         function print_select($id, $default, $values, $attributes = "") {
801                 print "<select name=\"$id\" id=\"$id\" $attributes>";
802                 foreach ($values as $v) {
803                         if ($v == $default)
804                                 $sel = " selected";
805                          else
806                                 $sel = "";
807                         
808                         print "<option$sel>$v</option>";
809                 }
810                 print "</select>";
811         }
812
813         function print_select_hash($id, $default, $values, $attributes = "") {
814                 print "<select name=\"$id\" id='$id' $attributes>";
815                 foreach (array_keys($values) as $v) {
816                         if ($v == $default)
817                                 $sel = "selected";
818                          else
819                                 $sel = "";
820                         
821                         print "<option $sel value=\"$v\">".$values[$v]."</option>";
822                 }
823
824                 print "</select>";
825         }
826
827         function get_filter_name($title, $content, $link, $filters) {
828
829                 if ($filters["title"]) {
830                         foreach ($filters["title"] as $filter) {
831                                 $reg_exp = $filter["reg_exp"];                  
832                                 if (preg_match("/$reg_exp/i", $title)) {
833                                         return array($filter["action"], $filter["action_param"]);
834                                 }
835                         }
836                 }
837
838                 if ($filters["content"]) {
839                         foreach ($filters["content"] as $filter) {
840                                 $reg_exp = $filter["reg_exp"];                  
841                                 if (preg_match("/$reg_exp/i", $content)) {
842                                         return array($filter["action"], $filter["action_param"]);
843                                 }               
844                         }
845                 }
846
847                 if ($filters["both"]) {
848                         foreach ($filters["both"] as $filter) {                 
849                                 $reg_exp = $filter["reg_exp"];          
850                                 if (preg_match("/$reg_exp/i", $title) || 
851                                         preg_match("/$reg_exp/i", $content)) {
852                                                 return array($filter["action"], $filter["action_param"]);
853                                 }
854                         }
855                 }
856
857                 if ($filters["link"]) {
858                         $reg_exp = $filter["reg_exp"];
859                         foreach ($filters["link"] as $filter) {
860                                 $reg_exp = $filter["reg_exp"];
861                                 if (preg_match("/$reg_exp/i", $link)) {
862                                         return array($filter["action"], $filter["action_param"]);
863                                 }
864                         }
865                 }
866
867                 return false;
868         }
869
870         function get_filter_matches($title, $content, $link, $filters) {
871
872                 $matches = array();
873
874                 if ($filters["title"]) {
875                         foreach ($filters["title"] as $filter) {
876                                 $reg_exp = $filter["reg_exp"];                  
877                                 if (preg_match("/$reg_exp/i", $title)) {
878                                         array_push($matches, array($filter["action"], $filter["action_param"]));
879                                 }
880                         }
881                 }
882
883                 if ($filters["content"]) {
884                         foreach ($filters["content"] as $filter) {
885                                 $reg_exp = $filter["reg_exp"];                  
886                                 if (preg_match("/$reg_exp/i", $content)) {
887                                         array_push($matches, array($filter["action"], $filter["action_param"]));
888                                 }               
889                         }
890                 }
891
892                 if ($filters["both"]) {
893                         foreach ($filters["both"] as $filter) {                 
894                                 $reg_exp = $filter["reg_exp"];          
895                                 if (preg_match("/$reg_exp/i", $title) || 
896                                         preg_match("/$reg_exp/i", $content)) {
897                                                 array_push($matches, array($filter["action"], $filter["action_param"]));
898                                 }
899                         }
900                 }
901
902                 if ($filters["link"]) {
903                         $reg_exp = $filter["reg_exp"];
904                         foreach ($filters["link"] as $filter) {
905                                 $reg_exp = $filter["reg_exp"];
906                                 if (preg_match("/$reg_exp/i", $link)) {
907                                         array_push($matches, array($filter["action"], $filter["action_param"]));
908                                 }
909                         }
910                 }
911
912                 return $matches;
913         }
914
915         function printFeedEntry($feed_id, $class, $feed_title, $unread, $icon_file, $link,
916                 $rtl_content = false, $last_updated = false, $last_error = false) {
917
918                 if (file_exists($icon_file) && filesize($icon_file) > 0) {
919                                 $feed_icon = "<img id=\"FIMG-$feed_id\" src=\"$icon_file\">";
920                 } else {
921                         $feed_icon = "<img id=\"FIMG-$feed_id\" src=\"images/blank_icon.gif\">";
922                 }
923
924                 if ($rtl_content) {
925                         $rtl_tag = "dir=\"rtl\"";
926                 } else {
927                         $rtl_tag = "dir=\"ltr\"";
928                 }
929
930                 $error_notify_msg = "";
931                 
932                 if ($last_error) {
933                         $link_title = "Error: $last_error ($last_updated)";
934                         $error_notify_msg = "(Error)";
935                 } else if ($last_updated) {
936                         $link_title = "Updated: $last_updated";
937                 }
938
939                 $feed = "<a title=\"$link_title\" id=\"FEEDL-$feed_id\" 
940                         href=\"#\" onclick=\"javascript:viewfeed('$feed_id', '', false);\">$feed_title</a>";
941
942                 print "<li id=\"FEEDR-$feed_id\" class=\"$class\">";
943                 if (get_pref($link, 'ENABLE_FEED_ICONS')) {
944                         print "$feed_icon";
945                 }
946
947                 print "<span $rtl_tag id=\"FEEDN-$feed_id\">$feed</span>";
948
949                 if ($unread != 0) {
950                         $fctr_class = "";
951                 } else {
952                         $fctr_class = "class=\"invisible\"";
953                 }
954
955                 print " <span $rtl_tag $fctr_class id=\"FEEDCTR-$feed_id\">
956                          (<span id=\"FEEDU-$feed_id\">$unread</span>)</span>";
957
958                 if (get_pref($link, "EXTENDED_FEEDLIST")) {                      
959                         print "<div class=\"feedExtInfo\">
960                                 <span id=\"FLUPD-$feed_id\">$last_updated $error_notify_msg</span></div>";
961                 }
962                          
963                 print "</li>";
964
965         }
966
967         function getmicrotime() {
968                 list($usec, $sec) = explode(" ",microtime());
969                 return ((float)$usec + (float)$sec);
970         }
971
972         function print_radio($id, $default, $values, $attributes = "") {
973                 foreach ($values as $v) {
974                 
975                         if ($v == $default)
976                                 $sel = "checked";
977                          else
978                                 $sel = "";
979
980                         if ($v == "Yes") {
981                                 $sel .= " value=\"1\"";
982                         } else {
983                                 $sel .= " value=\"0\"";
984                         }
985                         
986                         print "<input class=\"noborder\" 
987                                 type=\"radio\" $sel $attributes name=\"$id\">&nbsp;$v&nbsp;";
988
989                 }
990         }
991
992         function initialize_user_prefs($link, $uid) {
993
994                 $uid = db_escape_string($uid);
995
996                 db_query($link, "BEGIN");
997
998                 $result = db_query($link, "SELECT pref_name,def_value FROM ttrss_prefs");
999                 
1000                 $u_result = db_query($link, "SELECT pref_name 
1001                         FROM ttrss_user_prefs WHERE owner_uid = '$uid'");
1002
1003                 $active_prefs = array();
1004
1005                 while ($line = db_fetch_assoc($u_result)) {
1006                         array_push($active_prefs, $line["pref_name"]);                  
1007                 }
1008
1009                 while ($line = db_fetch_assoc($result)) {
1010                         if (array_search($line["pref_name"], $active_prefs) === FALSE) {
1011 //                              print "adding " . $line["pref_name"] . "<br>";
1012
1013                                 db_query($link, "INSERT INTO ttrss_user_prefs
1014                                         (owner_uid,pref_name,value) VALUES 
1015                                         ('$uid', '".$line["pref_name"]."','".$line["def_value"]."')");
1016
1017                         }
1018                 }
1019
1020                 db_query($link, "COMMIT");
1021
1022         }
1023
1024         function lookup_user_id($link, $user) {
1025
1026                 $result = db_query($link, "SELECT id FROM ttrss_users WHERE 
1027                         login = '$login'");
1028
1029                 if (db_num_rows($result) == 1) {
1030                         return db_fetch_result($result, 0, "id");
1031                 } else {
1032                         return false;
1033                 }
1034         }
1035
1036         function http_authenticate_user($link) {
1037
1038                 if (!$_SERVER["PHP_AUTH_USER"]) {
1039
1040                         header('WWW-Authenticate: Basic realm="Tiny Tiny RSS RSSGen"');
1041                         header('HTTP/1.0 401 Unauthorized');
1042                         exit;
1043                                         
1044                 } else {
1045                         $auth_result = authenticate_user($link, 
1046                                 $_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);
1047
1048                         if (!$auth_result) {
1049                                 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS RSSGen"');
1050                                 header('HTTP/1.0 401 Unauthorized');
1051                                 exit;
1052                         }
1053                 }
1054
1055                 return true;
1056         }
1057
1058         function authenticate_user($link, $login, $password, $force_auth = false) {
1059
1060                 if (!SINGLE_USER_MODE) {
1061
1062                         $pwd_hash = 'SHA1:' . sha1($password);
1063
1064                         if ($force_auth && defined('_DEBUG_USER_SWITCH')) {
1065                                 $query = "SELECT id,login,access_level
1066                     FROM ttrss_users WHERE
1067                          login = '$login'";
1068                         } else {
1069                                 $query = "SELECT id,login,access_level
1070                     FROM ttrss_users WHERE
1071                          login = '$login' AND pwd_hash = '$pwd_hash'";
1072                         }
1073
1074                         $result = db_query($link, $query);
1075         
1076                         if (db_num_rows($result) == 1) {
1077                                 $_SESSION["uid"] = db_fetch_result($result, 0, "id");
1078                                 $_SESSION["name"] = db_fetch_result($result, 0, "login");
1079                                 $_SESSION["access_level"] = db_fetch_result($result, 0, "access_level");
1080         
1081                                 db_query($link, "UPDATE ttrss_users SET last_login = NOW() WHERE id = " . 
1082                                         $_SESSION["uid"]);
1083         
1084                                 $user_theme = get_user_theme_path($link);
1085         
1086                                 $_SESSION["theme"] = $user_theme;
1087                                 $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"];
1088         
1089                                 initialize_user_prefs($link, $_SESSION["uid"]);
1090         
1091                                 return true;
1092                         }
1093         
1094                         return false;
1095
1096                 } else {
1097
1098                         $_SESSION["uid"] = 1;
1099                         $_SESSION["name"] = "admin";
1100
1101                         $user_theme = get_user_theme_path($link);
1102         
1103                         $_SESSION["theme"] = $user_theme;
1104                         $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"];
1105         
1106                         initialize_user_prefs($link, $_SESSION["uid"]);
1107         
1108                         return true;
1109                 }
1110         }
1111
1112         function make_password($length = 8) {
1113
1114                 $password = "";
1115                 $possible = "0123456789abcdfghjkmnpqrstvwxyzABCDFGHJKMNPQRSTVWXYZ"; 
1116                 
1117         $i = 0; 
1118     
1119                 while ($i < $length) { 
1120                         $char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
1121         
1122                         if (!strstr($password, $char)) { 
1123                                 $password .= $char;
1124                                 $i++;
1125                         }
1126                 }
1127                 return $password;
1128         }
1129
1130         // this is called after user is created to initialize default feeds, labels
1131         // or whatever else
1132         
1133         // user preferences are checked on every login, not here
1134
1135         function initialize_user($link, $uid) {
1136
1137                 db_query($link, "insert into ttrss_labels (owner_uid,sql_exp,description) 
1138                         values ('$uid','unread = true', 'Unread articles')");
1139
1140                 db_query($link, "insert into ttrss_labels (owner_uid,sql_exp,description) 
1141                         values ('$uid','last_read is null and unread = false', 'Updated articles')");
1142                 
1143                 db_query($link, "insert into ttrss_feeds (owner_uid,title,feed_url)
1144                         values ('$uid', 'Tiny Tiny RSS: New Releases',
1145                         'http://tt-rss.spb.ru/releases.rss')");
1146
1147         }
1148
1149         function logout_user() {
1150                 session_destroy();
1151                 if (isset($_COOKIE[session_name()])) {
1152                    setcookie(session_name(), '', time()-42000, '/');
1153                 }
1154         }
1155
1156         function get_script_urlpath() {
1157                 return preg_replace('/\/[^\/]*$/', "", $_SERVER["REQUEST_URI"]);
1158         }
1159
1160         function get_login_redirect() {
1161                 $server = $_SERVER["SERVER_NAME"];
1162
1163                 if (ENABLE_LOGIN_SSL) {
1164                         $protocol = "https";
1165                 } else {
1166                         $protocol = "http";
1167                 }               
1168
1169                 $url_path = get_script_urlpath();
1170
1171                 $redirect_uri = "$protocol://$server$url_path/login.php";
1172
1173                 return $redirect_uri;
1174         }
1175
1176         function validate_session($link) {
1177                 if (SESSION_CHECK_ADDRESS && $_SESSION["uid"]) {
1178                         if ($_SESSION["ip_address"]) {
1179                                 if ($_SESSION["ip_address"] != $_SERVER["REMOTE_ADDR"]) {
1180                                         return false;
1181                                 }
1182                         }
1183                 }
1184                 return true;
1185         }
1186
1187         function basic_nosid_redirect_check() {
1188                 if (!SINGLE_USER_MODE) {
1189                         if (!$_COOKIE[get_session_cookie_name()]) {
1190                                 $redirect_uri = get_login_redirect();
1191                                 $return_to = preg_replace('/.*?\//', '', $_SERVER["REQUEST_URI"]);
1192                                 header("Location: $redirect_uri?rt=$return_to");
1193                                 exit;
1194                         }
1195                 }
1196         }
1197
1198         function login_sequence($link) {
1199                 if (!SINGLE_USER_MODE) {
1200
1201                         if (defined('_DEBUG_USER_SWITCH') && $_SESSION["uid"]) {
1202                                 $swu = db_escape_string($_REQUEST["swu"]);
1203                                 if ($swu) {
1204                                         $_SESSION["prefs_cache"] = false;
1205                                         return authenticate_user($link, $swu, null, true);
1206                                 }
1207                         }
1208
1209                         if (!validate_session($link)) {
1210                                 logout_user();
1211                                 $redirect_uri = get_login_redirect();
1212                                 $return_to = preg_replace('/.*?\//', '', $_SERVER["REQUEST_URI"]);
1213                                 header("Location: $redirect_uri?rt=$return_to");
1214                                 exit;
1215                         }
1216
1217                         if (!USE_HTTP_AUTH) {
1218                                 if (!$_SESSION["uid"]) {
1219                                         $redirect_uri = get_login_redirect();
1220                                         $return_to = preg_replace('/.*?\//', '', $_SERVER["REQUEST_URI"]);
1221                                         header("Location: $redirect_uri?rt=$return_to");
1222                                         exit;
1223                                 }
1224                         } else {
1225                                 if (!$_SESSION["uid"]) {
1226                                         if (!$_SERVER["PHP_AUTH_USER"]) {
1227
1228                                                 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS"');
1229                                                 header('HTTP/1.0 401 Unauthorized');
1230                                                 exit;
1231                                                 
1232                                         } else {
1233                                                 $auth_result = authenticate_user($link, 
1234                                                         $_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);
1235
1236                                                 if (!$auth_result) {
1237                                                         header('WWW-Authenticate: Basic realm="Tiny Tiny RSS"');
1238                                                         header('HTTP/1.0 401 Unauthorized');
1239                                                         exit;
1240                                                 }
1241                                         }
1242                                 }                               
1243                         }
1244                 } else {
1245                         return authenticate_user($link, "admin", null);
1246                 }
1247         }
1248
1249         function truncate_string($str, $max_len) {
1250                 if (mb_strlen($str, "utf-8") > $max_len - 3) {
1251                         return mb_substr($str, 0, $max_len, "utf-8") . "...";
1252                 } else {
1253                         return $str;
1254                 }
1255         }
1256
1257         function get_user_theme_path($link) {
1258                 $result = db_query($link, "SELECT theme_path 
1259                         FROM 
1260                                 ttrss_themes,ttrss_users
1261                         WHERE ttrss_themes.id = theme_id AND ttrss_users.id = " . $_SESSION["uid"]);
1262                 if (db_num_rows($result) != 0) {
1263                         return db_fetch_result($result, 0, "theme_path");
1264                 } else {
1265                         return null;
1266                 }
1267         }
1268
1269         function smart_date_time($timestamp) {
1270                 if (date("Y.m.d", $timestamp) == date("Y.m.d")) {
1271                         return date("G:i", $timestamp);
1272                 } else if (date("Y", $timestamp) == date("Y")) {
1273                         return date("M d, G:i", $timestamp);
1274                 } else {
1275                         return date("Y/m/d G:i", $timestamp);
1276                 }
1277         }
1278
1279         function smart_date($timestamp) {
1280                 if (date("Y.m.d", $timestamp) == date("Y.m.d")) {
1281                         return "Today";
1282                 } else if (date("Y", $timestamp) == date("Y")) {
1283                         return date("D m", $timestamp);
1284                 } else {
1285                         return date("Y/m/d", $timestamp);
1286                 }
1287         }
1288
1289         function sql_bool_to_string($s) {
1290                 if ($s == "t" || $s == "1") {
1291                         return "true";
1292                 } else {
1293                         return "false";
1294                 }
1295         }
1296
1297         function sql_bool_to_bool($s) {
1298                 if ($s == "t" || $s == "1") {
1299                         return true;
1300                 } else {
1301                         return false;
1302                 }
1303         }
1304         
1305
1306         function toggleEvenOdd($a) {
1307                 if ($a == "even") 
1308                         return "odd";
1309                 else
1310                         return "even";
1311         }
1312
1313         function sanity_check($link) {
1314
1315                 error_reporting(0);
1316
1317                 $error_code = 0;
1318                 $result = db_query($link, "SELECT schema_version FROM ttrss_version");
1319                 $schema_version = db_fetch_result($result, 0, "schema_version");
1320
1321                 if ($schema_version != SCHEMA_VERSION) {
1322                         $error_code = 5;
1323                 }
1324
1325                 if (DB_TYPE == "mysql") {
1326                         $result = db_query($link, "SELECT true", false);
1327                         if (db_num_rows($result) != 1) {
1328                                 $error_code = 10;
1329                         }
1330                 }
1331
1332                 error_reporting (DEFAULT_ERROR_LEVEL);
1333
1334                 if ($error_code != 0) {
1335                         print_error_xml($error_code);
1336                         return false;
1337                 } else {
1338                         return true;
1339                 } 
1340         }
1341
1342         function file_is_locked($filename) {
1343                 error_reporting(0);
1344                 $fp = fopen($filename, "r");
1345                 error_reporting(DEFAULT_ERROR_LEVEL);
1346                 if ($fp) {
1347                         if (flock($fp, LOCK_EX | LOCK_NB)) {
1348                                 flock($fp, LOCK_UN);
1349                                 fclose($fp);
1350                                 return false;
1351                         }
1352                         fclose($fp);
1353                         return true;
1354                 }
1355                 return false;
1356         }
1357
1358         function make_lockfile($filename) {
1359                 $fp = fopen($filename, "w");
1360
1361                 if (flock($fp, LOCK_EX | LOCK_NB)) {            
1362                         return $fp;
1363                 } else {
1364                         return false;
1365                 }
1366         }
1367
1368         function sql_random_function() {
1369                 if (DB_TYPE == "mysql") {
1370                         return "RAND()";
1371                 } else {
1372                         return "RANDOM()";
1373                 }
1374         }
1375
1376         function catchup_feed($link, $feed, $cat_view) {
1377
1378                         if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
1379                         
1380                                 if ($cat_view) {
1381
1382                                         if ($feed > 0) {
1383                                                 $cat_qpart = "cat_id = '$feed'";
1384                                         } else {
1385                                                 $cat_qpart = "cat_id IS NULL";
1386                                         }
1387                                         
1388                                         $tmp_result = db_query($link, "SELECT id 
1389                                                 FROM ttrss_feeds WHERE $cat_qpart AND owner_uid = " . 
1390                                                 $_SESSION["uid"]);
1391
1392                                         while ($tmp_line = db_fetch_assoc($tmp_result)) {
1393
1394                                                 $tmp_feed = $tmp_line["id"];
1395
1396                                                 db_query($link, "UPDATE ttrss_user_entries 
1397                                                         SET unread = false,last_read = NOW() 
1398                                                         WHERE feed_id = '$tmp_feed' AND owner_uid = " . $_SESSION["uid"]);
1399                                         }
1400
1401                                 } else if ($feed > 0) {
1402
1403                                         $tmp_result = db_query($link, "SELECT id 
1404                                                 FROM ttrss_feeds WHERE parent_feed = '$feed'
1405                                                 ORDER BY cat_id,title");
1406
1407                                         $parent_ids = array();
1408
1409                                         if (db_num_rows($tmp_result) > 0) {
1410                                                 while ($p = db_fetch_assoc($tmp_result)) {
1411                                                         array_push($parent_ids, "feed_id = " . $p["id"]);
1412                                                 }
1413
1414                                                 $children_qpart = implode(" OR ", $parent_ids);
1415                                                 
1416                                                 db_query($link, "UPDATE ttrss_user_entries 
1417                                                         SET unread = false,last_read = NOW() 
1418                                                         WHERE (feed_id = '$feed' OR $children_qpart) 
1419                                                         AND owner_uid = " . $_SESSION["uid"]);
1420
1421                                         } else {                                                
1422                                                 db_query($link, "UPDATE ttrss_user_entries 
1423                                                         SET unread = false,last_read = NOW() 
1424                                                         WHERE feed_id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
1425                                         }
1426                                                 
1427                                 } else if ($feed < 0 && $feed > -10) { // special, like starred
1428
1429                                         if ($feed == -1) {
1430                                                 db_query($link, "UPDATE ttrss_user_entries 
1431                                                         SET unread = false,last_read = NOW()
1432                                                         WHERE marked = true AND owner_uid = ".$_SESSION["uid"]);
1433                                         }
1434                         
1435                                 } else if ($feed < -10) { // label
1436
1437                                         // TODO make this more efficient
1438
1439                                         $label_id = -$feed - 11;
1440
1441                                         $tmp_result = db_query($link, "SELECT sql_exp FROM ttrss_labels
1442                                                 WHERE id = '$label_id'");                                       
1443
1444                                         if ($tmp_result) {
1445                                                 $sql_exp = db_fetch_result($tmp_result, 0, "sql_exp");
1446
1447                                                 db_query($link, "BEGIN");
1448
1449                                                 $tmp2_result = db_query($link,
1450                                                         "SELECT 
1451                                                                 int_id 
1452                                                         FROM 
1453                                                                 ttrss_user_entries,ttrss_entries,ttrss_feeds
1454                                                         WHERE
1455                                                                 ref_id = ttrss_entries.id AND 
1456                                                                 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1457                                                                 $sql_exp AND
1458                                                                 ttrss_user_entries.owner_uid = " . $_SESSION["uid"]);
1459
1460                                                 while ($tmp_line = db_fetch_assoc($tmp2_result)) {
1461                                                         db_query($link, "UPDATE 
1462                                                                 ttrss_user_entries 
1463                                                         SET 
1464                                                                 unread = false, last_read = NOW()
1465                                                         WHERE
1466                                                                 int_id = " . $tmp_line["int_id"]);
1467                                                 }
1468                                                                 
1469                                                 db_query($link, "COMMIT");
1470
1471 /*                                              db_query($link, "UPDATE ttrss_user_entries,ttrss_entries 
1472                                                         SET unread = false,last_read = NOW()
1473                                                         WHERE $sql_exp
1474                                                         AND ref_id = id
1475                                                         AND owner_uid = ".$_SESSION["uid"]); */
1476                                         }
1477                                 }
1478                         } else { // tag
1479                                 db_query($link, "BEGIN");
1480
1481                                 $tag_name = db_escape_string($feed);
1482
1483                                 $result = db_query($link, "SELECT post_int_id FROM ttrss_tags
1484                                         WHERE tag_name = '$tag_name' AND owner_uid = " . $_SESSION["uid"]);
1485
1486                                 while ($line = db_fetch_assoc($result)) {
1487                                         db_query($link, "UPDATE ttrss_user_entries SET
1488                                                 unread = false, last_read = NOW() 
1489                                                 WHERE int_id = " . $line["post_int_id"]);
1490                                 }
1491                                 db_query($link, "COMMIT");
1492                         }
1493         }
1494
1495         function update_generic_feed($link, $feed, $cat_view) {
1496                         if ($cat_view) {
1497
1498                                 if ($feed > 0) {
1499                                         $cat_qpart = "cat_id = '$feed'";
1500                                 } else {
1501                                         $cat_qpart = "cat_id IS NULL";
1502                                 }
1503                                 
1504                                 $tmp_result = db_query($link, "SELECT feed_url FROM ttrss_feeds
1505                                         WHERE $cat_qpart AND owner_uid = " . $_SESSION["uid"]);
1506
1507                                 while ($tmp_line = db_fetch_assoc($tmp_result)) {                                       
1508                                         $feed_url = $tmp_line["feed_url"];
1509                                         update_rss_feed($link, $feed_url, $feed, ENABLE_UPDATE_DAEMON);
1510                                 }
1511
1512                         } else {
1513                                 $tmp_result = db_query($link, "SELECT feed_url FROM ttrss_feeds
1514                                         WHERE id = '$feed'");
1515                                 $feed_url = db_fetch_result($tmp_result, 0, "feed_url");                                
1516                                 update_rss_feed($link, $feed_url, $feed, ENABLE_UPDATE_DAEMON);
1517                         }
1518         }
1519
1520         function getAllCounters($link, $omode = "tflc") {
1521 /*              getLabelCounters($link);
1522                 getFeedCounters($link);
1523                 getTagCounters($link);
1524                 getGlobalCounters($link);
1525                 if (get_pref($link, 'ENABLE_FEED_CATS')) {
1526                         getCategoryCounters($link);
1527                 } */
1528
1529                 if (!$omode) $omode = "tflc";
1530
1531                 getGlobalCounters($link);
1532
1533                 if (strchr($omode, "l")) getLabelCounters($link);
1534                 if (strchr($omode, "f")) getFeedCounters($link);
1535                 if (strchr($omode, "t")) getTagCounters($link);
1536                 if (strchr($omode, "c")) {                      
1537                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
1538                                 getCategoryCounters($link);
1539                         }
1540                 }
1541         }       
1542
1543         function getCategoryCounters($link) {
1544                 $result = db_query($link, "SELECT cat_id,SUM((SELECT COUNT(int_id) 
1545                                 FROM ttrss_user_entries WHERE feed_id = ttrss_feeds.id 
1546                                         AND unread = true)) AS unread FROM ttrss_feeds 
1547                         WHERE 
1548                                 hidden = false AND owner_uid = ".$_SESSION["uid"]." GROUP BY cat_id");
1549
1550                 while ($line = db_fetch_assoc($result)) {
1551                         $line["cat_id"] = sprintf("%d", $line["cat_id"]);
1552                         print "<counter type=\"category\" id=\"".$line["cat_id"]."\" counter=\"".
1553                                 $line["unread"]."\"/>";
1554                 }
1555         }
1556
1557         function getCategoryUnread($link, $cat) {
1558
1559                 if ($cat != 0) {
1560                         $cat_query = "cat_id = '$cat'";
1561                 } else {
1562                         $cat_query = "cat_id IS NULL";
1563                 }
1564
1565                 $result = db_query($link, "SELECT id FROM ttrss_feeds WHERE $cat_query 
1566                                 AND hidden = false
1567                                 AND owner_uid = " . $_SESSION["uid"]);
1568
1569                 $cat_feeds = array();
1570                 while ($line = db_fetch_assoc($result)) {
1571                         array_push($cat_feeds, "feed_id = " . $line["id"]);
1572                 }
1573
1574                 if (count($cat_feeds) == 0) return 0;
1575
1576                 $match_part = implode(" OR ", $cat_feeds);
1577
1578                 $result = db_query($link, "SELECT COUNT(int_id) AS unread 
1579                         FROM ttrss_user_entries 
1580                         WHERE   unread = true AND ($match_part) AND owner_uid = " . $_SESSION["uid"]);
1581
1582                 $unread = 0;
1583
1584                 # this needs to be rewritten
1585                 while ($line = db_fetch_assoc($result)) {
1586                         $unread += $line["unread"];
1587                 }
1588
1589                 return $unread;
1590
1591         }
1592
1593         function getFeedUnread($link, $feed, $is_cat = false) {
1594                 $n_feed = sprintf("%d", $feed);
1595
1596                 if ($is_cat) {
1597                         return getCategoryUnread($link, $n_feed);               
1598                 } else if ($n_feed == -1) {
1599                         $match_part = "marked = true";
1600                 } else if ($n_feed > 0) {
1601
1602                         $result = db_query($link, "SELECT id FROM ttrss_feeds 
1603                                         WHERE parent_feed = '$n_feed'
1604                                         AND hidden = false
1605                                         AND owner_uid = " . $_SESSION["uid"]);
1606
1607                         if (db_num_rows($result) > 0) {
1608
1609                                 $linked_feeds = array();
1610                                 while ($line = db_fetch_assoc($result)) {
1611                                         array_push($linked_feeds, "feed_id = " . $line["id"]);
1612                                 }
1613
1614                                 array_push($linked_feeds, "feed_id = $n_feed");
1615                                 
1616                                 $match_part = implode(" OR ", $linked_feeds);
1617
1618                                 $result = db_query($link, "SELECT COUNT(int_id) AS unread 
1619                                         FROM ttrss_user_entries
1620                                         WHERE   unread = true AND ($match_part) 
1621                                         AND owner_uid = " . $_SESSION["uid"]);
1622
1623                                 $unread = 0;
1624
1625                                 # this needs to be rewritten
1626                                 while ($line = db_fetch_assoc($result)) {
1627                                         $unread += $line["unread"];
1628                                 }
1629
1630                                 return $unread;
1631
1632                         } else {
1633                                 $match_part = "feed_id = '$n_feed'";
1634                         }
1635                 } else if ($feed < -10) {
1636
1637                         $label_id = -$feed - 11;
1638
1639                         $result = db_query($link, "SELECT sql_exp FROM ttrss_labels WHERE
1640                                 id = '$label_id' AND owner_uid = " . $_SESSION["uid"]);
1641
1642                         $match_part = db_fetch_result($result, 0, "sql_exp");
1643                 }
1644
1645                 if ($match_part) {
1646                 
1647                         $result = db_query($link, "SELECT count(int_id) AS unread 
1648                                 FROM ttrss_user_entries,ttrss_feeds,ttrss_entries WHERE
1649                                 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1650                                 ttrss_user_entries.ref_id = ttrss_entries.id AND 
1651                                 ttrss_feeds.hidden = false AND
1652                                 unread = true AND ($match_part) AND ttrss_user_entries.owner_uid = " . $_SESSION["uid"]);
1653                                 
1654                 } else {
1655                 
1656                         $result = db_query($link, "SELECT COUNT(post_int_id) AS unread
1657                                 FROM ttrss_tags,ttrss_user_entries 
1658                                 WHERE tag_name = '$feed' AND post_int_id = int_id AND unread = true AND
1659                                         ttrss_tags.owner_uid = " . $_SESSION["uid"]);
1660                 }
1661                 
1662                 $unread = db_fetch_result($result, 0, "unread");
1663
1664                 return $unread;
1665         }
1666
1667         /* FIXME this needs reworking */
1668
1669         function getGlobalUnread($link, $user_id = false) {
1670
1671                 if (!$user_id) {
1672                         $user_id = $_SESSION["uid"];
1673                 }
1674
1675                 $result = db_query($link, "SELECT count(ttrss_entries.id) as c_id FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
1676                         WHERE unread = true AND 
1677                         ttrss_user_entries.feed_id = ttrss_feeds.id AND
1678                         ttrss_user_entries.ref_id = ttrss_entries.id AND 
1679                         hidden = false AND
1680                         ttrss_user_entries.owner_uid = '$user_id'");
1681                 $c_id = db_fetch_result($result, 0, "c_id");
1682                 return $c_id;
1683         }
1684
1685         function getGlobalCounters($link, $global_unread = -1) {
1686                 if ($global_unread == -1) {     
1687                         $global_unread = getGlobalUnread($link);
1688                 }
1689                 print "<counter type=\"global\" id='global-unread' 
1690                         counter='$global_unread'/>";
1691
1692                 $result = db_query($link, "SELECT COUNT(id) AS fn FROM 
1693                         ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"]);
1694
1695                 $subscribed_feeds = db_fetch_result($result, 0, "fn");
1696
1697                 print "<counter type=\"global\" id='subscribed-feeds' 
1698                         counter='$subscribed_feeds'/>";
1699
1700         }
1701
1702         function getTagCounters($link, $smart_mode = SMART_RPC_COUNTERS) {
1703
1704                 if ($smart_mode) {
1705                         if (!$_SESSION["tctr_last_value"]) {
1706                                 $_SESSION["tctr_last_value"] = array();
1707                         }
1708                 }
1709
1710                 $old_counters = $_SESSION["tctr_last_value"];
1711
1712                 $tctrs_modified = false;
1713
1714 /*              $result = db_query($link, "SELECT tag_name,count(ttrss_entries.id) AS count
1715                         FROM ttrss_tags,ttrss_entries,ttrss_user_entries WHERE
1716                         ttrss_user_entries.ref_id = ttrss_entries.id AND 
1717                         ttrss_tags.owner_uid = ".$_SESSION["uid"]." AND
1718                         post_int_id = ttrss_user_entries.int_id AND unread = true GROUP BY tag_name 
1719                 UNION
1720                         select tag_name,0 as count FROM ttrss_tags
1721                         WHERE ttrss_tags.owner_uid = ".$_SESSION["uid"]); */
1722
1723                 $result = db_query($link, "SELECT tag_name,SUM((SELECT COUNT(int_id) 
1724                         FROM ttrss_user_entries WHERE int_id = post_int_id 
1725                                 AND unread = true)) AS count FROM ttrss_tags 
1726                         WHERE owner_uid = ".$_SESSION['uid']." GROUP BY tag_name ORDER BY tag_name");
1727                         
1728                 $tags = array();
1729
1730                 while ($line = db_fetch_assoc($result)) {
1731                         $tags[$line["tag_name"]] += $line["count"];
1732                 }
1733
1734                 foreach (array_keys($tags) as $tag) {
1735                         $unread = $tags[$tag];                  
1736
1737                         $tag = htmlspecialchars($tag);
1738
1739                         if (!$smart_mode || $old_counters[$tag] != $unread) {                   
1740                                 $old_counters[$tag] = $unread;
1741                                 $tctrs_modified = true;
1742                                 print "<counter type=\"tag\" id=\"$tag\" counter=\"$unread\"/>";
1743                         }
1744
1745                 } 
1746
1747                 if ($smart_mode && $tctrs_modified) {
1748                         $_SESSION["tctr_last_value"] = $old_counters;
1749                 }
1750
1751         }
1752
1753         function getLabelCounters($link, $smart_mode = SMART_RPC_COUNTERS, $ret_mode = false) {
1754
1755                 if ($smart_mode) {
1756                         if (!$_SESSION["lctr_last_value"]) {
1757                                 $_SESSION["lctr_last_value"] = array();
1758                         }
1759                 }
1760
1761                 $ret_arr = array();
1762                 
1763                 $old_counters = $_SESSION["lctr_last_value"];
1764                 $lctrs_modified = false;
1765
1766                 $result = db_query($link, "SELECT count(ttrss_entries.id) as count FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
1767                         WHERE marked = true AND ttrss_user_entries.ref_id = ttrss_entries.id AND 
1768                         ttrss_user_entries.feed_id = ttrss_feeds.id AND
1769                         unread = true AND ttrss_user_entries.owner_uid = ".$_SESSION["uid"]);
1770
1771                 $count = db_fetch_result($result, 0, "count");
1772
1773                 if (!$ret_mode) {
1774                         print "<counter type=\"label\" id=\"-1\" counter=\"$count\"/>";
1775                 } else {
1776                         $ret_arr["-1"]["counter"] = $count;
1777                         $ret_arr["-1"]["description"] = "Starred";
1778                 }
1779
1780                 $result = db_query($link, "SELECT owner_uid,id,sql_exp,description FROM
1781                         ttrss_labels WHERE owner_uid = ".$_SESSION["uid"]." ORDER by description");
1782         
1783                 while ($line = db_fetch_assoc($result)) {
1784
1785                         $id = -$line["id"] - 11;
1786
1787                         $label_name = $line["description"];
1788
1789                         error_reporting (0);
1790
1791                         $tmp_result = db_query($link, "SELECT count(ttrss_entries.id) as count FROM ttrss_user_entries,ttrss_entries,ttrss_feeds
1792                                 WHERE (" . $line["sql_exp"] . ") AND unread = true AND 
1793                                 ttrss_feeds.hidden = false AND
1794                                 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1795                                 ttrss_user_entries.ref_id = ttrss_entries.id AND 
1796                                 ttrss_user_entries.owner_uid = ".$_SESSION["uid"]);
1797
1798                         $count = db_fetch_result($tmp_result, 0, "count");
1799
1800                         if (!$smart_mode || $old_counters[$id] != $count) {     
1801                                 $old_counters[$id] = $count;
1802                                 $lctrs_modified = true;
1803                                 if (!$ret_mode) {
1804                                         print "<counter type=\"label\" id=\"$id\" counter=\"$count\"/>";
1805                                 } else {
1806                                         $ret_arr[$id]["counter"] = $count;
1807                                         $ret_arr[$id]["description"] = $label_name;
1808                                 }
1809                         }
1810
1811                         error_reporting (DEFAULT_ERROR_LEVEL);
1812                 }
1813
1814                 if ($smart_mode && $lctrs_modified) {
1815                         $_SESSION["lctr_last_value"] = $old_counters;
1816                 }
1817
1818                 return $ret_arr;
1819         }
1820
1821 /*      function getFeedCounter($link, $id) {
1822         
1823                 $result = db_query($link, "SELECT 
1824                                 count(id) as count,last_error
1825                         FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
1826                         WHERE feed_id = '$id' AND unread = true
1827                         AND ttrss_user_entries.feed_id = ttrss_feeds.id
1828                         AND ttrss_user_entries.ref_id = ttrss_entries.id");
1829         
1830                         $count = db_fetch_result($result, 0, "count");
1831                         $last_error = htmlspecialchars(db_fetch_result($result, 0, "last_error"));
1832                         
1833                         print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" error=\"$last_error\"/>";           
1834         } */
1835
1836         function getFeedCounters($link, $smart_mode = SMART_RPC_COUNTERS) {
1837
1838                 if ($smart_mode) {
1839                         if (!$_SESSION["fctr_last_value"]) {
1840                                 $_SESSION["fctr_last_value"] = array();
1841                         }
1842                 }
1843
1844                 $old_counters = $_SESSION["fctr_last_value"];
1845
1846                 $result = db_query($link, "SELECT id,last_error,parent_feed,
1847                         SUBSTRING(last_updated,1,19) AS last_updated,
1848                         (SELECT count(id) 
1849                                 FROM ttrss_entries,ttrss_user_entries 
1850                                 WHERE feed_id = ttrss_feeds.id AND 
1851                                         ttrss_user_entries.ref_id = ttrss_entries.id
1852                                 AND unread = true AND owner_uid = ".$_SESSION["uid"].") as count
1853                         FROM ttrss_feeds WHERE owner_uid = ".$_SESSION["uid"] . "
1854                                 AND parent_feed IS NULL");
1855
1856                 $fctrs_modified = false;
1857
1858                 $short_date = get_pref($link, 'SHORT_DATE_FORMAT');
1859
1860                 while ($line = db_fetch_assoc($result)) {
1861                 
1862                         $id = $line["id"];
1863                         $count = $line["count"];
1864                         $last_error = htmlspecialchars($line["last_error"]);
1865
1866                         if (get_pref($link, 'HEADLINES_SMART_DATE')) {
1867                                 $last_updated = smart_date_time(strtotime($line["last_updated"]));
1868                         } else {
1869                                 $last_updated = date($short_date, strtotime($line["last_updated"]));
1870                         }                               
1871
1872                         $has_img = is_file(ICONS_DIR . "/$id.ico");
1873
1874                         $tmp_result = db_query($link,
1875                                 "SELECT id,COUNT(unread) AS unread
1876                                 FROM ttrss_feeds LEFT JOIN ttrss_user_entries 
1877                                         ON (ttrss_feeds.id = ttrss_user_entries.feed_id) 
1878                                 WHERE parent_feed = '$id' AND unread = true GROUP BY ttrss_feeds.id");
1879                         
1880                         if (db_num_rows($tmp_result) > 0) {                             
1881                                 while ($l = db_fetch_assoc($tmp_result)) {
1882                                         $count += $l["unread"];
1883                                 }
1884                         }
1885
1886                         if (!$smart_mode || $old_counters[$id] != $count) {
1887                                 $old_counters[$id] = $count;
1888                                 $fctrs_modified = true;
1889
1890                                 if ($last_error) {
1891                                         $error_part = "error=\"$last_error\"";
1892                                 } else {
1893                                         $error_part = "";
1894                                 }
1895
1896                                 if ($has_img) {
1897                                         $has_img_part = "hi=\"$has_img\"";
1898                                 } else {
1899                                         $has_img_part = "";
1900                                 }                               
1901
1902                                 print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" $has_img_part $error_part updated=\"$last_updated\"/>";
1903                         }
1904                 }
1905
1906                 if ($smart_mode && $fctrs_modified) {
1907                         $_SESSION["fctr_last_value"] = $old_counters;
1908                 }
1909         }
1910
1911         function get_script_dt_add() {
1912                 if (strpos(VERSION, "99") === false) {
1913                         return VERSION;
1914                 } else {
1915                         return time();
1916                 }
1917         }
1918
1919         function get_pgsql_version($link) {
1920                 $result = db_query($link, "SELECT version() AS version");
1921                 $version = split(" ", db_fetch_result($result, 0, "version"));
1922                 return $version[1];
1923         }
1924
1925         function print_error_xml($code, $add_msg = "") {
1926                 global $ERRORS;
1927
1928                 $error_msg = $ERRORS[$code];
1929                 
1930                 if ($add_msg) {
1931                         $error_msg = "$error_msg; $add_msg";
1932                 }
1933                 
1934                 print "<rpc-reply>";
1935                 print "<error error-code=\"$code\" error-msg=\"$error_msg\"/>";
1936                 print "</rpc-reply>";
1937         }
1938
1939         function subscribe_to_feed($link, $feed_link, $cat_id = 0) {
1940
1941                 $feed_link = trim(preg_replace("/^feed:/", "", $feed_link));
1942
1943                 if ($feed_link == "") return;
1944
1945                 if ($cat_id == "0" || !$cat_id) {
1946                         $cat_qpart = "NULL";
1947                 } else {
1948                         $cat_qpart = "'$cat_id'";
1949                 }
1950         
1951                 $result = db_query($link,
1952                         "SELECT id FROM ttrss_feeds 
1953                         WHERE feed_url = '$feed_link' AND owner_uid = ".$_SESSION["uid"]);
1954         
1955                 if (db_num_rows($result) == 0) {
1956                         
1957                         $result = db_query($link,
1958                                 "INSERT INTO ttrss_feeds (owner_uid,feed_url,title,cat_id) 
1959                                 VALUES ('".$_SESSION["uid"]."', '$feed_link', 
1960                                 '[Unknown]', $cat_qpart)");
1961         
1962                         $result = db_query($link,
1963                                 "SELECT id FROM ttrss_feeds WHERE feed_url = '$feed_link' 
1964                                 AND owner_uid = " . $_SESSION["uid"]);
1965         
1966                         $feed_id = db_fetch_result($result, 0, "id");
1967         
1968                         if ($feed_id) {
1969                                 update_rss_feed($link, $feed_link, $feed_id, true);
1970                         }
1971
1972                         return true;
1973                 } else {
1974                         return false;
1975                 }
1976         }
1977
1978         function print_feed_select($link, $id, $default_id = "", 
1979                 $attributes = "", $include_all_feeds = true) {
1980
1981                 print "<select id=\"$id\" name=\"$id\" $attributes>";
1982                 if ($include_all_feeds) { 
1983                         print "<option value=\"0\">All feeds</option>";
1984                 }
1985         
1986                 $result = db_query($link, "SELECT id,title FROM ttrss_feeds
1987                         WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
1988
1989                 if (db_num_rows($result) > 0 && $include_all_feeds) {
1990                         print "<option disabled>--------</option>";
1991                 }
1992
1993                 while ($line = db_fetch_assoc($result)) {
1994                         if ($line["id"] == $default_id) {
1995                                 $is_selected = "selected";
1996                         } else {
1997                                 $is_selected = "";
1998                         }
1999                         printf("<option $is_selected value='%d'>%s</option>", 
2000                                 $line["id"], htmlspecialchars(db_unescape_string($line["title"])));
2001                 }
2002         
2003                 print "</select>";
2004         }
2005
2006         function print_feed_cat_select($link, $id, $default_id = "", 
2007                 $attributes = "", $include_all_cats = true) {
2008                 
2009                 print "<select id=\"$id\" name=\"$id\" $attributes>";
2010
2011                 if ($include_all_cats) {
2012                         print "<option value=\"0\">"._('Uncategorized')."</option>";
2013                 }
2014
2015                 $result = db_query($link, "SELECT id,title FROM ttrss_feed_categories
2016                         WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
2017
2018                 if (db_num_rows($result) > 0 && $include_all_cats) {
2019                         print "<option disabled>--------</option>";
2020                 }
2021
2022                 while ($line = db_fetch_assoc($result)) {
2023                         if ($line["id"] == $default_id) {
2024                                 $is_selected = "selected";
2025                         } else {
2026                                 $is_selected = "";
2027                         }
2028                         printf("<option $is_selected value='%d'>%s</option>", 
2029                                 $line["id"], htmlspecialchars(db_unescape_string($line["title"])));
2030                 }
2031
2032                 print "</select>";
2033         }
2034         
2035         function checkbox_to_sql_bool($val) {
2036                 return ($val == "on") ? "true" : "false";
2037         }
2038
2039         function getFeedCatTitle($link, $id) {
2040                 if ($id == -1) {
2041                         return _("Special");
2042                 } else if ($id < -10) {
2043                         return _("Labels");
2044                 } else if ($id > 0) {
2045                         $result = db_query($link, "SELECT ttrss_feed_categories.title 
2046                                 FROM ttrss_feeds, ttrss_feed_categories WHERE ttrss_feeds.id = '$id' AND
2047                                         cat_id = ttrss_feed_categories.id");
2048                         if (db_num_rows($result) == 1) {
2049                                 return db_fetch_result($result, 0, "title");
2050                         } else {
2051                                 return _("Uncategorized");
2052                         }
2053                 } else {
2054                         return "getFeedCatTitle($id) failed";
2055                 }
2056
2057         }
2058
2059         function getFeedTitle($link, $id) {
2060                 if ($id == -1) {
2061                         return _("Starred articles");
2062                 } else if ($id < -10) {
2063                         $label_id = -10 - $id;
2064                         $result = db_query($link, "SELECT description FROM ttrss_labels WHERE id = '$label_id'");
2065                         if (db_num_rows($result) == 1) {
2066                                 return db_fetch_result($result, 0, "description");
2067                         } else {
2068                                 return "Unknown label ($label_id)";
2069                         }
2070
2071                 } else if ($id > 0) {
2072                         $result = db_query($link, "SELECT title FROM ttrss_feeds WHERE id = '$id'");
2073                         if (db_num_rows($result) == 1) {
2074                                 return db_fetch_result($result, 0, "title");
2075                         } else {
2076                                 return "Unknown feed ($id)";
2077                         }
2078                 } else {
2079                         return "getFeedTitle($id) failed";
2080                 }
2081
2082         }
2083
2084         function get_session_cookie_name() {
2085                 return ((!defined('TTRSS_SESSION_NAME')) ? "ttrss_sid" : TTRSS_SESSION_NAME);
2086         }
2087
2088         function print_init_params($link) {
2089                 print "<init-params>";
2090                 if ($_SESSION["stored-params"]) {
2091                         foreach (array_keys($_SESSION["stored-params"]) as $key) {
2092                                 if ($key) {
2093                                         $value = htmlspecialchars($_SESSION["stored-params"][$key]);
2094                                         print "<param key=\"$key\" value=\"$value\"/>";
2095                                 }
2096                         }
2097                 }
2098
2099                 print "<param key=\"daemon_enabled\" value=\"" . ENABLE_UPDATE_DAEMON . "\"/>";
2100                 print "<param key=\"feeds_frame_refresh\" value=\"" . FEEDS_FRAME_REFRESH . "\"/>";
2101                 print "<param key=\"daemon_refresh_only\" value=\"" . DAEMON_REFRESH_ONLY . "\"/>";
2102
2103                 print "<param key=\"on_catchup_show_next_feed\" value=\"" . 
2104                         get_pref($link, "ON_CATCHUP_SHOW_NEXT_FEED") . "\"/>";
2105
2106                 print "<param key=\"hide_read_feeds\" value=\"" . 
2107                         sprintf("%d", get_pref($link, "HIDE_READ_FEEDS")) . "\"/>";
2108
2109                 print "<param key=\"feeds_sort_by_unread\" value=\"" . 
2110                         sprintf("%d", get_pref($link, "FEEDS_SORT_BY_UNREAD")) . "\"/>";
2111
2112                 print "<param key=\"confirm_feed_catchup\" value=\"" . 
2113                         sprintf("%d", get_pref($link, "CONFIRM_FEED_CATCHUP")) . "\"/>";
2114
2115                 print "</init-params>";
2116         }
2117
2118         function print_runtime_info($link) {
2119                 print "<runtime-info>";
2120                 if (ENABLE_UPDATE_DAEMON) {
2121                         print "<param key=\"daemon_is_running\" value=\"".
2122                                 sprintf("%d", file_is_locked("update_daemon.lock")) . "\"/>";
2123                 }
2124                 print "</runtime-info>";
2125         }
2126
2127         function getSearchSql($search, $match_on) {
2128
2129                 $search_query_part = "";
2130
2131                 $keywords = split(" ", $search);
2132                 $query_keywords = array();
2133
2134                 if ($match_on == "both") {
2135
2136                         foreach ($keywords as $k) {
2137                                 array_push($query_keywords, "(UPPER(ttrss_entries.title) LIKE UPPER('%$k%')
2138                                         OR UPPER(ttrss_entries.content) LIKE UPPER('%$k%'))");
2139                         }
2140
2141                         $search_query_part = implode("AND", $query_keywords) . " AND ";
2142
2143                 } else if ($match_on == "title") {
2144
2145                         foreach ($keywords as $k) {
2146                                 array_push($query_keywords, "(UPPER(ttrss_entries.title) LIKE UPPER('%$k%'))");
2147                         }
2148
2149                         $search_query_part = implode("AND", $query_keywords) . " AND ";
2150
2151                 } else if ($match_on == "content") {
2152
2153                         foreach ($keywords as $k) {
2154                                 array_push($query_keywords, "(UPPER(ttrss_entries.content) LIKE UPPER('%$k%'))");
2155                         }
2156                 }
2157
2158                 $search_query_part = implode("AND", $query_keywords);
2159
2160                 return $search_query_part;
2161         }
2162
2163         function queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, $search, $search_mode, $match_on, $override_order = false) {
2164                         if ($search) {
2165                         
2166                                 $search_query_part = getSearchSql($search, $match_on);
2167                                 $search_query_part .= " AND ";
2168
2169                         } else {
2170                                 $search_query_part = "";
2171                         }
2172
2173                         $view_query_part = "";
2174         
2175                         if ($view_mode == "adaptive") {
2176                                 if ($search) {
2177                                         $view_query_part = " ";
2178                                 } else if ($feed != -1) {
2179                                         $unread = getFeedUnread($link, $feed, $cat_view);
2180                                         if ($unread > 0) {
2181                                                 $view_query_part = " unread = true AND ";
2182                                         }
2183                                 }
2184                         }
2185         
2186                         if ($view_mode == "marked") {
2187                                 $view_query_part = " marked = true AND ";
2188                         }
2189         
2190                         if ($view_mode == "unread") {
2191                                 $view_query_part = " unread = true AND ";
2192                         }
2193         
2194                         if ($limit > 0) {
2195                                 $limit_query_part = "LIMIT " . $limit;
2196                         } 
2197
2198                         $vfeed_query_part = "";
2199         
2200                         // override query strategy and enable feed display when searching globally
2201                         if ($search && $search_mode == "all_feeds") {
2202                                 $query_strategy_part = "ttrss_entries.id > 0";
2203                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";         
2204                         } else if (preg_match("/^-?[0-9][0-9]*$/", $feed) == false) {
2205                                 $query_strategy_part = "ttrss_entries.id > 0";
2206                                 $vfeed_query_part = "(SELECT title FROM ttrss_feeds WHERE
2207                                         id = feed_id) as feed_title,";
2208                         } else if ($feed >= 0 && $search && $search_mode == "this_cat") {
2209         
2210                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";         
2211
2212                                 $tmp_result = false;
2213
2214                                 if ($cat_view) {
2215                                         $tmp_result = db_query($link, "SELECT id 
2216                                                 FROM ttrss_feeds WHERE cat_id = '$feed'");
2217                                 } else {
2218                                         $tmp_result = db_query($link, "SELECT id
2219                                                 FROM ttrss_feeds WHERE cat_id = (SELECT cat_id FROM ttrss_feeds 
2220                                                         WHERE id = '$feed') AND id != '$feed'");
2221                                 }
2222         
2223                                 $cat_siblings = array();
2224         
2225                                 if (db_num_rows($tmp_result) > 0) {
2226                                         while ($p = db_fetch_assoc($tmp_result)) {
2227                                                 array_push($cat_siblings, "feed_id = " . $p["id"]);
2228                                         }
2229         
2230                                         $query_strategy_part = sprintf("(feed_id = %d OR %s)", 
2231                                                 $feed, implode(" OR ", $cat_siblings));
2232         
2233                                 } else {
2234                                         $query_strategy_part = "ttrss_entries.id > 0";
2235                                 }
2236                                 
2237                         } else if ($feed >= 0) {
2238         
2239                                 if ($cat_view) {
2240
2241                                         if ($feed > 0) {
2242                                                 $query_strategy_part = "cat_id = '$feed'";
2243                                         } else {
2244                                                 $query_strategy_part = "cat_id IS NULL";
2245                                         }
2246         
2247                                         $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2248
2249                                 } else {                
2250                                         $tmp_result = db_query($link, "SELECT id 
2251                                                 FROM ttrss_feeds WHERE parent_feed = '$feed'
2252                                                 ORDER BY cat_id,title");
2253                 
2254                                         $parent_ids = array();
2255                 
2256                                         if (db_num_rows($tmp_result) > 0) {
2257                                                 while ($p = db_fetch_assoc($tmp_result)) {
2258                                                         array_push($parent_ids, "feed_id = " . $p["id"]);
2259                                                 }
2260                 
2261                                                 $query_strategy_part = sprintf("(feed_id = %d OR %s)", 
2262                                                         $feed, implode(" OR ", $parent_ids));
2263                 
2264                                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2265                                         } else {
2266                                                 $query_strategy_part = "feed_id = '$feed'";
2267                                         }
2268                                 }
2269                         } else if ($feed == -1) { // starred virtual feed
2270                                 $query_strategy_part = "marked = true";
2271                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2272                         } else if ($feed <= -10) { // labels
2273                                 $label_id = -$feed - 11;
2274         
2275                                 $tmp_result = db_query($link, "SELECT sql_exp FROM ttrss_labels
2276                                         WHERE id = '$label_id'");
2277                         
2278                                 $query_strategy_part = db_fetch_result($tmp_result, 0, "sql_exp");
2279                 
2280                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2281                         } else {
2282                                 $query_strategy_part = "id > 0"; // dumb
2283                         }
2284
2285                         if (get_pref($link, 'REVERSE_HEADLINES')) {
2286                                 $order_by = "updated";
2287                         } else {        
2288                                 $order_by = "updated DESC";
2289                         }
2290
2291                         if ($override_order) {
2292                                 $order_by = $override_order;
2293                         }
2294         
2295                         $feed_title = "";
2296
2297                         if ($search && $search_mode == "all_feeds") {
2298                                 $feed_title = _("Global search results")." ($search)";
2299                         } else if ($search && preg_match('/^-?[0-9][0-9]*$/', $feed) == false) {
2300                                 $feed_title = _("Tag search results")." ($search, $feed)";
2301                         } else if (preg_match('/^-?[0-9][0-9]*$/', $feed) == false) {
2302                                 $feed_title = $feed;
2303                         } else if (preg_match('/^-?[0-9][0-9]*$/', $feed) != false && $feed >= 0) {
2304         
2305                                 if ($cat_view) {
2306
2307                                         if ($feed != 0) {                       
2308                                                 $result = db_query($link, "SELECT title FROM ttrss_feed_categories
2309                                                         WHERE id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
2310                                                 $feed_title = db_fetch_result($result, 0, "title");
2311                                         } else {
2312                                                 $feed_title = _("Uncategorized");
2313                                         }
2314
2315                                         if ($search) {
2316                                                 $feed_title = _("Category search results")." ($search, $feed_title)";
2317                                         }
2318
2319                                 } else {
2320                                         
2321                                         $result = db_query($link, "SELECT title,site_url,last_error FROM ttrss_feeds 
2322                                                 WHERE id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
2323                 
2324                                         $feed_title = db_fetch_result($result, 0, "title");
2325                                         $feed_site_url = db_fetch_result($result, 0, "site_url");
2326                                         $last_error = db_fetch_result($result, 0, "last_error");
2327
2328                                         if ($search) {
2329                                                 $feed_title = _("Feed search results") . " ($search, $feed_title)";
2330                                         }
2331                                 }
2332         
2333                         } else if ($feed == -1) {
2334                                 $feed_title = _("Starred articles");
2335                         } else if ($feed < -10) {
2336                                 $label_id = -$feed - 11;
2337                                 $result = db_query($link, "SELECT description FROM ttrss_labels
2338                                         WHERE id = '$label_id'");
2339                                 $feed_title = db_fetch_result($result, 0, "description");
2340
2341                                 if ($search) {
2342                                         $feed_title = _("Label search results") . " ($search, $feed_title)";
2343                                 }
2344                         } else {
2345                                 $feed_title = "?";
2346                         }
2347
2348                         $feed_title = db_unescape_string($feed_title);
2349
2350                         if ($feed < -10) error_reporting (0);
2351
2352                         if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
2353         
2354                                 if ($feed >= 0) {
2355                                         $feed_kind = "Feeds";
2356                                 } else {
2357                                         $feed_kind = "Labels";
2358                                 }
2359         
2360                                 $content_query_part = "content as content_preview,";
2361                                 
2362                                 $query = "SELECT 
2363                                                 guid,
2364                                                 ttrss_entries.id,ttrss_entries.title,
2365                                                 SUBSTRING(updated,1,16) as updated,
2366                                                 unread,feed_id,marked,link,last_read,
2367                                                 SUBSTRING(last_read,1,19) as last_read_noms,
2368                                                 $vfeed_query_part
2369                                                 $content_query_part
2370                                                 SUBSTRING(updated,1,19) as updated_noms,
2371                                                 author
2372                                         FROM
2373                                                 ttrss_entries,ttrss_user_entries,ttrss_feeds
2374                                         WHERE
2375                                         ttrss_feeds.hidden = false AND
2376                                         ttrss_user_entries.feed_id = ttrss_feeds.id AND
2377                                         ttrss_user_entries.ref_id = ttrss_entries.id AND
2378                                         ttrss_user_entries.owner_uid = '".$_SESSION["uid"]."' AND
2379                                         $search_query_part
2380                                         $view_query_part
2381                                         $query_strategy_part ORDER BY $order_by
2382                                         $limit_query_part";
2383                                         
2384                                 $result = db_query($link, $query);
2385         
2386                                 if ($_GET["debug"]) print $query;
2387         
2388                         } else {
2389                                 // browsing by tag
2390         
2391                                 $feed_kind = "Tags";
2392         
2393                                 $result = db_query($link, "SELECT
2394                                         guid,
2395                                         ttrss_entries.id as id,title,
2396                                         SUBSTRING(updated,1,16) as updated,
2397                                         unread,feed_id,
2398                                         marked,link,last_read,                          
2399                                         SUBSTRING(last_read,1,19) as last_read_noms,
2400                                         $vfeed_query_part
2401                                         $content_query_part
2402                                         SUBSTRING(updated,1,19) as updated_noms
2403                                         FROM
2404                                                 ttrss_entries,ttrss_user_entries,ttrss_tags
2405                                         WHERE
2406                                                 ref_id = ttrss_entries.id AND
2407                                                 ttrss_user_entries.owner_uid = '".$_SESSION["uid"]."' AND
2408                                                 post_int_id = int_id AND tag_name = '$feed' AND
2409                                                 $view_query_part
2410                                                 $search_query_part
2411                                                 $query_strategy_part ORDER BY $order_by
2412                                         $limit_query_part");    
2413                         }
2414
2415                         return array($result, $feed_title, $feed_site_url, $last_error);
2416                         
2417         }
2418
2419         function generate_syndicated_feed($link, $feed, $is_cat,
2420                 $search, $search_mode, $match_on) {
2421
2422                 $qfh_ret = queryFeedHeadlines($link, $feed, 
2423                                 30, false, $is_cat, $search, $search_mode, $match_on, "updated DESC");
2424
2425                 $result = $qfh_ret[0];
2426                 $feed_title = htmlspecialchars($qfh_ret[1]);
2427                 $feed_site_url = $qfh_ret[2];
2428                 $last_error = $qfh_ret[3];
2429
2430                 print "<rss version=\"2.0\">
2431                         <channel>
2432                         <title>$feed_title</title>
2433                         <link>$feed_site_url</link>
2434                         <generator>Tiny Tiny RSS v".VERSION."</generator>";
2435  
2436                 while ($line = db_fetch_assoc($result)) {
2437                         print "<item>";
2438                         print "<id>" . htmlspecialchars($line["guid"]) . "</id>";
2439                         print "<link>" . htmlspecialchars($line["link"]) . "</link>";
2440   
2441                         $rfc822_date = date('r', strtotime($line["updated"]));
2442   
2443                         print "<pubDate>$rfc822_date</pubDate>";
2444  
2445                         print "<title>" . 
2446                                 htmlspecialchars($line["title"]) . "</title>";
2447   
2448                         print "<description>" . 
2449                                 htmlspecialchars($line["content_preview"]) . "</description>";
2450   
2451                         print "</item>";
2452                 }
2453   
2454                 print "</channel></rss>";
2455
2456         }
2457
2458         function getCategoryTitle($link, $cat_id) {
2459
2460                 $result = db_query($link, "SELECT title FROM ttrss_feed_categories WHERE
2461                         id = '$cat_id'");
2462
2463                 if (db_num_rows($result) == 1) {
2464                         return db_fetch_result($result, 0, "title");
2465                 } else {
2466                         return "Uncategorized";
2467                 }
2468         }
2469
2470         function sanitize_rss($str) {
2471                 $res = $str;
2472
2473                 $res = preg_replace('/<script.*?>/i', 
2474                         "<p class=\"scriptWarn\">Disabled script: ", $res);
2475
2476                 $res = preg_replace('/<\/script.*?>/i', "</p>", $res);
2477
2478 /*              $res = preg_replace('/<embed.*?>/i', "", $res);
2479
2480                 $res = preg_replace('/<object.*?>.*?<\/object>/i', 
2481                         "<p class=\"objectWarn\">(Disabled html object 
2482                         - flash or other embedded content)</p>", $res);  */
2483
2484                 return $res;
2485         }
2486
2487         function send_headlines_digests($link, $limit = 100) {
2488
2489                 if (!DIGEST_ENABLE) return false;
2490
2491                 $user_limit = DIGEST_EMAIL_LIMIT;
2492                 $days = 1;
2493
2494                 print "Sending digests, batch of max $user_limit users, days = $days, headline limit = $limit\n\n";
2495
2496                 if (DB_TYPE == "pgsql") {
2497                         $interval_query = "last_digest_sent < NOW() - INTERVAL '$days days'";
2498                 } else if (DB_TYPE == "mysql") {
2499                         $interval_query = "last_digest_sent < DATE_SUB(NOW(), INTERVAL $days DAY)";
2500                 }
2501
2502                 $result = db_query($link, "SELECT id,email FROM ttrss_users 
2503                                 WHERE email != '' AND (last_digest_sent IS NULL OR $interval_query)");
2504
2505                 while ($line = db_fetch_assoc($result)) {
2506                         if (get_pref($link, 'DIGEST_ENABLE', $line['id'], false)) {
2507                                 print "Sending digest for UID:" . $line['id'] . " - " . $line["email"] . " ... ";
2508
2509                                 $tuple = prepare_headlines_digest($link, $line["id"], $days, $limit);
2510                                 $digest = $tuple[0];
2511                                 $headlines_count = $tuple[1];
2512
2513                                 if ($headlines_count > 0) {
2514                                         $rc = mail($line["login"] . " <" . $line["email"] . ">",
2515                                                 "[tt-rss] New headlines for last 24 hours", $digest,
2516                                                 "From: " . MAIL_FROM . "\n".
2517                                                 "Content-Type: text/plain; charset=\"utf-8\"\n".
2518                                                 "Content-Transfer-Encoding: 8bit\n");
2519                                         print "RC=$rc\n";
2520                                         db_query($link, "UPDATE ttrss_users SET last_digest_sent = NOW() 
2521                                                         WHERE id = " . $line["id"]);
2522                                 } else {
2523                                         print "No headlines\n";
2524                                 }
2525                         }
2526                 }
2527
2528 //              $digest = prepare_headlines_digest($link, $user_id, $days, $limit);
2529
2530         }
2531
2532         function prepare_headlines_digest($link, $user_id, $days = 1, $limit = 100) {
2533                 $tmp =  _("New headlines for last 24 hours, as of ") . date("Y/m/d H:m") . "\n";        
2534                 $tmp .= "=======================================================\n\n";
2535
2536                 if (DB_TYPE == "pgsql") {
2537                         $interval_query = "ttrss_entries.date_entered > NOW() - INTERVAL '$days days'";
2538                 } else if (DB_TYPE == "mysql") {
2539                         $interval_query = "ttrss_entries.date_entered > DATE_SUB(NOW(), INTERVAL $days DAY)";
2540                 }
2541
2542                 $result = db_query($link, "SELECT ttrss_entries.title,
2543                                 ttrss_feeds.title AS feed_title,
2544                                 date_entered,
2545                                 link,
2546                                 SUBSTRING(last_updated,1,19) AS last_updated
2547                         FROM 
2548                                 ttrss_user_entries,ttrss_entries,ttrss_feeds 
2549                         WHERE 
2550                                 ref_id = ttrss_entries.id AND feed_id = ttrss_feeds.id 
2551                                 AND include_in_digest = true
2552                                 AND $interval_query
2553                                 AND ttrss_user_entries.owner_uid = $user_id
2554                                 AND unread = true ORDER BY ttrss_feeds.title, date_entered DESC
2555                         LIMIT $limit");
2556
2557                 $cur_feed_title = "";
2558
2559                 $headlines_count = db_num_rows($result);
2560
2561                 while ($line = db_fetch_assoc($result)) {
2562                         $updated = smart_date_time(strtotime($line["last_updated"]));
2563                         $feed_title = $line["feed_title"];
2564
2565                         if ($cur_feed_title != $feed_title) {
2566                                 $cur_feed_title = $feed_title;
2567
2568                                 $tmp .= "$feed_title\n\n";
2569                         }
2570
2571                         $tmp .= " * " . trim($line["title"]) . " - $updated\n";
2572                         $tmp .= "   " . trim($line["link"]) . "\n";
2573                         $tmp .= "\n";
2574                 }
2575
2576                 $tmp .= "--- \n";
2577                 $tmp .= _("You have been sent this email because you have enabled daily digests in Tiny Tiny RSS at ") . 
2578                         DIGEST_HOSTNAME . "\n".
2579                         _("To unsubscribe, visit your configuration options or contact instance owner.\n");
2580                         
2581
2582                 return array($tmp, $headlines_count);
2583         }
2584
2585         function check_for_update($link) {
2586                 $releases_feed = "http://tt-rss.spb.ru/releases.rss";
2587
2588                 if (!CHECK_FOR_NEW_VERSION || $_SESSION["access_level"] < 10) {
2589                         return;
2590                 }
2591
2592                 error_reporting(0);
2593                 $rss = fetch_rss($releases_feed);
2594                 error_reporting (DEFAULT_ERROR_LEVEL);
2595
2596                 if ($rss) {
2597
2598                         $items = $rss->items;
2599
2600                         if (!$items || !is_array($items)) $items = $rss->entries;
2601                         if (!$items || !is_array($items)) $items = $rss;
2602
2603                         if (!is_array($items) || count($items) == 0) {
2604                                 return;
2605                         }                       
2606
2607                         $latest_item = $items[0];
2608
2609                         $latest_version = trim(preg_replace("/(Milestone)|(completed)/", "", $latest_item["title"]));
2610
2611                         $release_url = sanitize_rss($latest_item["link"]);
2612                         $content = sanitize_rss($latest_item["description"]);
2613
2614                         if (version_compare(VERSION, $latest_version) == -1) {
2615                                 return "<div class=\"notice\"><a href=\"javascript:showBlockElement('milestoneDetails')\">      
2616                                         New version of Tiny-Tiny RSS ($latest_version) is available (click for details)</a>
2617                                         <div id=\"milestoneDetails\">$content</div></div>";
2618                         }                       
2619                 }
2620         }
2621
2622         function markArticlesById($link, $ids, $cmode) {
2623
2624                 $tmp_ids = array();
2625
2626                 foreach ($ids as $id) {
2627                         array_push($tmp_ids, "ref_id = '$id'");
2628                 }
2629
2630                 $ids_qpart = join(" OR ", $tmp_ids);
2631
2632                 if ($cmode == 0) {
2633                         db_query($link, "UPDATE ttrss_user_entries SET 
2634                         marked = false,last_read = NOW()
2635                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2636                 } else if ($cmode == 1) {
2637                         db_query($link, "UPDATE ttrss_user_entries SET 
2638                         marked = true
2639                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2640                 } else {
2641                         db_query($link, "UPDATE ttrss_user_entries SET 
2642                         marked = NOT marked,last_read = NOW()
2643                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2644                 }
2645         }
2646
2647         function catchupArticlesById($link, $ids, $cmode) {
2648
2649                 $tmp_ids = array();
2650
2651                 foreach ($ids as $id) {
2652                         array_push($tmp_ids, "ref_id = '$id'");
2653                 }
2654
2655                 $ids_qpart = join(" OR ", $tmp_ids);
2656
2657                 if ($cmode == 0) {
2658                         db_query($link, "UPDATE ttrss_user_entries SET 
2659                         unread = false,last_read = NOW()
2660                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2661                 } else if ($cmode == 1) {
2662                         db_query($link, "UPDATE ttrss_user_entries SET 
2663                         unread = true
2664                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2665                 } else {
2666                         db_query($link, "UPDATE ttrss_user_entries SET 
2667                         unread = NOT unread,last_read = NOW()
2668                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2669                 }
2670         }
2671
2672         function escape_for_form($s) {
2673                 return htmlspecialchars(db_unescape_string($s));
2674         }
2675
2676         function make_guid_from_title($title) {
2677                 return preg_replace("/[ \"\',.:;]/", "-", 
2678                         mb_strtolower(strip_tags($title)));
2679         }
2680
2681         function print_headline_subtoolbar($link, $feed_site_url, $feed_title, 
2682                         $bottom = false, $rtl_content = false, $feed_id = 0,
2683                         $is_cat = false, $search = false, $match_on = false,
2684                         $search_mode = false) {
2685
2686                         if (!$bottom) {
2687                                 $class = "headlinesSubToolbar";
2688                                 $tid = "headlineActionsTop";
2689                         } else {
2690                                 $class = "headlinesSubToolbar";
2691                                 $tid = "headlineActionsBottom";
2692                         }
2693
2694                         print "<table class=\"$class\" id=\"$tid\"
2695                                 width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tr>";
2696
2697                         if ($rtl_content) {
2698                                 $rtl_cpart = "RTL";
2699                         } else {
2700                                 $rtl_cpart = "";
2701                         }
2702
2703                         if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) {
2704
2705                                 print "<td class=\"headlineActions$rtl_cpart\">".
2706                                         _('Select:')."
2707                                                                 <a href=\"javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, '', true)\">All</a>,
2708                                                                 <a href=\"javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, 'Unread', true)\">Unread</a>,
2709                                                                 <a href=\"javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false)\">None</a>
2710                                                 &nbsp;&nbsp;".
2711                                                 _('Toggle:')." <a href=\"javascript:selectionToggleUnread()\">Unread</a>,
2712                                                         <a href=\"javascript:selectionToggleMarked()\">Starred</a>
2713                                                 &nbsp;&nbsp;".
2714                                                 _('Mark as read:')."
2715                                                         <a href=\"#\" onclick=\"catchupPage()\">Page</a>,
2716                                                         <a href=\"#\" onclick=\"catchupCurrentFeed()\">Feed</a>";
2717                                 print "</td>";
2718
2719                                 if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS) {
2720                                         print "<td class=\"headlineActions$rtl_cpart\">
2721                                                 <a href=\"javascript:labelFromSearch('$search', '$search_mode',
2722                                                                 '$match_on', '$feed_id', '$is_cat');\">
2723                                                         "._('Convert this search to label')."</a></td>";
2724                                 }
2725
2726                         } else {
2727
2728                                 print "<td class=\"headlineActions$rtl_cpart\">".
2729                                         _('Select:')."
2730                                                                 <a href=\"javascript:cdmSelectArticles('all')\">"._('All')."</a>,
2731                                                                 <a href=\"javascript:cdmSelectArticles('unread')\">"._('Unread')."</a>,
2732                                                                 <a href=\"javascript:cdmSelectArticles('none')\">"._('None')."</a>
2733                                                 &nbsp;&nbsp;".
2734                                                 _('Toggle:')." <a href=\"javascript:selectionToggleUnread(true)\">"._('Unread')."</a>,
2735                                                         <a href=\"javascript:selectionToggleMarked(true)\">"._('Starred')."</a>
2736                                                 &nbsp;&nbsp;".
2737                                                 _('Mark as read:').
2738                                                         "<a href=\"#\" onclick=\"catchupPage()\">"._('Page')."</a>,
2739                                                         <a href=\"#\" onclick=\"catchupCurrentFeed()\">"._('Feed')."</a>";
2740                         
2741                                 print "</td>";
2742
2743                         }
2744
2745                         print "<td class=\"headlineTitle$rtl_cpart\">";
2746                 
2747                         if ($feed_site_url) {
2748                                 if (!$bottom) {
2749                                         $target = "target=\"_blank\"";
2750                                 }
2751                                 print "<a $target href=\"$feed_site_url\">$feed_title</a>";
2752                         } else {
2753                                 print $feed_title;
2754                         }
2755
2756                         if ($search) {
2757                                 $search_q = "&q=$search&m=$match_on&smode=$search_mode";
2758                         }
2759
2760                         if (!$bottom) {
2761                                 print "&nbsp;
2762                                         <a target=\"_new\" 
2763                                                 href=\"backend.php?op=rss&id=$feed_id&is_cat=$is_cat$search_q\">
2764                                                 <img class=\"noborder\" 
2765                                                         alt=\"Generated feed\" src=\"images/feed-icon-12x12.png\">
2766                                         </a>";
2767                         }
2768                                 
2769                         print "</td>";
2770                         print "</tr></table>";
2771
2772                 }
2773
2774         function outputFeedList($link, $tags = false) {
2775
2776                 print "<ul class=\"feedList\" id=\"feedList\">\n";
2777
2778                 $owner_uid = $_SESSION["uid"];
2779
2780                 /* virtual feeds */
2781
2782                 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2783                         print "<li class=\"feedCat\">"._('Special')."</li>";
2784                         print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
2785                 }
2786
2787                 $num_starred = getFeedUnread($link, -1);
2788
2789                 $class = "virt";
2790
2791                 if ($num_starred > 0) $class .= "Unread";
2792
2793                 printFeedEntry(-1, $class, _("Starred articles"), $num_starred, 
2794                         "images/mark_set.png", $link);
2795
2796                 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2797                         print "</ul>\n";
2798                 }
2799
2800                 if (!$tags) {
2801
2802                         if (GLOBAL_ENABLE_LABELS && get_pref($link, 'ENABLE_LABELS')) {
2803         
2804                                 $result = db_query($link, "SELECT id,sql_exp,description FROM
2805                                         ttrss_labels WHERE owner_uid = '$owner_uid' ORDER by description");
2806                 
2807                                 if (db_num_rows($result) > 0) {
2808                                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
2809                                                 print "<li class=\"feedCat\">"._('Labels')."</li>";
2810                                                 print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
2811                                         } else {
2812                                                 print "<li><hr></li>";
2813                                         }
2814                                 }
2815                 
2816                                 while ($line = db_fetch_assoc($result)) {
2817         
2818                                         error_reporting (0);
2819
2820                                         $label_id = -$line['id'] - 11;
2821                                         $count = getFeedUnread($link, $label_id);
2822
2823                                         $class = "label";
2824         
2825                                         if ($count > 0) {
2826                                                 $class .= "Unread";
2827                                         }
2828                                         
2829                                         error_reporting (DEFAULT_ERROR_LEVEL);
2830         
2831                                         printFeedEntry($label_id, 
2832                                                 $class, db_unescape_string($line["description"]), 
2833                                                 $count, "images/label.png", $link);
2834                 
2835                                 }
2836
2837                                 if (db_num_rows($result) > 0) {
2838                                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
2839                                                 print "</ul>";
2840                                         }
2841                                 }
2842
2843                         }
2844
2845                         if (!get_pref($link, 'ENABLE_FEED_CATS')) {
2846                                 print "<li><hr></li>";
2847                         }
2848
2849                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
2850                                 if (get_pref($link, "FEEDS_SORT_BY_UNREAD")) {
2851                                         $order_by_qpart = "category,unread DESC,title";
2852                                 } else {
2853                                         $order_by_qpart = "category,title";
2854                                 }
2855                         } else {
2856                                 if (get_pref($link, "FEEDS_SORT_BY_UNREAD")) {
2857                                         $order_by_qpart = "unread DESC,title";
2858                                 } else {                
2859                                         $order_by_qpart = "title";
2860                                 }
2861                         }
2862
2863                         $result = db_query($link, "SELECT ttrss_feeds.*,
2864                                 SUBSTRING(last_updated,1,19) AS last_updated_noms,
2865                                 (SELECT COUNT(id) FROM ttrss_entries,ttrss_user_entries
2866                                         WHERE feed_id = ttrss_feeds.id AND unread = true
2867                                                 AND ttrss_user_entries.ref_id = ttrss_entries.id
2868                                                 AND owner_uid = '$owner_uid') as unread,
2869                                 cat_id,last_error,
2870                                 ttrss_feed_categories.title AS category,
2871                                 ttrss_feed_categories.collapsed 
2872                                 FROM ttrss_feeds LEFT JOIN ttrss_feed_categories 
2873                                         ON (ttrss_feed_categories.id = cat_id)                          
2874                                 WHERE 
2875                                         ttrss_feeds.hidden = false AND
2876                                         ttrss_feeds.owner_uid = '$owner_uid' AND parent_feed IS NULL
2877                                 ORDER BY $order_by_qpart"); 
2878
2879                         $actid = $_GET["actid"];
2880         
2881                         /* real feeds */
2882         
2883                         $lnum = 0;
2884         
2885                         $total_unread = 0;
2886
2887                         $category = "";
2888
2889                         $short_date = get_pref($link, 'SHORT_DATE_FORMAT');
2890         
2891                         while ($line = db_fetch_assoc($result)) {
2892                         
2893                                 $feed = db_unescape_string($line["title"]);
2894                                 $feed_id = $line["id"];   
2895         
2896                                 $subop = $_GET["subop"];
2897                                 
2898                                 $unread = $line["unread"];
2899
2900                                 if (get_pref($link, 'HEADLINES_SMART_DATE')) {
2901                                         $last_updated = smart_date_time(strtotime($line["last_updated_noms"]));
2902                                 } else {
2903                                         $last_updated = date($short_date, strtotime($line["last_updated_noms"]));
2904                                 }
2905
2906                                 $rtl_content = sql_bool_to_bool($line["rtl_content"]);
2907
2908                                 if ($rtl_content) {
2909                                         $rtl_tag = "dir=\"RTL\"";
2910                                 } else {
2911                                         $rtl_tag = "";
2912                                 }
2913
2914                                 $tmp_result = db_query($link,
2915                                         "SELECT id,COUNT(unread) AS unread
2916                                         FROM ttrss_feeds LEFT JOIN ttrss_user_entries 
2917                                                 ON (ttrss_feeds.id = ttrss_user_entries.feed_id) 
2918                                         WHERE parent_feed = '$feed_id' AND unread = true 
2919                                         GROUP BY ttrss_feeds.id");
2920                         
2921                                 if (db_num_rows($tmp_result) > 0) {                             
2922                                         while ($l = db_fetch_assoc($tmp_result)) {
2923                                                 $unread += $l["unread"];
2924                                         }
2925                                 }
2926
2927                                 $cat_id = $line["cat_id"];
2928
2929                                 $tmp_category = $line["category"];
2930
2931                                 if (!$tmp_category) {
2932                                         $tmp_category = _("Uncategorized");
2933                                 }
2934                                 
2935         //                      $class = ($lnum % 2) ? "even" : "odd";
2936
2937                                 if ($line["last_error"]) {
2938                                         $class = "error";
2939                                 } else {
2940                                         $class = "feed";
2941                                 }
2942         
2943                                 if ($unread > 0) $class .= "Unread";
2944         
2945                                 if ($actid == $feed_id) {
2946                                         $class .= "Selected";
2947                                 }
2948         
2949                                 $total_unread += $unread;
2950
2951                                 if ($category != $tmp_category && get_pref($link, 'ENABLE_FEED_CATS')) {
2952                                 
2953                                         if ($category) {
2954                                                 print "</ul></li>";
2955                                         }
2956                                 
2957                                         $category = $tmp_category;
2958
2959                                         $collapsed = $line["collapsed"];
2960
2961                                         // workaround for NULL category
2962                                         if ($category == _("Uncategorized")) {
2963                                                 if ($_COOKIE["ttrss_vf_uclps"] == 1) {
2964                                                         $collapsed = "t";
2965                                                 }
2966                                         }
2967
2968                                         if ($collapsed == "t" || $collapsed == "1") {
2969                                                 $holder_class = "invisible";
2970                                                 $ellipsis = "...";
2971                                         } else {
2972                                                 $holder_class = "";
2973                                                 $ellipsis = "";
2974                                         }
2975
2976                                         $cat_id = sprintf("%d", $cat_id);
2977
2978                                         $cat_unread = getCategoryUnread($link, $cat_id);
2979
2980                                         $catctr_class = ($cat_unread > 0) ? "catCtrHasUnread" : "catCtrNoUnread";
2981
2982                                         print "<li class=\"feedCat\" id=\"FCAT-$cat_id\">
2983                                                 <a id=\"FCATN-$cat_id\" href=\"#\"onclick=\"javascript:toggleCollapseCat($cat_id)\">$tmp_category</a>
2984                                                         <a href=\"#\" onclick=\"javascript:viewCategory($cat_id)\" id=\"FCAP-$cat_id\">
2985                                                         <span id=\"FCATCTR-$cat_id\" title=\"Click to browse category\" 
2986                                                         class=\"$catctr_class\">($cat_unread)</span> $ellipsis
2987                                                         </a></li>";
2988
2989                                         // !!! NO SPACE before <ul...feedCatList - breaks firstChild DOM function
2990                                         // -> keyboard navigation, etc.
2991                                         print "<li id=\"feedCatHolder\" class=\"$holder_class\"><ul class=\"feedCatList\" id=\"FCATLIST-$cat_id\">";
2992                                 }
2993         
2994                                 printFeedEntry($feed_id, $class, $feed, $unread, 
2995                                         "icons/$feed_id.ico", $link, $rtl_content, 
2996                                         $last_updated, $line["last_error"]);
2997         
2998                                 ++$lnum;
2999                         }
3000
3001                         if (db_num_rows($result) == 0) {
3002                                 print "<li>"._('No feeds to display.')."</li>";
3003                         }
3004
3005                 } else {
3006
3007                         // tags
3008
3009 /*                      $result = db_query($link, "SELECT tag_name,count(ttrss_entries.id) AS count
3010                                 FROM ttrss_tags,ttrss_entries,ttrss_user_entries WHERE
3011                                 post_int_id = ttrss_user_entries.int_id AND 
3012                                 unread = true AND ref_id = ttrss_entries.id
3013                                 AND ttrss_tags.owner_uid = '$owner_uid' GROUP BY tag_name       
3014                         UNION
3015                                 select tag_name,0 as count FROM ttrss_tags WHERE owner_uid = '$owner_uid'
3016                         ORDER BY tag_name"); */
3017
3018                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
3019                                 print "<li class=\"feedCat\">"._('Tags')."</li>";
3020                                 print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
3021                         }
3022
3023                         $result = db_query($link, "SELECT tag_name,SUM((SELECT COUNT(int_id) 
3024                                 FROM ttrss_user_entries WHERE int_id = post_int_id 
3025                                         AND unread = true)) AS count FROM ttrss_tags 
3026                                 WHERE owner_uid = ".$_SESSION['uid']." GROUP BY tag_name ORDER BY tag_name");
3027
3028                         $tags = array();
3029         
3030                         while ($line = db_fetch_assoc($result)) {
3031                                 $tags[$line["tag_name"]] += $line["count"];
3032                         }
3033         
3034                         foreach (array_keys($tags) as $tag) {
3035         
3036                                 $unread = $tags[$tag];
3037         
3038                                 $class = "tag";
3039         
3040                                 if ($unread > 0) {
3041                                         $class .= "Unread";
3042                                 }
3043         
3044                                 printFeedEntry($tag, $class, $tag, $unread, "images/tag.png", $link);
3045         
3046                         } 
3047
3048                         if (db_num_rows($result) == 0) {
3049                                 print "<li>No tags to display.</li>";
3050                         }
3051
3052                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
3053                                 print "</ul>\n";
3054                         }
3055
3056                 }
3057
3058                 print "</ul>";
3059
3060         }
3061
3062         function get_article_tags($link, $id) {
3063
3064                 $a_id = db_escape_string($id);
3065
3066                 $tmp_result = db_query($link, "SELECT DISTINCT tag_name FROM
3067                         ttrss_tags WHERE post_int_id = (SELECT int_id FROM ttrss_user_entries WHERE
3068                                 ref_id = '$a_id' AND owner_uid = '".$_SESSION["uid"]."') ORDER BY tag_name");
3069
3070                 $tags = array();        
3071         
3072                 while ($tmp_line = db_fetch_assoc($tmp_result)) {
3073                         array_push($tags, $tmp_line["tag_name"]);                               
3074                 }
3075
3076                 return $tags;
3077         }
3078
3079         function trim_value(&$value) {
3080                 $value = trim($value);
3081         }       
3082
3083         function trim_array($array) {
3084                 $tmp = $array;
3085                 array_walk($tmp, 'trim_value');
3086                 return $tmp;
3087         }
3088
3089         function tag_is_valid($tag) {
3090                 return ($tag !='' && !preg_match("/^[0-9]*$/", $tag));
3091         }
3092
3093 ?>