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