]>
git.wh0rd.org - tt-rss.git/blob - functions.php
3 /* if ($_GET["debug"]) {
4 define('DEFAULT_ERROR_LEVEL', E_ALL);
6 define('DEFAULT_ERROR_LEVEL', E_ERROR | E_WARNING | E_PARSE);
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';
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';
23 define('MAGPIE_OUTPUT_ENCODING', 'UTF-8');
25 function purge_feed($link, $feed_id, $purge_interval, $debug = false) {
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'"); */
35 $pg_version = get_pgsql_version($link);
37 if (preg_match("/^7\./", $pg_version) ||
preg_match("/^8\.0/", $pg_version)) {
39 $result = db_query($link, "DELETE FROM ttrss_user_entries WHERE
40 ttrss_entries.id = ref_id AND
42 feed_id = '$feed_id' AND
43 ttrss_entries.date_entered < NOW() - INTERVAL '$purge_interval days'");
47 $result = db_query($link, "DELETE FROM ttrss_user_entries
49 WHERE ttrss_entries.id = ref_id AND
51 feed_id = '$feed_id' AND
52 ttrss_entries.date_entered < NOW() - INTERVAL '$purge_interval days'");
55 $rows = pg_affected_rows($result);
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)"); */
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
68 feed_id = '$feed_id' AND
69 ttrss_entries.date_entered < DATE_SUB(NOW(), INTERVAL $purge_interval DAY)");
71 $rows = mysql_affected_rows($link);
76 print "Purged feed $feed_id ($purge_interval): deleted $rows articles\n";
80 function global_purge_old_posts($link, $do_output = false, $limit = false) {
82 $random_qpart = sql_random_function();
85 $limit_qpart = "LIMIT $limit";
90 $result = db_query($link,
91 "SELECT id,purge_interval,owner_uid FROM ttrss_feeds
92 ORDER BY $random_qpart $limit_qpart");
94 while ($line = db_fetch_assoc($result)) {
96 $feed_id = $line["id"];
97 $purge_interval = $line["purge_interval"];
98 $owner_uid = $line["owner_uid"];
100 if ($purge_interval == 0) {
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'");
106 if (db_num_rows($tmp_result) != 0) {
107 $purge_interval = db_fetch_result($tmp_result, 0, "value");
112 // print "Feed $feed_id: purge interval = $purge_interval\n";
115 if ($purge_interval > 0) {
116 purge_feed($link, $feed_id, $purge_interval, $do_output);
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");
126 function purge_old_posts($link) {
128 $user_id = $_SESSION["uid"];
130 $result = db_query($link, "SELECT id,purge_interval FROM ttrss_feeds
131 WHERE owner_uid = '$user_id'");
133 while ($line = db_fetch_assoc($result)) {
135 $feed_id = $line["id"];
136 $purge_interval = $line["purge_interval"];
138 if ($purge_interval == 0) $purge_interval = get_pref($link, 'PURGE_OLD_DAYS');
140 if ($purge_interval > 0) {
141 purge_feed($link, $feed_id, $purge_interval);
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");
150 function update_all_feeds($link, $fetch, $user_id = false, $force_daemon = false) {
152 if (WEB_DEMO_MODE
) return;
155 $user_id = $_SESSION["uid"];
156 purge_old_posts($link);
159 // db_query($link, "BEGIN");
161 if (MAX_UPDATE_TIME
> 0) {
162 if (DB_TYPE
== "mysql") {
165 $q_order = "RANDOM()";
168 $q_order = "last_updated DESC";
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'
178 while ($line = db_fetch_assoc($result)) {
179 $upd_intl = $line["update_interval"];
181 if (!$upd_intl ||
$upd_intl == 0) {
182 $upd_intl = get_pref($link, 'DEFAULT_UPDATE_INTERVAL', $user_id, false);
186 // Updates for this feed are disabled
190 if ($fetch ||
(!$line["last_updated"] ||
191 time() - strtotime($line["last_updated"]) > ($upd_intl * 60))) {
193 // print "<!-- feed: ".$line["feed_url"]." -->";
195 update_rss_feed($link, $line["feed_url"], $line["id"], $force_daemon);
197 $upd_elapsed = time() - $upd_start;
199 if (MAX_UPDATE_TIME
> 0 && $upd_elapsed > MAX_UPDATE_TIME
) {
205 // db_query($link, "COMMIT");
209 function fetch_file_contents($url) {
210 if (USE_CURL_FOR_ICONS
) {
211 $tmpfile = tempnam(TMP_DIRECTORY
, "ttrss-tmp");
213 $ch = curl_init($url);
214 $fp = fopen($tmpfile, "w");
217 curl_setopt($ch, CURLOPT_FILE
, $fp);
223 $contents = file_get_contents($tmpfile);
229 return file_get_contents($url);
234 // adapted from wordpress favicon plugin by Jeff Minard (http://thecodepro.com/)
235 // http://dev.wp-plugins.org/file/favatars/trunk/favatars.php
237 function get_favicon_url($url) {
239 if ($html = @fetch_file_contents
($url)) {
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]);
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;
253 $faviconURL = $url.'/'.$linkUrl;
257 // If unsuccessful, attempt to "guess" the favicon location
258 $urlParts = parse_url($url);
259 $faviconURL = $urlParts['scheme'].'://'.$urlParts['host'].'/favicon.ico';
263 // Run a test to see if what we have attempted to get actually exists.
264 if(USE_CURL_FOR_ICONS ||
url_validate($faviconURL)) {
271 function url_validate($link) {
273 $url_parts = @parse_url
($link);
275 if ( empty( $url_parts["host"] ) )
278 if ( !empty( $url_parts["path"] ) ) {
279 $documentpath = $url_parts["path"];
284 if ( !empty( $url_parts["query"] ) )
285 $documentpath .= "?" . $url_parts["query"];
287 $host = $url_parts["host"];
288 $port = $url_parts["port"];
293 $socket = @fsockopen
( $host, $port, $errno, $errstr, 30 );
298 fwrite ($socket, "HEAD ".$documentpath." HTTP/1.0\r\nHost: $host\r\n\r\n");
300 $http_response = fgets( $socket, 22 );
302 $responses = "/(200 OK)|(30[0-9] Moved)/";
303 if ( preg_match($responses, $http_response) ) {
312 function check_feed_favicon($site_url, $feed, $link) {
313 $favicon_url = get_favicon_url($site_url);
315 # print "FAVICON [$site_url]: $favicon_url\n";
319 $icon_file = ICONS_DIR
. "/$feed.ico";
321 if ($favicon_url && !file_exists($icon_file)) {
322 $contents = fetch_file_contents($favicon_url);
324 $fp = fopen($icon_file, "w");
327 fwrite($fp, $contents);
329 chmod($icon_file, 0644);
333 error_reporting(DEFAULT_ERROR_LEVEL
);
337 function update_rss_feed($link, $feed_url, $feed, $ignore_daemon = false) {
339 if (WEB_DEMO_MODE
) return;
341 if (DAEMON_REFRESH_ONLY
&& !$_GET["daemon"] && !$ignore_daemon) {
345 $result = db_query($link, "SELECT update_interval,auth_login,auth_pass
346 FROM ttrss_feeds WHERE id = '$feed'");
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"));
351 $update_interval = db_fetch_result($result, 0, "update_interval");
353 if ($update_interval < 0) { return; }
355 $feed = db_escape_string($feed);
357 $fetch_url = $feed_url;
359 if ($auth_login && $auth_pass) {
360 $url_parts = array();
361 preg_match("/(^[^:]*):\/\/(.*)/", $fetch_url, $url_parts);
363 if ($url_parts[1] && $url_parts[2]) {
364 $fetch_url = $url_parts[1] . "://$auth_login:$auth_pass@" . $url_parts[2];
369 if (RSS_BACKEND_TYPE
== "magpie") {
371 $rss = fetch_rss($fetch_url);
372 error_reporting (DEFAULT_ERROR_LEVEL
);
373 } else if (RSS_BACKEND_TYPE
== "simplepie") {
375 if (!file_exists(SIMPLEPIE_CACHE_DIR
)) {
376 mkdir(SIMPLEPIE_CACHE_DIR
);
379 $rss = new SimplePie();
380 $rss->feed_url($fetch_url);
381 $rss->cache_location(SIMPLEPIE_CACHE_DIR
);
385 $feed = db_escape_string($feed);
389 if (RSS_BACKEND_TYPE
== "simplepie") {
390 $rss_check = $rss->data
;
395 // db_query($link, "BEGIN");
397 $result = db_query($link, "SELECT title,icon_url,site_url,owner_uid
398 FROM ttrss_feeds WHERE id = '$feed'");
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");
404 $owner_uid = db_fetch_result($result, 0, "owner_uid");
406 if (get_pref($link, 'ENABLE_FEED_ICONS', $owner_uid, false)) {
407 check_feed_favicon($rss->channel
["link"], $feed, $link);
410 if (!$registered_title ||
$registered_title == "[Unknown]") {
412 if (RSS_BACKEND_TYPE
== "magpie") {
413 $feed_title = db_escape_string($rss->channel
["title"]);
415 $feed_title = $rss->get_feed_title();
418 db_query($link, "UPDATE ttrss_feeds SET
419 title = '$feed_title' WHERE id = '$feed'");
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_"]);
427 $site_url = $rss->get_feed_link();
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'");
435 // print "I: " . $rss->channel["image"]["url"];
437 if (RSS_BACKEND_TYPE
== "magpie") {
438 $icon_url = $rss->image
["url"];
440 $icon_url = $rss->get_image_url(); # FIXME
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'");
451 $result = db_query($link, "SELECT reg_exp,
452 ttrss_filter_types.name AS name,
453 ttrss_filter_actions.name AS action,
455 FROM ttrss_filters,ttrss_filter_types,ttrss_filter_actions WHERE
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')");
462 while ($line = db_fetch_assoc($result)) {
463 if (!$filters[$line["name"]]) $filters[$line["name"]] = array();
465 $filter["reg_exp"] = $line["reg_exp"];
466 $filter["action"] = $line["action"];
467 $filter["action_param"] = $line["action_param"];
469 array_push($filters[$line["name"]], $filter);
472 if (RSS_BACKEND_TYPE
== "magpie") {
473 $iterator = $rss->items
;
475 if (!$iterator ||
!is_array($iterator)) $iterator = $rss->entries
;
476 if (!$iterator ||
!is_array($iterator)) $iterator = $rss;
479 $iterator = $rss->get_items();
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'"); */
489 foreach ($iterator as $item) {
491 if (RSS_BACKEND_TYPE
== "magpie") {
493 $entry_guid = $item["id"];
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"]);
499 if (!$entry_guid) continue;
501 $entry_timestamp = "";
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'];
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);
512 if ($entry_timestamp == "") {
513 $entry_timestamp = time();
514 $no_orig_date = 'true';
516 $no_orig_date = 'false';
519 $entry_timestamp_fmt = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp);
521 $entry_title = trim(strip_tags($item["title"]));
523 // strange Magpie workaround
524 $entry_link = $item["link_"];
525 if (!$entry_link) $entry_link = $item["link"];
527 if (!$entry_title) continue;
528 # if (!$entry_link) continue;
530 $entry_link = strip_tags($entry_link);
532 $entry_content = $item["content:escaped"];
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"];
540 // if (!$entry_content) continue;
543 if (is_array($entry_content)) {
544 $entry_content = $entry_content["encoded"];
545 if (!$entry_content) $entry_content = $entry_content["escaped"];
549 // print_r(htmlspecialchars($entry_content));
552 $entry_content_unescaped = $entry_content;
553 $content_hash = "SHA1:" . sha1(strip_tags($entry_content));
555 $entry_comments = strip_tags($item["comments"]);
557 $entry_author = db_escape_string(strip_tags($item['dc']['creator']));
559 if (!$entry_author) {
560 $entry_author = db_escape_string(strip_tags($item['author']));
563 $entry_guid = db_escape_string(strip_tags($entry_guid));
565 $result = db_query($link, "SELECT id FROM ttrss_entries
566 WHERE guid = '$entry_guid'");
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);
573 $num_comments = db_escape_string($item["slash"]["comments"]);
575 if (!$num_comments) $num_comments = 0;
580 $entry_content = sanitize_rss($entry_content);
582 db_query($link, "BEGIN");
584 if (db_num_rows($result) == 0) {
586 // base post entry does not exist, create it
588 $result = db_query($link,
589 "INSERT INTO ttrss_entries
605 '$entry_timestamp_fmt',
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
619 $base_entry_id = db_fetch_result($result, 0, "id");
621 db_query($link, "UPDATE ttrss_entries SET date_entered = NOW()
622 WHERE id = '$base_entry_id'");
625 // now it should exist, if not - bad luck then
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,
634 WHERE guid = '$entry_guid'");
636 if (db_num_rows($result) == 1) {
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,
645 $ref_id = db_fetch_result($result, 0, "id");
647 // check for user post link to main table
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'";
653 $dupcheck_qpart = "";
656 // error_reporting(0);
658 $tuple = get_filter_name($entry_title, $entry_content,
659 $entry_link, $filters);
661 $filter_name = $tuple[0];
662 $filter_param = $tuple[1];
664 if ($filter_name == "filter") {
668 // error_reporting (DEFAULT_ERROR_LEVEL);
670 $result = db_query($link,
671 "SELECT ref_id FROM ttrss_user_entries WHERE
672 ref_id = '$ref_id' AND owner_uid = '$owner_uid'
675 // okay it doesn't exist - create user entry
676 if (db_num_rows($result) == 0) {
678 if ($filter_name != 'catchup') {
680 $last_read_qpart = 'NULL';
683 $last_read_qpart = 'NOW()';
686 if ($filter_name == 'mark') {
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)");
699 $post_needs_update = false;
701 if (get_pref($link, "UPDATE_POST_ON_CHECKSUM_CHANGE", $owner_uid, false) &&
702 ($content_hash != $orig_content_hash)) {
703 $post_needs_update = true;
706 if ($orig_title != $entry_title) {
707 $post_needs_update = true;
710 if ($orig_num_comments != $num_comments) {
711 $post_needs_update = true;
714 // this doesn't seem to be very reliable
716 // if ($orig_timestamp != $entry_timestamp && !$orig_no_orig_date) {
717 // $post_needs_update = true;
720 // if post needs update, update it and mark all user entries
721 // linking to this post as updated
722 if ($post_needs_update) {
724 // print "<!-- post $orig_title needs update : $post_needs_update -->";
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'");
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'");
735 db_query($link, "UPDATE ttrss_user_entries
736 SET last_read = null WHERE ref_id = '$ref_id' AND unread = false");
742 db_query($link, "COMMIT");
745 // <a href="http://technorati.com/tag/Xorg" rel="tag">Xorg</a>, //
749 preg_match_all("/<a.*?href=.http:\/\/.*?technorati.com\/tag\/([^\"\'>]+)/i",
750 $entry_content_unescaped, $entry_tags);
752 // print "<br>$entry_title : $entry_content_unescaped<br>";
753 // print_r($entry_tags);
756 $entry_tags = $entry_tags[1];
758 # check for manual tags
760 if ($filter_name == "tag") {
762 $manual_tags = trim_array(split(",", $filter_param));
764 foreach ($manual_tags as $tag) {
765 if (!preg_match("/^[0-9]*$/", $tag)) {
766 array_push($entry_tags, $tag);
771 if (count($entry_tags) > 0) {
773 db_query($link, "BEGIN");
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'");
781 if (db_num_rows($result) == 1) {
783 $entry_id = db_fetch_result($result, 0, "id");
784 $entry_int_id = db_fetch_result($result, 0, "int_id");
786 foreach ($entry_tags as $tag) {
787 $tag = db_escape_string(strtolower($tag));
789 $tag = str_replace("+", " ", $tag);
790 $tag = str_replace("technorati tag: ", "", $tag);
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");
796 // print db_fetch_result($result, 0, "id");
798 if ($result && db_num_rows($result) == 0) {
800 // print "tagging $entry_id as $tag<br>";
802 db_query($link, "INSERT INTO ttrss_tags
803 (owner_uid,tag_name,post_int_id)
804 VALUES ('$owner_uid','$tag', '$entry_int_id')");
808 db_query($link, "COMMIT");
812 db_query($link, "UPDATE ttrss_feeds
813 SET last_updated = NOW(), last_error = '' WHERE id = '$feed'");
815 // db_query($link, "COMMIT");
818 $error_msg = db_escape_string(magpie_error());
820 "UPDATE ttrss_feeds SET last_error = '$error_msg',
821 last_updated = NOW() WHERE id = '$feed'");
826 function print_select($id, $default, $values, $attributes = "") {
827 print "<select name=\"$id\" id=\"$id\" $attributes>";
828 foreach ($values as $v) {
834 print "<option$sel>$v</option>";
839 function print_select_hash($id, $default, $values, $attributes = "") {
840 print "<select name=\"$id\" id='$id' $attributes>";
841 foreach (array_keys($values) as $v) {
847 print "<option $sel value=\"$v\">".$values[$v]."</option>";
853 function get_filter_name($title, $content, $link, $filters) {
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"]);
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"]);
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"]);
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"]);
896 function printFeedEntry($feed_id, $class, $feed_title, $unread, $icon_file, $link,
897 $rtl_content = false, $last_updated = false, $last_error = false) {
899 if (file_exists($icon_file) && filesize($icon_file) > 0) {
900 $feed_icon = "<img id=\"FIMG-$feed_id\" src=\"$icon_file\">";
902 $feed_icon = "<img id=\"FIMG-$feed_id\" src=\"images/blank_icon.gif\">";
906 $rtl_tag = "dir=\"rtl\"";
908 $rtl_tag = "dir=\"ltr\"";
911 $error_notify_msg = "";
914 $link_title = "Error: $last_error ($last_updated)";
915 $error_notify_msg = "(Error)";
916 } else if ($last_updated) {
917 $link_title = "Updated: $last_updated";
920 $feed = "<a title=\"$link_title\" id=\"FEEDL-$feed_id\"
921 href=\"#\" onclick=\"javascript:viewfeed('$feed_id', '', false);\">$feed_title</a>";
923 print "<li id=\"FEEDR-$feed_id\" class=\"$class\">";
924 if (get_pref($link, 'ENABLE_FEED_ICONS')) {
928 print "<span $rtl_tag id=\"FEEDN-$feed_id\">$feed</span>";
933 $fctr_class = "class=\"invisible\"";
936 print " <span $rtl_tag $fctr_class id=\"FEEDCTR-$feed_id\">
937 (<span id=\"FEEDU-$feed_id\">$unread</span>)</span>";
939 if (get_pref($link, "EXTENDED_FEEDLIST")) {
940 print "<div class=\"feedExtInfo\">
941 <span id=\"FLUPD-$feed_id\">$last_updated $error_notify_msg</span></div>";
948 function getmicrotime() {
949 list($usec, $sec) = explode(" ",microtime());
950 return ((float)$usec +
(float)$sec);
953 function print_radio($id, $default, $values, $attributes = "") {
954 foreach ($values as $v) {
962 $sel .= " value=\"1\"";
964 $sel .= " value=\"0\"";
967 print "<input class=\"noborder\"
968 type=\"radio\" $sel $attributes name=\"$id\"> $v ";
973 function initialize_user_prefs($link, $uid) {
975 $uid = db_escape_string($uid);
977 db_query($link, "BEGIN");
979 $result = db_query($link, "SELECT pref_name,def_value FROM ttrss_prefs");
981 $u_result = db_query($link, "SELECT pref_name
982 FROM ttrss_user_prefs WHERE owner_uid = '$uid'");
984 $active_prefs = array();
986 while ($line = db_fetch_assoc($u_result)) {
987 array_push($active_prefs, $line["pref_name"]);
990 while ($line = db_fetch_assoc($result)) {
991 if (array_search($line["pref_name"], $active_prefs) === FALSE) {
992 // print "adding " . $line["pref_name"] . "<br>";
994 db_query($link, "INSERT INTO ttrss_user_prefs
995 (owner_uid,pref_name,value) VALUES
996 ('$uid', '".$line["pref_name"]."','".$line["def_value"]."')");
1001 db_query($link, "COMMIT");
1005 function lookup_user_id($link, $user) {
1007 $result = db_query($link, "SELECT id FROM ttrss_users WHERE
1010 if (db_num_rows($result) == 1) {
1011 return db_fetch_result($result, 0, "id");
1017 function http_authenticate_user($link) {
1019 if (!$_SERVER["PHP_AUTH_USER"]) {
1021 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS RSSGen"');
1022 header('HTTP/1.0 401 Unauthorized');
1026 $auth_result = authenticate_user($link,
1027 $_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);
1029 if (!$auth_result) {
1030 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS RSSGen"');
1031 header('HTTP/1.0 401 Unauthorized');
1039 function authenticate_user($link, $login, $password, $force_auth = false) {
1041 if (!SINGLE_USER_MODE
) {
1043 $pwd_hash = 'SHA1:' . sha1($password);
1045 if ($force_auth && defined('_DEBUG_USER_SWITCH')) {
1046 $query = "SELECT id,login,access_level
1047 FROM ttrss_users WHERE
1050 $query = "SELECT id,login,access_level
1051 FROM ttrss_users WHERE
1052 login = '$login' AND pwd_hash = '$pwd_hash'";
1055 $result = db_query($link, $query);
1057 if (db_num_rows($result) == 1) {
1058 $_SESSION["uid"] = db_fetch_result($result, 0, "id");
1059 $_SESSION["name"] = db_fetch_result($result, 0, "login");
1060 $_SESSION["access_level"] = db_fetch_result($result, 0, "access_level");
1062 db_query($link, "UPDATE ttrss_users SET last_login = NOW() WHERE id = " .
1065 $user_theme = get_user_theme_path($link);
1067 $_SESSION["theme"] = $user_theme;
1068 $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"];
1070 initialize_user_prefs($link, $_SESSION["uid"]);
1079 $_SESSION["uid"] = 1;
1080 $_SESSION["name"] = "admin";
1082 $user_theme = get_user_theme_path($link);
1084 $_SESSION["theme"] = $user_theme;
1085 $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"];
1087 initialize_user_prefs($link, $_SESSION["uid"]);
1093 function make_password($length = 8) {
1096 $possible = "0123456789abcdfghjkmnpqrstvwxyzABCDFGHJKMNPQRSTVWXYZ";
1100 while ($i < $length) {
1101 $char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
1103 if (!strstr($password, $char)) {
1111 // this is called after user is created to initialize default feeds, labels
1114 // user preferences are checked on every login, not here
1116 function initialize_user($link, $uid) {
1118 db_query($link, "insert into ttrss_labels (owner_uid,sql_exp,description)
1119 values ('$uid','unread = true', 'Unread articles')");
1121 db_query($link, "insert into ttrss_labels (owner_uid,sql_exp,description)
1122 values ('$uid','last_read is null and unread = false', 'Updated articles')");
1124 db_query($link, "insert into ttrss_feeds (owner_uid,title,feed_url)
1125 values ('$uid', 'Tiny Tiny RSS: New Releases',
1126 'http://tt-rss.spb.ru/releases.rss')");
1130 function logout_user() {
1132 if (isset($_COOKIE[session_name()])) {
1133 setcookie(session_name(), '', time()-42000, '/');
1137 function get_script_urlpath() {
1138 return preg_replace('/\/[^\/]*$/', "", $_SERVER["REQUEST_URI"]);
1141 function get_login_redirect() {
1142 $server = $_SERVER["SERVER_NAME"];
1144 if (ENABLE_LOGIN_SSL
) {
1145 $protocol = "https";
1150 $url_path = get_script_urlpath();
1152 $redirect_uri = "$protocol://$server$url_path/login.php";
1154 return $redirect_uri;
1157 function validate_session($link) {
1158 if (SESSION_CHECK_ADDRESS
&& $_SESSION["uid"]) {
1159 if ($_SESSION["ip_address"]) {
1160 if ($_SESSION["ip_address"] != $_SERVER["REMOTE_ADDR"]) {
1168 function basic_nosid_redirect_check() {
1169 if (!SINGLE_USER_MODE
) {
1170 if (!$_COOKIE[get_session_cookie_name()]) {
1171 $redirect_uri = get_login_redirect();
1172 $return_to = preg_replace('/.*?\//', '', $_SERVER["REQUEST_URI"]);
1173 header("Location: $redirect_uri?rt=$return_to");
1179 function login_sequence($link) {
1180 if (!SINGLE_USER_MODE
) {
1182 if (defined('_DEBUG_USER_SWITCH') && $_SESSION["uid"]) {
1183 $swu = db_escape_string($_REQUEST["swu"]);
1185 $_SESSION["prefs_cache"] = false;
1186 return authenticate_user($link, $swu, null, true);
1190 if (!validate_session($link)) {
1192 $redirect_uri = get_login_redirect();
1193 $return_to = preg_replace('/.*?\//', '', $_SERVER["REQUEST_URI"]);
1194 header("Location: $redirect_uri?rt=$return_to");
1198 if (!USE_HTTP_AUTH
) {
1199 if (!$_SESSION["uid"]) {
1200 $redirect_uri = get_login_redirect();
1201 $return_to = preg_replace('/.*?\//', '', $_SERVER["REQUEST_URI"]);
1202 header("Location: $redirect_uri?rt=$return_to");
1206 if (!$_SESSION["uid"]) {
1207 if (!$_SERVER["PHP_AUTH_USER"]) {
1209 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS"');
1210 header('HTTP/1.0 401 Unauthorized');
1214 $auth_result = authenticate_user($link,
1215 $_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);
1217 if (!$auth_result) {
1218 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS"');
1219 header('HTTP/1.0 401 Unauthorized');
1226 return authenticate_user($link, "admin", null);
1230 function truncate_string($str, $max_len) {
1231 if (mb_strlen($str, "utf-8") > $max_len - 3) {
1232 return mb_substr($str, 0, $max_len, "utf-8") . "...";
1238 function get_user_theme_path($link) {
1239 $result = db_query($link, "SELECT theme_path
1241 ttrss_themes,ttrss_users
1242 WHERE ttrss_themes.id = theme_id AND ttrss_users.id = " . $_SESSION["uid"]);
1243 if (db_num_rows($result) != 0) {
1244 return db_fetch_result($result, 0, "theme_path");
1250 function smart_date_time($timestamp) {
1251 if (date("Y.m.d", $timestamp) == date("Y.m.d")) {
1252 return date("G:i", $timestamp);
1253 } else if (date("Y", $timestamp) == date("Y")) {
1254 return date("M d, G:i", $timestamp);
1256 return date("Y/m/d G:i", $timestamp);
1260 function smart_date($timestamp) {
1261 if (date("Y.m.d", $timestamp) == date("Y.m.d")) {
1263 } else if (date("Y", $timestamp) == date("Y")) {
1264 return date("D m", $timestamp);
1266 return date("Y/m/d", $timestamp);
1270 function sql_bool_to_string($s) {
1271 if ($s == "t" ||
$s == "1") {
1278 function sql_bool_to_bool($s) {
1279 if ($s == "t" ||
$s == "1") {
1287 function toggleEvenOdd($a) {
1294 function sanity_check($link) {
1299 $result = db_query($link, "SELECT schema_version FROM ttrss_version");
1300 $schema_version = db_fetch_result($result, 0, "schema_version");
1302 if ($schema_version != SCHEMA_VERSION
) {
1306 if (DB_TYPE
== "mysql") {
1307 $result = db_query($link, "SELECT true", false);
1308 if (db_num_rows($result) != 1) {
1313 error_reporting (DEFAULT_ERROR_LEVEL
);
1315 if ($error_code != 0) {
1316 print_error_xml($error_code);
1323 function file_is_locked($filename) {
1325 $fp = fopen($filename, "r");
1326 error_reporting(DEFAULT_ERROR_LEVEL
);
1328 if (flock($fp, LOCK_EX | LOCK_NB
)) {
1329 flock($fp, LOCK_UN
);
1339 function make_lockfile($filename) {
1340 $fp = fopen($filename, "w");
1342 if (flock($fp, LOCK_EX | LOCK_NB
)) {
1349 function sql_random_function() {
1350 if (DB_TYPE
== "mysql") {
1357 function catchup_feed($link, $feed, $cat_view) {
1359 if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
1364 $cat_qpart = "cat_id = '$feed'";
1366 $cat_qpart = "cat_id IS NULL";
1369 $tmp_result = db_query($link, "SELECT id
1370 FROM ttrss_feeds WHERE $cat_qpart AND owner_uid = " .
1373 while ($tmp_line = db_fetch_assoc($tmp_result)) {
1375 $tmp_feed = $tmp_line["id"];
1377 db_query($link, "UPDATE ttrss_user_entries
1378 SET unread = false,last_read = NOW()
1379 WHERE feed_id = '$tmp_feed' AND owner_uid = " . $_SESSION["uid"]);
1382 } else if ($feed > 0) {
1384 $tmp_result = db_query($link, "SELECT id
1385 FROM ttrss_feeds WHERE parent_feed = '$feed'
1386 ORDER BY cat_id,title");
1388 $parent_ids = array();
1390 if (db_num_rows($tmp_result) > 0) {
1391 while ($p = db_fetch_assoc($tmp_result)) {
1392 array_push($parent_ids, "feed_id = " . $p["id"]);
1395 $children_qpart = implode(" OR ", $parent_ids);
1397 db_query($link, "UPDATE ttrss_user_entries
1398 SET unread = false,last_read = NOW()
1399 WHERE (feed_id = '$feed' OR $children_qpart)
1400 AND owner_uid = " . $_SESSION["uid"]);
1403 db_query($link, "UPDATE ttrss_user_entries
1404 SET unread = false,last_read = NOW()
1405 WHERE feed_id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
1408 } else if ($feed < 0 && $feed > -10) { // special, like starred
1411 db_query($link, "UPDATE ttrss_user_entries
1412 SET unread = false,last_read = NOW()
1413 WHERE marked = true AND owner_uid = ".$_SESSION["uid"]);
1416 } else if ($feed < -10) { // label
1418 // TODO make this more efficient
1420 $label_id = -$feed - 11;
1422 $tmp_result = db_query($link, "SELECT sql_exp FROM ttrss_labels
1423 WHERE id = '$label_id'");
1426 $sql_exp = db_fetch_result($tmp_result, 0, "sql_exp");
1428 db_query($link, "BEGIN");
1430 $tmp2_result = db_query($link,
1434 ttrss_user_entries,ttrss_entries,ttrss_feeds
1436 ref_id = ttrss_entries.id AND
1437 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1439 ttrss_user_entries.owner_uid = " . $_SESSION["uid"]);
1441 while ($tmp_line = db_fetch_assoc($tmp2_result)) {
1442 db_query($link, "UPDATE
1445 unread = false, last_read = NOW()
1447 int_id = " . $tmp_line["int_id"]);
1450 db_query($link, "COMMIT");
1452 /* db_query($link, "UPDATE ttrss_user_entries,ttrss_entries
1453 SET unread = false,last_read = NOW()
1456 AND owner_uid = ".$_SESSION["uid"]); */
1460 db_query($link, "BEGIN");
1462 $tag_name = db_escape_string($feed);
1464 $result = db_query($link, "SELECT post_int_id FROM ttrss_tags
1465 WHERE tag_name = '$tag_name' AND owner_uid = " . $_SESSION["uid"]);
1467 while ($line = db_fetch_assoc($result)) {
1468 db_query($link, "UPDATE ttrss_user_entries SET
1469 unread = false, last_read = NOW()
1470 WHERE int_id = " . $line["post_int_id"]);
1472 db_query($link, "COMMIT");
1476 function update_generic_feed($link, $feed, $cat_view) {
1480 $cat_qpart = "cat_id = '$feed'";
1482 $cat_qpart = "cat_id IS NULL";
1485 $tmp_result = db_query($link, "SELECT feed_url FROM ttrss_feeds
1486 WHERE $cat_qpart AND owner_uid = " . $_SESSION["uid"]);
1488 while ($tmp_line = db_fetch_assoc($tmp_result)) {
1489 $feed_url = $tmp_line["feed_url"];
1490 update_rss_feed($link, $feed_url, $feed, ENABLE_UPDATE_DAEMON
);
1494 $tmp_result = db_query($link, "SELECT feed_url FROM ttrss_feeds
1495 WHERE id = '$feed'");
1496 $feed_url = db_fetch_result($tmp_result, 0, "feed_url");
1497 update_rss_feed($link, $feed_url, $feed, ENABLE_UPDATE_DAEMON
);
1501 function getAllCounters($link, $omode = "tflc") {
1502 /* getLabelCounters($link);
1503 getFeedCounters($link);
1504 getTagCounters($link);
1505 getGlobalCounters($link);
1506 if (get_pref($link, 'ENABLE_FEED_CATS')) {
1507 getCategoryCounters($link);
1510 if (!$omode) $omode = "tflc";
1512 getGlobalCounters($link);
1514 if (strchr($omode, "l")) getLabelCounters($link);
1515 if (strchr($omode, "f")) getFeedCounters($link);
1516 if (strchr($omode, "t")) getTagCounters($link);
1517 if (strchr($omode, "c")) {
1518 if (get_pref($link, 'ENABLE_FEED_CATS')) {
1519 getCategoryCounters($link);
1524 function getCategoryCounters($link) {
1525 $result = db_query($link, "SELECT cat_id,SUM((SELECT COUNT(int_id)
1526 FROM ttrss_user_entries WHERE feed_id = ttrss_feeds.id
1527 AND unread = true)) AS unread FROM ttrss_feeds
1529 hidden = false AND owner_uid = ".$_SESSION["uid"]." GROUP BY cat_id");
1531 while ($line = db_fetch_assoc($result)) {
1532 $line["cat_id"] = sprintf("%d", $line["cat_id"]);
1533 print "<counter type=\"category\" id=\"".$line["cat_id"]."\" counter=\"".
1534 $line["unread"]."\"/>";
1538 function getCategoryUnread($link, $cat) {
1541 $cat_query = "cat_id = '$cat'";
1543 $cat_query = "cat_id IS NULL";
1546 $result = db_query($link, "SELECT id FROM ttrss_feeds WHERE $cat_query
1548 AND owner_uid = " . $_SESSION["uid"]);
1550 $cat_feeds = array();
1551 while ($line = db_fetch_assoc($result)) {
1552 array_push($cat_feeds, "feed_id = " . $line["id"]);
1555 if (count($cat_feeds) == 0) return 0;
1557 $match_part = implode(" OR ", $cat_feeds);
1559 $result = db_query($link, "SELECT COUNT(int_id) AS unread
1560 FROM ttrss_user_entries
1561 WHERE unread = true AND ($match_part) AND owner_uid = " . $_SESSION["uid"]);
1565 # this needs to be rewritten
1566 while ($line = db_fetch_assoc($result)) {
1567 $unread +
= $line["unread"];
1574 function getFeedUnread($link, $feed, $is_cat = false) {
1575 $n_feed = sprintf("%d", $feed);
1578 return getCategoryUnread($link, $n_feed);
1579 } else if ($n_feed == -1) {
1580 $match_part = "marked = true";
1581 } else if ($n_feed > 0) {
1583 $result = db_query($link, "SELECT id FROM ttrss_feeds
1584 WHERE parent_feed = '$n_feed'
1586 AND owner_uid = " . $_SESSION["uid"]);
1588 if (db_num_rows($result) > 0) {
1590 $linked_feeds = array();
1591 while ($line = db_fetch_assoc($result)) {
1592 array_push($linked_feeds, "feed_id = " . $line["id"]);
1595 array_push($linked_feeds, "feed_id = $n_feed");
1597 $match_part = implode(" OR ", $linked_feeds);
1599 $result = db_query($link, "SELECT COUNT(int_id) AS unread
1600 FROM ttrss_user_entries
1601 WHERE unread = true AND ($match_part)
1602 AND owner_uid = " . $_SESSION["uid"]);
1606 # this needs to be rewritten
1607 while ($line = db_fetch_assoc($result)) {
1608 $unread +
= $line["unread"];
1614 $match_part = "feed_id = '$n_feed'";
1616 } else if ($feed < -10) {
1618 $label_id = -$feed - 11;
1620 $result = db_query($link, "SELECT sql_exp FROM ttrss_labels WHERE
1621 id = '$label_id' AND owner_uid = " . $_SESSION["uid"]);
1623 $match_part = db_fetch_result($result, 0, "sql_exp");
1628 $result = db_query($link, "SELECT count(int_id) AS unread
1629 FROM ttrss_user_entries,ttrss_feeds,ttrss_entries WHERE
1630 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1631 ttrss_user_entries.ref_id = ttrss_entries.id AND
1632 ttrss_feeds.hidden = false AND
1633 unread = true AND ($match_part) AND ttrss_user_entries.owner_uid = " . $_SESSION["uid"]);
1637 $result = db_query($link, "SELECT COUNT(post_int_id) AS unread
1638 FROM ttrss_tags,ttrss_user_entries
1639 WHERE tag_name = '$feed' AND post_int_id = int_id AND unread = true AND
1640 ttrss_tags.owner_uid = " . $_SESSION["uid"]);
1643 $unread = db_fetch_result($result, 0, "unread");
1648 /* FIXME this needs reworking */
1650 function getGlobalUnread($link, $user_id = false) {
1653 $user_id = $_SESSION["uid"];
1656 $result = db_query($link, "SELECT count(ttrss_entries.id) as c_id FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
1657 WHERE unread = true AND
1658 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1659 ttrss_user_entries.ref_id = ttrss_entries.id AND
1661 ttrss_user_entries.owner_uid = '$user_id'");
1662 $c_id = db_fetch_result($result, 0, "c_id");
1666 function getGlobalCounters($link, $global_unread = -1) {
1667 if ($global_unread == -1) {
1668 $global_unread = getGlobalUnread($link);
1670 print "<counter type=\"global\" id='global-unread'
1671 counter='$global_unread'/>";
1673 $result = db_query($link, "SELECT COUNT(id) AS fn FROM
1674 ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"]);
1676 $subscribed_feeds = db_fetch_result($result, 0, "fn");
1678 print "<counter type=\"global\" id='subscribed-feeds'
1679 counter='$subscribed_feeds'/>";
1683 function getTagCounters($link, $smart_mode = SMART_RPC_COUNTERS
) {
1686 if (!$_SESSION["tctr_last_value"]) {
1687 $_SESSION["tctr_last_value"] = array();
1691 $old_counters = $_SESSION["tctr_last_value"];
1693 $tctrs_modified = false;
1695 /* $result = db_query($link, "SELECT tag_name,count(ttrss_entries.id) AS count
1696 FROM ttrss_tags,ttrss_entries,ttrss_user_entries WHERE
1697 ttrss_user_entries.ref_id = ttrss_entries.id AND
1698 ttrss_tags.owner_uid = ".$_SESSION["uid"]." AND
1699 post_int_id = ttrss_user_entries.int_id AND unread = true GROUP BY tag_name
1701 select tag_name,0 as count FROM ttrss_tags
1702 WHERE ttrss_tags.owner_uid = ".$_SESSION["uid"]); */
1704 $result = db_query($link, "SELECT tag_name,SUM((SELECT COUNT(int_id)
1705 FROM ttrss_user_entries WHERE int_id = post_int_id
1706 AND unread = true)) AS count FROM ttrss_tags
1707 WHERE owner_uid = 2 GROUP BY tag_name ORDER BY tag_name");
1711 while ($line = db_fetch_assoc($result)) {
1712 $tags[$line["tag_name"]] +
= $line["count"];
1715 foreach (array_keys($tags) as $tag) {
1716 $unread = $tags[$tag];
1718 $tag = htmlspecialchars($tag);
1720 if (!$smart_mode ||
$old_counters[$tag] != $unread) {
1721 $old_counters[$tag] = $unread;
1722 $tctrs_modified = true;
1723 print "<counter type=\"tag\" id=\"$tag\" counter=\"$unread\"/>";
1728 if ($smart_mode && $tctrs_modified) {
1729 $_SESSION["tctr_last_value"] = $old_counters;
1734 function getLabelCounters($link, $smart_mode = SMART_RPC_COUNTERS
, $ret_mode = false) {
1737 if (!$_SESSION["lctr_last_value"]) {
1738 $_SESSION["lctr_last_value"] = array();
1744 $old_counters = $_SESSION["lctr_last_value"];
1745 $lctrs_modified = false;
1747 $result = db_query($link, "SELECT count(ttrss_entries.id) as count FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
1748 WHERE marked = true AND ttrss_user_entries.ref_id = ttrss_entries.id AND
1749 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1750 unread = true AND ttrss_user_entries.owner_uid = ".$_SESSION["uid"]);
1752 $count = db_fetch_result($result, 0, "count");
1755 print "<counter type=\"label\" id=\"-1\" counter=\"$count\"/>";
1757 $ret_arr["-1"]["counter"] = $count;
1758 $ret_arr["-1"]["description"] = "Starred";
1761 $result = db_query($link, "SELECT owner_uid,id,sql_exp,description FROM
1762 ttrss_labels WHERE owner_uid = ".$_SESSION["uid"]." ORDER by description");
1764 while ($line = db_fetch_assoc($result)) {
1766 $id = -$line["id"] - 11;
1768 $label_name = $line["description"];
1770 error_reporting (0);
1772 $tmp_result = db_query($link, "SELECT count(ttrss_entries.id) as count FROM ttrss_user_entries,ttrss_entries,ttrss_feeds
1773 WHERE (" . $line["sql_exp"] . ") AND unread = true AND
1774 ttrss_feeds.hidden = false AND
1775 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1776 ttrss_user_entries.ref_id = ttrss_entries.id AND
1777 ttrss_user_entries.owner_uid = ".$_SESSION["uid"]);
1779 $count = db_fetch_result($tmp_result, 0, "count");
1781 if (!$smart_mode ||
$old_counters[$id] != $count) {
1782 $old_counters[$id] = $count;
1783 $lctrs_modified = true;
1785 print "<counter type=\"label\" id=\"$id\" counter=\"$count\"/>";
1787 $ret_arr[$id]["counter"] = $count;
1788 $ret_arr[$id]["description"] = $label_name;
1792 error_reporting (DEFAULT_ERROR_LEVEL
);
1795 if ($smart_mode && $lctrs_modified) {
1796 $_SESSION["lctr_last_value"] = $old_counters;
1802 /* function getFeedCounter($link, $id) {
1804 $result = db_query($link, "SELECT
1805 count(id) as count,last_error
1806 FROM ttrss_entries,ttrss_user_entries,ttrss_feeds
1807 WHERE feed_id = '$id' AND unread = true
1808 AND ttrss_user_entries.feed_id = ttrss_feeds.id
1809 AND ttrss_user_entries.ref_id = ttrss_entries.id");
1811 $count = db_fetch_result($result, 0, "count");
1812 $last_error = htmlspecialchars(db_fetch_result($result, 0, "last_error"));
1814 print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" error=\"$last_error\"/>";
1817 function getFeedCounters($link, $smart_mode = SMART_RPC_COUNTERS
) {
1820 if (!$_SESSION["fctr_last_value"]) {
1821 $_SESSION["fctr_last_value"] = array();
1825 $old_counters = $_SESSION["fctr_last_value"];
1827 $result = db_query($link, "SELECT id,last_error,parent_feed,
1828 SUBSTRING(last_updated,1,19) AS last_updated,
1830 FROM ttrss_entries,ttrss_user_entries
1831 WHERE feed_id = ttrss_feeds.id AND
1832 ttrss_user_entries.ref_id = ttrss_entries.id
1833 AND unread = true AND owner_uid = ".$_SESSION["uid"].") as count
1834 FROM ttrss_feeds WHERE owner_uid = ".$_SESSION["uid"] . "
1835 AND parent_feed IS NULL");
1837 $fctrs_modified = false;
1839 $short_date = get_pref($link, 'SHORT_DATE_FORMAT');
1841 while ($line = db_fetch_assoc($result)) {
1844 $count = $line["count"];
1845 $last_error = htmlspecialchars($line["last_error"]);
1847 if (get_pref($link, 'HEADLINES_SMART_DATE')) {
1848 $last_updated = smart_date_time(strtotime($line["last_updated"]));
1850 $last_updated = date($short_date, strtotime($line["last_updated"]));
1853 $has_img = is_file(ICONS_DIR
. "/$id.ico");
1855 $tmp_result = db_query($link,
1856 "SELECT id,COUNT(unread) AS unread
1857 FROM ttrss_feeds LEFT JOIN ttrss_user_entries
1858 ON (ttrss_feeds.id = ttrss_user_entries.feed_id)
1859 WHERE parent_feed = '$id' AND unread = true GROUP BY ttrss_feeds.id");
1861 if (db_num_rows($tmp_result) > 0) {
1862 while ($l = db_fetch_assoc($tmp_result)) {
1863 $count +
= $l["unread"];
1867 if (!$smart_mode ||
$old_counters[$id] != $count) {
1868 $old_counters[$id] = $count;
1869 $fctrs_modified = true;
1872 $error_part = "error=\"$last_error\"";
1878 $has_img_part = "hi=\"$has_img\"";
1883 print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" $has_img_part $error_part updated=\"$last_updated\"/>";
1887 if ($smart_mode && $fctrs_modified) {
1888 $_SESSION["fctr_last_value"] = $old_counters;
1892 function get_script_dt_add() {
1893 if (strpos(VERSION
, "99") === false) {
1900 function get_pgsql_version($link) {
1901 $result = db_query($link, "SELECT version() AS version");
1902 $version = split(" ", db_fetch_result($result, 0, "version"));
1906 function print_error_xml($code, $add_msg = "") {
1909 $error_msg = $ERRORS[$code];
1912 $error_msg = "$error_msg; $add_msg";
1915 print "<rpc-reply>";
1916 print "<error error-code=\"$code\" error-msg=\"$error_msg\"/>";
1917 print "</rpc-reply>";
1920 function subscribe_to_feed($link, $feed_link, $cat_id = 0) {
1922 $feed_link = trim(preg_replace("/^feed:/", "", $feed_link));
1924 if ($feed_link == "") return;
1926 if ($cat_id == "0" ||
!$cat_id) {
1927 $cat_qpart = "NULL";
1929 $cat_qpart = "'$cat_id'";
1932 $result = db_query($link,
1933 "SELECT id FROM ttrss_feeds
1934 WHERE feed_url = '$feed_link' AND owner_uid = ".$_SESSION["uid"]);
1936 if (db_num_rows($result) == 0) {
1938 $result = db_query($link,
1939 "INSERT INTO ttrss_feeds (owner_uid,feed_url,title,cat_id)
1940 VALUES ('".$_SESSION["uid"]."', '$feed_link',
1941 '[Unknown]', $cat_qpart)");
1943 $result = db_query($link,
1944 "SELECT id FROM ttrss_feeds WHERE feed_url = '$feed_link'
1945 AND owner_uid = " . $_SESSION["uid"]);
1947 $feed_id = db_fetch_result($result, 0, "id");
1950 update_rss_feed($link, $feed_link, $feed_id, true);
1959 function print_feed_select($link, $id, $default_id = "",
1960 $attributes = "", $include_all_feeds = true) {
1962 print "<select id=\"$id\" name=\"$id\" $attributes>";
1963 if ($include_all_feeds) {
1964 print "<option value=\"0\">All feeds</option>";
1967 $result = db_query($link, "SELECT id,title FROM ttrss_feeds
1968 WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
1970 if (db_num_rows($result) > 0 && $include_all_feeds) {
1971 print "<option disabled>--------</option>";
1974 while ($line = db_fetch_assoc($result)) {
1975 if ($line["id"] == $default_id) {
1976 $is_selected = "selected";
1980 printf("<option $is_selected value='%d'>%s</option>",
1981 $line["id"], htmlspecialchars(db_unescape_string($line["title"])));
1987 function print_feed_cat_select($link, $id, $default_id = "",
1988 $attributes = "", $include_all_cats = true) {
1990 print "<select id=\"$id\" name=\"$id\" $attributes>";
1992 if ($include_all_cats) {
1993 print "<option value=\"0\">Uncategorized</option>";
1996 $result = db_query($link, "SELECT id,title FROM ttrss_feed_categories
1997 WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
1999 if (db_num_rows($result) > 0 && $include_all_cats) {
2000 print "<option disabled>--------</option>";
2003 while ($line = db_fetch_assoc($result)) {
2004 if ($line["id"] == $default_id) {
2005 $is_selected = "selected";
2009 printf("<option $is_selected value='%d'>%s</option>",
2010 $line["id"], htmlspecialchars(db_unescape_string($line["title"])));
2016 function checkbox_to_sql_bool($val) {
2017 return ($val == "on") ?
"true" : "false";
2020 function getFeedCatTitle($link, $id) {
2023 } else if ($id < -10) {
2025 } else if ($id > 0) {
2026 $result = db_query($link, "SELECT ttrss_feed_categories.title
2027 FROM ttrss_feeds, ttrss_feed_categories WHERE ttrss_feeds.id = '$id' AND
2028 cat_id = ttrss_feed_categories.id");
2029 if (db_num_rows($result) == 1) {
2030 return db_fetch_result($result, 0, "title");
2032 return "Uncategorized";
2035 return "getFeedCatTitle($id) failed";
2040 function getFeedTitle($link, $id) {
2042 return "Starred articles";
2043 } else if ($id < -10) {
2044 $label_id = -10 - $id;
2045 $result = db_query($link, "SELECT description FROM ttrss_labels WHERE id = '$label_id'");
2046 if (db_num_rows($result) == 1) {
2047 return db_fetch_result($result, 0, "description");
2049 return "Unknown label ($label_id)";
2052 } else if ($id > 0) {
2053 $result = db_query($link, "SELECT title FROM ttrss_feeds WHERE id = '$id'");
2054 if (db_num_rows($result) == 1) {
2055 return db_fetch_result($result, 0, "title");
2057 return "Unknown feed ($id)";
2060 return "getFeedTitle($id) failed";
2065 function get_session_cookie_name() {
2066 return ((!defined('TTRSS_SESSION_NAME')) ?
"ttrss_sid" : TTRSS_SESSION_NAME
);
2069 function print_init_params($link) {
2070 print "<init-params>";
2071 if ($_SESSION["stored-params"]) {
2072 foreach (array_keys($_SESSION["stored-params"]) as $key) {
2074 $value = htmlspecialchars($_SESSION["stored-params"][$key]);
2075 print "<param key=\"$key\" value=\"$value\"/>";
2080 print "<param key=\"daemon_enabled\" value=\"" . ENABLE_UPDATE_DAEMON
. "\"/>";
2081 print "<param key=\"feeds_frame_refresh\" value=\"" . FEEDS_FRAME_REFRESH
. "\"/>";
2082 print "<param key=\"daemon_refresh_only\" value=\"" . DAEMON_REFRESH_ONLY
. "\"/>";
2084 print "<param key=\"on_catchup_show_next_feed\" value=\"" .
2085 get_pref($link, "ON_CATCHUP_SHOW_NEXT_FEED") . "\"/>";
2087 print "<param key=\"hide_read_feeds\" value=\"" .
2088 sprintf("%d", get_pref($link, "HIDE_READ_FEEDS")) . "\"/>";
2090 print "<param key=\"feeds_sort_by_unread\" value=\"" .
2091 sprintf("%d", get_pref($link, "FEEDS_SORT_BY_UNREAD")) . "\"/>";
2093 print "<param key=\"confirm_feed_catchup\" value=\"" .
2094 sprintf("%d", get_pref($link, "CONFIRM_FEED_CATCHUP")) . "\"/>";
2096 print "</init-params>";
2099 function print_runtime_info($link) {
2100 print "<runtime-info>";
2101 if (ENABLE_UPDATE_DAEMON
) {
2102 print "<param key=\"daemon_is_running\" value=\"".
2103 sprintf("%d", file_is_locked("update_daemon.lock")) . "\"/>";
2105 print "</runtime-info>";
2108 function getSearchSql($search, $match_on) {
2110 $search_query_part = "";
2112 $keywords = split(" ", $search);
2113 $query_keywords = array();
2115 if ($match_on == "both") {
2117 foreach ($keywords as $k) {
2118 array_push($query_keywords, "(UPPER(ttrss_entries.title) LIKE UPPER('%$k%')
2119 OR UPPER(ttrss_entries.content) LIKE UPPER('%$k%'))");
2122 $search_query_part = implode("AND", $query_keywords) . " AND ";
2124 } else if ($match_on == "title") {
2126 foreach ($keywords as $k) {
2127 array_push($query_keywords, "(UPPER(ttrss_entries.title) LIKE UPPER('%$k%'))");
2130 $search_query_part = implode("AND", $query_keywords) . " AND ";
2132 } else if ($match_on == "content") {
2134 foreach ($keywords as $k) {
2135 array_push($query_keywords, "(UPPER(ttrss_entries.content) LIKE UPPER('%$k%'))");
2139 $search_query_part = implode("AND", $query_keywords);
2141 return $search_query_part;
2144 function queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, $search, $search_mode, $match_on, $override_order = false) {
2147 $search_query_part = getSearchSql($search, $match_on);
2148 $search_query_part .= " AND ";
2151 $search_query_part = "";
2154 $view_query_part = "";
2156 if ($view_mode == "adaptive") {
2158 $view_query_part = " ";
2159 } else if ($feed != -1) {
2160 $unread = getFeedUnread($link, $feed, $cat_view);
2162 $view_query_part = " unread = true AND ";
2167 if ($view_mode == "marked") {
2168 $view_query_part = " marked = true AND ";
2171 if ($view_mode == "unread") {
2172 $view_query_part = " unread = true AND ";
2176 $limit_query_part = "LIMIT " . $limit;
2179 $vfeed_query_part = "";
2181 // override query strategy and enable feed display when searching globally
2182 if ($search && $search_mode == "all_feeds") {
2183 $query_strategy_part = "ttrss_entries.id > 0";
2184 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2185 } else if (preg_match("/^-?[0-9][0-9]*$/", $feed) == false) {
2186 $query_strategy_part = "ttrss_entries.id > 0";
2187 $vfeed_query_part = "(SELECT title FROM ttrss_feeds WHERE
2188 id = feed_id) as feed_title,";
2189 } else if ($feed >= 0 && $search && $search_mode == "this_cat") {
2191 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2193 $tmp_result = false;
2196 $tmp_result = db_query($link, "SELECT id
2197 FROM ttrss_feeds WHERE cat_id = '$feed'");
2199 $tmp_result = db_query($link, "SELECT id
2200 FROM ttrss_feeds WHERE cat_id = (SELECT cat_id FROM ttrss_feeds
2201 WHERE id = '$feed') AND id != '$feed'");
2204 $cat_siblings = array();
2206 if (db_num_rows($tmp_result) > 0) {
2207 while ($p = db_fetch_assoc($tmp_result)) {
2208 array_push($cat_siblings, "feed_id = " . $p["id"]);
2211 $query_strategy_part = sprintf("(feed_id = %d OR %s)",
2212 $feed, implode(" OR ", $cat_siblings));
2215 $query_strategy_part = "ttrss_entries.id > 0";
2218 } else if ($feed >= 0) {
2223 $query_strategy_part = "cat_id = '$feed'";
2225 $query_strategy_part = "cat_id IS NULL";
2228 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2231 $tmp_result = db_query($link, "SELECT id
2232 FROM ttrss_feeds WHERE parent_feed = '$feed'
2233 ORDER BY cat_id,title");
2235 $parent_ids = array();
2237 if (db_num_rows($tmp_result) > 0) {
2238 while ($p = db_fetch_assoc($tmp_result)) {
2239 array_push($parent_ids, "feed_id = " . $p["id"]);
2242 $query_strategy_part = sprintf("(feed_id = %d OR %s)",
2243 $feed, implode(" OR ", $parent_ids));
2245 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2247 $query_strategy_part = "feed_id = '$feed'";
2250 } else if ($feed == -1) { // starred virtual feed
2251 $query_strategy_part = "marked = true";
2252 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2253 } else if ($feed <= -10) { // labels
2254 $label_id = -$feed - 11;
2256 $tmp_result = db_query($link, "SELECT sql_exp FROM ttrss_labels
2257 WHERE id = '$label_id'");
2259 $query_strategy_part = db_fetch_result($tmp_result, 0, "sql_exp");
2261 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2263 $query_strategy_part = "id > 0"; // dumb
2266 if (get_pref($link, 'REVERSE_HEADLINES')) {
2267 $order_by = "updated";
2269 $order_by = "updated DESC";
2272 if ($override_order) {
2273 $order_by = $override_order;
2278 if ($search && $search_mode == "all_feeds") {
2279 $feed_title = "Global search results ($search)";
2280 } else if ($search && preg_match('/^-?[0-9][0-9]*$/', $feed) == false) {
2281 $feed_title = "Tag search results ($search, $feed)";
2282 } else if (preg_match('/^-?[0-9][0-9]*$/', $feed) == false) {
2283 $feed_title = $feed;
2284 } else if (preg_match('/^-?[0-9][0-9]*$/', $feed) != false && $feed >= 0) {
2289 $result = db_query($link, "SELECT title FROM ttrss_feed_categories
2290 WHERE id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
2291 $feed_title = db_fetch_result($result, 0, "title");
2293 $feed_title = "Uncategorized";
2297 $feed_title = "Category search results ($search, $feed_title)";
2302 $result = db_query($link, "SELECT title,site_url,last_error FROM ttrss_feeds
2303 WHERE id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
2305 $feed_title = db_fetch_result($result, 0, "title");
2306 $feed_site_url = db_fetch_result($result, 0, "site_url");
2307 $last_error = db_fetch_result($result, 0, "last_error");
2310 $feed_title = "Feed search results ($search, $feed_title)";
2314 } else if ($feed == -1) {
2315 $feed_title = "Starred articles";
2316 } else if ($feed < -10) {
2317 $label_id = -$feed - 11;
2318 $result = db_query($link, "SELECT description FROM ttrss_labels
2319 WHERE id = '$label_id'");
2320 $feed_title = db_fetch_result($result, 0, "description");
2323 $feed_title = "Label search results ($search, $feed_title)";
2329 $feed_title = db_unescape_string($feed_title);
2331 if ($feed < -10) error_reporting (0);
2333 if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
2336 $feed_kind = "Feeds";
2338 $feed_kind = "Labels";
2341 $content_query_part = "content as content_preview,";
2345 ttrss_entries.id,ttrss_entries.title,
2346 SUBSTRING(updated,1,16) as updated,
2347 unread,feed_id,marked,link,last_read,
2348 SUBSTRING(last_read,1,19) as last_read_noms,
2351 SUBSTRING(updated,1,19) as updated_noms,
2354 ttrss_entries,ttrss_user_entries,ttrss_feeds
2356 ttrss_feeds.hidden = false AND
2357 ttrss_user_entries.feed_id = ttrss_feeds.id AND
2358 ttrss_user_entries.ref_id = ttrss_entries.id AND
2359 ttrss_user_entries.owner_uid = '".$_SESSION["uid"]."' AND
2362 $query_strategy_part ORDER BY $order_by
2365 $result = db_query($link, $query);
2367 if ($_GET["debug"]) print $query;
2372 $feed_kind = "Tags";
2374 $result = db_query($link, "SELECT
2376 ttrss_entries.id as id,title,
2377 SUBSTRING(updated,1,16) as updated,
2379 marked,link,last_read,
2380 SUBSTRING(last_read,1,19) as last_read_noms,
2383 SUBSTRING(updated,1,19) as updated_noms
2385 ttrss_entries,ttrss_user_entries,ttrss_tags
2387 ref_id = ttrss_entries.id AND
2388 ttrss_user_entries.owner_uid = '".$_SESSION["uid"]."' AND
2389 post_int_id = int_id AND tag_name = '$feed' AND
2392 $query_strategy_part ORDER BY $order_by
2393 $limit_query_part");
2396 return array($result, $feed_title, $feed_site_url, $last_error);
2400 function generate_syndicated_feed($link, $feed, $is_cat,
2401 $search, $search_mode, $match_on) {
2403 $qfh_ret = queryFeedHeadlines($link, $feed,
2404 30, false, $is_cat, $search, $search_mode, $match_on, "updated DESC");
2406 $result = $qfh_ret[0];
2407 $feed_title = htmlspecialchars($qfh_ret[1]);
2408 $feed_site_url = $qfh_ret[2];
2409 $last_error = $qfh_ret[3];
2411 print "<rss version=\"2.0\">
2413 <title>$feed_title</title>
2414 <link>$feed_site_url</link>
2415 <generator>Tiny Tiny RSS v".VERSION
."</generator>";
2417 while ($line = db_fetch_assoc($result)) {
2419 print "<id>" . htmlspecialchars($line["guid"]) . "</id>";
2420 print "<link>" . htmlspecialchars($line["link"]) . "</link>";
2422 $rfc822_date = date('r', strtotime($line["updated"]));
2424 print "<pubDate>$rfc822_date</pubDate>";
2427 htmlspecialchars($line["title"]) . "</title>";
2429 print "<description>" .
2430 htmlspecialchars($line["content_preview"]) . "</description>";
2435 print "</channel></rss>";
2439 function getCategoryTitle($link, $cat_id) {
2441 $result = db_query($link, "SELECT title FROM ttrss_feed_categories WHERE
2444 if (db_num_rows($result) == 1) {
2445 return db_fetch_result($result, 0, "title");
2447 return "Uncategorized";
2451 function sanitize_rss($str) {
2454 $res = preg_replace('/<script.*?>/i',
2455 "<p class=\"scriptWarn\">Disabled script: ", $res);
2457 $res = preg_replace('/<\/script.*?>/i', "</p>", $res);
2459 /* $res = preg_replace('/<embed.*?>/i', "", $res);
2461 $res = preg_replace('/<object.*?>.*?<\/object>/i',
2462 "<p class=\"objectWarn\">(Disabled html object
2463 - flash or other embedded content)</p>", $res); */
2468 function send_headlines_digests($link, $limit = 100) {
2470 if (!DIGEST_ENABLE
) return false;
2472 $user_limit = DIGEST_EMAIL_LIMIT
;
2475 print "Sending digests, batch of max $user_limit users, days = $days, headline limit = $limit\n\n";
2477 if (DB_TYPE
== "pgsql") {
2478 $interval_query = "last_digest_sent < NOW() - INTERVAL '$days days'";
2479 } else if (DB_TYPE
== "mysql") {
2480 $interval_query = "last_digest_sent < DATE_SUB(NOW(), INTERVAL $days DAY)";
2483 $result = db_query($link, "SELECT id,email FROM ttrss_users
2484 WHERE email != '' AND (last_digest_sent IS NULL OR $interval_query)");
2486 while ($line = db_fetch_assoc($result)) {
2487 if (get_pref($link, 'DIGEST_ENABLE', $line['id'], false)) {
2488 print "Sending digest for UID:" . $line['id'] . " - " . $line["email"] . " ... ";
2490 $tuple = prepare_headlines_digest($link, $line["id"], $days, $limit);
2491 $digest = $tuple[0];
2492 $headlines_count = $tuple[1];
2494 if ($headlines_count > 0) {
2495 $rc = mail($line["login"] . " <" . $line["email"] . ">",
2496 "[tt-rss] New headlines for last 24 hours", $digest,
2497 "From: " . MAIL_FROM
. "\n".
2498 "Content-Type: text/plain; charset=\"utf-8\"\n".
2499 "Content-Transfer-Encoding: 8bit\n");
2501 db_query($link, "UPDATE ttrss_users SET last_digest_sent = NOW()
2502 WHERE id = " . $line["id"]);
2504 print "No headlines\n";
2509 // $digest = prepare_headlines_digest($link, $user_id, $days, $limit);
2513 function prepare_headlines_digest($link, $user_id, $days = 1, $limit = 100) {
2514 $tmp = "New headlines for last 24 hours, as of " . date("Y/m/d H:m") . "\n";
2515 $tmp .= "=======================================================\n\n";
2517 if (DB_TYPE
== "pgsql") {
2518 $interval_query = "ttrss_entries.date_entered > NOW() - INTERVAL '$days days'";
2519 } else if (DB_TYPE
== "mysql") {
2520 $interval_query = "ttrss_entries.date_entered > DATE_SUB(NOW(), INTERVAL $days DAY)";
2523 $result = db_query($link, "SELECT ttrss_entries.title,
2524 ttrss_feeds.title AS feed_title,
2527 SUBSTRING(last_updated,1,19) AS last_updated
2529 ttrss_user_entries,ttrss_entries,ttrss_feeds
2531 ref_id = ttrss_entries.id AND feed_id = ttrss_feeds.id
2532 AND include_in_digest = true
2534 AND ttrss_user_entries.owner_uid = $user_id
2535 AND unread = true ORDER BY ttrss_feeds.title, date_entered DESC
2538 $cur_feed_title = "";
2540 $headlines_count = db_num_rows($result);
2542 while ($line = db_fetch_assoc($result)) {
2543 $updated = smart_date_time(strtotime($line["last_updated"]));
2544 $feed_title = $line["feed_title"];
2546 if ($cur_feed_title != $feed_title) {
2547 $cur_feed_title = $feed_title;
2549 $tmp .= "$feed_title\n\n";
2552 $tmp .= " * " . trim($line["title"]) . " - $updated\n";
2553 $tmp .= " " . trim($line["link"]) . "\n";
2558 $tmp .= "You have been sent this email because you have enabled daily digests in Tiny Tiny RSS at " .
2559 DIGEST_HOSTNAME
. "\n".
2560 "To unsubscribe, visit your configuration options or contact instance owner.\n";
2563 return array($tmp, $headlines_count);
2566 function check_for_update($link) {
2567 $releases_feed = "http://tt-rss.spb.ru/releases.rss";
2569 if (!CHECK_FOR_NEW_VERSION ||
$_SESSION["access_level"] < 10) {
2574 $rss = fetch_rss($releases_feed);
2575 error_reporting (DEFAULT_ERROR_LEVEL
);
2579 $items = $rss->items
;
2581 if (!$items ||
!is_array($items)) $items = $rss->entries
;
2582 if (!$items ||
!is_array($items)) $items = $rss;
2584 if (!is_array($items) ||
count($items) == 0) {
2588 $latest_item = $items[0];
2590 $latest_version = trim(preg_replace("/(Milestone)|(completed)/", "", $latest_item["title"]));
2592 $release_url = sanitize_rss($latest_item["link"]);
2593 $content = sanitize_rss($latest_item["description"]);
2595 if (version_compare(VERSION
, $latest_version) == -1) {
2596 return "<div class=\"notice\"><a href=\"javascript:showBlockElement('milestoneDetails')\">
2597 New version of Tiny-Tiny RSS ($latest_version) is available (click for details)</a>
2598 <div id=\"milestoneDetails\">$content</div></div>";
2603 function markArticlesById($link, $ids, $cmode) {
2607 foreach ($ids as $id) {
2608 array_push($tmp_ids, "ref_id = '$id'");
2611 $ids_qpart = join(" OR ", $tmp_ids);
2614 db_query($link, "UPDATE ttrss_user_entries SET
2615 marked = false,last_read = NOW()
2616 WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2617 } else if ($cmode == 1) {
2618 db_query($link, "UPDATE ttrss_user_entries SET
2620 WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2622 db_query($link, "UPDATE ttrss_user_entries SET
2623 marked = NOT marked,last_read = NOW()
2624 WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2628 function catchupArticlesById($link, $ids, $cmode) {
2632 foreach ($ids as $id) {
2633 array_push($tmp_ids, "ref_id = '$id'");
2636 $ids_qpart = join(" OR ", $tmp_ids);
2639 db_query($link, "UPDATE ttrss_user_entries SET
2640 unread = false,last_read = NOW()
2641 WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2642 } else if ($cmode == 1) {
2643 db_query($link, "UPDATE ttrss_user_entries SET
2645 WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2647 db_query($link, "UPDATE ttrss_user_entries SET
2648 unread = NOT unread,last_read = NOW()
2649 WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
2653 function escape_for_form($s) {
2654 return htmlspecialchars(db_unescape_string($s));
2657 function make_guid_from_title($title) {
2658 return preg_replace("/[ \"\',.:;]/", "-",
2659 mb_strtolower(strip_tags($title)));
2662 function print_headline_subtoolbar($link, $feed_site_url, $feed_title,
2663 $bottom = false, $rtl_content = false, $feed_id = 0,
2664 $is_cat = false, $search = false, $match_on = false,
2665 $search_mode = false) {
2668 $class = "headlinesSubToolbar";
2669 $tid = "headlineActionsTop";
2671 $class = "headlinesSubToolbar";
2672 $tid = "headlineActionsBottom";
2675 print "<table class=\"$class\" id=\"$tid\"
2676 width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tr>";
2684 if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) {
2686 print "<td class=\"headlineActions$rtl_cpart\">
2688 <a href=\"javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, '', true)\">All</a>,
2689 <a href=\"javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', true, 'Unread', true)\">Unread</a>,
2690 <a href=\"javascript:selectTableRowsByIdPrefix('headlinesList', 'RROW-', 'RCHK-', false)\">None</a>
2692 Toggle: <a href=\"javascript:selectionToggleUnread()\">Unread</a>,
2693 <a href=\"javascript:selectionToggleMarked()\">Starred</a>
2696 <a href=\"#\" onclick=\"catchupPage()\">Page</a>,
2697 <a href=\"#\" onclick=\"catchupCurrentFeed()\">Feed</a>";
2700 if ($search && $feed_id >= 0 && get_pref($link, 'ENABLE_LABELS') && GLOBAL_ENABLE_LABELS
) {
2701 print "<td class=\"headlineActions$rtl_cpart\">
2702 <a href=\"javascript:labelFromSearch('$search', '$search_mode',
2703 '$match_on', '$feed_id', '$is_cat');\">
2704 Convert this search to label</a></td>";
2709 print "<td class=\"headlineActions$rtl_cpart\">
2711 <a href=\"javascript:cdmSelectArticles('all')\">All</a>,
2712 <a href=\"javascript:cdmSelectArticles('unread')\">Unread</a>,
2713 <a href=\"javascript:cdmSelectArticles('none')\">None</a>
2715 Toggle: <a href=\"javascript:selectionToggleUnread(true)\">Unread</a>,
2716 <a href=\"javascript:selectionToggleMarked(true)\">Starred</a>
2719 <a href=\"#\" onclick=\"catchupPage()\">Page</a>,
2720 <a href=\"#\" onclick=\"catchupCurrentFeed()\">Feed</a>";
2726 print "<td class=\"headlineTitle$rtl_cpart\">";
2728 if ($feed_site_url) {
2730 $target = "target=\"_blank\"";
2732 print "<a $target href=\"$feed_site_url\">$feed_title</a>";
2738 $search_q = "&q=$search&m=$match_on&smode=$search_mode";
2744 href=\"backend.php?op=rss&id=$feed_id&is_cat=$is_cat$search_q\">
2745 <img class=\"noborder\"
2746 alt=\"Generated feed\" src=\"images/feed-icon-12x12.png\">
2751 print "</tr></table>";
2755 function outputFeedList($link, $tags = false) {
2757 print "<ul class=\"feedList\" id=\"feedList\">\n";
2759 $owner_uid = $_SESSION["uid"];
2763 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2764 print "<li class=\"feedCat\">Special</li>";
2765 print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
2768 $num_starred = getFeedUnread($link, -1);
2772 if ($num_starred > 0) $class .= "Unread";
2774 printFeedEntry(-1, $class, "Starred articles", $num_starred,
2775 "images/mark_set.png", $link);
2777 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2783 if (GLOBAL_ENABLE_LABELS
&& get_pref($link, 'ENABLE_LABELS')) {
2785 $result = db_query($link, "SELECT id,sql_exp,description FROM
2786 ttrss_labels WHERE owner_uid = '$owner_uid' ORDER by description");
2788 if (db_num_rows($result) > 0) {
2789 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2790 print "<li class=\"feedCat\">Labels</li>";
2791 print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
2793 print "<li><hr></li>";
2797 while ($line = db_fetch_assoc($result)) {
2799 error_reporting (0);
2801 $label_id = -$line['id'] - 11;
2802 $count = getFeedUnread($link, $label_id);
2810 error_reporting (DEFAULT_ERROR_LEVEL
);
2812 printFeedEntry($label_id,
2813 $class, db_unescape_string($line["description"]),
2814 $count, "images/label.png", $link);
2818 if (db_num_rows($result) > 0) {
2819 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2826 if (!get_pref($link, 'ENABLE_FEED_CATS')) {
2827 print "<li><hr></li>";
2830 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2831 if (get_pref($link, "FEEDS_SORT_BY_UNREAD")) {
2832 $order_by_qpart = "category,unread DESC,title";
2834 $order_by_qpart = "category,title";
2837 if (get_pref($link, "FEEDS_SORT_BY_UNREAD")) {
2838 $order_by_qpart = "unread DESC,title";
2840 $order_by_qpart = "title";
2844 $result = db_query($link, "SELECT ttrss_feeds.*,
2845 SUBSTRING(last_updated,1,19) AS last_updated_noms,
2846 (SELECT COUNT(id) FROM ttrss_entries,ttrss_user_entries
2847 WHERE feed_id = ttrss_feeds.id AND unread = true
2848 AND ttrss_user_entries.ref_id = ttrss_entries.id
2849 AND owner_uid = '$owner_uid') as unread,
2851 ttrss_feed_categories.title AS category,
2852 ttrss_feed_categories.collapsed
2853 FROM ttrss_feeds LEFT JOIN ttrss_feed_categories
2854 ON (ttrss_feed_categories.id = cat_id)
2856 ttrss_feeds.hidden = false AND
2857 ttrss_feeds.owner_uid = '$owner_uid' AND parent_feed IS NULL
2858 ORDER BY $order_by_qpart");
2860 $actid = $_GET["actid"];
2870 $short_date = get_pref($link, 'SHORT_DATE_FORMAT');
2872 while ($line = db_fetch_assoc($result)) {
2874 $feed = db_unescape_string($line["title"]);
2875 $feed_id = $line["id"];
2877 $subop = $_GET["subop"];
2879 $unread = $line["unread"];
2881 if (get_pref($link, 'HEADLINES_SMART_DATE')) {
2882 $last_updated = smart_date_time(strtotime($line["last_updated_noms"]));
2884 $last_updated = date($short_date, strtotime($line["last_updated_noms"]));
2887 $rtl_content = sql_bool_to_bool($line["rtl_content"]);
2890 $rtl_tag = "dir=\"RTL\"";
2895 $tmp_result = db_query($link,
2896 "SELECT id,COUNT(unread) AS unread
2897 FROM ttrss_feeds LEFT JOIN ttrss_user_entries
2898 ON (ttrss_feeds.id = ttrss_user_entries.feed_id)
2899 WHERE parent_feed = '$feed_id' AND unread = true
2900 GROUP BY ttrss_feeds.id");
2902 if (db_num_rows($tmp_result) > 0) {
2903 while ($l = db_fetch_assoc($tmp_result)) {
2904 $unread +
= $l["unread"];
2908 $cat_id = $line["cat_id"];
2910 $tmp_category = $line["category"];
2912 if (!$tmp_category) {
2913 $tmp_category = "Uncategorized";
2916 // $class = ($lnum % 2) ? "even" : "odd";
2918 if ($line["last_error"]) {
2924 if ($unread > 0) $class .= "Unread";
2926 if ($actid == $feed_id) {
2927 $class .= "Selected";
2930 $total_unread +
= $unread;
2932 if ($category != $tmp_category && get_pref($link, 'ENABLE_FEED_CATS')) {
2938 $category = $tmp_category;
2940 $collapsed = $line["collapsed"];
2942 // workaround for NULL category
2943 if ($category == "Uncategorized") {
2944 if ($_COOKIE["ttrss_vf_uclps"] == 1) {
2949 if ($collapsed == "t" ||
$collapsed == "1") {
2950 $holder_class = "invisible";
2957 $cat_id = sprintf("%d", $cat_id);
2959 $cat_unread = getCategoryUnread($link, $cat_id);
2961 $catctr_class = ($cat_unread > 0) ?
"catCtrHasUnread" : "catCtrNoUnread";
2963 print "<li class=\"feedCat\" id=\"FCAT-$cat_id\">
2964 <a id=\"FCATN-$cat_id\" href=\"#\"onclick=\"javascript:toggleCollapseCat($cat_id)\">$tmp_category</a>
2965 <a href=\"#\" onclick=\"javascript:viewCategory($cat_id)\" id=\"FCAP-$cat_id\">
2966 <span id=\"FCATCTR-$cat_id\" title=\"Click to browse category\"
2967 class=\"$catctr_class\">($cat_unread)</span> $ellipsis
2970 // !!! NO SPACE before <ul...feedCatList - breaks firstChild DOM function
2971 // -> keyboard navigation, etc.
2972 print "<li id=\"feedCatHolder\" class=\"$holder_class\"><ul class=\"feedCatList\" id=\"FCATLIST-$cat_id\">";
2975 printFeedEntry($feed_id, $class, $feed, $unread,
2976 "icons/$feed_id.ico", $link, $rtl_content,
2977 $last_updated, $line["last_error"]);
2982 if (db_num_rows($result) == 0) {
2983 print "<li>No feeds to display.</li>";
2990 /* $result = db_query($link, "SELECT tag_name,count(ttrss_entries.id) AS count
2991 FROM ttrss_tags,ttrss_entries,ttrss_user_entries WHERE
2992 post_int_id = ttrss_user_entries.int_id AND
2993 unread = true AND ref_id = ttrss_entries.id
2994 AND ttrss_tags.owner_uid = '$owner_uid' GROUP BY tag_name
2996 select tag_name,0 as count FROM ttrss_tags WHERE owner_uid = '$owner_uid'
2997 ORDER BY tag_name"); */
2999 if (get_pref($link, 'ENABLE_FEED_CATS')) {
3000 print "<li class=\"feedCat\">Tags</li>";
3001 print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
3004 $result = db_query($link, "SELECT tag_name,SUM((SELECT COUNT(int_id)
3005 FROM ttrss_user_entries WHERE int_id = post_int_id
3006 AND unread = true)) AS count FROM ttrss_tags
3007 WHERE owner_uid = 2 GROUP BY tag_name ORDER BY tag_name");
3011 while ($line = db_fetch_assoc($result)) {
3012 $tags[$line["tag_name"]] +
= $line["count"];
3015 foreach (array_keys($tags) as $tag) {
3017 $unread = $tags[$tag];
3025 printFeedEntry($tag, $class, $tag, $unread, "images/tag.png", $link);
3029 if (db_num_rows($result) == 0) {
3030 print "<li>No tags to display.</li>";
3033 if (get_pref($link, 'ENABLE_FEED_CATS')) {
3043 function get_article_tags($link, $id) {
3045 $a_id = db_escape_string($id);
3047 $tmp_result = db_query($link, "SELECT DISTINCT tag_name FROM
3048 ttrss_tags WHERE post_int_id = (SELECT int_id FROM ttrss_user_entries WHERE
3049 ref_id = '$a_id' AND owner_uid = '".$_SESSION["uid"]."') ORDER BY tag_name");
3053 while ($tmp_line = db_fetch_assoc($tmp_result)) {
3054 array_push($tags, $tmp_line["tag_name"]);
3060 function trim_value(&$value) {
3061 $value = trim($value);
3064 function trim_array($array) {
3066 array_walk($tmp, 'trim_value');