]> git.wh0rd.org Git - tt-rss.git/blob - functions.php
published feeds work
[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
11         if (ENABLE_TRANSLATIONS == true) { 
12                 require_once "accept-to-gettext.php";
13                 require_once "gettext/gettext.inc";
14
15                 function startup_gettext() {
16         
17                         # Get locale from Accept-Language header
18                         $lang = al2gt(array("en_US", "ru_RU"), "text/html");
19         
20                         if ($lang) {
21                                 _setlocale(LC_MESSAGES, $lang);
22                                 _bindtextdomain("messages", "locale");
23                                 _textdomain("messages");
24                                 _bind_textdomain_codeset("messages", "UTF-8");
25                         }
26                 }
27
28                 startup_gettext();
29
30         } else {
31                 function __($msg) {
32                         return $msg;
33                 }
34                 function startup_gettext() {
35                         // no-op
36                         return true;
37                 }
38         }
39
40         require_once 'db-prefs.php';
41         require_once 'compat.php';
42         require_once 'errors.php';
43         require_once 'version.php';
44
45         define('MAGPIE_USER_AGENT_EXT', ' (Tiny Tiny RSS/' . VERSION . ')');
46         define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');
47
48         require_once "magpierss/rss_fetch.inc";
49         require_once 'magpierss/rss_utils.inc';
50
51         include_once "tw/tw-config.php";
52         include_once "tw/tw.php";
53         include_once TW_SETUP . "paranoya.php";
54
55         $tw_parser = new twParser();
56
57         function _debug($msg) {
58                 $ts = strftime("%H:%M:%S", time());
59                 print "[$ts] $msg\n";
60         }
61
62         function purge_feed($link, $feed_id, $purge_interval, $debug = false) {
63
64                 $rows = -1;
65
66                 if (DB_TYPE == "pgsql") {
67 /*                      $result = db_query($link, "DELETE FROM ttrss_user_entries WHERE
68                                 marked = false AND feed_id = '$feed_id' AND
69                                 (SELECT date_entered FROM ttrss_entries WHERE
70                                         id = ref_id) < NOW() - INTERVAL '$purge_interval days'"); */
71
72                         $pg_version = get_pgsql_version($link);
73
74                         if (preg_match("/^7\./", $pg_version) || preg_match("/^8\.0/", $pg_version)) {
75
76                                 $result = db_query($link, "DELETE FROM ttrss_user_entries WHERE 
77                                         ttrss_entries.id = ref_id AND 
78                                         marked = false AND 
79                                         feed_id = '$feed_id' AND 
80                                         ttrss_entries.date_entered < NOW() - INTERVAL '$purge_interval days'");
81
82                         } else {
83
84                                 $result = db_query($link, "DELETE FROM ttrss_user_entries 
85                                         USING ttrss_entries 
86                                         WHERE ttrss_entries.id = ref_id AND 
87                                         marked = false AND 
88                                         feed_id = '$feed_id' AND 
89                                         ttrss_entries.date_entered < NOW() - INTERVAL '$purge_interval days'");
90                         }
91
92                         $rows = pg_affected_rows($result);
93                         
94                 } else {
95                 
96 /*                      $result = db_query($link, "DELETE FROM ttrss_user_entries WHERE
97                                 marked = false AND feed_id = '$feed_id' AND
98                                 (SELECT date_entered FROM ttrss_entries WHERE 
99                                         id = ref_id) < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)"); */
100
101                         $result = db_query($link, "DELETE FROM ttrss_user_entries 
102                                 USING ttrss_user_entries, ttrss_entries 
103                                 WHERE ttrss_entries.id = ref_id AND 
104                                 marked = false AND 
105                                 feed_id = '$feed_id' AND 
106                                 ttrss_entries.date_entered < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)");
107                                         
108                         $rows = mysql_affected_rows($link);
109
110                 }
111
112                 if ($debug) {
113                         _debug("Purged feed $feed_id ($purge_interval): deleted $rows articles");
114                 }
115         }
116
117         function global_purge_old_posts($link, $do_output = false, $limit = false) {
118
119                 $random_qpart = sql_random_function();
120
121                 if ($limit) {
122                         $limit_qpart = "LIMIT $limit";
123                 } else {
124                         $limit_qpart = "";
125                 }
126                 
127                 $result = db_query($link, 
128                         "SELECT id,purge_interval,owner_uid FROM ttrss_feeds 
129                                 ORDER BY $random_qpart $limit_qpart");
130
131                 while ($line = db_fetch_assoc($result)) {
132
133                         $feed_id = $line["id"];
134                         $purge_interval = $line["purge_interval"];
135                         $owner_uid = $line["owner_uid"];
136
137                         if ($purge_interval == 0) {
138                         
139                                 $tmp_result = db_query($link, 
140                                         "SELECT value FROM ttrss_user_prefs WHERE
141                                                 pref_name = 'PURGE_OLD_DAYS' AND owner_uid = '$owner_uid'");
142
143                                 if (db_num_rows($tmp_result) != 0) {                    
144                                         $purge_interval = db_fetch_result($tmp_result, 0, "value");
145                                 }
146                         }
147
148                         if ($do_output) {
149 //                              print "Feed $feed_id: purge interval = $purge_interval\n";
150                         }
151
152                         if ($purge_interval > 0) {
153                                 purge_feed($link, $feed_id, $purge_interval, $do_output);
154                         }
155                 }       
156
157                 // purge orphaned posts in main content table
158                 db_query($link, "DELETE FROM ttrss_entries WHERE 
159                         (SELECT COUNT(int_id) FROM ttrss_user_entries WHERE ref_id = id) = 0");
160
161         }
162
163         function purge_old_posts($link) {
164
165                 $user_id = $_SESSION["uid"];
166         
167                 $result = db_query($link, "SELECT id,purge_interval FROM ttrss_feeds 
168                         WHERE owner_uid = '$user_id'");
169
170                 while ($line = db_fetch_assoc($result)) {
171
172                         $feed_id = $line["id"];
173                         $purge_interval = $line["purge_interval"];
174
175                         if ($purge_interval == 0) $purge_interval = get_pref($link, 'PURGE_OLD_DAYS');
176
177                         if ($purge_interval > 0) {
178                                 purge_feed($link, $feed_id, $purge_interval);
179                         }
180                 }       
181
182                 // purge orphaned posts in main content table
183                 db_query($link, "DELETE FROM ttrss_entries WHERE 
184                         (SELECT COUNT(int_id) FROM ttrss_user_entries WHERE ref_id = id) = 0");
185         }
186
187         function update_all_feeds($link, $fetch, $user_id = false, $force_daemon = false) {
188
189                 if (WEB_DEMO_MODE) return;
190
191                 if (!$user_id) {
192                         $user_id = $_SESSION["uid"];
193                         purge_old_posts($link);
194                 }
195
196 //              db_query($link, "BEGIN");
197
198                 if (MAX_UPDATE_TIME > 0) {
199                         if (DB_TYPE == "mysql") {
200                                 $q_order = "RAND()";
201                         } else {
202                                 $q_order = "RANDOM()";
203                         }
204                 } else {
205                         $q_order = "last_updated DESC";
206                 }
207
208                 $result = db_query($link, "SELECT feed_url,id,
209                         SUBSTRING(last_updated,1,19) AS last_updated,
210                         update_interval FROM ttrss_feeds WHERE owner_uid = '$user_id'
211                         ORDER BY $q_order");
212
213                 $upd_start = time();
214
215                 while ($line = db_fetch_assoc($result)) {
216                         $upd_intl = $line["update_interval"];
217
218                         if (!$upd_intl || $upd_intl == 0) {
219                                 $upd_intl = get_pref($link, 'DEFAULT_UPDATE_INTERVAL', $user_id, false);
220                         }
221
222                         if ($upd_intl < 0) { 
223                                 // Updates for this feed are disabled
224                                 continue; 
225                         }
226
227                         if ($fetch || (!$line["last_updated"] || 
228                                 time() - strtotime($line["last_updated"]) > ($upd_intl * 60))) {
229
230 //                              print "<!-- feed: ".$line["feed_url"]." -->";
231
232                                 update_rss_feed($link, $line["feed_url"], $line["id"], $force_daemon);
233
234                                 $upd_elapsed = time() - $upd_start;
235
236                                 if (MAX_UPDATE_TIME > 0 && $upd_elapsed > MAX_UPDATE_TIME) {
237                                         return;
238                                 }
239                         }
240                 }
241
242 //              db_query($link, "COMMIT");
243
244         }
245
246         function fetch_file_contents($url) {
247                 if (USE_CURL_FOR_ICONS) {
248                         $tmpfile = tempnam(TMP_DIRECTORY, "ttrss-tmp");
249
250                         $ch = curl_init($url);
251                         $fp = fopen($tmpfile, "w");
252
253                         if ($fp) {
254                                 curl_setopt($ch, CURLOPT_FILE, $fp);
255                                 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
256                                 curl_setopt($ch, CURLOPT_TIMEOUT, 45);
257                                 curl_exec($ch);
258                                 curl_close($ch);
259                                 fclose($fp);                                    
260                         }
261
262                         $contents =  file_get_contents($tmpfile);
263                         unlink($tmpfile);
264
265                         return $contents;
266
267                 } else {
268                         return file_get_contents($url);
269                 }
270
271         }
272
273         // adapted from wordpress favicon plugin by Jeff Minard (http://thecodepro.com/)
274         // http://dev.wp-plugins.org/file/favatars/trunk/favatars.php
275
276         function get_favicon_url($url) {
277
278                 if ($html = @fetch_file_contents($url)) {
279
280                         if ( preg_match('/<link[^>]+rel="(?:shortcut )?icon"[^>]+?href="([^"]+?)"/si', $html, $matches)) {
281                                 // Attempt to grab a favicon link from their webpage url
282                                 $linkUrl = html_entity_decode($matches[1]);
283
284                                 if (substr($linkUrl, 0, 1) == '/') {
285                                         $urlParts = parse_url($url);
286                                         $faviconURL = $urlParts['scheme'].'://'.$urlParts['host'].$linkUrl;
287                                 } else if (substr($linkUrl, 0, 7) == 'http://') {
288                                         $faviconURL = $linkUrl;
289                                 } else if (substr($url, -1, 1) == '/') {
290                                         $faviconURL = $url.$linkUrl;
291                                 } else {
292                                         $faviconURL = $url.'/'.$linkUrl;
293                                 }
294
295                         } else {
296                                 // If unsuccessful, attempt to "guess" the favicon location
297                                 $urlParts = parse_url($url);
298                                 $faviconURL = $urlParts['scheme'].'://'.$urlParts['host'].'/favicon.ico';
299                         }
300                 }
301
302                 // Run a test to see if what we have attempted to get actually exists.
303                 if(USE_CURL_FOR_ICONS || url_validate($faviconURL)) {
304                         return $faviconURL;
305                 } else {
306                         return false;
307                 }
308         }
309
310         function url_validate($link) {
311                 
312                 $url_parts = @parse_url($link);
313
314                 if ( empty( $url_parts["host"] ) )
315                                 return false;
316
317                 if ( !empty( $url_parts["path"] ) ) {
318                                 $documentpath = $url_parts["path"];
319                 } else {
320                                 $documentpath = "/";
321                 }
322
323                 if ( !empty( $url_parts["query"] ) )
324                                 $documentpath .= "?" . $url_parts["query"];
325
326                 $host = $url_parts["host"];
327                 $port = $url_parts["port"];
328                 
329                 if ( empty($port) )
330                                 $port = "80";
331
332                 $socket = @fsockopen( $host, $port, $errno, $errstr, 30 );
333                 
334                 if ( !$socket )
335                                 return false;
336                                 
337                 fwrite ($socket, "HEAD ".$documentpath." HTTP/1.0\r\nHost: $host\r\n\r\n");
338
339                 $http_response = fgets( $socket, 22 );
340
341                 $responses = "/(200 OK)|(30[0-9] Moved)/";
342                 if ( preg_match($responses, $http_response) ) {
343                                 fclose($socket);
344                                 return true;
345                 } else {
346                                 return false;
347                 }
348
349         } 
350
351         function check_feed_favicon($site_url, $feed, $link) {
352                 $favicon_url = get_favicon_url($site_url);
353
354 #               print "FAVICON [$site_url]: $favicon_url\n";
355
356                 error_reporting(0);
357
358                 $icon_file = ICONS_DIR . "/$feed.ico";
359
360                 if ($favicon_url && !file_exists($icon_file)) {
361                         $contents = fetch_file_contents($favicon_url);
362
363                         $fp = fopen($icon_file, "w");
364
365                         if ($fp) {
366                                 fwrite($fp, $contents);
367                                 fclose($fp);
368                                 chmod($icon_file, 0644);
369                         }
370                 }
371
372                 error_reporting(DEFAULT_ERROR_LEVEL);
373
374         }
375
376         function update_rss_feed($link, $feed_url, $feed, $ignore_daemon = false) {
377
378                 if (DAEMON_REFRESH_ONLY && !$_GET["daemon"] && !$ignore_daemon) {
379                         return;                 
380                 }
381
382                 if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) {
383                         _debug("update_rss_feed: start");
384                 }
385
386                 $result = db_query($link, "SELECT update_interval,auth_login,auth_pass  
387                         FROM ttrss_feeds WHERE id = '$feed'");
388
389                 $auth_login = db_fetch_result($result, 0, "auth_login");
390                 $auth_pass = db_fetch_result($result, 0, "auth_pass");
391
392                 $update_interval = db_fetch_result($result, 0, "update_interval");
393
394                 if ($update_interval < 0) { return; }
395
396                 $feed = db_escape_string($feed);
397
398                 $fetch_url = $feed_url;
399
400                 if ($auth_login && $auth_pass) {
401                         $url_parts = array();
402                         preg_match("/(^[^:]*):\/\/(.*)/", $fetch_url, $url_parts);
403
404                         if ($url_parts[1] && $url_parts[2]) {
405                                 $fetch_url = $url_parts[1] . "://$auth_login:$auth_pass@" . $url_parts[2];
406                         }
407
408                 }
409
410                 if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) {
411                         _debug("update_rss_feed: fetching...");
412                 }
413
414                 if (!defined('DAEMON_EXTENDED_DEBUG')) {
415                         error_reporting(0);
416                 }
417
418                 $rss = fetch_rss($fetch_url);
419
420                 if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) {
421                         _debug("update_rss_feed: fetch done, parsing...");
422                 } else {
423                         error_reporting (DEFAULT_ERROR_LEVEL);
424                 }
425
426                 $feed = db_escape_string($feed);
427
428                 if ($rss) {
429
430                         if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) {
431                                 _debug("update_rss_feed: processing feed data...");
432                         }
433
434 //                      db_query($link, "BEGIN");
435
436                         $result = db_query($link, "SELECT title,icon_url,site_url,owner_uid
437                                 FROM ttrss_feeds WHERE id = '$feed'");
438
439                         $registered_title = db_fetch_result($result, 0, "title");
440                         $orig_icon_url = db_fetch_result($result, 0, "icon_url");
441                         $orig_site_url = db_fetch_result($result, 0, "site_url");
442
443                         $owner_uid = db_fetch_result($result, 0, "owner_uid");
444
445                         if (get_pref($link, 'ENABLE_FEED_ICONS', $owner_uid, false)) {  
446                                 if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) {
447                                         _debug("update_rss_feed: checking favicon...");
448                                 }
449                                 check_feed_favicon($rss->channel["link"], $feed, $link);
450                         }
451
452                         if (!$registered_title || $registered_title == "[Unknown]") {
453
454                                 $feed_title = db_escape_string($rss->channel["title"]);
455
456                                 if (defined('DAEMON_EXTENDED_DEBUG') || $_GET['xdebug']) {
457                                         _debug("update_rss_feed: registering title: $feed_title");
458                                 }
459                                 
460                                 db_query($link, "UPDATE ttrss_feeds SET 
461                                         title = '$feed_title' WHERE id = '$feed'");
462                         }
463
464                         $site_url = $rss->channel["link"];
465                         // weird, weird Magpie
466                         if (!$site_url) $site_url = db_escape_string($rss->channel["link_"]);
467
468                         if ($site_url && $orig_site_url != db_escape_string($site_url)) {
469                                 db_query($link, "UPDATE ttrss_feeds SET 
470                                         site_url = '$site_url' WHERE id = '$feed'");
471                         }
472
473 //                      print "I: " . $rss->channel["image"]["url"];
474
475                         $icon_url = $rss->image["url"];
476
477                         if ($icon_url && !$orig_icon_url != db_escape_string($icon_url)) {
478                                 $icon_url = db_escape_string($icon_url);
479                                 db_query($link, "UPDATE ttrss_feeds SET icon_url = '$icon_url' WHERE id = '$feed'");
480                         }
481
482                         if (defined('DAEMON_EXTENDED_DEBUG' || $_GET['xdebug'])) {
483                                 _debug("update_rss_feed: loading filters...");
484                         }
485
486                         $filters = array();
487
488                         $result = db_query($link, "SELECT reg_exp,
489                                 ttrss_filter_types.name AS name,
490                                 ttrss_filter_actions.name AS action,
491                                 inverse,
492                                 action_param
493                                 FROM ttrss_filters,ttrss_filter_types,ttrss_filter_actions WHERE                                        
494                                         enabled = true AND
495                                         owner_uid = $owner_uid AND
496                                         ttrss_filter_types.id = filter_type AND
497                                         ttrss_filter_actions.id = action_id AND
498                                 (feed_id IS NULL OR feed_id = '$feed') ORDER BY reg_exp");
499
500                         while ($line = db_fetch_assoc($result)) {
501                                 if (!$filters[$line["name"]]) $filters[$line["name"]] = array();
502
503                                 $filter["reg_exp"] = $line["reg_exp"];
504                                 $filter["action"] = $line["action"];
505                                 $filter["action_param"] = $line["action_param"];
506                                 $filter["inverse"] = sql_bool_to_bool($line["inverse"]);
507                         
508                                 array_push($filters[$line["name"]], $filter);
509                         }
510
511                         $iterator = $rss->items;
512
513                         if (!$iterator || !is_array($iterator)) $iterator = $rss->entries;
514                         if (!$iterator || !is_array($iterator)) $iterator = $rss;
515
516                         if (!is_array($iterator)) {
517                                 /* db_query($link, "UPDATE ttrss_feeds 
518                                         SET last_error = 'Parse error: can\'t find any articles.'
519                                         WHERE id = '$feed'"); */
520
521                                 // clear any errors and mark feed as updated if fetched okay
522                                 // even if it's blank
523
524                                 if (defined('DAEMON_EXTENDED_DEBUG')) {
525                                         _debug("update_rss_feed: entry iterator is not an array, no articles?");
526                                 }
527
528                                 db_query($link, "UPDATE ttrss_feeds 
529                                         SET last_updated = NOW(), last_error = '' WHERE id = '$feed'");
530
531                                 return; // no articles
532                         }
533
534                         if (defined('DAEMON_EXTENDED_DEBUG')) {
535                                 _debug("update_rss_feed: processing articles...");
536                         }
537
538                         foreach ($iterator as $item) {
539
540                                 $entry_guid = $item["id"];
541
542                                 if (!$entry_guid) $entry_guid = $item["guid"];
543                                 if (!$entry_guid) $entry_guid = $item["link"];
544                                 if (!$entry_guid) $entry_guid = make_guid_from_title($item["title"]);
545
546                                 if (defined('DAEMON_EXTENDED_DEBUG')) {
547                                         _debug("update_rss_feed: guid $entry_guid");
548                                 }
549
550                                 if (!$entry_guid) continue;
551
552                                 $entry_timestamp = "";
553
554                                 $rss_2_date = $item['pubdate'];
555                                 $rss_1_date = $item['dc']['date'];
556                                 $atom_date = $item['issued'];
557                                 if (!$atom_date) $atom_date = $item['updated'];
558                         
559                                 if ($atom_date != "") $entry_timestamp = parse_w3cdtf($atom_date);
560                                 if ($rss_1_date != "") $entry_timestamp = parse_w3cdtf($rss_1_date);
561                                 if ($rss_2_date != "") $entry_timestamp = strtotime($rss_2_date);
562                                 
563                                 if ($entry_timestamp == "" || $entry_timestamp == -1 || !$entry_timestamp) {
564                                         $entry_timestamp = time();
565                                         $no_orig_date = 'true';
566                                 } else {
567                                         $no_orig_date = 'false';
568                                 }
569
570                                 $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
571
572                                 $entry_title = trim(strip_tags($item["title"]));
573
574                                 // strange Magpie workaround
575                                 $entry_link = $item["link_"];
576                                 if (!$entry_link) $entry_link = $item["link"];
577
578                                 if (!$entry_title) continue;
579 #                                       if (!$entry_link) continue;
580
581                                 $entry_link = strip_tags($entry_link);
582
583                                 $entry_content = $item["content:escaped"];
584
585                                 if (!$entry_content) $entry_content = $item["content:encoded"];
586                                 if (!$entry_content) $entry_content = $item["content"];
587                                 if (!$entry_content) $entry_content = $item["atom_content"];
588                                 if (!$entry_content) $entry_content = $item["summary"];
589                                 if (!$entry_content) $entry_content = $item["description"];
590
591 //                              if (!$entry_content) continue;
592
593                                 // WTF
594                                 if (is_array($entry_content)) {
595                                         $entry_content = $entry_content["encoded"];
596                                         if (!$entry_content) $entry_content = $entry_content["escaped"];
597                                 }
598
599 //                              print_r($item);
600 //                              print_r(htmlspecialchars($entry_content));
601 //                              print "<br>";
602
603                                 $entry_content_unescaped = $entry_content;
604
605                                 $entry_comments = strip_tags($item["comments"]);
606
607                                 $entry_author = db_escape_string(strip_tags($item['dc']['creator']));
608
609                                 if ($item['author']) {
610
611                                         if (is_array($item['author'])) {
612
613                                                 if (!$entry_author) {
614                                                         $entry_author = db_escape_string(strip_tags($item['author']['name']));
615                                                 }
616
617                                                 if (!$entry_author) {
618                                                         $entry_author = db_escape_string(strip_tags($item['author']['email']));
619                                                 }
620                                         }
621
622                                         if (!$entry_author) {
623                                                 $entry_author = db_escape_string(strip_tags($item['author']));
624                                         }
625                                 }
626
627                                 if (preg_match('/^[\t\n\r ]*$/', $entry_author)) $entry_author = '';
628
629                                 $entry_guid = db_escape_string(strip_tags($entry_guid));
630
631                                 $result = db_query($link, "SELECT id FROM       ttrss_entries 
632                                         WHERE guid = '$entry_guid'");
633
634                                 $entry_content = db_escape_string($entry_content);
635
636                                 $content_hash = "SHA1:" . sha1(strip_tags($entry_content));
637
638                                 $entry_title = db_escape_string($entry_title);
639                                 $entry_link = db_escape_string($entry_link);
640                                 $entry_comments = mb_substr(db_escape_string($entry_comments), 0, 250);
641                                 $entry_author = mb_substr($entry_author, 0, 250);
642
643                                 $num_comments = db_escape_string($item["slash"]["comments"]);
644
645                                 if (!$num_comments) $num_comments = 0;
646
647                                 // parse <category> entries into tags
648
649                                 $t_ctr = $item['category#'];
650
651                                 $additional_tags = false;
652
653                                 if ($t_ctr == 0) {
654                                         $additional_tags = false;
655                                 } else if ($t_ctr == 1) {
656                                         $additional_tags = array($item['category']);
657                                 } else {
658                                         $additional_tags = array();
659                                         for ($i = 0; $i <= $t_ctr; $i++ ) {
660                                                 if ($item["category#$i"]) {
661                                                         array_push($additional_tags, $item["category#$i"]);
662                                                 }
663                                         }
664                                 }
665
666                                 // parse <dc:subject> elements
667
668                                 $t_ctr = $item['dc']['subject#'];
669
670                                 if ($t_ctr == 1) {
671                                         $additional_tags = array($item['dc']['subject']);
672                                 } else if ($t_ctr > 1) {
673                                         $additional_tags = array();
674                                         for ($i = 0; $i <= $t_ctr; $i++ ) {
675                                                 if ($item['dc']["subject#$i"]) {
676                                                         array_push($additional_tags, $item['dc']["subject#$i"]);
677                                                 }
678                                         }
679                                 }
680
681                                 # sanitize content
682                                 
683 //                              $entry_content = sanitize_rss($entry_content);
684
685                                 if (defined('DAEMON_EXTENDED_DEBUG')) {
686                                         _debug("update_rss_feed: done collecting data [TITLE:$entry_title]");
687                                 }
688
689                                 db_query($link, "BEGIN");
690
691                                 if (db_num_rows($result) == 0) {
692
693                                         if (defined('DAEMON_EXTENDED_DEBUG')) {
694                                                 _debug("update_rss_feed: base guid not found");
695                                         }
696
697                                         // base post entry does not exist, create it
698
699                                         $result = db_query($link,
700                                                 "INSERT INTO ttrss_entries 
701                                                         (title,
702                                                         guid,
703                                                         link,
704                                                         updated,
705                                                         content,
706                                                         content_hash,
707                                                         no_orig_date,
708                                                         date_entered,
709                                                         comments,
710                                                         num_comments,
711                                                         author)
712                                                 VALUES
713                                                         ('$entry_title', 
714                                                         '$entry_guid', 
715                                                         '$entry_link',
716                                                         '$entry_timestamp_fmt', 
717                                                         '$entry_content', 
718                                                         '$content_hash',
719                                                         $no_orig_date, 
720                                                         NOW(), 
721                                                         '$entry_comments',
722                                                         '$num_comments',
723                                                         '$entry_author')");
724                                 } else {
725                                         // we keep encountering the entry in feeds, so we need to
726                                         // update date_entered column so that we don't get horrible
727                                         // dupes when the entry gets purged and reinserted again e.g.
728                                         // in the case of SLOW SLOW OMG SLOW updating feeds
729
730                                         $base_entry_id = db_fetch_result($result, 0, "id");
731
732                                         db_query($link, "UPDATE ttrss_entries SET date_entered = NOW()
733                                                 WHERE id = '$base_entry_id'");
734                                 }
735
736                                 // now it should exist, if not - bad luck then
737
738                                 $result = db_query($link, "SELECT 
739                                                 id,content_hash,no_orig_date,title,
740                                                 substring(date_entered,1,19) as date_entered,
741                                                 substring(updated,1,19) as updated,
742                                                 num_comments
743                                         FROM 
744                                                 ttrss_entries 
745                                         WHERE guid = '$entry_guid'");
746
747                                 if (db_num_rows($result) == 1) {
748
749                                         if (defined('DAEMON_EXTENDED_DEBUG')) {
750                                                 _debug("update_rss_feed: base guid found, checking for user record");
751                                         }
752
753                                         // this will be used below in update handler
754                                         $orig_content_hash = db_fetch_result($result, 0, "content_hash");
755                                         $orig_title = db_fetch_result($result, 0, "title");
756                                         $orig_num_comments = db_fetch_result($result, 0, "num_comments");
757                                         $orig_date_entered = strtotime(db_fetch_result($result, 
758                                                 0, "date_entered"));
759
760                                         $ref_id = db_fetch_result($result, 0, "id");
761
762                                         // check for user post link to main table
763
764                                         // do we allow duplicate posts with same GUID in different feeds?
765                                         if (get_pref($link, "ALLOW_DUPLICATE_POSTS", $owner_uid, false)) {
766                                                 $dupcheck_qpart = "AND feed_id = '$feed'";
767                                         } else { 
768                                                 $dupcheck_qpart = "";
769                                         }
770
771 //                                      error_reporting(0);
772
773                                         $article_filters = get_article_filters($filters, $entry_title, 
774                                                         $entry_content, $entry_link);
775
776                                         if (defined('DAEMON_EXTENDED_DEBUG')) {
777                                                 _debug("update_rss_feed: article filters: ");
778                                                 if (count($article_filters) != 0) {
779                                                         print_r($article_filters);
780                                                 }
781                                         }
782
783                                         if (find_article_filter($article_filters, "filter")) {
784                                                 continue;
785                                         }
786
787 //                                      error_reporting (DEFAULT_ERROR_LEVEL);
788
789                                         $result = db_query($link,
790                                                 "SELECT ref_id FROM ttrss_user_entries WHERE
791                                                         ref_id = '$ref_id' AND owner_uid = '$owner_uid'
792                                                         $dupcheck_qpart");
793
794                                         // okay it doesn't exist - create user entry
795                                         if (db_num_rows($result) == 0) {
796
797                                                 if (defined('DAEMON_EXTENDED_DEBUG')) {
798                                                         _debug("update_rss_feed: user record not found, creating...");
799                                                 }
800
801                                                 if (!find_article_filter($article_filters, 'catchup')) {
802                                                         $unread = 'true';
803                                                         $last_read_qpart = 'NULL';
804                                                 } else {
805                                                         $unread = 'false';
806                                                         $last_read_qpart = 'NOW()';
807                                                 }                                               
808
809                                                 if (find_article_filter($article_filters, 'mark')) {
810                                                         $marked = 'true';
811                                                 } else {
812                                                         $marked = 'false';
813                                                 }
814                                                 
815                                                 $result = db_query($link,
816                                                         "INSERT INTO ttrss_user_entries 
817                                                                 (ref_id, owner_uid, feed_id, unread, last_read, marked) 
818                                                         VALUES ('$ref_id', '$owner_uid', '$feed', $unread,
819                                                                 $last_read_qpart, $marked)");
820                                         }
821                                         
822                                         $post_needs_update = false;
823
824                                         if (get_pref($link, "UPDATE_POST_ON_CHECKSUM_CHANGE", $owner_uid, false) &&
825                                                 ($content_hash != $orig_content_hash)) {
826 //                                              print "<!-- [$entry_title] $content_hash vs $orig_content_hash -->";
827                                                 $post_needs_update = true;
828                                         }
829
830                                         if (db_escape_string($orig_title) != $entry_title) {
831                                                 $post_needs_update = true;
832                                         }
833
834                                         if ($orig_num_comments != $num_comments) {
835                                                 $post_needs_update = true;
836                                         }
837
838 //                                      this doesn't seem to be very reliable
839 //
840 //                                      if ($orig_timestamp != $entry_timestamp && !$orig_no_orig_date) {
841 //                                              $post_needs_update = true;
842 //                                      }
843
844                                         // if post needs update, update it and mark all user entries 
845                                         // linking to this post as updated                                      
846                                         if ($post_needs_update) {
847
848                                                 if (defined('DAEMON_EXTENDED_DEBUG')) {
849                                                         _debug("update_rss_feed: post $entry_guid needs update...");
850                                                 }
851
852 //                                              print "<!-- post $orig_title needs update : $post_needs_update -->";
853
854                                                 db_query($link, "UPDATE ttrss_entries 
855                                                         SET title = '$entry_title', content = '$entry_content',
856                                                                 content_hash = '$content_hash',
857                                                                 num_comments = '$num_comments'
858                                                         WHERE id = '$ref_id'");
859
860                                                 if (get_pref($link, "MARK_UNREAD_ON_UPDATE", $owner_uid, false)) {
861                                                         db_query($link, "UPDATE ttrss_user_entries 
862                                                                 SET last_read = null, unread = true WHERE ref_id = '$ref_id'");
863                                                 } else {
864                                                         db_query($link, "UPDATE ttrss_user_entries 
865                                                                 SET last_read = null WHERE ref_id = '$ref_id' AND unread = false");
866                                                 }
867
868                                         }
869                                 }
870
871                                 db_query($link, "COMMIT");
872
873                                 if (defined('DAEMON_EXTENDED_DEBUG')) {
874                                         _debug("update_rss_feed: looking for tags...");
875                                 }
876
877                                 /* taaaags */
878                                 // <a href="..." rel="tag">Xorg</a>, //
879
880                                 $entry_tags = null;
881
882                                 preg_match_all("/<a.*?rel=['\"]tag['\"].*?>([^<]+)<\/a>/i", 
883                                         $entry_content_unescaped, $entry_tags);
884
885 /*                              print "<p><br/>$entry_title : $entry_content_unescaped<br>";
886                                 print_r($entry_tags);
887                                 print "<br/></p>"; */
888
889                                 $entry_tags = $entry_tags[1];
890
891                                 # check for manual tags
892
893                                 $tag_filter = find_article_filter($article_filters, "tag"); 
894
895                                 if ($tag_filter) {
896
897                                         $manual_tags = trim_array(split(",", $tag_filter[1]));
898
899                                         foreach ($manual_tags as $tag) {
900                                                 if (tag_is_valid($tag)) {
901                                                         array_push($entry_tags, $tag);
902                                                 }
903                                         }
904                                 }
905
906                                 $boring_tags = trim_array(split(",", mb_strtolower(get_pref($link, 
907                                         'BLACKLISTED_TAGS', $owner_uid, ''), 'utf-8')));
908
909                                 if ($additional_tags && is_array($additional_tags)) {
910                                         foreach ($additional_tags as $tag) {
911                                                 if (tag_is_valid($tag) && 
912                                                                 array_search($tag, $boring_tags) === FALSE) {
913                                                         array_push($entry_tags, $tag);
914                                                 }
915                                         }
916                                 } 
917
918 //                              print "<p>TAGS: "; print_r($entry_tags); print "</p>";
919
920                                 if (count($entry_tags) > 0) {
921                                 
922                                         db_query($link, "BEGIN");
923                         
924                                         $result = db_query($link, "SELECT id,int_id 
925                                                 FROM ttrss_entries,ttrss_user_entries 
926                                                 WHERE guid = '$entry_guid' 
927                                                 AND feed_id = '$feed' AND ref_id = id
928                                                 AND owner_uid = '$owner_uid'");
929
930                                         if (db_num_rows($result) == 1) {
931
932                                                 $entry_id = db_fetch_result($result, 0, "id");
933                                                 $entry_int_id = db_fetch_result($result, 0, "int_id");
934                                                 
935                                                 foreach ($entry_tags as $tag) {
936
937                                                         $tag = sanitize_tag($tag);
938                                                         $tag = db_escape_string($tag);
939
940                                                         if (!tag_is_valid($tag)) continue;
941                                                         
942                                                         $result = db_query($link, "SELECT id FROM ttrss_tags            
943                                                                 WHERE tag_name = '$tag' AND post_int_id = '$entry_int_id' AND 
944                                                                 owner_uid = '$owner_uid' LIMIT 1");
945         
946         //                                              print db_fetch_result($result, 0, "id");
947         
948                                                         if ($result && db_num_rows($result) == 0) {
949                                                                 
950                                                                 db_query($link, "INSERT INTO ttrss_tags 
951                                                                         (owner_uid,tag_name,post_int_id)
952                                                                         VALUES ('$owner_uid','$tag', '$entry_int_id')");
953                                                         }                                                       
954                                                 }
955                                         }
956                                         db_query($link, "COMMIT");
957                                 } 
958                         } 
959
960                         db_query($link, "UPDATE ttrss_feeds 
961                                 SET last_updated = NOW(), last_error = '' WHERE id = '$feed'");
962
963 //                      db_query($link, "COMMIT");
964
965                 } else {
966                         $error_msg = db_escape_string(magpie_error());
967                         db_query($link, 
968                                 "UPDATE ttrss_feeds SET last_error = '$error_msg', 
969                                         last_updated = NOW() WHERE id = '$feed'");
970                 }
971
972                 if (defined('DAEMON_EXTENDED_DEBUG')) {
973                         _debug("update_rss_feed: done");
974                 }
975
976         }
977
978         function print_select($id, $default, $values, $attributes = "") {
979                 print "<select name=\"$id\" id=\"$id\" $attributes>";
980                 foreach ($values as $v) {
981                         if ($v == $default)
982                                 $sel = " selected";
983                          else
984                                 $sel = "";
985                         
986                         print "<option$sel>$v</option>";
987                 }
988                 print "</select>";
989         }
990
991         function print_select_hash($id, $default, $values, $attributes = "") {
992                 print "<select name=\"$id\" id='$id' $attributes>";
993                 foreach (array_keys($values) as $v) {
994                         if ($v == $default)
995                                 $sel = "selected";
996                          else
997                                 $sel = "";
998                         
999                         print "<option $sel value=\"$v\">".$values[$v]."</option>";
1000                 }
1001
1002                 print "</select>";
1003         }
1004
1005         function get_article_filters($filters, $title, $content, $link) {
1006                 $matches = array();
1007
1008                 if ($filters["title"]) {
1009                         foreach ($filters["title"] as $filter) {
1010                                 $reg_exp = $filter["reg_exp"];          
1011                                 $inverse = $filter["inverse"];  
1012                                 if ((!$inverse && preg_match("/$reg_exp/i", $title)) || 
1013                                                 ($inverse && !preg_match("/$reg_exp/i", $title))) {
1014
1015                                         array_push($matches, array($filter["action"], $filter["action_param"]));
1016                                 }
1017                         }
1018                 }
1019
1020                 if ($filters["content"]) {
1021                         foreach ($filters["content"] as $filter) {
1022                                 $reg_exp = $filter["reg_exp"];
1023                                 $inverse = $filter["inverse"];
1024
1025                                 if ((!$inverse && preg_match("/$reg_exp/i", $content)) || 
1026                                                 ($inverse && !preg_match("/$reg_exp/i", $content))) {
1027
1028                                         array_push($matches, array($filter["action"], $filter["action_param"]));
1029                                 }               
1030                         }
1031                 }
1032
1033                 if ($filters["both"]) {
1034                         foreach ($filters["both"] as $filter) {                 
1035                                 $reg_exp = $filter["reg_exp"];          
1036                                 $inverse = $filter["inverse"];
1037
1038                                 if ($inverse) {
1039                                         if (!preg_match("/$reg_exp/i", $title) || !preg_match("/$reg_exp/i", $content)) {
1040                                                 array_push($matches, array($filter["action"], $filter["action_param"]));
1041                                         }
1042                                 } else {
1043                                         if (preg_match("/$reg_exp/i", $title) || preg_match("/$reg_exp/i", $content)) {
1044                                                 array_push($matches, array($filter["action"], $filter["action_param"]));
1045                                         }
1046                                 }
1047                         }
1048                 }
1049
1050                 if ($filters["link"]) {
1051                         $reg_exp = $filter["reg_exp"];
1052                         foreach ($filters["link"] as $filter) {
1053                                 $reg_exp = $filter["reg_exp"];
1054                                 $inverse = $filter["inverse"];
1055
1056                                 if ((!$inverse && preg_match("/$reg_exp/i", $link)) || 
1057                                                 ($inverse && !preg_match("/$reg_exp/i", $link))) {
1058                                                 
1059                                         array_push($matches, array($filter["action"], $filter["action_param"]));
1060                                 }
1061                         }
1062                 }
1063
1064                 return $matches;
1065         }
1066
1067         function find_article_filter($filters, $filter_name) {
1068                 foreach ($filters as $f) {
1069                         if ($f[0] == $filter_name) {
1070                                 return $f;
1071                         };
1072                 }
1073                 return false;
1074         }
1075
1076         function printFeedEntry($feed_id, $class, $feed_title, $unread, $icon_file, $link,
1077                 $rtl_content = false, $last_updated = false, $last_error = false) {
1078
1079                 if (file_exists($icon_file) && filesize($icon_file) > 0) {
1080                                 $feed_icon = "<img id=\"FIMG-$feed_id\" src=\"$icon_file\">";
1081                 } else {
1082                         $feed_icon = "<img id=\"FIMG-$feed_id\" src=\"images/blank_icon.gif\">";
1083                 }
1084
1085                 if ($rtl_content) {
1086                         $rtl_tag = "dir=\"rtl\"";
1087                 } else {
1088                         $rtl_tag = "dir=\"ltr\"";
1089                 }
1090
1091                 $error_notify_msg = "";
1092                 
1093                 if ($last_error) {
1094                         $link_title = "Error: $last_error ($last_updated)";
1095                         $error_notify_msg = "(Error)";
1096                 } else if ($last_updated) {
1097                         $link_title = "Updated: $last_updated";
1098                 }
1099
1100                 $feed = "<a title=\"$link_title\" id=\"FEEDL-$feed_id\" 
1101                         href=\"javascript:viewfeed('$feed_id', '', false, '', false, 0);\">$feed_title</a>";
1102
1103                 print "<li id=\"FEEDR-$feed_id\" class=\"$class\">";
1104                 if (get_pref($link, 'ENABLE_FEED_ICONS')) {
1105                         print "$feed_icon";
1106                 }
1107
1108                 print "<span $rtl_tag id=\"FEEDN-$feed_id\">$feed</span>";
1109
1110                 if ($unread != 0) {
1111                         $fctr_class = "";
1112                 } else {
1113                         $fctr_class = "class=\"invisible\"";
1114                 }
1115
1116                 print " <span $rtl_tag $fctr_class id=\"FEEDCTR-$feed_id\">
1117                          (<span id=\"FEEDU-$feed_id\">$unread</span>)</span>";
1118
1119                 if (get_pref($link, "EXTENDED_FEEDLIST")) {                      
1120                         print "<div class=\"feedExtInfo\">
1121                                 <span id=\"FLUPD-$feed_id\">$last_updated $error_notify_msg</span></div>";
1122                 }
1123                          
1124                 print "</li>";
1125
1126         }
1127
1128         function getmicrotime() {
1129                 list($usec, $sec) = explode(" ",microtime());
1130                 return ((float)$usec + (float)$sec);
1131         }
1132
1133         function print_radio($id, $default, $values, $attributes = "") {
1134                 foreach ($values as $v) {
1135                 
1136                         if ($v == $default)
1137                                 $sel = "checked";
1138                          else
1139                                 $sel = "";
1140
1141                         if ($v == "Yes") {
1142                                 $sel .= " value=\"1\"";
1143                         } else {
1144                                 $sel .= " value=\"0\"";
1145                         }
1146                         
1147                         print "<input class=\"noborder\" 
1148                                 type=\"radio\" $sel $attributes name=\"$id\">&nbsp;$v&nbsp;";
1149
1150                 }
1151         }
1152
1153         function initialize_user_prefs($link, $uid) {
1154
1155                 $uid = db_escape_string($uid);
1156
1157                 db_query($link, "BEGIN");
1158
1159                 $result = db_query($link, "SELECT pref_name,def_value FROM ttrss_prefs");
1160                 
1161                 $u_result = db_query($link, "SELECT pref_name 
1162                         FROM ttrss_user_prefs WHERE owner_uid = '$uid'");
1163
1164                 $active_prefs = array();
1165
1166                 while ($line = db_fetch_assoc($u_result)) {
1167                         array_push($active_prefs, $line["pref_name"]);                  
1168                 }
1169
1170                 while ($line = db_fetch_assoc($result)) {
1171                         if (array_search($line["pref_name"], $active_prefs) === FALSE) {
1172 //                              print "adding " . $line["pref_name"] . "<br>";
1173
1174                                 db_query($link, "INSERT INTO ttrss_user_prefs
1175                                         (owner_uid,pref_name,value) VALUES 
1176                                         ('$uid', '".$line["pref_name"]."','".$line["def_value"]."')");
1177
1178                         }
1179                 }
1180
1181                 db_query($link, "COMMIT");
1182
1183         }
1184
1185         function lookup_user_id($link, $user) {
1186
1187                 $result = db_query($link, "SELECT id FROM ttrss_users WHERE 
1188                         login = '$login'");
1189
1190                 if (db_num_rows($result) == 1) {
1191                         return db_fetch_result($result, 0, "id");
1192                 } else {
1193                         return false;
1194                 }
1195         }
1196
1197         function http_authenticate_user($link) {
1198
1199                 error_log("http_authenticate_user: ".$_SERVER["PHP_AUTH_USER"]."\n", 3, '/tmp/tt-rss.log');
1200
1201                 if (!$_SERVER["PHP_AUTH_USER"]) {
1202
1203                         header('WWW-Authenticate: Basic realm="Tiny Tiny RSS RSSGen"');
1204                         header('HTTP/1.0 401 Unauthorized');
1205                         exit;
1206                                         
1207                 } else {
1208                         $auth_result = authenticate_user($link, 
1209                                 $_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);
1210
1211                         if (!$auth_result) {
1212                                 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS RSSGen"');
1213                                 header('HTTP/1.0 401 Unauthorized');
1214                                 exit;
1215                         }
1216                 }
1217
1218                 return true;
1219         }
1220
1221         function authenticate_user($link, $login, $password, $force_auth = false) {
1222
1223                 if (!SINGLE_USER_MODE) {
1224
1225                         $pwd_hash = 'SHA1:' . sha1($password);
1226
1227                         if ($force_auth && defined('_DEBUG_USER_SWITCH')) {
1228                                 $query = "SELECT id,login,access_level
1229                     FROM ttrss_users WHERE
1230                          login = '$login'";
1231                         } else {
1232                                 $query = "SELECT id,login,access_level
1233                     FROM ttrss_users WHERE
1234                          login = '$login' AND pwd_hash = '$pwd_hash'";
1235                         }
1236
1237                         $result = db_query($link, $query);
1238         
1239                         if (db_num_rows($result) == 1) {
1240                                 $_SESSION["uid"] = db_fetch_result($result, 0, "id");
1241                                 $_SESSION["name"] = db_fetch_result($result, 0, "login");
1242                                 $_SESSION["access_level"] = db_fetch_result($result, 0, "access_level");
1243         
1244                                 db_query($link, "UPDATE ttrss_users SET last_login = NOW() WHERE id = " . 
1245                                         $_SESSION["uid"]);
1246         
1247                                 $user_theme = get_user_theme_path($link);
1248         
1249                                 $_SESSION["theme"] = $user_theme;
1250                                 $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"];
1251         
1252                                 initialize_user_prefs($link, $_SESSION["uid"]);
1253         
1254                                 return true;
1255                         }
1256         
1257                         return false;
1258
1259                 } else {
1260
1261                         $_SESSION["uid"] = 1;
1262                         $_SESSION["name"] = "admin";
1263
1264                         $user_theme = get_user_theme_path($link);
1265         
1266                         $_SESSION["theme"] = $user_theme;
1267                         $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"];
1268         
1269                         initialize_user_prefs($link, $_SESSION["uid"]);
1270         
1271                         return true;
1272                 }
1273         }
1274
1275         function make_password($length = 8) {
1276
1277                 $password = "";
1278                 $possible = "0123456789abcdfghjkmnpqrstvwxyzABCDFGHJKMNPQRSTVWXYZ"; 
1279                 
1280         $i = 0; 
1281     
1282                 while ($i < $length) { 
1283                         $char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
1284         
1285                         if (!strstr($password, $char)) { 
1286                                 $password .= $char;
1287                                 $i++;
1288                         }
1289                 }
1290                 return $password;
1291         }
1292
1293         // this is called after user is created to initialize default feeds, labels
1294         // or whatever else
1295         
1296         // user preferences are checked on every login, not here
1297
1298         function initialize_user($link, $uid) {
1299
1300                 db_query($link, "insert into ttrss_labels (owner_uid,sql_exp,description) 
1301                         values ('$uid','unread = true', 'Unread articles')");
1302
1303                 db_query($link, "insert into ttrss_labels (owner_uid,sql_exp,description) 
1304                         values ('$uid','last_read is null and unread = false', 'Updated articles')");
1305                 
1306                 db_query($link, "insert into ttrss_feeds (owner_uid,title,feed_url)
1307                         values ('$uid', 'Tiny Tiny RSS: New Releases',
1308                         'http://tt-rss.spb.ru/releases.rss')");
1309
1310                 db_query($link, "insert into ttrss_feeds (owner_uid,title,feed_url)
1311                         values ('$uid', 'Tiny Tiny RSS: Forum',
1312                         'http://tt-rss.spb.ru/forum/rss.php')");
1313         }
1314
1315         function logout_user() {
1316                 session_destroy();
1317                 if (isset($_COOKIE[session_name()])) {
1318                    setcookie(session_name(), '', time()-42000, '/');
1319                 }
1320         }
1321
1322         function get_script_urlpath() {
1323                 return preg_replace('/\/[^\/]*$/', "", $_SERVER["REQUEST_URI"]);
1324         }
1325
1326         function validate_session($link) {
1327                 if (SESSION_CHECK_ADDRESS && $_SESSION["uid"]) {
1328                         if ($_SESSION["ip_address"]) {
1329                                 if ($_SESSION["ip_address"] != $_SERVER["REMOTE_ADDR"]) {
1330                                         $_SESSION["login_error_msg"] = "Session failed to validate (incorrect IP)";
1331                                         return false;
1332                                 }
1333                         }
1334                 }
1335
1336 /*              if ($_SESSION["cookie_lifetime"] && $_SESSION["uid"]) {
1337
1338                         //print_r($_SESSION);
1339
1340                         if (time() > $_SESSION["cookie_lifetime"]) {
1341                                 return false;
1342                         }
1343                 } */
1344
1345                 return true;
1346         }
1347
1348         function login_sequence($link, $mobile = false) {
1349                 if (!SINGLE_USER_MODE) {
1350
1351                         if (defined('_DEBUG_USER_SWITCH') && $_SESSION["uid"]) {
1352                                 $swu = db_escape_string($_REQUEST["swu"]);
1353                                 if ($swu) {
1354                                         $_SESSION["prefs_cache"] = false;
1355                                         return authenticate_user($link, $swu, null, true);
1356                                 }
1357                         }
1358
1359                         $login_action = $_POST["login_action"];
1360
1361                         # try to authenticate user if called from login form                    
1362                         if ($login_action == "do_login") {
1363                                 $login = $_POST["login"];
1364                                 $password = $_POST["password"];
1365                                 $remember_me = $_POST["remember_me"];
1366
1367                                 if (authenticate_user($link, $login, $password)) {
1368                                         $_POST["password"] = "";
1369
1370                                         header("Location: " . $_SERVER["REQUEST_URI"]);
1371                                         exit;
1372
1373                                         return;
1374                                 } else {
1375                                         $_SESSION["login_error_msg"] = "Incorrect username or password";
1376                                 }
1377                         }
1378
1379 //                      print session_id();
1380 //                      print_r($_SESSION);
1381
1382                         if (!$_SESSION["uid"] || !validate_session($link)) {
1383                                 render_login_form($link, $mobile);
1384                                 exit;
1385                         } else {
1386                                 /* bump login timestamp */
1387                                 db_query($link, "UPDATE ttrss_users SET last_login = NOW() WHERE id = " . 
1388                                         $_SESSION["uid"]);
1389                         }
1390
1391                 } else {
1392                         return authenticate_user($link, "admin", null);
1393                 }
1394         }
1395
1396         function truncate_string($str, $max_len) {
1397                 if (mb_strlen($str, "utf-8") > $max_len - 3) {
1398                         return mb_substr($str, 0, $max_len, "utf-8") . "...";
1399                 } else {
1400                         return $str;
1401                 }
1402         }
1403
1404         function get_user_theme_path($link) {
1405                 $result = db_query($link, "SELECT theme_path 
1406                         FROM 
1407                                 ttrss_themes,ttrss_users
1408                         WHERE ttrss_themes.id = theme_id AND ttrss_users.id = " . $_SESSION["uid"]);
1409                 if (db_num_rows($result) != 0) {
1410                         return db_fetch_result($result, 0, "theme_path");
1411                 } else {
1412                         return null;
1413                 }
1414         }
1415
1416         function smart_date_time($timestamp) {
1417                 if (date("Y.m.d", $timestamp) == date("Y.m.d")) {
1418                         return date("G:i", $timestamp);
1419                 } else if (date("Y", $timestamp) == date("Y")) {
1420                         return date("M d, G:i", $timestamp);
1421                 } else {
1422                         return date("Y/m/d, G:i", $timestamp);
1423                 }
1424         }
1425
1426         function smart_date($timestamp) {
1427                 if (date("Y.m.d", $timestamp) == date("Y.m.d")) {
1428                         return "Today";
1429                 } else if (date("Y", $timestamp) == date("Y")) {
1430                         return date("D m", $timestamp);
1431                 } else {
1432                         return date("Y/m/d", $timestamp);
1433                 }
1434         }
1435
1436         function sql_bool_to_string($s) {
1437                 if ($s == "t" || $s == "1") {
1438                         return "true";
1439                 } else {
1440                         return "false";
1441                 }
1442         }
1443
1444         function sql_bool_to_bool($s) {
1445                 if ($s == "t" || $s == "1") {
1446                         return true;
1447                 } else {
1448                         return false;
1449                 }
1450         }
1451         
1452
1453         function toggleEvenOdd($a) {
1454                 if ($a == "even") 
1455                         return "odd";
1456                 else
1457                         return "even";
1458         }
1459
1460         function sanity_check($link) {
1461
1462                 error_reporting(0);
1463
1464                 $error_code = 0;
1465                 $result = db_query($link, "SELECT schema_version FROM ttrss_version");
1466                 $schema_version = db_fetch_result($result, 0, "schema_version");
1467
1468                 if ($schema_version != SCHEMA_VERSION) {
1469                         $error_code = 5;
1470                 }
1471
1472                 if (DB_TYPE == "mysql") {
1473                         $result = db_query($link, "SELECT true", false);
1474                         if (db_num_rows($result) != 1) {
1475                                 $error_code = 10;
1476                         }
1477                 }
1478
1479                 error_reporting (DEFAULT_ERROR_LEVEL);
1480
1481                 if ($error_code != 0) {
1482                         print_error_xml($error_code);
1483                         return false;
1484                 } else {
1485                         return true;
1486                 }
1487         }
1488
1489         function file_is_locked($filename) {
1490                 error_reporting(0);
1491                 $fp = fopen($filename, "r");
1492                 error_reporting(DEFAULT_ERROR_LEVEL);
1493                 if ($fp) {
1494                         if (flock($fp, LOCK_EX | LOCK_NB)) {
1495                                 flock($fp, LOCK_UN);
1496                                 fclose($fp);
1497                                 return false;
1498                         }
1499                         fclose($fp);
1500                         return true;
1501                 }
1502                 return false;
1503         }
1504
1505         function make_lockfile($filename) {
1506                 $fp = fopen($filename, "w");
1507
1508                 if (flock($fp, LOCK_EX | LOCK_NB)) {            
1509                         return $fp;
1510                 } else {
1511                         return false;
1512                 }
1513         }
1514
1515         function make_stampfile($filename) {
1516                 $fp = fopen($filename, "w");
1517
1518                 if (flock($fp, LOCK_EX | LOCK_NB)) {
1519                         fwrite($fp, time() . "\n");
1520                         flock($fp, LOCK_UN);
1521                         fclose($fp);
1522                         return true;
1523                 } else {
1524                         return false;
1525                 }
1526         }
1527
1528         function read_stampfile($filename) {
1529
1530                 error_reporting(0);
1531                 $fp = fopen($filename, "r");
1532                 error_reporting (DEFAULT_ERROR_LEVEL);
1533
1534                 if (flock($fp, LOCK_EX)) {
1535                         $stamp = fgets($fp);
1536                         flock($fp, LOCK_UN);
1537                         fclose($fp);
1538                         return $stamp;
1539                 } else {
1540                         return false;
1541                 }
1542         }
1543
1544         function sql_random_function() {
1545                 if (DB_TYPE == "mysql") {
1546                         return "RAND()";
1547                 } else {
1548                         return "RANDOM()";
1549                 }
1550         }
1551
1552         function catchup_feed($link, $feed, $cat_view) {
1553
1554                         if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
1555                         
1556                                 if ($cat_view) {
1557
1558                                         if ($feed > 0) {
1559                                                 $cat_qpart = "cat_id = '$feed'";
1560                                         } else {
1561                                                 $cat_qpart = "cat_id IS NULL";
1562                                         }
1563                                         
1564                                         $tmp_result = db_query($link, "SELECT id 
1565                                                 FROM ttrss_feeds WHERE $cat_qpart AND owner_uid = " . 
1566                                                 $_SESSION["uid"]);
1567
1568                                         while ($tmp_line = db_fetch_assoc($tmp_result)) {
1569
1570                                                 $tmp_feed = $tmp_line["id"];
1571
1572                                                 db_query($link, "UPDATE ttrss_user_entries 
1573                                                         SET unread = false,last_read = NOW() 
1574                                                         WHERE feed_id = '$tmp_feed' AND owner_uid = " . $_SESSION["uid"]);
1575                                         }
1576
1577                                 } else if ($feed > 0) {
1578
1579                                         $tmp_result = db_query($link, "SELECT id 
1580                                                 FROM ttrss_feeds WHERE parent_feed = '$feed'
1581                                                 ORDER BY cat_id,title");
1582
1583                                         $parent_ids = array();
1584
1585                                         if (db_num_rows($tmp_result) > 0) {
1586                                                 while ($p = db_fetch_assoc($tmp_result)) {
1587                                                         array_push($parent_ids, "feed_id = " . $p["id"]);
1588                                                 }
1589
1590                                                 $children_qpart = implode(" OR ", $parent_ids);
1591                                                 
1592                                                 db_query($link, "UPDATE ttrss_user_entries 
1593                                                         SET unread = false,last_read = NOW() 
1594                                                         WHERE (feed_id = '$feed' OR $children_qpart) 
1595                                                         AND owner_uid = " . $_SESSION["uid"]);
1596
1597                                         } else {                                                
1598                                                 db_query($link, "UPDATE ttrss_user_entries 
1599                                                         SET unread = false,last_read = NOW() 
1600                                                         WHERE feed_id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
1601                                         }
1602                                                 
1603                                 } else if ($feed < 0 && $feed > -10) { // special, like starred
1604
1605                                         if ($feed == -1) {
1606                                                 db_query($link, "UPDATE ttrss_user_entries 
1607                                                         SET unread = false,last_read = NOW()
1608                                                         WHERE marked = true AND owner_uid = ".$_SESSION["uid"]);
1609                                         }
1610
1611                                         if ($feed == -2) {
1612                                                 db_query($link, "UPDATE ttrss_user_entries 
1613                                                         SET unread = false,last_read = NOW()
1614                                                         WHERE published = true AND owner_uid = ".$_SESSION["uid"]);
1615                                         }
1616
1617                                 } else if ($feed < -10) { // label
1618
1619                                         // TODO make this more efficient
1620
1621                                         $label_id = -$feed - 11;
1622
1623                                         $tmp_result = db_query($link, "SELECT sql_exp FROM ttrss_labels
1624                                                 WHERE id = '$label_id'");                                       
1625
1626                                         if ($tmp_result) {
1627                                                 $sql_exp = db_fetch_result($tmp_result, 0, "sql_exp");
1628
1629                                                 db_query($link, "BEGIN");
1630
1631                                                 $tmp2_result = db_query($link,
1632                                                         "SELECT 
1633                                                                 int_id 
1634                                                         FROM 
1635                                                                 ttrss_user_entries,ttrss_entries,ttrss_feeds
1636                                                         WHERE
1637                                                                 ref_id = ttrss_entries.id AND 
1638                                                                 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1639                                                                 $sql_exp AND
1640                                                                 ttrss_user_entries.owner_uid = " . $_SESSION["uid"]);
1641
1642                                                 while ($tmp_line = db_fetch_assoc($tmp2_result)) {
1643                                                         db_query($link, "UPDATE 
1644                                                                 ttrss_user_entries 
1645                                                         SET 
1646                                                                 unread = false, last_read = NOW()
1647                                                         WHERE
1648                                                                 int_id = " . $tmp_line["int_id"]);
1649                                                 }
1650                                                                 
1651                                                 db_query($link, "COMMIT");
1652
1653 /*                                              db_query($link, "UPDATE ttrss_user_entries,ttrss_entries 
1654                                                         SET unread = false,last_read = NOW()
1655                                                         WHERE $sql_exp
1656                                                         AND ref_id = id
1657                                                         AND owner_uid = ".$_SESSION["uid"]); */
1658                                         }
1659                                 }
1660                         } else { // tag
1661                                 db_query($link, "BEGIN");
1662
1663                                 $tag_name = db_escape_string($feed);
1664
1665                                 $result = db_query($link, "SELECT post_int_id FROM ttrss_tags
1666                                         WHERE tag_name = '$tag_name' AND owner_uid = " . $_SESSION["uid"]);
1667
1668                                 while ($line = db_fetch_assoc($result)) {
1669                                         db_query($link, "UPDATE ttrss_user_entries SET
1670                                                 unread = false, last_read = NOW() 
1671                                                 WHERE int_id = " . $line["post_int_id"]);
1672                                 }
1673                                 db_query($link, "COMMIT");
1674                         }
1675         }
1676
1677         function update_generic_feed($link, $feed, $cat_view) {
1678                         if ($cat_view) {
1679
1680                                 if ($feed > 0) {
1681                                         $cat_qpart = "cat_id = '$feed'";
1682                                 } else {
1683                                         $cat_qpart = "cat_id IS NULL";
1684                                 }
1685                                 
1686                                 $tmp_result = db_query($link, "SELECT feed_url FROM ttrss_feeds
1687                                         WHERE $cat_qpart AND owner_uid = " . $_SESSION["uid"]);
1688
1689                                 while ($tmp_line = db_fetch_assoc($tmp_result)) {                                       
1690                                         $feed_url = $tmp_line["feed_url"];
1691                                         update_rss_feed($link, $feed_url, $feed, ENABLE_UPDATE_DAEMON);
1692                                 }
1693
1694                         } else {
1695                                 $tmp_result = db_query($link, "SELECT feed_url FROM ttrss_feeds
1696                                         WHERE id = '$feed'");
1697                                 $feed_url = db_fetch_result($tmp_result, 0, "feed_url");                                
1698                                 update_rss_feed($link, $feed_url, $feed, ENABLE_UPDATE_DAEMON);
1699                         }
1700         }
1701
1702         function getAllCounters($link, $omode = "tflc") {
1703 /*              getLabelCounters($link);
1704                 getFeedCounters($link);
1705                 getTagCounters($link);
1706                 getGlobalCounters($link);
1707                 if (get_pref($link, 'ENABLE_FEED_CATS')) {
1708                         getCategoryCounters($link);
1709                 } */
1710
1711                 if (!$omode) $omode = "tflc";
1712
1713                 getGlobalCounters($link);
1714
1715                 if (strchr($omode, "l")) getLabelCounters($link);
1716                 if (strchr($omode, "f")) getFeedCounters($link);
1717                 if (strchr($omode, "t")) getTagCounters($link);
1718                 if (strchr($omode, "c")) {                      
1719                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
1720                                 getCategoryCounters($link);
1721                         }
1722                 }
1723         }       
1724
1725         function getCategoryCounters($link) {
1726                 $result = db_query($link, "SELECT cat_id,SUM((SELECT COUNT(int_id) 
1727                                 FROM ttrss_user_entries WHERE feed_id = ttrss_feeds.id 
1728                                         AND unread = true)) AS unread FROM ttrss_feeds 
1729                         WHERE 
1730                                 hidden = false AND owner_uid = ".$_SESSION["uid"]." GROUP BY cat_id");
1731
1732                 while ($line = db_fetch_assoc($result)) {
1733                         $line["cat_id"] = sprintf("%d", $line["cat_id"]);
1734                         print "<counter type=\"category\" id=\"".$line["cat_id"]."\" counter=\"".
1735                                 $line["unread"]."\"/>";
1736                 }
1737         }
1738
1739         function getCategoryUnread($link, $cat) {
1740
1741                 if ($cat != 0) {
1742                         $cat_query = "cat_id = '$cat'";
1743                 } else {
1744                         $cat_query = "cat_id IS NULL";
1745                 }
1746
1747                 $result = db_query($link, "SELECT id FROM ttrss_feeds WHERE $cat_query 
1748                                 AND hidden = false
1749                                 AND owner_uid = " . $_SESSION["uid"]);
1750
1751                 $cat_feeds = array();
1752                 while ($line = db_fetch_assoc($result)) {
1753                         array_push($cat_feeds, "feed_id = " . $line["id"]);
1754                 }
1755
1756                 if (count($cat_feeds) == 0) return 0;
1757
1758                 $match_part = implode(" OR ", $cat_feeds);
1759
1760                 $result = db_query($link, "SELECT COUNT(int_id) AS unread 
1761                         FROM ttrss_user_entries 
1762                         WHERE   unread = true AND ($match_part) AND owner_uid = " . $_SESSION["uid"]);
1763
1764                 $unread = 0;
1765
1766                 # this needs to be rewritten
1767                 while ($line = db_fetch_assoc($result)) {
1768                         $unread += $line["unread"];
1769                 }
1770
1771                 return $unread;
1772
1773         }
1774
1775         function getFeedUnread($link, $feed, $is_cat = false) {
1776                 $n_feed = sprintf("%d", $feed);
1777
1778                 if ($is_cat) {
1779                         return getCategoryUnread($link, $n_feed);               
1780                 } else if ($n_feed == -1) {
1781                         $match_part = "marked = true";
1782                 } else if ($n_feed == -2) {
1783                         $match_part = "published = true";
1784                 } else if ($n_feed > 0) {
1785
1786                         $result = db_query($link, "SELECT id FROM ttrss_feeds 
1787                                         WHERE parent_feed = '$n_feed'
1788                                         AND hidden = false
1789                                         AND owner_uid = " . $_SESSION["uid"]);
1790
1791                         if (db_num_rows($result) > 0) {
1792
1793                                 $linked_feeds = array();
1794                                 while ($line = db_fetch_assoc($result)) {
1795                                         array_push($linked_feeds, "feed_id = " . $line["id"]);
1796                                 }
1797
1798                                 array_push($linked_feeds, "feed_id = $n_feed");
1799                                 
1800                                 $match_part = implode(" OR ", $linked_feeds);
1801
1802                                 $result = db_query($link, "SELECT COUNT(int_id) AS unread 
1803                                         FROM ttrss_user_entries
1804                                         WHERE   unread = true AND ($match_part) 
1805                                         AND owner_uid = " . $_SESSION["uid"]);
1806
1807                                 $unread = 0;
1808
1809                                 # this needs to be rewritten
1810                                 while ($line = db_fetch_assoc($result)) {
1811                                         $unread += $line["unread"];
1812                                 }
1813
1814                                 return $unread;
1815
1816                         } else {
1817                                 $match_part = "feed_id = '$n_feed'";
1818                         }
1819                 } else if ($feed < -10) {
1820
1821                         $label_id = -$feed - 11;
1822
1823                         $result = db_query($link, "SELECT sql_exp FROM ttrss_labels WHERE
1824                                 id = '$label_id' AND owner_uid = " . $_SESSION["uid"]);
1825
1826                         $match_part = db_fetch_result($result, 0, "sql_exp");
1827                 }
1828
1829                 if ($match_part) {
1830                 
1831                         $result = db_query($link, "SELECT count(int_id) AS unread 
1832                                 FROM ttrss_user_entries,ttrss_feeds,ttrss_entries WHERE
1833                                 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1834                                 ttrss_user_entries.ref_id = ttrss_entries.id AND 
1835                                 ttrss_feeds.hidden = false AND
1836                                 unread = true AND ($match_part) AND ttrss_user_entries.owner_uid = " . $_SESSION["uid"]);
1837                                 
1838                 } else {
1839                 
1840                         $result = db_query($link, "SELECT COUNT(post_int_id) AS unread
1841                                 FROM ttrss_tags,ttrss_user_entries 
1842                                 WHERE tag_name = '$feed' AND post_int_id = int_id AND unread = true AND
1843                                         ttrss_tags.owner_uid = " . $_SESSION["uid"]);
1844                 }
1845                 
1846                 $unread = db_fetch_result($result, 0, "unread");
1847
1848                 return $unread;
1849         }
1850
1851         /* FIXME this needs reworking */
1852
1853         function getGlobalUnread($link, $user_id = false) {
1854
1855                 if (!$user_id) {
1856                         $user_id = $_SESSION["uid"];
1857                 }
1858
1859                 $result = db_query($link, "SELECT count(ttrss_entries.id) as c_id FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
1860                         WHERE unread = true AND 
1861                         ttrss_user_entries.feed_id = ttrss_feeds.id AND
1862                         ttrss_user_entries.ref_id = ttrss_entries.id AND 
1863                         hidden = false AND
1864                         ttrss_user_entries.owner_uid = '$user_id'");
1865                 $c_id = db_fetch_result($result, 0, "c_id");
1866                 return $c_id;
1867         }
1868
1869         function getGlobalCounters($link, $global_unread = -1) {
1870                 if ($global_unread == -1) {     
1871                         $global_unread = getGlobalUnread($link);
1872                 }
1873                 print "<counter type=\"global\" id='global-unread' 
1874                         counter='$global_unread'/>";
1875
1876                 $result = db_query($link, "SELECT COUNT(id) AS fn FROM 
1877                         ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"]);
1878
1879                 $subscribed_feeds = db_fetch_result($result, 0, "fn");
1880
1881                 print "<counter type=\"global\" id='subscribed-feeds' 
1882                         counter='$subscribed_feeds'/>";
1883
1884         }
1885
1886         function getTagCounters($link, $smart_mode = SMART_RPC_COUNTERS) {
1887
1888                 if ($smart_mode) {
1889                         if (!$_SESSION["tctr_last_value"]) {
1890                                 $_SESSION["tctr_last_value"] = array();
1891                         }
1892                 }
1893
1894                 $old_counters = $_SESSION["tctr_last_value"];
1895
1896                 $tctrs_modified = false;
1897
1898 /*              $result = db_query($link, "SELECT tag_name,count(ttrss_entries.id) AS count
1899                         FROM ttrss_tags,ttrss_entries,ttrss_user_entries WHERE
1900                         ttrss_user_entries.ref_id = ttrss_entries.id AND 
1901                         ttrss_tags.owner_uid = ".$_SESSION["uid"]." AND
1902                         post_int_id = ttrss_user_entries.int_id AND unread = true GROUP BY tag_name 
1903                 UNION
1904                         select tag_name,0 as count FROM ttrss_tags
1905                         WHERE ttrss_tags.owner_uid = ".$_SESSION["uid"]); */
1906
1907                 $result = db_query($link, "SELECT tag_name,SUM((SELECT COUNT(int_id) 
1908                         FROM ttrss_user_entries WHERE int_id = post_int_id 
1909                                 AND unread = true)) AS count FROM ttrss_tags 
1910                         WHERE owner_uid = ".$_SESSION['uid']." GROUP BY tag_name ORDER BY tag_name");
1911                         
1912                 $tags = array();
1913
1914                 while ($line = db_fetch_assoc($result)) {
1915                         $tags[$line["tag_name"]] += $line["count"];
1916                 }
1917
1918                 foreach (array_keys($tags) as $tag) {
1919                         $unread = $tags[$tag];                  
1920
1921                         $tag = htmlspecialchars($tag);
1922
1923                         if (!$smart_mode || $old_counters[$tag] != $unread) {                   
1924                                 $old_counters[$tag] = $unread;
1925                                 $tctrs_modified = true;
1926                                 print "<counter type=\"tag\" id=\"$tag\" counter=\"$unread\"/>";
1927                         }
1928
1929                 } 
1930
1931                 if ($smart_mode && $tctrs_modified) {
1932                         $_SESSION["tctr_last_value"] = $old_counters;
1933                 }
1934
1935         }
1936
1937         function getLabelCounters($link, $smart_mode = SMART_RPC_COUNTERS, $ret_mode = false) {
1938
1939                 if ($smart_mode) {
1940                         if (!$_SESSION["lctr_last_value"]) {
1941                                 $_SESSION["lctr_last_value"] = array();
1942                         }
1943                 }
1944
1945                 $ret_arr = array();
1946                 
1947                 $old_counters = $_SESSION["lctr_last_value"];
1948                 $lctrs_modified = false;
1949
1950                 $result = db_query($link, "SELECT count(ttrss_entries.id) as count FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
1951                         WHERE marked = true AND ttrss_user_entries.ref_id = ttrss_entries.id AND 
1952                         ttrss_user_entries.feed_id = ttrss_feeds.id AND
1953                         hidden = false AND unread = true AND ttrss_user_entries.owner_uid = ".$_SESSION["uid"]);
1954
1955                 $count = db_fetch_result($result, 0, "count");
1956
1957                 if (!$ret_mode) {
1958                         print "<counter type=\"label\" id=\"-1\" counter=\"$count\"/>";
1959                 } else {
1960                         $ret_arr["-1"]["counter"] = $count;
1961                         $ret_arr["-1"]["description"] = "Starred";
1962                 }
1963
1964                 $result = db_query($link, "SELECT count(ttrss_entries.id) as count FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
1965                         WHERE published = true AND ttrss_user_entries.ref_id = ttrss_entries.id AND 
1966                         ttrss_user_entries.feed_id = ttrss_feeds.id AND
1967                         hidden = false AND unread = true AND ttrss_user_entries.owner_uid = ".$_SESSION["uid"]);
1968
1969                 $count = db_fetch_result($result, 0, "count");
1970
1971                 if (!$ret_mode) {
1972                         print "<counter type=\"label\" id=\"-2\" counter=\"$count\"/>";
1973                 } else {
1974                         $ret_arr["-2"]["counter"] = $count;
1975                         $ret_arr["-2"]["description"] = "Published";
1976                 }
1977
1978
1979                 $result = db_query($link, "SELECT owner_uid,id,sql_exp,description FROM
1980                         ttrss_labels WHERE owner_uid = ".$_SESSION["uid"]." ORDER by description");
1981         
1982                 while ($line = db_fetch_assoc($result)) {
1983
1984                         $id = -$line["id"] - 11;
1985
1986                         $label_name = $line["description"];
1987
1988                         error_reporting (0);
1989
1990                         $tmp_result = db_query($link, "SELECT count(ttrss_entries.id) as count FROM ttrss_user_entries,ttrss_entries,ttrss_feeds
1991                                 WHERE (" . $line["sql_exp"] . ") AND unread = true AND 
1992                                 ttrss_feeds.hidden = false AND
1993                                 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1994                                 ttrss_user_entries.ref_id = ttrss_entries.id AND 
1995                                 ttrss_user_entries.owner_uid = ".$_SESSION["uid"]);
1996
1997                         $count = db_fetch_result($tmp_result, 0, "count");
1998
1999                         if (!$smart_mode || $old_counters[$id] != $count) {     
2000                                 $old_counters[$id] = $count;
2001                                 $lctrs_modified = true;
2002                                 if (!$ret_mode) {
2003                                         print "<counter type=\"label\" id=\"$id\" counter=\"$count\"/>";
2004                                 } else {
2005                                         $ret_arr[$id]["counter"] = $count;
2006                                         $ret_arr[$id]["description"] = $label_name;
2007                                 }
2008                         }
2009
2010                         error_reporting (DEFAULT_ERROR_LEVEL);
2011                 }
2012
2013                 if ($smart_mode && $lctrs_modified) {
2014                         $_SESSION["lctr_last_value"] = $old_counters;
2015                 }
2016
2017                 return $ret_arr;
2018         }
2019
2020 /*      function getFeedCounter($link, $id) {
2021         
2022                 $result = db_query($link, "SELECT 
2023                                 count(id) as count,last_error
2024                         FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
2025                         WHERE feed_id = '$id' AND unread = true
2026                         AND ttrss_user_entries.feed_id = ttrss_feeds.id
2027                         AND ttrss_user_entries.ref_id = ttrss_entries.id");
2028         
2029                         $count = db_fetch_result($result, 0, "count");
2030                         $last_error = htmlspecialchars(db_fetch_result($result, 0, "last_error"));
2031                         
2032                         print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" error=\"$last_error\"/>";           
2033         } */
2034
2035         function getFeedCounters($link, $smart_mode = SMART_RPC_COUNTERS) {
2036
2037                 if ($smart_mode) {
2038                         if (!$_SESSION["fctr_last_value"]) {
2039                                 $_SESSION["fctr_last_value"] = array();
2040                         }
2041                 }
2042
2043                 $old_counters = $_SESSION["fctr_last_value"];
2044
2045 /*              $result = db_query($link, "SELECT id,last_error,parent_feed,
2046                         SUBSTRING(last_updated,1,19) AS last_updated,
2047                         (SELECT count(id) 
2048                                 FROM ttrss_entries,ttrss_user_entries 
2049                                 WHERE feed_id = ttrss_feeds.id AND 
2050                                         ttrss_user_entries.ref_id = ttrss_entries.id
2051                                 AND unread = true AND owner_uid = ".$_SESSION["uid"].") as count
2052                         FROM ttrss_feeds WHERE owner_uid = ".$_SESSION["uid"] . "
2053                         AND parent_feed IS NULL"); */
2054
2055                 $result = db_query($link, "SELECT ttrss_feeds.id,
2056                                 SUBSTRING(ttrss_feeds.last_updated,1,19) AS last_updated, 
2057                                 last_error, 
2058                                 COUNT(ttrss_entries.id) AS count 
2059                         FROM ttrss_feeds 
2060                                 LEFT JOIN ttrss_user_entries ON (ttrss_user_entries.feed_id = ttrss_feeds.id 
2061                                         AND ttrss_user_entries.owner_uid = ttrss_feeds.owner_uid 
2062                                         AND ttrss_user_entries.unread = true) 
2063                                 LEFT JOIN ttrss_entries ON (ttrss_user_entries.ref_id = ttrss_entries.id) 
2064                         WHERE ttrss_feeds.owner_uid = ".$_SESSION["uid"]."
2065                                 AND parent_feed IS NULL 
2066                         GROUP BY ttrss_feeds.id, ttrss_feeds.title, ttrss_feeds.last_updated, last_error");
2067
2068                 $fctrs_modified = false;
2069
2070                 $short_date = get_pref($link, 'SHORT_DATE_FORMAT');
2071
2072                 while ($line = db_fetch_assoc($result)) {
2073                 
2074                         $id = $line["id"];
2075                         $count = $line["count"];
2076                         $last_error = htmlspecialchars($line["last_error"]);
2077
2078                         if (get_pref($link, 'HEADLINES_SMART_DATE')) {
2079                                 $last_updated = smart_date_time(strtotime($line["last_updated"]));
2080                         } else {
2081                                 $last_updated = date($short_date, strtotime($line["last_updated"]));
2082                         }                               
2083
2084                         $has_img = is_file(ICONS_DIR . "/$id.ico");
2085
2086                         $tmp_result = db_query($link,
2087                                 "SELECT id,COUNT(unread) AS unread
2088                                 FROM ttrss_feeds LEFT JOIN ttrss_user_entries 
2089                                         ON (ttrss_feeds.id = ttrss_user_entries.feed_id) 
2090                                 WHERE parent_feed = '$id' AND unread = true GROUP BY ttrss_feeds.id");
2091                         
2092                         if (db_num_rows($tmp_result) > 0) {                             
2093                                 while ($l = db_fetch_assoc($tmp_result)) {
2094                                         $count += $l["unread"];
2095                                 }
2096                         }
2097
2098                         if (!$smart_mode || $old_counters[$id] != $count) {
2099                                 $old_counters[$id] = $count;
2100                                 $fctrs_modified = true;
2101
2102                                 if ($last_error) {
2103                                         $error_part = "error=\"$last_error\"";
2104                                 } else {
2105                                         $error_part = "";
2106                                 }
2107
2108                                 if ($has_img) {
2109                                         $has_img_part = "hi=\"$has_img\"";
2110                                 } else {
2111                                         $has_img_part = "";
2112                                 }                               
2113
2114                                 print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" $has_img_part $error_part updated=\"$last_updated\"/>";
2115                         }
2116                 }
2117
2118                 if ($smart_mode && $fctrs_modified) {
2119                         $_SESSION["fctr_last_value"] = $old_counters;
2120                 }
2121         }
2122
2123         function get_script_dt_add() {
2124                 if (strpos(VERSION, ".99") === false) {
2125                         return VERSION;
2126                 } else {
2127                         return time();
2128                 }
2129         }
2130
2131         function get_pgsql_version($link) {
2132                 $result = db_query($link, "SELECT version() AS version");
2133                 $version = split(" ", db_fetch_result($result, 0, "version"));
2134                 return $version[1];
2135         }
2136
2137         function print_error_xml($code, $add_msg = "") {
2138                 global $ERRORS;
2139
2140                 $error_msg = $ERRORS[$code];
2141                 
2142                 if ($add_msg) {
2143                         $error_msg = "$error_msg; $add_msg";
2144                 }
2145                 
2146                 print "<rpc-reply>";
2147                 print "<error error-code=\"$code\" error-msg=\"$error_msg\"/>";
2148                 print "</rpc-reply>";
2149         }
2150
2151         function subscribe_to_feed($link, $feed_link, $cat_id = 0, 
2152                         $auth_login = '', $auth_pass = '') {
2153
2154                 # check for feed:http://url
2155                 $feed_link = trim(preg_replace("/^feed:/", "", $feed_link));
2156
2157                 # check for feed://URL
2158                 if (strpos($feed_link, "//") === 0) {
2159                         $feed_link = "http:$feed_link";
2160                 }
2161
2162                 if ($feed_link == "") return;
2163
2164                 if ($cat_id == "0" || !$cat_id) {
2165                         $cat_qpart = "NULL";
2166                 } else {
2167                         $cat_qpart = "'$cat_id'";
2168                 }
2169         
2170                 $result = db_query($link,
2171                         "SELECT id FROM ttrss_feeds 
2172                         WHERE feed_url = '$feed_link' AND owner_uid = ".$_SESSION["uid"]);
2173         
2174                 if (db_num_rows($result) == 0) {
2175                         
2176                         $result = db_query($link,
2177                                 "INSERT INTO ttrss_feeds 
2178                                         (owner_uid,feed_url,title,cat_id, auth_login,auth_pass) 
2179                                 VALUES ('".$_SESSION["uid"]."', '$feed_link', 
2180                                 '[Unknown]', $cat_qpart, '$auth_login', '$auth_pass')");
2181         
2182                         $result = db_query($link,
2183                                 "SELECT id FROM ttrss_feeds WHERE feed_url = '$feed_link' 
2184                                         AND owner_uid = " . $_SESSION["uid"]);
2185         
2186                         $feed_id = db_fetch_result($result, 0, "id");
2187         
2188                         if ($feed_id) {
2189                                 update_rss_feed($link, $feed_link, $feed_id, true);
2190                         }
2191
2192                         return true;
2193                 } else {
2194                         return false;
2195                 }
2196         }
2197
2198         function print_feed_select($link, $id, $default_id = "", 
2199                 $attributes = "", $include_all_feeds = true) {
2200
2201                 print "<select id=\"$id\" name=\"$id\" $attributes>";
2202                 if ($include_all_feeds) { 
2203                         print "<option value=\"0\">All feeds</option>";
2204                 }
2205         
2206                 $result = db_query($link, "SELECT id,title FROM ttrss_feeds
2207                         WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
2208
2209                 if (db_num_rows($result) > 0 && $include_all_feeds) {
2210                         print "<option disabled>--------</option>";
2211                 }
2212
2213                 while ($line = db_fetch_assoc($result)) {
2214                         if ($line["id"] == $default_id) {
2215                                 $is_selected = "selected";
2216                         } else {
2217                                 $is_selected = "";
2218                         }
2219                         printf("<option $is_selected value='%d'>%s</option>", 
2220                                 $line["id"], htmlspecialchars($line["title"]));
2221                 }
2222         
2223                 print "</select>";
2224         }
2225
2226         function print_feed_cat_select($link, $id, $default_id = "", 
2227                 $attributes = "", $include_all_cats = true) {
2228                 
2229                 print "<select id=\"$id\" name=\"$id\" $attributes>";
2230
2231                 if ($include_all_cats) {
2232                         print "<option value=\"0\">".__('Uncategorized')."</option>";
2233                 }
2234
2235                 $result = db_query($link, "SELECT id,title FROM ttrss_feed_categories
2236                         WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
2237
2238                 if (db_num_rows($result) > 0 && $include_all_cats) {
2239                         print "<option disabled>--------</option>";
2240                 }
2241
2242                 while ($line = db_fetch_assoc($result)) {
2243                         if ($line["id"] == $default_id) {
2244                                 $is_selected = "selected";
2245                         } else {
2246                                 $is_selected = "";
2247                         }
2248                         printf("<option $is_selected value='%d'>%s</option>", 
2249                                 $line["id"], htmlspecialchars($line["title"]));
2250                 }
2251
2252                 print "</select>";
2253         }
2254         
2255         function checkbox_to_sql_bool($val) {
2256                 return ($val == "on") ? "true" : "false";
2257         }
2258
2259         function getFeedCatTitle($link, $id) {
2260                 if ($id == -1) {
2261                         return __("Special");
2262                 } else if ($id < -10) {
2263                         return __("Labels");
2264                 } else if ($id > 0) {
2265                         $result = db_query($link, "SELECT ttrss_feed_categories.title 
2266                                 FROM ttrss_feeds, ttrss_feed_categories WHERE ttrss_feeds.id = '$id' AND
2267                                         cat_id = ttrss_feed_categories.id");
2268                         if (db_num_rows($result) == 1) {
2269                                 return db_fetch_result($result, 0, "title");
2270                         } else {
2271                                 return __("Uncategorized");
2272                         }
2273                 } else {
2274                         return "getFeedCatTitle($id) failed";
2275                 }
2276
2277         }
2278
2279         function getFeedTitle($link, $id) {
2280                 if ($id == -1) {
2281                         return __("Starred articles");
2282                 } else if ($id < -10) {
2283                         $label_id = -10 - $id;
2284                         $result = db_query($link, "SELECT description FROM ttrss_labels WHERE id = '$label_id'");
2285                         if (db_num_rows($result) == 1) {
2286                                 return db_fetch_result($result, 0, "description");
2287                         } else {
2288                                 return "Unknown label ($label_id)";
2289                         }
2290
2291                 } else if ($id > 0) {
2292                         $result = db_query($link, "SELECT title FROM ttrss_feeds WHERE id = '$id'");
2293                         if (db_num_rows($result) == 1) {
2294                                 return db_fetch_result($result, 0, "title");
2295                         } else {
2296                                 return "Unknown feed ($id)";
2297                         }
2298                 } else {
2299                         return "getFeedTitle($id) failed";
2300                 }
2301
2302         }
2303
2304         function get_session_cookie_name() {
2305                 return ((!defined('TTRSS_SESSION_NAME')) ? "ttrss_sid" : TTRSS_SESSION_NAME);
2306         }
2307
2308         function print_init_params($link) {
2309                 print "<init-params>";
2310                 if ($_SESSION["stored-params"]) {
2311                         foreach (array_keys($_SESSION["stored-params"]) as $key) {
2312                                 if ($key) {
2313                                         $value = htmlspecialchars($_SESSION["stored-params"][$key]);
2314                                         print "<param key=\"$key\" value=\"$value\"/>";
2315                                 }
2316                         }
2317                 }
2318
2319                 print "<param key=\"daemon_enabled\" value=\"" . ENABLE_UPDATE_DAEMON . "\"/>";
2320                 print "<param key=\"feeds_frame_refresh\" value=\"" . FEEDS_FRAME_REFRESH . "\"/>";
2321                 print "<param key=\"daemon_refresh_only\" value=\"" . DAEMON_REFRESH_ONLY . "\"/>";
2322
2323                 print "<param key=\"on_catchup_show_next_feed\" value=\"" . 
2324                         get_pref($link, "ON_CATCHUP_SHOW_NEXT_FEED") . "\"/>";
2325
2326                 print "<param key=\"hide_read_feeds\" value=\"" . 
2327                         (int) get_pref($link, "HIDE_READ_FEEDS") . "\"/>";
2328
2329                 print "<param key=\"feeds_sort_by_unread\" value=\"" . 
2330                         (int) get_pref($link, "FEEDS_SORT_BY_UNREAD") . "\"/>";
2331
2332                 print "<param key=\"confirm_feed_catchup\" value=\"" . 
2333                         (int) get_pref($link, "CONFIRM_FEED_CATCHUP") . "\"/>";
2334
2335                 print "<param key=\"cdm_auto_catchup\" value=\"" . 
2336                         (int) get_pref($link, "CDM_AUTO_CATCHUP") . "\"/>";
2337
2338                 print "<param key=\"icons_url\" value=\"" . ICONS_URL . "\"/>";
2339
2340                 print "<param key=\"cookie_lifetime\" value=\"" . SESSION_COOKIE_LIFETIME . "\"/>";
2341
2342                 print "<param key=\"default_view_mode\" value=\"" . 
2343                         get_pref($link, "_DEFAULT_VIEW_MODE") . "\"/>";
2344
2345                 print "<param key=\"default_view_limit\" value=\"" . 
2346                         (int) get_pref($link, "_DEFAULT_VIEW_LIMIT") . "\"/>";
2347
2348                 print "<param key=\"prefs_active_tab\" value=\"" . 
2349                         get_pref($link, "_PREFS_ACTIVE_TAB") . "\"/>";
2350
2351                 print "<param key=\"infobox_disable_overlay\" value=\"" . 
2352                         get_pref($link, "_INFOBOX_DISABLE_OVERLAY") . "\"/>";
2353
2354                 print "</init-params>";
2355         }
2356
2357         function print_runtime_info($link) {
2358                 print "<runtime-info>";
2359                 if (ENABLE_UPDATE_DAEMON) {
2360                         print "<param key=\"daemon_is_running\" value=\"".
2361                                 sprintf("%d", file_is_locked("update_daemon.lock")) . "\"/>";
2362
2363                         if ($_SESSION["daemon_stamp_check"] + 600 < time()) {
2364
2365                                 $stamp = (int)read_stampfile("update_daemon.stamp");
2366
2367                                 if ($stamp) {
2368                                         if ($stamp + 86400*3 < time()) {
2369                                                 print "<param key=\"daemon_stamp_ok\" value=\"0\"/>";
2370                                         } else {
2371                                                 print "<param key=\"daemon_stamp_ok\" value=\"1\"/>";
2372                                         }
2373
2374                                         $stamp_fmt = date("Y.m.d, G:i", $stamp);
2375
2376                                         print "<param key=\"daemon_stamp\" value=\"$stamp_fmt\"/>";
2377                                 }
2378
2379                                 $_SESSION["daemon_stamp_check"] = time();
2380                         }
2381                 }
2382
2383                 if (CHECK_FOR_NEW_VERSION && $_SESSION["access_level"] >= 10) {
2384                         
2385                         if ($_SESSION["last_version_check"] + 600 < time()) {
2386                                 $new_version_details = check_for_update($link);
2387
2388                                 print "<param key=\"new_version_available\" value=\"".
2389                                         sprintf("%d", $new_version_details != ""). "\"/>";
2390
2391                                 $_SESSION["last_version_check"] = time();
2392                         }
2393                 }
2394
2395                 print "</runtime-info>";
2396         }
2397
2398         function getSearchSql($search, $match_on) {
2399
2400                 $search_query_part = "";
2401
2402                 $keywords = split(" ", $search);
2403                 $query_keywords = array();
2404
2405                 if ($match_on == "both") {
2406
2407                         foreach ($keywords as $k) {
2408                                 array_push($query_keywords, "(UPPER(ttrss_entries.title) LIKE UPPER('%$k%')
2409                                         OR UPPER(ttrss_entries.content) LIKE UPPER('%$k%'))");
2410                         }
2411
2412                         $search_query_part = implode("AND", $query_keywords) . " AND ";
2413
2414                 } else if ($match_on == "title") {
2415
2416                         foreach ($keywords as $k) {
2417                                 array_push($query_keywords, "(UPPER(ttrss_entries.title) LIKE UPPER('%$k%'))");
2418                         }
2419
2420                         $search_query_part = implode("AND", $query_keywords) . " AND ";
2421
2422                 } else if ($match_on == "content") {
2423
2424                         foreach ($keywords as $k) {
2425                                 array_push($query_keywords, "(UPPER(ttrss_entries.content) LIKE UPPER('%$k%'))");
2426                         }
2427                 }
2428
2429                 $search_query_part = implode("AND", $query_keywords);
2430
2431                 return $search_query_part;
2432         }
2433
2434         function queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, $search, $search_mode, $match_on, $override_order = false, $offset = 0) {
2435
2436                         if ($search) {
2437                         
2438                                 $search_query_part = getSearchSql($search, $match_on);
2439                                 $search_query_part .= " AND ";
2440
2441                         } else {
2442                                 $search_query_part = "";
2443                         }
2444
2445                         $view_query_part = "";
2446         
2447                         if ($view_mode == "adaptive") {
2448                                 if ($search) {
2449                                         $view_query_part = " ";
2450                                 } else if ($feed != -1) {
2451                                         $unread = getFeedUnread($link, $feed, $cat_view);
2452                                         if ($unread > 0) {
2453                                                 $view_query_part = " unread = true AND ";
2454                                         }
2455                                 }
2456                         }
2457         
2458                         if ($view_mode == "marked") {
2459                                 $view_query_part = " marked = true AND ";
2460                         }
2461         
2462                         if ($view_mode == "unread") {
2463                                 $view_query_part = " unread = true AND ";
2464                         }
2465         
2466                         if ($limit > 0) {
2467                                 $limit_query_part = "LIMIT " . $limit;
2468                         } 
2469
2470                         $vfeed_query_part = "";
2471         
2472                         // override query strategy and enable feed display when searching globally
2473                         if ($search && $search_mode == "all_feeds") {
2474                                 $query_strategy_part = "ttrss_entries.id > 0";
2475                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";         
2476                         } else if (preg_match("/^-?[0-9][0-9]*$/", $feed) == false) {
2477                                 $query_strategy_part = "ttrss_entries.id > 0";
2478                                 $vfeed_query_part = "(SELECT title FROM ttrss_feeds WHERE
2479                                         id = feed_id) as feed_title,";
2480                         } else if ($feed >= 0 && $search && $search_mode == "this_cat") {
2481         
2482                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";         
2483
2484                                 $tmp_result = false;
2485
2486                                 if ($cat_view) {
2487                                         $tmp_result = db_query($link, "SELECT id 
2488                                                 FROM ttrss_feeds WHERE cat_id = '$feed'");
2489                                 } else {
2490                                         $tmp_result = db_query($link, "SELECT id
2491                                                 FROM ttrss_feeds WHERE cat_id = (SELECT cat_id FROM ttrss_feeds 
2492                                                         WHERE id = '$feed') AND id != '$feed'");
2493                                 }
2494         
2495                                 $cat_siblings = array();
2496         
2497                                 if (db_num_rows($tmp_result) > 0) {
2498                                         while ($p = db_fetch_assoc($tmp_result)) {
2499                                                 array_push($cat_siblings, "feed_id = " . $p["id"]);
2500                                         }
2501         
2502                                         $query_strategy_part = sprintf("(feed_id = %d OR %s)", 
2503                                                 $feed, implode(" OR ", $cat_siblings));
2504         
2505                                 } else {
2506                                         $query_strategy_part = "ttrss_entries.id > 0";
2507                                 }
2508                                 
2509                         } else if ($feed >= 0) {
2510         
2511                                 if ($cat_view) {
2512
2513                                         if ($feed > 0) {
2514                                                 $query_strategy_part = "cat_id = '$feed'";
2515                                         } else {
2516                                                 $query_strategy_part = "cat_id IS NULL";
2517                                         }
2518         
2519                                         $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2520
2521                                 } else {                
2522                                         $tmp_result = db_query($link, "SELECT id 
2523                                                 FROM ttrss_feeds WHERE parent_feed = '$feed'
2524                                                 ORDER BY cat_id,title");
2525                 
2526                                         $parent_ids = array();
2527                 
2528                                         if (db_num_rows($tmp_result) > 0) {
2529                                                 while ($p = db_fetch_assoc($tmp_result)) {
2530                                                         array_push($parent_ids, "feed_id = " . $p["id"]);
2531                                                 }
2532                 
2533                                                 $query_strategy_part = sprintf("(feed_id = %d OR %s)", 
2534                                                         $feed, implode(" OR ", $parent_ids));
2535                 
2536                                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2537                                         } else {
2538                                                 $query_strategy_part = "feed_id = '$feed'";
2539                                         }
2540                                 }
2541                         } else if ($feed == -1) { // starred virtual feed
2542                                 $query_strategy_part = "marked = true";
2543                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2544                         } else if ($feed == -2) { // published virtual feed
2545                                 $query_strategy_part = "published = true";
2546                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2547                         } else if ($feed <= -10) { // labels
2548                                 $label_id = -$feed - 11;
2549         
2550                                 $tmp_result = db_query($link, "SELECT sql_exp FROM ttrss_labels
2551                                         WHERE id = '$label_id'");
2552                         
2553                                 $query_strategy_part = db_fetch_result($tmp_result, 0, "sql_exp");
2554
2555                                 if (!$query_strategy_part) {
2556                                         return false;
2557                                 }
2558
2559                                 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2560                         } else {
2561                                 $query_strategy_part = "id > 0"; // dumb
2562                         }
2563
2564                         if (get_pref($link, 'REVERSE_HEADLINES')) {
2565                                 $order_by = "updated";
2566                         } else {        
2567                                 $order_by = "updated DESC";
2568                         }
2569
2570                         if ($override_order) {
2571                                 $order_by = $override_order;
2572                         }
2573         
2574                         $feed_title = "";
2575
2576                         if ($search && $search_mode == "all_feeds") {
2577                                 $feed_title = __("Search results")." ($search)";
2578                         } else if ($search && preg_match('/^-?[0-9][0-9]*$/', $feed) == false) {
2579                                 $feed_title = __("Search results")." ($search, $feed)";
2580                         } else if (preg_match('/^-?[0-9][0-9]*$/', $feed) == false) {
2581                                 $feed_title = $feed;
2582                         } else if (preg_match('/^-?[0-9][0-9]*$/', $feed) != false && $feed >= 0) {
2583         
2584                                 if ($cat_view) {
2585
2586                                         if ($feed != 0) {                       
2587                                                 $result = db_query($link, "SELECT title FROM ttrss_feed_categories
2588                                                         WHERE id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
2589                                                 $feed_title = db_fetch_result($result, 0, "title");
2590                                         } else {
2591                                                 $feed_title = __("Uncategorized");
2592                                         }
2593
2594                                         if ($search) {
2595                                                 $feed_title = __("Searched for")." $search ($feed_title)";
2596                                         }
2597
2598                                 } else {
2599                                         
2600                                         $result = db_query($link, "SELECT title,site_url,last_error FROM ttrss_feeds 
2601                                                 WHERE id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
2602                 
2603                                         $feed_title = db_fetch_result($result, 0, "title");
2604                                         $feed_site_url = db_fetch_result($result, 0, "site_url");
2605                                         $last_error = db_fetch_result($result, 0, "last_error");
2606
2607                                         if ($search) {
2608                                                 $feed_title = __("Searched for") . " $search ($feed_title)";
2609                                         }
2610                                 }
2611         
2612                         } else if ($feed == -1) {
2613                                 $feed_title = __("Starred articles");
2614                         } else if ($feed == -2) {
2615                                 $feed_title = __("Published articles");
2616                         } else if ($feed < -10) {
2617                                 $label_id = -$feed - 11;
2618                                 $result = db_query($link, "SELECT description FROM ttrss_labels
2619                                         WHERE id = '$label_id'");
2620                                 $feed_title = db_fetch_result($result, 0, "description");
2621
2622                                 if ($search) {
2623                                         $feed_title = __("Searched for") . " $search ($feed_title)";
2624                                 }
2625                         } else {
2626                                 $feed_title = "?";
2627                         }
2628
2629                         if ($feed < -10) error_reporting (0);
2630
2631                         if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
2632         
2633                                 if ($feed >= 0) {
2634                                         $feed_kind = "Feeds";
2635                                 } else {
2636                                         $feed_kind = "Labels";
2637                                 }
2638         
2639                                 $content_query_part = "content as content_preview,";
2640
2641                                 if ($limit_query_part) {
2642                                         $offset_query_part = "OFFSET $offset";
2643                                 }
2644
2645                                 $query = "SELECT 
2646                                                 guid,
2647                                                 ttrss_entries.id,ttrss_entries.title,
2648                                                 updated,
2649                                                 unread,feed_id,marked,published,link,last_read,
2650                                                 SUBSTRING(last_read,1,19) as last_read_noms,
2651                                                 $vfeed_query_part
2652                                                 $content_query_part
2653                                                 SUBSTRING(updated,1,19) as updated_noms,
2654                                                 author
2655                                         FROM
2656                                                 ttrss_entries,ttrss_user_entries,ttrss_feeds
2657                                         WHERE
2658                                         ttrss_feeds.hidden = false AND
2659                                         ttrss_user_entries.feed_id = ttrss_feeds.id AND
2660                                         ttrss_user_entries.ref_id = ttrss_entries.id AND
2661                                         ttrss_user_entries.owner_uid = '".$_SESSION["uid"]."' AND
2662                                         $search_query_part
2663                                         $view_query_part
2664                                         $query_strategy_part ORDER BY $order_by
2665                                         $limit_query_part $offset_query_part";
2666                                         
2667                                 $result = db_query($link, $query);
2668         
2669                                 if ($_GET["debug"]) print $query;
2670         
2671                         } else {
2672                                 // browsing by tag
2673         
2674                                 $feed_kind = "Tags";
2675         
2676                                 $result = db_query($link, "SELECT
2677                                         guid,
2678                                         ttrss_entries.id as id,title,
2679                                         updated,
2680                                         unread,feed_id,
2681                                         marked,link,last_read,                          
2682                                         SUBSTRING(last_read,1,19) as last_read_noms,
2683                                         $vfeed_query_part
2684                                         $content_query_part
2685                                         SUBSTRING(updated,1,19) as updated_noms
2686                                         FROM
2687                                                 ttrss_entries,ttrss_user_entries,ttrss_tags
2688                                         WHERE
2689                                                 ref_id = ttrss_entries.id AND
2690                                                 ttrss_user_entries.owner_uid = '".$_SESSION["uid"]."' AND
2691                                                 post_int_id = int_id AND tag_name = '$feed' AND
2692                                                 $view_query_part
2693                                                 $search_query_part
2694                                                 $query_strategy_part ORDER BY $order_by
2695                                         $limit_query_part");    
2696                         }
2697
2698                         return array($result, $feed_title, $feed_site_url, $last_error);
2699                         
2700         }
2701
2702         function generate_syndicated_feed($link, $feed, $is_cat,
2703                 $search, $search_mode, $match_on) {
2704
2705                 $qfh_ret = queryFeedHeadlines($link, $feed, 
2706                                 30, false, $is_cat, $search, $search_mode, $match_on, "updated DESC");
2707
2708                 $result = $qfh_ret[0];
2709                 $feed_title = htmlspecialchars($qfh_ret[1]);
2710                 $feed_site_url = $qfh_ret[2];
2711                 $last_error = $qfh_ret[3];
2712
2713 #               if (!$feed_site_url) $feed_site_url = "http://localhost/";
2714
2715                 print "<rss version=\"2.0\">
2716                         <channel>
2717                         <title>$feed_title</title>
2718                         <link>$feed_site_url</link>
2719                         <description>Feed generated by Tiny Tiny RSS</description>";
2720  
2721                 while ($line = db_fetch_assoc($result)) {
2722                         print "<item>";
2723                         print "<guid>" . htmlspecialchars($line["guid"]) . "</guid>";
2724                         print "<link>" . htmlspecialchars($line["link"]) . "</link>";
2725
2726                         $tags = get_article_tags($link, $line["id"]);
2727
2728                         foreach ($tags as $tag) {
2729                                 print "<category>" . htmlspecialchars($tag) . "</category>";
2730                         }
2731
2732                         $rfc822_date = date('r', strtotime($line["updated"]));
2733   
2734                         print "<pubDate>$rfc822_date</pubDate>";
2735  
2736                         print "<title>" . 
2737                                 htmlspecialchars($line["title"]) . "</title>";
2738   
2739                         print "<description><![CDATA[" . 
2740                                 $line["content_preview"] . "]]></description>";
2741   
2742                         print "</item>";
2743                 }
2744   
2745                 print "</channel></rss>";
2746
2747         }
2748
2749         function getCategoryTitle($link, $cat_id) {
2750
2751                 $result = db_query($link, "SELECT title FROM ttrss_feed_categories WHERE
2752                         id = '$cat_id'");
2753
2754                 if (db_num_rows($result) == 1) {
2755                         return db_fetch_result($result, 0, "title");
2756                 } else {
2757                         return "Uncategorized";
2758                 }
2759         }
2760
2761         // http://ru2.php.net/strip-tags
2762
2763         function strip_tags_long($textstring, $allowed){
2764         while($textstring != strip_tags($textstring, $allowed))
2765     {
2766     while (strlen($textstring) != 0)
2767          {
2768          if (strlen($textstring) > 1024) {
2769               $otherlen = 1024;
2770          } else {
2771               $otherlen = strlen($textstring);
2772          }
2773          $temptext = strip_tags(substr($textstring,0,$otherlen), $allowed);
2774          $safetext .= $temptext;
2775          $textstring = substr_replace($textstring,'',0,$otherlen);
2776          }  
2777     $textstring = $safetext;
2778     }
2779         return $textstring;
2780         }
2781
2782
2783         function sanitize_rss($link, $str, $force_strip_tags = false) {
2784                 $res = $str;
2785
2786                 if (get_pref($link, "STRIP_UNSAFE_TAGS") || $force_strip_tags) {
2787                         global $tw_parser;
2788                         global $tw_paranoya_setup;
2789
2790                         $res = $tw_parser->strip_tags($res, $tw_paranoya_setup);
2791
2792 //                      $res = preg_replace("/\r\n|\n|\r/", "", $res);
2793 //                      $res = strip_tags_long($res, "<p><a><i><em><b><strong><blockquote><br><img><div><span>");                       
2794                 }
2795
2796                 return $res;
2797         }
2798
2799         function send_headlines_digests($link, $limit = 100) {
2800
2801                 if (!DIGEST_ENABLE) return false;
2802
2803                 $user_limit = DIGEST_EMAIL_LIMIT;
2804                 $days = 1;
2805
2806                 print "Sending digests, batch of max $user_limit users, days = $days, headline limit = $limit\n\n";
2807
2808                 if (DB_TYPE == "pgsql") {
2809                         $interval_query = "last_digest_sent < NOW() - INTERVAL '$days days'";
2810                 } else if (DB_TYPE == "mysql") {
2811                         $interval_query = "last_digest_sent < DATE_SUB(NOW(), INTERVAL $days DAY)";
2812                 }
2813
2814                 $result = db_query($link, "SELECT id,email FROM ttrss_users 
2815                                 WHERE email != '' AND (last_digest_sent IS NULL OR $interval_query)");
2816
2817                 while ($line = db_fetch_assoc($result)) {
2818                         if (get_pref($link, 'DIGEST_ENABLE', $line['id'], false)) {
2819                                 print "Sending digest for UID:" . $line['id'] . " - " . $line["email"] . " ... ";
2820
2821                                 $tuple = prepare_headlines_digest($link, $line["id"], $days, $limit);
2822                                 $digest = $tuple[0];
2823                                 $headlines_count = $tuple[1];
2824
2825                                 if ($headlines_count > 0) {
2826                                         $rc = mail($line["login"] . " <" . $line["email"] . ">",
2827                                                 "[tt-rss] New headlines for last 24 hours", $digest,
2828                                                 "From: " . MAIL_FROM . "\n".
2829                                                 "Content-Type: text/plain; charset=\"utf-8\"\n".
2830                                                 "Content-Transfer-Encoding: 8bit\n");
2831                                         print "RC=$rc\n";
2832                                         db_query($link, "UPDATE ttrss_users SET last_digest_sent = NOW() 
2833                                                         WHERE id = " . $line["id"]);
2834                                 } else {
2835                                         print "No headlines\n";
2836                                 }
2837                         }
2838                 }
2839
2840 //              $digest = prepare_headlines_digest($link, $user_id, $days, $limit);
2841
2842         }
2843
2844         function prepare_headlines_digest($link, $user_id, $days = 1, $limit = 100) {
2845                 $tmp =  __("New headlines for last 24 hours, as of ") . date("Y/m/d H:m") . "\n";       
2846                 $tmp .= "=======================================================\n\n";
2847
2848                 if (DB_TYPE == "pgsql") {
2849                         $interval_query = "ttrss_entries.date_entered > NOW() - INTERVAL '$days days'";
2850                 } else if (DB_TYPE == "mysql") {
2851                         $interval_query = "ttrss_entries.date_entered > DATE_SUB(NOW(), INTERVAL $days DAY)";
2852                 }
2853
2854                 $result = db_query($link, "SELECT ttrss_entries.title,
2855                                 ttrss_feeds.title AS feed_title,
2856                                 date_entered,
2857                                 link,
2858                                 SUBSTRING(last_updated,1,19) AS last_updated
2859                         FROM 
2860                                 ttrss_user_entries,ttrss_entries,ttrss_feeds 
2861                         WHERE 
2862                                 ref_id = ttrss_entries.id AND feed_id = ttrss_feeds.id 
2863                                 AND include_in_digest = true
2864                                 AND $interval_query
2865                                 AND ttrss_user_entries.owner_uid = $user_id
2866                                 AND unread = true ORDER BY ttrss_feeds.title, date_entered DESC
2867                         LIMIT $limit");
2868
2869                 $cur_feed_title = "";
2870
2871                 $headlines_count = db_num_rows($result);
2872
2873                 while ($line = db_fetch_assoc($result)) {
2874                         $updated = smart_date_time(strtotime($line["last_updated"]));
2875                         $feed_title = $line["feed_title"];
2876
2877                         if ($cur_feed_title != $feed_title) {
2878                                 $cur_feed_title = $feed_title;
2879
2880                                 $tmp .= "$feed_title\n\n";
2881                         }
2882
2883                         $tmp .= " * " . trim($line["title"]) . " - $updated\n";
2884                         $tmp .= "   " . trim($line["link"]) . "\n";
2885                         $tmp .= "\n";
2886                 }
2887
2888                 $tmp .= "--- \n";
2889                 $tmp .= __("You have been sent this email because you have enabled daily digests in Tiny Tiny RSS at ") . 
2890                         DIGEST_HOSTNAME . "\n".
2891                         __("To unsubscribe, visit your configuration options or contact instance owner.\n");
2892                         
2893
2894                 return array($tmp, $headlines_count);
2895         }
2896
2897         function check_for_update($link, $brief_fmt = true) {
2898                 $releases_feed = "http://tt-rss.spb.ru/releases.rss";
2899
2900                 if (!CHECK_FOR_NEW_VERSION || $_SESSION["access_level"] < 10) {
2901                         return;
2902                 }
2903
2904                 error_reporting(0);
2905                 $rss = fetch_rss($releases_feed);
2906                 error_reporting (DEFAULT_ERROR_LEVEL);
2907
2908                 if ($rss) {
2909
2910                         $items = $rss->items;
2911
2912                         if (!$items || !is_array($items)) $items = $rss->entries;
2913                         if (!$items || !is_array($items)) $items = $rss;
2914
2915                         if (!is_array($items) || count($items) == 0) {
2916                                 return;
2917                         }                       
2918
2919                         $latest_item = $items[0];
2920
2921                         $latest_version = trim(preg_replace("/(Milestone)|(completed)/", "", $latest_item["title"]));
2922
2923                         $release_url = sanitize_rss($link, $latest_item["link"]);
2924                         $content = sanitize_rss($link, $latest_item["description"]);
2925
2926                         if (version_compare(VERSION, $latest_version) == -1) {
2927                                 if ($brief_fmt) {
2928                                         return format_notice("<a href=\"javascript:showBlockElement('milestoneDetails')\">      
2929                                                 New version of Tiny-Tiny RSS ($latest_version) is available (click for details)</a>
2930                                                 <div id=\"milestoneDetails\">$content</div>");
2931                                 } else {
2932                                         return "New version of Tiny-Tiny RSS ($latest_version) is available:
2933                                                 <div class='milestoneDetails'>$content</div>
2934                                                 Visit <a target=\"_new\" href=\"http://tt-rss.spb.ru/\">official site</a> for
2935                                                 download and update information.";      
2936                                 }
2937
2938                         }                       
2939                 }
2940         }
2941
2942         function markArticlesById($link, $ids, $cmode) {
2943
2944                 $tmp_ids = array();
2945
2946                 foreach ($ids as $id) {
2947                         array_push($tmp_ids, "ref_id = '$id'");
2948                 }
2949
2950                 $ids_qpart = join(" OR ", $tmp_ids);
2951
2952                 if ($cmode == 0) {
2953                         db_query($link, "UPDATE ttrss_user_entries SET 
2954                         marked = false,last_read = NOW()
2955                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2956                 } else if ($cmode == 1) {
2957                         db_query($link, "UPDATE ttrss_user_entries SET 
2958                         marked = true
2959                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2960                 } else {
2961                         db_query($link, "UPDATE ttrss_user_entries SET 
2962                         marked = NOT marked,last_read = NOW()
2963                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2964                 }
2965         }
2966
2967         function publishArticlesById($link, $ids, $cmode) {
2968
2969                 $tmp_ids = array();
2970
2971                 foreach ($ids as $id) {
2972                         array_push($tmp_ids, "ref_id = '$id'");
2973                 }
2974
2975                 $ids_qpart = join(" OR ", $tmp_ids);
2976
2977                 if ($cmode == 0) {
2978                         db_query($link, "UPDATE ttrss_user_entries SET 
2979                         published = false,last_read = NOW()
2980                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2981                 } else if ($cmode == 1) {
2982                         db_query($link, "UPDATE ttrss_user_entries SET 
2983                         published = true
2984                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2985                 } else {
2986                         db_query($link, "UPDATE ttrss_user_entries SET 
2987                         published = NOT published,last_read = NOW()
2988                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2989                 }
2990         }
2991
2992         function catchupArticlesById($link, $ids, $cmode) {
2993
2994                 $tmp_ids = array();
2995
2996                 foreach ($ids as $id) {
2997                         array_push($tmp_ids, "ref_id = '$id'");
2998                 }
2999
3000                 $ids_qpart = join(" OR ", $tmp_ids);
3001
3002                 if ($cmode == 0) {
3003                         db_query($link, "UPDATE ttrss_user_entries SET 
3004                         unread = false,last_read = NOW()
3005                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
3006                 } else if ($cmode == 1) {
3007                         db_query($link, "UPDATE ttrss_user_entries SET 
3008                         unread = true
3009                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
3010                 } else {
3011                         db_query($link, "UPDATE ttrss_user_entries SET 
3012                         unread = NOT unread,last_read = NOW()
3013                         WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
3014                 }
3015         }
3016
3017         function catchupArticleById($link, $id, $cmode) {
3018
3019                 if ($cmode == 0) {
3020                         db_query($link, "UPDATE ttrss_user_entries SET 
3021                         unread = false,last_read = NOW()
3022                         WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
3023                 } else if ($cmode == 1) {
3024                         db_query($link, "UPDATE ttrss_user_entries SET 
3025                         unread = true
3026                         WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
3027                 } else {
3028                         db_query($link, "UPDATE ttrss_user_entries SET 
3029                         unread = NOT unread,last_read = NOW()
3030                         WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
3031                 }
3032         }
3033
3034         function make_guid_from_title($title) {
3035                 return preg_replace("/[ \"\',.:;]/", "-", 
3036                         mb_strtolower(strip_tags($title), 'utf-8'));
3037         }
3038
3039         function print_headline_subtoolbar($link, $feed_site_url, $feed_title, 
3040                         $bottom = false, $rtl_content = false, $feed_id = 0,
3041                         $is_cat = false, $search = false, $match_on = false,
3042                         $search_mode = false, $offset = 0, $limit = 0) {
3043
3044                         $user_page_offset = $offset + 1;
3045
3046                         if (!$bottom) {
3047                                 $class = "headlinesSubToolbar";
3048                                 $tid = "headlineActionsTop";
3049                         } else {
3050                                 $class = "headlinesSubToolbar";
3051                                 $tid = "headlineActionsBottom";
3052                         }
3053
3054                         print "<table class=\"$class\" id=\"$tid\"
3055                                 width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tr>";
3056
3057                         if ($rtl_content) {
3058                                 $rtl_cpart = "RTL";
3059                         } else {
3060                                 $rtl_cpart = "";
3061                         }
3062
3063                         $page_prev_link = "javascript:viewFeedGoPage(-1)";
3064                         $page_next_link = "javascript:viewFeedGoPage(1)";
3065                         $page_first_link = "javascript:viewFeedGoPage(0)";
3066
3067                         $catchup_page_link = "javascript:catchupPage()";
3068                         $catchup_feed_link = "javascript:catchupCurrentFeed()";
3069
3070                         if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) {
3071
3072                                 $sel_all_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, '', true)";
3073                                 $sel_unread_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, 'Unread', true)";
3074                                 $sel_none_link = "javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false)";
3075
3076                                 $tog_unread_link = "javascript:selectionToggleUnread()";
3077                                 $tog_marked_link = "javascript:selectionToggleMarked()";
3078                                 $tog_published_link = "javascript:selectionTogglePublished()";
3079
3080                         } else {
3081
3082                                 $sel_all_link = "javascript:cdmSelectArticles('all')";
3083                                 $sel_unread_link = "javascript:cdmSelectArticles('unread')";
3084                                 $sel_none_link = "javascript:cdmSelectArticles('none')";
3085
3086                                 $tog_unread_link = "javascript:selectionToggleUnread(true)";
3087                                 $tog_marked_link = "javascript:selectionToggleMarked(true)";
3088                                 $tog_published_link = "javascript:selectionTogglePublished(true)";
3089
3090                         }
3091
3092                         if (strpos($_SESSION["client.userAgent"], "MSIE") === false) {
3093
3094                                 print "<td class=\"headlineActions$rtl_cpart\">
3095                                         <ul class=\"headlineDropdownMenu\">
3096                                         <li class=\"top2\">
3097                                         ".__('Select:')."
3098                                                 <a href=\"$sel_all_link\">".__('All')."</a>,
3099                                                 <a href=\"$sel_unread_link\">".__('Unread')."</a>,
3100                                                 <a href=\"$sel_none_link\">".__('None')."</a></li>
3101                                         <li class=\"vsep\">&nbsp;</li>
3102                                         <li class=\"top\">Toggle<ul>
3103                                                 <li onclick=\"$tog_unread_link\">".__('Unread')."</li>
3104                                                 <li onclick=\"$tog_marked_link\">".__('Starred')."</li>
3105                                                 <li onclick=\"$tog_published_link\">".__('Published')."</li>
3106                                                 </ul></li>
3107                                         <li class=\"vsep\">&nbsp;</li>
3108                                         <li class=\"top\"><a href=\"$catchup_page_link\">".__('Mark as read')."</a><ul>
3109                                                 <li onclick=\"$catchup_page_link\">".__('This page')."</li>
3110                                                 <li onclick=\"$catchup_feed_link\">".__('Entire feed')."</li></ul></li>
3111                                         ";
3112
3113                                         $enable_pagination = get_pref($link, "_PREFS_ENABLE_PAGINATION");
3114
3115                                         if ($limit != 0 && !$search && $enable_pagination) {
3116                                                 print "
3117                                                 <li class=\"vsep\">&nbsp;</li>
3118                                                 <li class=\"top\"><a href=\"$page_next_link\">".__('Next page')."</a><ul>
3119                                                         <li onclick=\"$page_prev_link\">".__('Previous page')."</li>
3120                                                         <li onclick=\"$page_first_link\">".__('First page')."</li></ul></li>
3121                                                         </ul>";
3122                                                 }
3123
3124                                         if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS) {
3125                                                 print "
3126                                                         <li class=\"vsep\">&nbsp;</li>
3127                                                         <li class=\"top3\">
3128                                                         <a href=\"javascript:labelFromSearch('$search', '$search_mode',
3129                                                                 '$match_on', '$feed_id', '$is_cat');\">
3130                                                                 ".__('Convert to label')."</a></td>";
3131                                         }
3132                                         print " 
3133                                         </td>"; 
3134
3135                         } else {
3136                         // old style subtoolbar:
3137
3138                                 print "<td class=\"headlineActions$rtl_cpart\">".
3139                                         __('Select:')."
3140                                                                 <a href=\"$sel_all_link\">".__('All')."</a>,
3141                                                                 <a href=\"$sel_unread_link\">".__('Unread')."</a>,
3142                                                                 <a href=\"$sel_none_link\">".__('None')."</a>
3143                                                 &nbsp;&nbsp;".
3144                                                 __('Toggle:')." <a href=\"$tog_unread_link\">".__('Unread')."</a>,
3145                                                         <a href=\"$tog_marked_link\">".__('Starred')."</a>
3146                                                 &nbsp;&nbsp;".
3147                                                 __('Mark as read:')."
3148                                                         <a href=\"#\" onclick=\"$catchup_page_link\">".__('Page')."</a>,
3149                                                         <a href=\"#\" onclick=\"$catchup_feed_link\">".__('Feed')."</a>";
3150
3151                                 if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS) {
3152
3153                                         print "&nbsp;&nbsp;
3154                                                         <a href=\"javascript:labelFromSearch('$search', '$search_mode',
3155                                                                 '$match_on', '$feed_id', '$is_cat');\">
3156                                                         ".__('Convert to label')."</a>";
3157                                 }
3158
3159                                 print "</td>";  
3160
3161                         }
3162
3163 /*                      if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS) {
3164                                 print "<td class=\"headlineActions$rtl_cpart\">
3165                                         <a href=\"javascript:labelFromSearch('$search', '$search_mode',
3166                                                         '$match_on', '$feed_id', '$is_cat');\">
3167                                                 ".__('Convert to Label')."</a></td>";
3168 } */
3169
3170                         print "<td class=\"headlineTitle$rtl_cpart\">";
3171                 
3172                         if ($feed_site_url) {
3173                                 if (!$bottom) {
3174                                         $target = "target=\"_blank\"";
3175                                 }
3176                                 print "<a $target href=\"$feed_site_url\">$feed_title</a>";
3177                         } else {
3178                                 print $feed_title;
3179                         }
3180
3181                         if ($search) {
3182                                 $search_q = "&q=$search&m=$match_on&smode=$search_mode";
3183                         }
3184
3185                         if ($user_page_offset > 1) {
3186                                 print " [$user_page_offset] ";
3187                         }
3188
3189                         if (!$bottom) {
3190                                 print "
3191                                         <a target=\"_new\" 
3192                                                 href=\"backend.php?op=rss&id=$feed_id&is_cat=$is_cat$search_q\">
3193                                                 <img class=\"noborder\" 
3194                                                         alt=\"".__('Generated feed')."\" src=\"images/feed-icon-12x12.png\">
3195                                         </a>";
3196                         }
3197                                 
3198                         print "</td>";
3199                         print "</tr></table>";
3200
3201                 }
3202
3203         function outputFeedList($link, $tags = false) {
3204
3205                 print "<ul class=\"feedList\" id=\"feedList\">";
3206
3207                 $owner_uid = $_SESSION["uid"];
3208
3209                 /* virtual feeds */
3210
3211                 if (get_pref($link, 'ENABLE_FEED_CATS')) {
3212                         print "<li class=\"feedCat\">".__('Special')."</li>";
3213                         print "<li id=\"feedCatHolder\" class=\"feedCatHolder\"><ul class=\"feedCatList\">";
3214                 }
3215
3216                 $num_starred = getFeedUnread($link, -1);
3217                 $num_published = getFeedUnread($link, -2);
3218
3219                 $class = "virt";
3220
3221                 if ($num_starred > 0) $class .= "Unread";
3222
3223                 printFeedEntry(-1, $class, __("Starred articles"), $num_starred, 
3224                         "images/mark_set.png", $link);
3225
3226                 $class = "virt";
3227
3228                 if ($num_published > 0) $class .= "Unread";
3229
3230                 printFeedEntry(-2, $class, __("Published articles"), $num_published, 
3231                         "images/pub_set.png", $link);
3232
3233                 if (get_pref($link, 'ENABLE_FEED_CATS')) {
3234                         print "</ul>";
3235                 }
3236
3237                 if (!$tags) {
3238
3239                         if (GLOBAL_ENABLE_LABELS && get_pref($link, 'ENABLE_LABELS')) {
3240         
3241                                 $result = db_query($link, "SELECT id,sql_exp,description FROM
3242                                         ttrss_labels WHERE owner_uid = '$owner_uid' ORDER by description");
3243                 
3244                                 if (db_num_rows($result) > 0) {
3245                                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
3246                                                 print "<li class=\"feedCat\">".__('Labels')."</li>";
3247                                                 print "<li id=\"feedCatHolder\" class=\"feedCatHolder\"><ul class=\"feedCatList\">";
3248                                         } else {
3249                                                 print "<li><hr></li>";
3250                                         }
3251                                 }
3252                 
3253                                 while ($line = db_fetch_assoc($result)) {
3254         
3255                                         error_reporting (0);
3256
3257                                         $label_id = -$line['id'] - 11;
3258                                         $count = getFeedUnread($link, $label_id);
3259
3260                                         $class = "label";
3261         
3262                                         if ($count > 0) {
3263                                                 $class .= "Unread";
3264                                         }
3265                                         
3266                                         error_reporting (DEFAULT_ERROR_LEVEL);
3267         
3268                                         printFeedEntry($label_id, 
3269                                                 $class, $line["description"], 
3270                                                 $count, "images/label.png", $link);
3271                 
3272                                 }
3273
3274                                 if (db_num_rows($result) > 0) {
3275                                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
3276                                                 print "</ul>";
3277                                         }
3278                                 }
3279
3280                         }
3281
3282                         if (!get_pref($link, 'ENABLE_FEED_CATS')) {
3283                                 print "<li><hr></li>";
3284                         }
3285
3286                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
3287                                 if (get_pref($link, "FEEDS_SORT_BY_UNREAD")) {
3288                                         $order_by_qpart = "category,unread DESC,title";
3289                                 } else {
3290                                         $order_by_qpart = "category,title";
3291                                 }
3292                         } else {
3293                                 if (get_pref($link, "FEEDS_SORT_BY_UNREAD")) {
3294                                         $order_by_qpart = "unread DESC,title";
3295                                 } else {                
3296                                         $order_by_qpart = "title";
3297                                 }
3298                         }
3299
3300                         $result = db_query($link, "SELECT ttrss_feeds.*,
3301                                 SUBSTRING(last_updated,1,19) AS last_updated_noms,
3302                                 (SELECT COUNT(id) FROM ttrss_entries,ttrss_user_entries
3303                                         WHERE feed_id = ttrss_feeds.id AND unread = true
3304                                                 AND ttrss_user_entries.ref_id = ttrss_entries.id
3305                                                 AND owner_uid = '$owner_uid') as unread,
3306                                 cat_id,last_error,
3307                                 ttrss_feed_categories.title AS category,
3308                                 ttrss_feed_categories.collapsed 
3309                                 FROM ttrss_feeds LEFT JOIN ttrss_feed_categories 
3310                                         ON (ttrss_feed_categories.id = cat_id)                          
3311                                 WHERE 
3312                                         ttrss_feeds.hidden = false AND
3313                                         ttrss_feeds.owner_uid = '$owner_uid' AND parent_feed IS NULL
3314                                 ORDER BY $order_by_qpart"); 
3315
3316                         $actid = $_GET["actid"];
3317         
3318                         /* real feeds */
3319         
3320                         $lnum = 0;
3321         
3322                         $total_unread = 0;
3323
3324                         $category = "";
3325
3326                         $short_date = get_pref($link, 'SHORT_DATE_FORMAT');
3327         
3328                         while ($line = db_fetch_assoc($result)) {
3329                         
3330                                 $feed = trim($line["title"]);
3331
3332                                 if (!$feed) $feed = "[Untitled]";
3333
3334                                 $feed_id = $line["id"];   
3335         
3336                                 $subop = $_GET["subop"];
3337                                 
3338                                 $unread = $line["unread"];
3339
3340                                 if (get_pref($link, 'HEADLINES_SMART_DATE')) {
3341                                         $last_updated = smart_date_time(strtotime($line["last_updated_noms"]));
3342                                 } else {
3343                                         $last_updated = date($short_date, strtotime($line["last_updated_noms"]));
3344                                 }
3345
3346                                 $rtl_content = sql_bool_to_bool($line["rtl_content"]);
3347
3348                                 if ($rtl_content) {
3349                                         $rtl_tag = "dir=\"RTL\"";
3350                                 } else {
3351                                         $rtl_tag = "";
3352                                 }
3353
3354                                 $tmp_result = db_query($link,
3355                                         "SELECT id,COUNT(unread) AS unread
3356                                         FROM ttrss_feeds LEFT JOIN ttrss_user_entries 
3357                                                 ON (ttrss_feeds.id = ttrss_user_entries.feed_id) 
3358                                         WHERE parent_feed = '$feed_id' AND unread = true 
3359                                         GROUP BY ttrss_feeds.id");
3360                         
3361                                 if (db_num_rows($tmp_result) > 0) {                             
3362                                         while ($l = db_fetch_assoc($tmp_result)) {
3363                                                 $unread += $l["unread"];
3364                                         }
3365                                 }
3366
3367                                 $cat_id = $line["cat_id"];
3368
3369                                 $tmp_category = $line["category"];
3370
3371                                 if (!$tmp_category) {
3372                                         $tmp_category = __("Uncategorized");
3373                                 }
3374                                 
3375         //                      $class = ($lnum % 2) ? "even" : "odd";
3376
3377                                 if ($line["last_error"]) {
3378                                         $class = "error";
3379                                 } else {
3380                                         $class = "feed";
3381                                 }
3382         
3383                                 if ($unread > 0) $class .= "Unread";
3384         
3385                                 if ($actid == $feed_id) {
3386                                         $class .= "Selected";
3387                                 }
3388         
3389                                 $total_unread += $unread;
3390
3391                                 if ($category != $tmp_category && get_pref($link, 'ENABLE_FEED_CATS')) {
3392                                 
3393                                         if ($category) {
3394                                                 print "</ul></li>";
3395                                         }
3396                                 
3397                                         $category = $tmp_category;
3398
3399                                         $collapsed = $line["collapsed"];
3400
3401                                         // workaround for NULL category
3402                                         if ($category == __("Uncategorized")) {
3403                                                 if ($_COOKIE["ttrss_vf_uclps"] == 1) {
3404                                                         $collapsed = "t";
3405                                                 }
3406                                         }
3407
3408                                         if ($collapsed == "t" || $collapsed == "1") {
3409                                                 $holder_class = "invisible";
3410                                                 $ellipsis = "...";
3411                                         } else {
3412                                                 $holder_class = "feedCatHolder";
3413                                                 $ellipsis = "";
3414                                         }
3415
3416                                         $cat_id = sprintf("%d", $cat_id);
3417
3418                                         $cat_unread = getCategoryUnread($link, $cat_id);
3419
3420                                         $catctr_class = ($cat_unread > 0) ? "catCtrHasUnread" : "catCtrNoUnread";
3421
3422                                         print "<li class=\"feedCat\" id=\"FCAT-$cat_id\">
3423                                                 <a id=\"FCATN-$cat_id\" href=\"javascript:toggleCollapseCat($cat_id)\">$tmp_category</a>
3424                                                         <a href=\"#\" onclick=\"javascript:viewCategory($cat_id)\" id=\"FCAP-$cat_id\">
3425                                                         <span id=\"FCATCTR-$cat_id\" title=\"Click to browse category\" 
3426                                                         class=\"$catctr_class\">($cat_unread)</span> $ellipsis
3427                                                         </a></li>";
3428
3429                                         // !!! NO SPACE before <ul...feedCatList - breaks firstChild DOM function
3430                                         // -> keyboard navigation, etc.
3431                                         print "<li id=\"feedCatHolder\" class=\"$holder_class\"><ul class=\"feedCatList\" id=\"FCATLIST-$cat_id\">";
3432                                 }
3433         
3434                                 printFeedEntry($feed_id, $class, $feed, $unread, 
3435                                         ICONS_DIR."/$feed_id.ico", $link, $rtl_content, 
3436                                         $last_updated, $line["last_error"]);
3437         
3438                                 ++$lnum;
3439                         }
3440
3441                         if (db_num_rows($result) == 0) {
3442                                 print "<li>".__('No feeds to display.')."</li>";
3443                         }
3444
3445                 } else {
3446
3447                         // tags
3448
3449 /*                      $result = db_query($link, "SELECT tag_name,count(ttrss_entries.id) AS count
3450                                 FROM ttrss_tags,ttrss_entries,ttrss_user_entries WHERE
3451                                 post_int_id = ttrss_user_entries.int_id AND 
3452                                 unread = true AND ref_id = ttrss_entries.id
3453                                 AND ttrss_tags.owner_uid = '$owner_uid' GROUP BY tag_name       
3454                         UNION
3455                                 select tag_name,0 as count FROM ttrss_tags WHERE owner_uid = '$owner_uid'
3456                         ORDER BY tag_name"); */
3457
3458                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
3459                                 print "<li class=\"feedCat\">".__('Tags')."</li>";
3460                                 print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
3461                         }
3462
3463                         $result = db_query($link, "SELECT tag_name,SUM((SELECT COUNT(int_id) 
3464                                 FROM ttrss_user_entries WHERE int_id = post_int_id 
3465                                         AND unread = true)) AS count FROM ttrss_tags 
3466                                 WHERE owner_uid = ".$_SESSION['uid']." GROUP BY tag_name ORDER BY tag_name");
3467
3468                         $tags = array();
3469         
3470                         while ($line = db_fetch_assoc($result)) {
3471                                 $tags[$line["tag_name"]] += $line["count"];
3472                         }
3473         
3474                         foreach (array_keys($tags) as $tag) {
3475         
3476                                 $unread = $tags[$tag];
3477         
3478                                 $class = "tag";
3479         
3480                                 if ($unread > 0) {
3481                                         $class .= "Unread";
3482                                 }
3483         
3484                                 printFeedEntry($tag, $class, $tag, $unread, "images/tag.png", $link);
3485         
3486                         } 
3487
3488                         if (db_num_rows($result) == 0) {
3489                                 print "<li>No tags to display.</li>";
3490                         }
3491
3492                         if (get_pref($link, 'ENABLE_FEED_CATS')) {
3493                                 print "</ul>";
3494                         }
3495
3496                 }
3497
3498                 print "</ul>";
3499
3500         }
3501
3502         function get_article_tags($link, $id) {
3503
3504                 $a_id = db_escape_string($id);
3505
3506                 $tmp_result = db_query($link, "SELECT DISTINCT tag_name, 
3507                         owner_uid as owner FROM
3508                         ttrss_tags WHERE post_int_id = (SELECT int_id FROM ttrss_user_entries WHERE
3509                                 ref_id = '$a_id' LIMIT 1) ORDER BY tag_name");
3510
3511                 $tags = array();        
3512         
3513                 while ($tmp_line = db_fetch_assoc($tmp_result)) {
3514                         array_push($tags, $tmp_line["tag_name"]);                               
3515                 }
3516
3517                 return $tags;
3518         }
3519
3520         function trim_value(&$value) {
3521                 $value = trim($value);
3522         }       
3523
3524         function trim_array($array) {
3525                 $tmp = $array;
3526                 array_walk($tmp, 'trim_value');
3527                 return $tmp;
3528         }
3529
3530         function tag_is_valid($tag) {
3531                 if ($tag == '') return false;
3532                 if (preg_match("/^[0-9]*$/", $tag)) return false;
3533
3534                 $tag = iconv("utf-8", "utf-8", $tag);
3535                 if (!$tag) return false;
3536
3537                 return true;
3538         }
3539
3540         function render_login_form($link, $mobile = false) {
3541                 if (!$mobile) {
3542                         require_once "login_form.php";
3543                 } else {
3544                         require_once "mobile/login_form.php";
3545                 }
3546         }
3547
3548         // from http://developer.apple.com/internet/safari/faq.html
3549         function no_cache_incantation() {
3550                 header("Expires: Mon, 22 Dec 1980 00:00:00 GMT"); // Happy birthday to me :)
3551                 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified
3552                 header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); // HTTP/1.1
3553                 header("Cache-Control: post-check=0, pre-check=0", false);
3554                 header("Pragma: no-cache"); // HTTP/1.0
3555         }
3556
3557         function format_warning($msg, $id = "") {
3558                 return "<div class=\"warning\" id=\"$id\"> 
3559                         <img src=\"images/sign_excl.png\">$msg</div>";
3560         }
3561
3562         function format_notice($msg) {
3563                 return "<div class=\"notice\"> 
3564                         <img src=\"images/sign_info.png\">$msg</div>";
3565         }
3566
3567         function format_error($msg) {
3568                 return "<div class=\"error\"> 
3569                         <img src=\"images/sign_excl.png\">$msg</div>";
3570         }
3571
3572         function print_notice($msg) {
3573                 return print format_notice($msg);
3574         }
3575
3576         function print_warning($msg) {
3577                 return print format_warning($msg);
3578         }
3579
3580         function print_error($msg) {
3581                 return print format_error($msg);
3582         }
3583
3584
3585         function T_sprintf() {
3586                 $args = func_get_args();
3587                 return vsprintf(__(array_shift($args)), $args);
3588         }
3589
3590         function outputArticleXML($link, $id, $feed_id, $mark_as_read = true) {
3591
3592                 /* we can figure out feed_id from article id anyway, why do we
3593                  * pass feed_id here? */
3594
3595                 $result = db_query($link, "SELECT feed_id FROM ttrss_user_entries
3596                         WHERE ref_id = '$id'");
3597
3598                 $feed_id = db_fetch_result($result, 0, "feed_id");
3599
3600                 print "<article id='$id'><![CDATA[";
3601
3602                 $result = db_query($link, "SELECT rtl_content FROM ttrss_feeds
3603                         WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
3604
3605                 if (db_num_rows($result) == 1) {
3606                         $rtl_content = sql_bool_to_bool(db_fetch_result($result, 0, "rtl_content"));
3607                 } else {
3608                         $rtl_content = false;
3609                 }
3610
3611                 if ($rtl_content) {
3612                         $rtl_tag = "dir=\"RTL\"";
3613                         $rtl_class = "RTL";
3614                 } else {
3615                         $rtl_tag = "";
3616                         $rtl_class = "";
3617                 }
3618
3619                 if ($mark_as_read) {
3620                         $result = db_query($link, "UPDATE ttrss_user_entries 
3621                                 SET unread = false,last_read = NOW() 
3622                                 WHERE ref_id = '$id' AND owner_uid = " . $_SESSION["uid"]);
3623                 }
3624
3625                 $result = db_query($link, "SELECT title,link,content,feed_id,comments,int_id,
3626                         SUBSTRING(updated,1,16) as updated,
3627                         (SELECT icon_url FROM ttrss_feeds WHERE id = feed_id) as icon_url,
3628                         num_comments,
3629                         author
3630                         FROM ttrss_entries,ttrss_user_entries
3631                         WHERE   id = '$id' AND ref_id = id AND owner_uid = " . $_SESSION["uid"]);
3632
3633                 if ($result) {
3634
3635                         $link_target = "";
3636
3637                         if (get_pref($link, 'OPEN_LINKS_IN_NEW_WINDOW')) {
3638                                 $link_target = "target=\"_new\"";
3639                         }
3640
3641                         $line = db_fetch_assoc($result);
3642
3643                         if ($line["icon_url"]) {
3644                                 $feed_icon = "<img class=\"feedIcon\" src=\"" . $line["icon_url"] . "\">";
3645                         } else {
3646                                 $feed_icon = "&nbsp;";
3647                         }
3648
3649 /*                      if ($line["comments"] && $line["link"] != $line["comments"]) {
3650                                 $entry_comments = "(<a href=\"".$line["comments"]."\">Comments</a>)";
3651                         } else {
3652                                 $entry_comments = "";
3653                         } */
3654
3655                         $num_comments = $line["num_comments"];
3656                         $entry_comments = "";
3657
3658                         if ($num_comments > 0) {
3659                                 if ($line["comments"]) {
3660                                         $comments_url = $line["comments"];
3661                                 } else {
3662                                         $comments_url = $line["link"];
3663                                 }
3664                                 $entry_comments = "<a $link_target href=\"$comments_url\">$num_comments comments</a>";
3665                         } else {
3666                                 if ($line["comments"] && $line["link"] != $line["comments"]) {
3667                                         $entry_comments = "<a $link_target href=\"".$line["comments"]."\">comments</a>";
3668                                 }                               
3669                         }
3670
3671                         print "<div class=\"postReply\">";
3672
3673                         print "<div class=\"postHeader\">";
3674
3675                         $entry_author = $line["author"];
3676
3677                         if ($entry_author) {
3678                                 $entry_author = __(" - by ") . $entry_author;
3679                         }
3680
3681                         $parsed_updated = date(get_pref($link, 'LONG_DATE_FORMAT'), 
3682                                 strtotime($line["updated"]));
3683                 
3684                         print "<div class=\"postDate$rtl_class\">$parsed_updated</div>";
3685
3686                         if ($line["link"]) {
3687                                 print "<div clear='both'><a $link_target href=\"" . $line["link"] . "\">" . 
3688                                         $line["title"] . "</a>$entry_author</div>";
3689                         } else {
3690                                 print "<div clear='both'>" . $line["title"] . "$entry_author</div>";
3691                         }
3692
3693                         $tmp_result = db_query($link, "SELECT DISTINCT tag_name FROM
3694                                 ttrss_tags WHERE post_int_id = " . $line["int_id"] . "
3695                                 ORDER BY tag_name");
3696         
3697                         $tags_str = "";
3698                         $f_tags_str = "";
3699
3700                         $num_tags = 0;
3701
3702                         while ($tmp_line = db_fetch_assoc($tmp_result)) {
3703                                 $num_tags++;
3704                                 $tag = $tmp_line["tag_name"];
3705                                 $tag_escaped = str_replace("'", "\\'", $tag);
3706
3707                                 $tag_str = "<a href=\"javascript:viewfeed('$tag_escaped')\">$tag</a>, ";
3708                                 
3709                                 if ($num_tags == 6) {
3710                                         $tags_str .= "<a href=\"javascript:showBlockElement('allEntryTags')\">...</a>";
3711                                 } else if ($num_tags < 6) {
3712                                         $tags_str .= $tag_str;
3713                                 }
3714                                 $f_tags_str .= $tag_str;
3715                         }
3716
3717                         $tags_str = preg_replace("/, $/", "", $tags_str);
3718                         $f_tags_str = preg_replace("/, $/", "", $f_tags_str);
3719
3720                         if (!$entry_comments) $entry_comments = "&nbsp;"; # placeholder
3721
3722                         if (!$tags_str) $tags_str = '<span class="tagList">'.__('no tags').'</span>';
3723
3724                         print "<div style='float : right'>$tags_str 
3725                                 <a title=\"Edit tags for this article\" 
3726                                         href=\"javascript:editArticleTags($id, $feed_id)\">(+)</a></div>
3727                                 <div clear='both'>$entry_comments</div>";
3728
3729                         print "</div>";
3730
3731                         print "<div class=\"postIcon\">" . $feed_icon . "</div>";
3732                         print "<div class=\"postContent\">";
3733                         
3734                         if (db_num_rows($tmp_result) > 0) {
3735                                 print "<div id=\"allEntryTags\">".__('Tags:')." $f_tags_str</div>";
3736                         }
3737
3738                         $line["content"] = sanitize_rss($link, $line["content"]);
3739
3740                         if (get_pref($link, 'OPEN_LINKS_IN_NEW_WINDOW')) {
3741                                 $line["content"] = preg_replace("/href=/i", "target=\"_new\" href=", $line["content"]);
3742                         }
3743
3744                         print $line["content"] . "</div>";
3745                         
3746                         print "</div>";
3747
3748                 }
3749
3750                 print "]]></article>";
3751
3752         }
3753
3754         function outputHeadlinesList($link, $feed, $subop, $view_mode, $limit, $cat_view,
3755                                         $next_unread_feed, $offset) {
3756
3757                 $timing_info = getmicrotime();
3758
3759                 $topmost_article_ids = array();
3760
3761                 if (!$offset) {
3762                         $offset = 0;
3763                 }
3764
3765                 if ($subop == "undefined") $subop = "";
3766
3767                 if ($subop == "CatchupSelected") {
3768                         $ids = split(",", db_escape_string($_GET["ids"]));
3769                         $cmode = sprintf("%d", $_GET["cmode"]);
3770
3771                         catchupArticlesById($link, $ids, $cmode);
3772                 }
3773
3774                 if ($subop == "ForceUpdate" && sprintf("%d", $feed) > 0) {
3775                         update_generic_feed($link, $feed, $cat_view);
3776                 }
3777
3778                 if ($subop == "MarkAllRead")  {
3779                         catchup_feed($link, $feed, $cat_view);
3780
3781                         if (get_pref($link, 'ON_CATCHUP_SHOW_NEXT_FEED')) {
3782                                 if ($next_unread_feed) {
3783                                         $feed = $next_unread_feed;
3784                                 }
3785                         }
3786                 }
3787
3788                 if ($feed_id > 0) {             
3789                         $result = db_query($link,
3790                                 "SELECT id FROM ttrss_feeds WHERE id = '$feed' LIMIT 1");
3791                 
3792                         if (db_num_rows($result) == 0) {
3793                                 print "<div align='center'>".__('Feed not found.')."</div>";                            
3794                                 return;
3795                         }
3796                 }
3797
3798                 if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
3799
3800                         $result = db_query($link, "SELECT rtl_content FROM ttrss_feeds
3801                                 WHERE id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
3802
3803                         if (db_num_rows($result) == 1) {
3804                                 $rtl_content = sql_bool_to_bool(db_fetch_result($result, 0, "rtl_content"));
3805                         } else {
3806                                 $rtl_content = false;
3807                         }
3808         
3809                         if ($rtl_content) {
3810                                 $rtl_tag = "dir=\"RTL\"";
3811                         } else {
3812                                 $rtl_tag = "";
3813                         }
3814                 } else {
3815                         $rtl_tag = "";
3816                         $rtl_content = false;
3817                 }
3818
3819                 $script_dt_add = get_script_dt_add();
3820
3821                 /// START /////////////////////////////////////////////////////////////////////////////////
3822
3823                 $search = db_escape_string($_GET["query"]);
3824                 $search_mode = db_escape_string($_GET["search_mode"]);
3825                 $match_on = db_escape_string($_GET["match_on"]);
3826
3827                 if (!$match_on) {
3828                         $match_on = "both";
3829                 }
3830
3831                 $real_offset = $offset * $limit;
3832
3833                 if ($_GET["debug"]) $timing_info = print_checkpoint("H0", $timing_info);
3834
3835                 $qfh_ret = queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, 
3836                         $search, $search_mode, $match_on, false, $real_offset);
3837
3838                 if ($_GET["debug"]) $timing_info = print_checkpoint("H1", $timing_info);
3839
3840                 $result = $qfh_ret[0];
3841                 $feed_title = $qfh_ret[1];
3842                 $feed_site_url = $qfh_ret[2];
3843                 $last_error = $qfh_ret[3];
3844                 
3845                 /// STOP //////////////////////////////////////////////////////////////////////////////////
3846
3847                 if (!$offset) {
3848                         print "<div id=\"headlinesContainer\" $rtl_tag>";
3849
3850                         if (!$result) {
3851                                 print "<div align='center'>".__("Could not display feed (query failed). Please check label match syntax or local configuration.")."</div>";
3852                                 return;
3853                         }
3854
3855                         print_headline_subtoolbar($link, $feed_site_url, $feed_title, false, 
3856                                 $rtl_content, $feed, $cat_view, $search, $match_on, $search_mode, 
3857                                 $offset, $limit);
3858
3859                         print "<div id=\"headlinesInnerContainer\" onscroll=\"headlines_scroll_handler()\">";
3860                 }
3861
3862                 if (db_num_rows($result) > 0) {
3863
3864 #                       print "\{$offset}";
3865
3866                         if (!get_pref($link, 'COMBINED_DISPLAY_MODE') && !$offset) {
3867                                 print "<table class=\"headlinesList\" id=\"headlinesList\" 
3868                                         cellspacing=\"0\">";
3869                         }
3870
3871                         $lnum = 0;
3872         
3873                         error_reporting (DEFAULT_ERROR_LEVEL);
3874         
3875                         $num_unread = 0;
3876         
3877                         while ($line = db_fetch_assoc($result)) {
3878
3879                                 $class = ($lnum % 2) ? "even" : "odd";
3880         
3881                                 $id = $line["id"];
3882                                 $feed_id = $line["feed_id"];
3883
3884                                 if (count($topmost_article_ids) < 5) {
3885                                         array_push($topmost_article_ids, $id);
3886                                 }
3887
3888                                 if ($line["last_read"] == "" && 
3889                                                 ($line["unread"] != "t" && $line["unread"] != "1")) {
3890         
3891                                         $update_pic = "<img id='FUPDPIC-$id' src=\"images/updated.png\" 
3892                                                 alt=\"Updated\">";
3893                                 } else {
3894                                         $update_pic = "<img id='FUPDPIC-$id' src=\"images/blank_icon.gif\" 
3895                                                 alt=\"Updated\">";
3896                                 }
3897         
3898                                 if ($line["unread"] == "t" || $line["unread"] == "1") {
3899                                         $class .= "Unread";
3900                                         ++$num_unread;
3901                                         $is_unread = true;
3902                                 } else {
3903                                         $is_unread = false;
3904                                 }
3905         
3906                                 if ($line["marked"] == "t" || $line["marked"] == "1") {
3907                                         $marked_pic = "<img id=\"FMPIC-$id\" src=\"images/mark_set.png\" 
3908                                                 class=\"markedPic\"
3909                                                 alt=\"Reset mark\" onclick='javascript:tMark($id)'>";
3910                                 } else {
3911                                         $marked_pic = "<img id=\"FMPIC-$id\" src=\"images/mark_unset.png\" 
3912                                                 class=\"markedPic\"
3913                                                 alt=\"Set mark\" onclick='javascript:tMark($id)'>";
3914                                 }
3915
3916                                 if ($line["published"] == "t" || $line["published"] == "1") {
3917                                         $published_pic = "<img id=\"FPPIC-$id\" src=\"images/pub_set.png\" 
3918                                                 class=\"markedPic\"
3919                                                 alt=\"Unpublish\" onclick='javascript:tPub($id)'>";
3920                                 } else {
3921                                         $published_pic = "<img id=\"FPPIC-$id\" src=\"images/pub_unset.png\" 
3922                                                 class=\"markedPic\"
3923                                                 alt=\"Publish\" onclick='javascript:tPub($id)'>";
3924                                 }
3925
3926 #                               $content_link = "<a target=\"_new\" href=\"".$line["link"]."\">" .
3927 #                                       $line["title"] . "</a>";
3928
3929                                 $content_link = "<a href=\"javascript:view($id,$feed_id);\">" .
3930                                         $line["title"] . "</a>";
3931
3932 #                               $content_link = "<a href=\"javascript:viewContentUrl('".$line["link"]."');\">" .
3933 #                                       $line["title"] . "</a>";
3934
3935                                 if (get_pref($link, 'HEADLINES_SMART_DATE')) {
3936                                         $updated_fmt = smart_date_time(strtotime($line["updated_noms"]));
3937                                 } else {
3938                                         $short_date = get_pref($link, 'SHORT_DATE_FORMAT');
3939                                         $updated_fmt = date($short_date, strtotime($line["updated_noms"]));
3940                                 }                               
3941
3942                                 if (get_pref($link, 'SHOW_CONTENT_PREVIEW')) {
3943                                         $content_preview = truncate_string(strip_tags($line["content_preview"]), 
3944                                                 100);
3945                                 }
3946
3947                                 $entry_author = $line["author"];
3948
3949                                 if ($entry_author) {
3950                                         $entry_author = " - by $entry_author";
3951                                 }
3952
3953                                 if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) {
3954                                         
3955                                         print "<tr class='$class' id='RROW-$id'>";
3956                 
3957                                         print "<td class='hlUpdPic'>$update_pic</td>";
3958                 
3959                                         print "<td class='hlSelectRow'>
3960                                                 <input type=\"checkbox\" onclick=\"tSR(this)\"
3961                                                         id=\"RCHK-$id\">
3962                                                 </td>";
3963                 
3964                                         print "<td class='hlMarkedPic'>$marked_pic</td>";
3965                                         print "<td class='hlMarkedPic'>$published_pic</td>";
3966
3967                                         if ($line["feed_title"]) {                      
3968                                                 print "<td class='hlContent'>$content_link</td>";
3969                                                 print "<td class='hlFeed'>
3970                                                         <a href=\"javascript:viewfeed($feed_id, '', false)\">".
3971                                                                 $line["feed_title"]."</a>&nbsp;</td>";
3972                                         } else {                        
3973                                                 print "<td class='hlContent' valign='middle'>";
3974
3975                                                 print "<a href=\"javascript:view($id,$feed_id);\">" .
3976                                                         $line["title"];
3977
3978                                                 if (get_pref($link, 'SHOW_CONTENT_PREVIEW')) {
3979                                                         if ($content_preview) {
3980                                                                 print "<span class=\"contentPreview\"> - $content_preview</span>";
3981                                                         }
3982                                                 }
3983                 
3984                                                 print "</a>";
3985                                                 print "</td>";
3986                                         }
3987                                         
3988                                         print "<td class=\"hlUpdated\"><nobr>$updated_fmt&nbsp;</nobr></td>";
3989                 
3990                                         print "</tr>";
3991
3992                                 } else {
3993                                         
3994                                         if ($is_unread) {
3995                                                 $add_class = "Unread";
3996                                         } else {
3997                                                 $add_class = "";
3998                                         }       
3999                                         
4000                                         print "<div class=\"cdmArticle$add_class\" 
4001                                                 id=\"RROW-$id\" onmouseover='cdmMouseIn(this)' 
4002                                                 onmouseout='cdmMouseOut(this)'>";
4003
4004                                         print "<div class=\"cdmHeader\">";
4005
4006                                         print "<div class=\"articleUpdated\">$updated_fmt</div>";
4007                                         
4008                                         print "<a class=\"title\" 
4009                                                 onclick=\"javascript:toggleUnread($id, 0)\"
4010                                                 target=\"new\" href=\"".$line["link"]."\">".$line["title"]."</a>";
4011
4012                                         print $entry_author;
4013
4014                                         if ($line["feed_title"]) {      
4015                                                 print "&nbsp;(<a href='javascript:viewfeed($feed_id)'>".$line["feed_title"]."</a>)";
4016                                         }
4017
4018                                         print "</div>";
4019
4020                                         print "<div class=\"cdmContent\">" . $line["content_preview"] . "</div><br clear=\"all\">";
4021
4022                                         print "<div class=\"cdmFooter\"><span class='s0'>";
4023
4024                                         /* print "<div class=\"markedPic\">Star it: $marked_pic</div>"; */
4025
4026                                         print __("Select:").
4027                                                         " <input type=\"checkbox\" onclick=\"toggleSelectRowById(this, 
4028                                                         'RROW-$id')\" class=\"feedCheckBox\" id=\"RCHK-$id\">";
4029
4030                                         print "</span><span class='s1'>$marked_pic</span> ";
4031                                         print "<span class='s1'>$published_pic</span> ";
4032
4033                                         $tags = get_article_tags($link, $id);
4034
4035                                         $tags_str = "";
4036
4037                                         foreach ($tags as $tag) {
4038                                                 $num_tags++;
4039                                                 $tags_str .= "<a href=\"javascript:viewfeed('$tag')\">$tag</a>, "; 
4040                                         }
4041
4042                                         $tags_str = preg_replace("/, $/", "", $tags_str);
4043
4044                                         if ($tags_str == "") $tags_str = "no tags";
4045
4046 //                                      print "<img src='images/tag.png' class='markedPic'>";
4047
4048                                         print "<span class='s1'>Tags: $tags_str <a title=\"Edit tags for this article\" 
4049                                                         href=\"javascript:editArticleTags($id, $feed_id, true)\">(+)</a>";
4050
4051                                         print "</span>";
4052
4053                                         print "<span class='s2'>Toggle: <a class=\"cdmToggleLink\"
4054                                                         href=\"javascript:toggleUnread($id)\">
4055                                                         Unread</a></span>";
4056
4057                                         print "</div>";
4058                                         print "</div>"; 
4059
4060                                 }                               
4061         
4062                                 ++$lnum;
4063                         }
4064
4065                         if (!get_pref($link, 'COMBINED_DISPLAY_MODE') && !$offset) {                    
4066                                 print "</table>";
4067                         }
4068
4069 //                      print_headline_subtoolbar($link, 
4070 //                              "javascript:catchupPage()", "Mark page as read", true, $rtl_content);
4071
4072
4073                 } else {
4074                         if (!$offset) print "<div class='whiteBox'>".__('No articles found.')."</div>";
4075                 }
4076
4077                 if (!$offset) {
4078                         print "</div>";
4079                         print "</div>";
4080                 }
4081
4082                 return $topmost_article_ids;
4083         }
4084
4085 // from here: http://www.roscripts.com/Create_tag_cloud-71.html
4086
4087         function printTagCloud($link) {
4088
4089                 /* get first ref_id to count from */
4090
4091                 /*
4092
4093                 $query = "";
4094
4095                 if (DB_TYPE == "pgsql") {
4096                         $query = "SELECT MIN(id) AS id FROM ttrss_user_entries, ttrss_entries 
4097                                 WHERE int_id = id AND owner_uid = ".$_SESSION["uid"]."
4098                                 AND date_entered > NOW() - INTERVAL '30 days'";
4099                 } else {
4100                         $query = "SELECT MIN(id) AS id FROM ttrss_user_entries, ttrss_entries 
4101                                 WHERE int_id = id AND owner_uid = ".$_SESSION["uid"]." 
4102                                 AND date_entered > DATE_SUB(NOW(), INTERVAL 30 DAY)";
4103                 }
4104
4105                 $result = db_query($link, $query);
4106                 $first_id = db_fetch_result($result, 0, "id"); */
4107
4108                 //AND post_int_id >= '$first_id'
4109                 $query = "SELECT tag_name, COUNT(post_int_id) AS count 
4110                         FROM ttrss_tags WHERE owner_uid = ".$_SESSION["uid"]." 
4111                         GROUP BY tag_name ORDER BY count DESC LIMIT 50";
4112
4113                 $result = db_query($link, $query);
4114
4115                 $tags = array();
4116
4117                 while ($line = db_fetch_assoc($result)) {
4118                         $tags[$line["tag_name"]] = $line["count"];
4119                 }
4120
4121                 ksort($tags);
4122
4123                 $max_size = 32; // max font size in pixels
4124                 $min_size = 11; // min font size in pixels
4125                    
4126                 // largest and smallest array values
4127                 $max_qty = max(array_values($tags));
4128                 $min_qty = min(array_values($tags));
4129                    
4130                 // find the range of values
4131                 $spread = $max_qty - $min_qty;
4132                 if ($spread == 0) { // we don't want to divide by zero
4133                                 $spread = 1;
4134                 }
4135                    
4136                 // set the font-size increment
4137                 $step = ($max_size - $min_size) / ($spread);
4138                    
4139                 // loop through the tag array
4140                 foreach ($tags as $key => $value) {
4141                         // calculate font-size
4142                         // find the $value in excess of $min_qty
4143                         // multiply by the font-size increment ($size)
4144                         // and add the $min_size set above
4145                         $size = round($min_size + (($value - $min_qty) * $step));
4146
4147                         $key_escaped = str_replace("'", "\\'", $key);
4148
4149                         echo "<a href=\"javascript:viewfeed('$key_escaped') \" style=\"font-size: " . 
4150                                 $size . "px\" title=\"$value articles tagged with " . 
4151                                 $key . '">' . $key . '</a> ';
4152                 }
4153         }
4154
4155         function print_checkpoint($n, $s) {
4156                 $ts = getmicrotime();   
4157                 echo sprintf("<!-- CP[$n] %.4f seconds -->", $ts - $s);
4158                 return $ts;
4159         }
4160
4161         function sanitize_tag($tag) {
4162                 $tag = trim($tag);
4163
4164                 $tag = mb_strtolower($tag, 'utf-8');
4165
4166                 $tag = preg_replace('/[\"\+\>\<]/', "", $tag);  
4167
4168 //              $tag = str_replace('"', "", $tag);      
4169 //              $tag = str_replace("+", " ", $tag);     
4170                 $tag = str_replace("technorati tag: ", "", $tag);
4171
4172                 return $tag;
4173         }
4174
4175         function generate_publish_key() {
4176                 return sha1(uniqid(rand(), true));
4177         }
4178
4179 ?>