]>
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) && $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 get_filter_matches($title, $content, $link, $filters) {
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"]));
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"]));
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"]));
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"]));
941 function printFeedEntry($feed_id, $class, $feed_title, $unread, $icon_file, $link,
942 $rtl_content = false, $last_updated = false, $last_error = false) {
944 if (file_exists($icon_file) && filesize($icon_file) > 0) {
945 $feed_icon = "<img id=\"FIMG-$feed_id\" src=\"$icon_file\">";
947 $feed_icon = "<img id=\"FIMG-$feed_id\" src=\"images/blank_icon.gif\">";
951 $rtl_tag = "dir=\"rtl\"";
953 $rtl_tag = "dir=\"ltr\"";
956 $error_notify_msg = "";
959 $link_title = "Error: $last_error ($last_updated)";
960 $error_notify_msg = "(Error)";
961 } else if ($last_updated) {
962 $link_title = "Updated: $last_updated";
965 $feed = "<a title=\"$link_title\" id=\"FEEDL-$feed_id\"
966 href=\"#\" onclick=\"javascript:viewfeed('$feed_id', '', false);\">$feed_title</a>";
968 print "<li id=\"FEEDR-$feed_id\" class=\"$class\">";
969 if (get_pref($link, 'ENABLE_FEED_ICONS')) {
973 print "<span $rtl_tag id=\"FEEDN-$feed_id\">$feed</span>";
978 $fctr_class = "class=\"invisible\"";
981 print " <span $rtl_tag $fctr_class id=\"FEEDCTR-$feed_id\">
982 (<span id=\"FEEDU-$feed_id\">$unread</span>)</span>";
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>";
993 function getmicrotime() {
994 list($usec, $sec) = explode(" ",microtime());
995 return ((float)$usec +
(float)$sec);
998 function print_radio($id, $default, $values, $attributes = "") {
999 foreach ($values as $v) {
1007 $sel .= " value=\"1\"";
1009 $sel .= " value=\"0\"";
1012 print "<input class=\"noborder\"
1013 type=\"radio\" $sel $attributes name=\"$id\"> $v ";
1018 function initialize_user_prefs($link, $uid) {
1020 $uid = db_escape_string($uid);
1022 db_query($link, "BEGIN");
1024 $result = db_query($link, "SELECT pref_name,def_value FROM ttrss_prefs");
1026 $u_result = db_query($link, "SELECT pref_name
1027 FROM ttrss_user_prefs WHERE owner_uid = '$uid'");
1029 $active_prefs = array();
1031 while ($line = db_fetch_assoc($u_result)) {
1032 array_push($active_prefs, $line["pref_name"]);
1035 while ($line = db_fetch_assoc($result)) {
1036 if (array_search($line["pref_name"], $active_prefs) === FALSE) {
1037 // print "adding " . $line["pref_name"] . "<br>";
1039 db_query($link, "INSERT INTO ttrss_user_prefs
1040 (owner_uid,pref_name,value) VALUES
1041 ('$uid', '".$line["pref_name"]."','".$line["def_value"]."')");
1046 db_query($link, "COMMIT");
1050 function lookup_user_id($link, $user) {
1052 $result = db_query($link, "SELECT id FROM ttrss_users WHERE
1055 if (db_num_rows($result) == 1) {
1056 return db_fetch_result($result, 0, "id");
1062 function http_authenticate_user($link) {
1064 if (!$_SERVER["PHP_AUTH_USER"]) {
1066 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS RSSGen"');
1067 header('HTTP/1.0 401 Unauthorized');
1071 $auth_result = authenticate_user($link,
1072 $_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);
1074 if (!$auth_result) {
1075 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS RSSGen"');
1076 header('HTTP/1.0 401 Unauthorized');
1084 function authenticate_user($link, $login, $password, $force_auth = false) {
1086 if (!SINGLE_USER_MODE
) {
1088 $pwd_hash = 'SHA1:' . sha1($password);
1090 if ($force_auth && defined('_DEBUG_USER_SWITCH')) {
1091 $query = "SELECT id,login,access_level
1092 FROM ttrss_users WHERE
1095 $query = "SELECT id,login,access_level
1096 FROM ttrss_users WHERE
1097 login = '$login' AND pwd_hash = '$pwd_hash'";
1100 $result = db_query($link, $query);
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");
1107 db_query($link, "UPDATE ttrss_users SET last_login = NOW() WHERE id = " .
1110 $user_theme = get_user_theme_path($link);
1112 $_SESSION["theme"] = $user_theme;
1113 $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"];
1115 initialize_user_prefs($link, $_SESSION["uid"]);
1124 $_SESSION["uid"] = 1;
1125 $_SESSION["name"] = "admin";
1127 $user_theme = get_user_theme_path($link);
1129 $_SESSION["theme"] = $user_theme;
1130 $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"];
1132 initialize_user_prefs($link, $_SESSION["uid"]);
1138 function make_password($length = 8) {
1141 $possible = "0123456789abcdfghjkmnpqrstvwxyzABCDFGHJKMNPQRSTVWXYZ";
1145 while ($i < $length) {
1146 $char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
1148 if (!strstr($password, $char)) {
1156 // this is called after user is created to initialize default feeds, labels
1159 // user preferences are checked on every login, not here
1161 function initialize_user($link, $uid) {
1163 db_query($link, "insert into ttrss_labels (owner_uid,sql_exp,description)
1164 values ('$uid','unread = true', 'Unread articles')");
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')");
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')");
1175 function logout_user() {
1177 if (isset($_COOKIE[session_name()])) {
1178 setcookie(session_name(), '', time()-42000, '/');
1182 function get_script_urlpath() {
1183 return preg_replace('/\/[^\/]*$/', "", $_SERVER["REQUEST_URI"]);
1186 function get_login_redirect() {
1187 $server = $_SERVER["SERVER_NAME"];
1189 if (ENABLE_LOGIN_SSL
) {
1190 $protocol = "https";
1195 $url_path = get_script_urlpath();
1197 $redirect_uri = "$protocol://$server$url_path/login.php";
1199 return $redirect_uri;
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"]) {
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");
1224 function login_sequence($link) {
1225 if (!SINGLE_USER_MODE
) {
1227 if (defined('_DEBUG_USER_SWITCH') && $_SESSION["uid"]) {
1228 $swu = db_escape_string($_REQUEST["swu"]);
1230 $_SESSION["prefs_cache"] = false;
1231 return authenticate_user($link, $swu, null, true);
1235 if (!validate_session($link)) {
1237 $redirect_uri = get_login_redirect();
1238 $return_to = preg_replace('/.*?\//', '', $_SERVER["REQUEST_URI"]);
1239 header("Location: $redirect_uri?rt=$return_to");
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");
1251 if (!$_SESSION["uid"]) {
1252 if (!$_SERVER["PHP_AUTH_USER"]) {
1254 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS"');
1255 header('HTTP/1.0 401 Unauthorized');
1259 $auth_result = authenticate_user($link,
1260 $_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);
1262 if (!$auth_result) {
1263 header('WWW-Authenticate: Basic realm="Tiny Tiny RSS"');
1264 header('HTTP/1.0 401 Unauthorized');
1271 return authenticate_user($link, "admin", null);
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") . "...";
1283 function get_user_theme_path($link) {
1284 $result = db_query($link, "SELECT theme_path
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");
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);
1301 return date("Y/m/d G:i", $timestamp);
1305 function smart_date($timestamp) {
1306 if (date("Y.m.d", $timestamp) == date("Y.m.d")) {
1308 } else if (date("Y", $timestamp) == date("Y")) {
1309 return date("D m", $timestamp);
1311 return date("Y/m/d", $timestamp);
1315 function sql_bool_to_string($s) {
1316 if ($s == "t" ||
$s == "1") {
1323 function sql_bool_to_bool($s) {
1324 if ($s == "t" ||
$s == "1") {
1332 function toggleEvenOdd($a) {
1339 function sanity_check($link) {
1344 $result = db_query($link, "SELECT schema_version FROM ttrss_version");
1345 $schema_version = db_fetch_result($result, 0, "schema_version");
1347 if ($schema_version != SCHEMA_VERSION
) {
1351 if (DB_TYPE
== "mysql") {
1352 $result = db_query($link, "SELECT true", false);
1353 if (db_num_rows($result) != 1) {
1358 error_reporting (DEFAULT_ERROR_LEVEL
);
1360 if ($error_code != 0) {
1361 print_error_xml($error_code);
1368 function file_is_locked($filename) {
1370 $fp = fopen($filename, "r");
1371 error_reporting(DEFAULT_ERROR_LEVEL
);
1373 if (flock($fp, LOCK_EX | LOCK_NB
)) {
1374 flock($fp, LOCK_UN
);
1384 function make_lockfile($filename) {
1385 $fp = fopen($filename, "w");
1387 if (flock($fp, LOCK_EX | LOCK_NB
)) {
1394 function sql_random_function() {
1395 if (DB_TYPE
== "mysql") {
1402 function catchup_feed($link, $feed, $cat_view) {
1404 if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
1409 $cat_qpart = "cat_id = '$feed'";
1411 $cat_qpart = "cat_id IS NULL";
1414 $tmp_result = db_query($link, "SELECT id
1415 FROM ttrss_feeds WHERE $cat_qpart AND owner_uid = " .
1418 while ($tmp_line = db_fetch_assoc($tmp_result)) {
1420 $tmp_feed = $tmp_line["id"];
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"]);
1427 } else if ($feed > 0) {
1429 $tmp_result = db_query($link, "SELECT id
1430 FROM ttrss_feeds WHERE parent_feed = '$feed'
1431 ORDER BY cat_id,title");
1433 $parent_ids = array();
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"]);
1440 $children_qpart = implode(" OR ", $parent_ids);
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"]);
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"]);
1453 } else if ($feed < 0 && $feed > -10) { // special, like starred
1456 db_query($link, "UPDATE ttrss_user_entries
1457 SET unread = false,last_read = NOW()
1458 WHERE marked = true AND owner_uid = ".$_SESSION["uid"]);
1461 } else if ($feed < -10) { // label
1463 // TODO make this more efficient
1465 $label_id = -$feed - 11;
1467 $tmp_result = db_query($link, "SELECT sql_exp FROM ttrss_labels
1468 WHERE id = '$label_id'");
1471 $sql_exp = db_fetch_result($tmp_result, 0, "sql_exp");
1473 db_query($link, "BEGIN");
1475 $tmp2_result = db_query($link,
1479 ttrss_user_entries,ttrss_entries,ttrss_feeds
1481 ref_id = ttrss_entries.id AND
1482 ttrss_user_entries.feed_id = ttrss_feeds.id AND
1484 ttrss_user_entries.owner_uid = " . $_SESSION["uid"]);
1486 while ($tmp_line = db_fetch_assoc($tmp2_result)) {
1487 db_query($link, "UPDATE
1490 unread = false, last_read = NOW()
1492 int_id = " . $tmp_line["int_id"]);
1495 db_query($link, "COMMIT");
1497 /* db_query($link, "UPDATE ttrss_user_entries,ttrss_entries
1498 SET unread = false,last_read = NOW()
1501 AND owner_uid = ".$_SESSION["uid"]); */
1505 db_query($link, "BEGIN");
1507 $tag_name = db_escape_string($feed);
1509 $result = db_query($link, "SELECT post_int_id FROM ttrss_tags
1510 WHERE tag_name = '$tag_name' AND owner_uid = " . $_SESSION["uid"]);
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"]);
1517 db_query($link, "COMMIT");
1521 function update_generic_feed($link, $feed, $cat_view) {
1525 $cat_qpart = "cat_id = '$feed'";
1527 $cat_qpart = "cat_id IS NULL";
1530 $tmp_result = db_query($link, "SELECT feed_url FROM ttrss_feeds
1531 WHERE $cat_qpart AND owner_uid = " . $_SESSION["uid"]);
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
);
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
);
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);
1555 if (!$omode) $omode = "tflc";
1557 getGlobalCounters($link);
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);
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
1574 hidden = false AND owner_uid = ".$_SESSION["uid"]." GROUP BY cat_id");
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"]."\"/>";
1583 function getCategoryUnread($link, $cat) {
1586 $cat_query = "cat_id = '$cat'";
1588 $cat_query = "cat_id IS NULL";
1591 $result = db_query($link, "SELECT id FROM ttrss_feeds WHERE $cat_query
1593 AND owner_uid = " . $_SESSION["uid"]);
1595 $cat_feeds = array();
1596 while ($line = db_fetch_assoc($result)) {
1597 array_push($cat_feeds, "feed_id = " . $line["id"]);
1600 if (count($cat_feeds) == 0) return 0;
1602 $match_part = implode(" OR ", $cat_feeds);
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"]);
1610 # this needs to be rewritten
1611 while ($line = db_fetch_assoc($result)) {
1612 $unread +
= $line["unread"];
1619 function getFeedUnread($link, $feed, $is_cat = false) {
1620 $n_feed = sprintf("%d", $feed);
1623 return getCategoryUnread($link, $n_feed);
1624 } else if ($n_feed == -1) {
1625 $match_part = "marked = true";
1626 } else if ($n_feed > 0) {
1628 $result = db_query($link, "SELECT id FROM ttrss_feeds
1629 WHERE parent_feed = '$n_feed'
1631 AND owner_uid = " . $_SESSION["uid"]);
1633 if (db_num_rows($result) > 0) {
1635 $linked_feeds = array();
1636 while ($line = db_fetch_assoc($result)) {
1637 array_push($linked_feeds, "feed_id = " . $line["id"]);
1640 array_push($linked_feeds, "feed_id = $n_feed");
1642 $match_part = implode(" OR ", $linked_feeds);
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"]);
1651 # this needs to be rewritten
1652 while ($line = db_fetch_assoc($result)) {
1653 $unread +
= $line["unread"];
1659 $match_part = "feed_id = '$n_feed'";
1661 } else if ($feed < -10) {
1663 $label_id = -$feed - 11;
1665 $result = db_query($link, "SELECT sql_exp FROM ttrss_labels WHERE
1666 id = '$label_id' AND owner_uid = " . $_SESSION["uid"]);
1668 $match_part = db_fetch_result($result, 0, "sql_exp");
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"]);
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"]);
1688 $unread = db_fetch_result($result, 0, "unread");
1693 /* FIXME this needs reworking */
1695 function getGlobalUnread($link, $user_id = false) {
1698 $user_id = $_SESSION["uid"];
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
1706 ttrss_user_entries.owner_uid = '$user_id'");
1707 $c_id = db_fetch_result($result, 0, "c_id");
1711 function getGlobalCounters($link, $global_unread = -1) {
1712 if ($global_unread == -1) {
1713 $global_unread = getGlobalUnread($link);
1715 print "<counter type=\"global\" id='global-unread'
1716 counter='$global_unread'/>";
1718 $result = db_query($link, "SELECT COUNT(id) AS fn FROM
1719 ttrss_feeds WHERE owner_uid = " . $_SESSION["uid"]);
1721 $subscribed_feeds = db_fetch_result($result, 0, "fn");
1723 print "<counter type=\"global\" id='subscribed-feeds'
1724 counter='$subscribed_feeds'/>";
1728 function getTagCounters($link, $smart_mode = SMART_RPC_COUNTERS
) {
1731 if (!$_SESSION["tctr_last_value"]) {
1732 $_SESSION["tctr_last_value"] = array();
1736 $old_counters = $_SESSION["tctr_last_value"];
1738 $tctrs_modified = false;
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
1746 select tag_name,0 as count FROM ttrss_tags
1747 WHERE ttrss_tags.owner_uid = ".$_SESSION["uid"]); */
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");
1756 while ($line = db_fetch_assoc($result)) {
1757 $tags[$line["tag_name"]] +
= $line["count"];
1760 foreach (array_keys($tags) as $tag) {
1761 $unread = $tags[$tag];
1763 $tag = htmlspecialchars($tag);
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\"/>";
1773 if ($smart_mode && $tctrs_modified) {
1774 $_SESSION["tctr_last_value"] = $old_counters;
1779 function getLabelCounters($link, $smart_mode = SMART_RPC_COUNTERS
, $ret_mode = false) {
1782 if (!$_SESSION["lctr_last_value"]) {
1783 $_SESSION["lctr_last_value"] = array();
1789 $old_counters = $_SESSION["lctr_last_value"];
1790 $lctrs_modified = false;
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"]);
1797 $count = db_fetch_result($result, 0, "count");
1800 print "<counter type=\"label\" id=\"-1\" counter=\"$count\"/>";
1802 $ret_arr["-1"]["counter"] = $count;
1803 $ret_arr["-1"]["description"] = "Starred";
1806 $result = db_query($link, "SELECT owner_uid,id,sql_exp,description FROM
1807 ttrss_labels WHERE owner_uid = ".$_SESSION["uid"]." ORDER by description");
1809 while ($line = db_fetch_assoc($result)) {
1811 $id = -$line["id"] - 11;
1813 $label_name = $line["description"];
1815 error_reporting (0);
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"]);
1824 $count = db_fetch_result($tmp_result, 0, "count");
1826 if (!$smart_mode ||
$old_counters[$id] != $count) {
1827 $old_counters[$id] = $count;
1828 $lctrs_modified = true;
1830 print "<counter type=\"label\" id=\"$id\" counter=\"$count\"/>";
1832 $ret_arr[$id]["counter"] = $count;
1833 $ret_arr[$id]["description"] = $label_name;
1837 error_reporting (DEFAULT_ERROR_LEVEL
);
1840 if ($smart_mode && $lctrs_modified) {
1841 $_SESSION["lctr_last_value"] = $old_counters;
1847 /* function getFeedCounter($link, $id) {
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");
1856 $count = db_fetch_result($result, 0, "count");
1857 $last_error = htmlspecialchars(db_fetch_result($result, 0, "last_error"));
1859 print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" error=\"$last_error\"/>";
1862 function getFeedCounters($link, $smart_mode = SMART_RPC_COUNTERS
) {
1865 if (!$_SESSION["fctr_last_value"]) {
1866 $_SESSION["fctr_last_value"] = array();
1870 $old_counters = $_SESSION["fctr_last_value"];
1872 $result = db_query($link, "SELECT id,last_error,parent_feed,
1873 SUBSTRING(last_updated,1,19) AS last_updated,
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");
1882 $fctrs_modified = false;
1884 $short_date = get_pref($link, 'SHORT_DATE_FORMAT');
1886 while ($line = db_fetch_assoc($result)) {
1889 $count = $line["count"];
1890 $last_error = htmlspecialchars($line["last_error"]);
1892 if (get_pref($link, 'HEADLINES_SMART_DATE')) {
1893 $last_updated = smart_date_time(strtotime($line["last_updated"]));
1895 $last_updated = date($short_date, strtotime($line["last_updated"]));
1898 $has_img = is_file(ICONS_DIR
. "/$id.ico");
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");
1906 if (db_num_rows($tmp_result) > 0) {
1907 while ($l = db_fetch_assoc($tmp_result)) {
1908 $count +
= $l["unread"];
1912 if (!$smart_mode ||
$old_counters[$id] != $count) {
1913 $old_counters[$id] = $count;
1914 $fctrs_modified = true;
1917 $error_part = "error=\"$last_error\"";
1923 $has_img_part = "hi=\"$has_img\"";
1928 print "<counter type=\"feed\" id=\"$id\" counter=\"$count\" $has_img_part $error_part updated=\"$last_updated\"/>";
1932 if ($smart_mode && $fctrs_modified) {
1933 $_SESSION["fctr_last_value"] = $old_counters;
1937 function get_script_dt_add() {
1938 if (strpos(VERSION
, "99") === false) {
1945 function get_pgsql_version($link) {
1946 $result = db_query($link, "SELECT version() AS version");
1947 $version = split(" ", db_fetch_result($result, 0, "version"));
1951 function print_error_xml($code, $add_msg = "") {
1954 $error_msg = $ERRORS[$code];
1957 $error_msg = "$error_msg; $add_msg";
1960 print "<rpc-reply>";
1961 print "<error error-code=\"$code\" error-msg=\"$error_msg\"/>";
1962 print "</rpc-reply>";
1965 function subscribe_to_feed($link, $feed_link, $cat_id = 0) {
1967 $feed_link = trim(preg_replace("/^feed:/", "", $feed_link));
1969 if ($feed_link == "") return;
1971 if ($cat_id == "0" ||
!$cat_id) {
1972 $cat_qpart = "NULL";
1974 $cat_qpart = "'$cat_id'";
1977 $result = db_query($link,
1978 "SELECT id FROM ttrss_feeds
1979 WHERE feed_url = '$feed_link' AND owner_uid = ".$_SESSION["uid"]);
1981 if (db_num_rows($result) == 0) {
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)");
1988 $result = db_query($link,
1989 "SELECT id FROM ttrss_feeds WHERE feed_url = '$feed_link'
1990 AND owner_uid = " . $_SESSION["uid"]);
1992 $feed_id = db_fetch_result($result, 0, "id");
1995 update_rss_feed($link, $feed_link, $feed_id, true);
2004 function print_feed_select($link, $id, $default_id = "",
2005 $attributes = "", $include_all_feeds = true) {
2007 print "<select id=\"$id\" name=\"$id\" $attributes>";
2008 if ($include_all_feeds) {
2009 print "<option value=\"0\">All feeds</option>";
2012 $result = db_query($link, "SELECT id,title FROM ttrss_feeds
2013 WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
2015 if (db_num_rows($result) > 0 && $include_all_feeds) {
2016 print "<option disabled>--------</option>";
2019 while ($line = db_fetch_assoc($result)) {
2020 if ($line["id"] == $default_id) {
2021 $is_selected = "selected";
2025 printf("<option $is_selected value='%d'>%s</option>",
2026 $line["id"], htmlspecialchars(db_unescape_string($line["title"])));
2032 function print_feed_cat_select($link, $id, $default_id = "",
2033 $attributes = "", $include_all_cats = true) {
2035 print "<select id=\"$id\" name=\"$id\" $attributes>";
2037 if ($include_all_cats) {
2038 print "<option value=\"0\">Uncategorized</option>";
2041 $result = db_query($link, "SELECT id,title FROM ttrss_feed_categories
2042 WHERE owner_uid = ".$_SESSION["uid"]." ORDER BY title");
2044 if (db_num_rows($result) > 0 && $include_all_cats) {
2045 print "<option disabled>--------</option>";
2048 while ($line = db_fetch_assoc($result)) {
2049 if ($line["id"] == $default_id) {
2050 $is_selected = "selected";
2054 printf("<option $is_selected value='%d'>%s</option>",
2055 $line["id"], htmlspecialchars(db_unescape_string($line["title"])));
2061 function checkbox_to_sql_bool($val) {
2062 return ($val == "on") ?
"true" : "false";
2065 function getFeedCatTitle($link, $id) {
2068 } else if ($id < -10) {
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");
2077 return "Uncategorized";
2080 return "getFeedCatTitle($id) failed";
2085 function getFeedTitle($link, $id) {
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");
2094 return "Unknown label ($label_id)";
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");
2102 return "Unknown feed ($id)";
2105 return "getFeedTitle($id) failed";
2110 function get_session_cookie_name() {
2111 return ((!defined('TTRSS_SESSION_NAME')) ?
"ttrss_sid" : TTRSS_SESSION_NAME
);
2114 function print_init_params($link) {
2115 print "<init-params>";
2116 if ($_SESSION["stored-params"]) {
2117 foreach (array_keys($_SESSION["stored-params"]) as $key) {
2119 $value = htmlspecialchars($_SESSION["stored-params"][$key]);
2120 print "<param key=\"$key\" value=\"$value\"/>";
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
. "\"/>";
2129 print "<param key=\"on_catchup_show_next_feed\" value=\"" .
2130 get_pref($link, "ON_CATCHUP_SHOW_NEXT_FEED") . "\"/>";
2132 print "<param key=\"hide_read_feeds\" value=\"" .
2133 sprintf("%d", get_pref($link, "HIDE_READ_FEEDS")) . "\"/>";
2135 print "<param key=\"feeds_sort_by_unread\" value=\"" .
2136 sprintf("%d", get_pref($link, "FEEDS_SORT_BY_UNREAD")) . "\"/>";
2138 print "<param key=\"confirm_feed_catchup\" value=\"" .
2139 sprintf("%d", get_pref($link, "CONFIRM_FEED_CATCHUP")) . "\"/>";
2141 print "</init-params>";
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")) . "\"/>";
2150 print "</runtime-info>";
2153 function getSearchSql($search, $match_on) {
2155 $search_query_part = "";
2157 $keywords = split(" ", $search);
2158 $query_keywords = array();
2160 if ($match_on == "both") {
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%'))");
2167 $search_query_part = implode("AND", $query_keywords) . " AND ";
2169 } else if ($match_on == "title") {
2171 foreach ($keywords as $k) {
2172 array_push($query_keywords, "(UPPER(ttrss_entries.title) LIKE UPPER('%$k%'))");
2175 $search_query_part = implode("AND", $query_keywords) . " AND ";
2177 } else if ($match_on == "content") {
2179 foreach ($keywords as $k) {
2180 array_push($query_keywords, "(UPPER(ttrss_entries.content) LIKE UPPER('%$k%'))");
2184 $search_query_part = implode("AND", $query_keywords);
2186 return $search_query_part;
2189 function queryFeedHeadlines($link, $feed, $limit, $view_mode, $cat_view, $search, $search_mode, $match_on, $override_order = false) {
2192 $search_query_part = getSearchSql($search, $match_on);
2193 $search_query_part .= " AND ";
2196 $search_query_part = "";
2199 $view_query_part = "";
2201 if ($view_mode == "adaptive") {
2203 $view_query_part = " ";
2204 } else if ($feed != -1) {
2205 $unread = getFeedUnread($link, $feed, $cat_view);
2207 $view_query_part = " unread = true AND ";
2212 if ($view_mode == "marked") {
2213 $view_query_part = " marked = true AND ";
2216 if ($view_mode == "unread") {
2217 $view_query_part = " unread = true AND ";
2221 $limit_query_part = "LIMIT " . $limit;
2224 $vfeed_query_part = "";
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") {
2236 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2238 $tmp_result = false;
2241 $tmp_result = db_query($link, "SELECT id
2242 FROM ttrss_feeds WHERE cat_id = '$feed'");
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'");
2249 $cat_siblings = array();
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"]);
2256 $query_strategy_part = sprintf("(feed_id = %d OR %s)",
2257 $feed, implode(" OR ", $cat_siblings));
2260 $query_strategy_part = "ttrss_entries.id > 0";
2263 } else if ($feed >= 0) {
2268 $query_strategy_part = "cat_id = '$feed'";
2270 $query_strategy_part = "cat_id IS NULL";
2273 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2276 $tmp_result = db_query($link, "SELECT id
2277 FROM ttrss_feeds WHERE parent_feed = '$feed'
2278 ORDER BY cat_id,title");
2280 $parent_ids = array();
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"]);
2287 $query_strategy_part = sprintf("(feed_id = %d OR %s)",
2288 $feed, implode(" OR ", $parent_ids));
2290 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2292 $query_strategy_part = "feed_id = '$feed'";
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;
2301 $tmp_result = db_query($link, "SELECT sql_exp FROM ttrss_labels
2302 WHERE id = '$label_id'");
2304 $query_strategy_part = db_fetch_result($tmp_result, 0, "sql_exp");
2306 $vfeed_query_part = "ttrss_feeds.title AS feed_title,";
2308 $query_strategy_part = "id > 0"; // dumb
2311 if (get_pref($link, 'REVERSE_HEADLINES')) {
2312 $order_by = "updated";
2314 $order_by = "updated DESC";
2317 if ($override_order) {
2318 $order_by = $override_order;
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) {
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");
2338 $feed_title = "Uncategorized";
2342 $feed_title = "Category search results ($search, $feed_title)";
2347 $result = db_query($link, "SELECT title,site_url,last_error FROM ttrss_feeds
2348 WHERE id = '$feed' AND owner_uid = " . $_SESSION["uid"]);
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");
2355 $feed_title = "Feed search results ($search, $feed_title)";
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");
2368 $feed_title = "Label search results ($search, $feed_title)";
2374 $feed_title = db_unescape_string($feed_title);
2376 if ($feed < -10) error_reporting (0);
2378 if (preg_match("/^-?[0-9][0-9]*$/", $feed) != false) {
2381 $feed_kind = "Feeds";
2383 $feed_kind = "Labels";
2386 $content_query_part = "content as content_preview,";
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,
2396 SUBSTRING(updated,1,19) as updated_noms,
2399 ttrss_entries,ttrss_user_entries,ttrss_feeds
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
2407 $query_strategy_part ORDER BY $order_by
2410 $result = db_query($link, $query);
2412 if ($_GET["debug"]) print $query;
2417 $feed_kind = "Tags";
2419 $result = db_query($link, "SELECT
2421 ttrss_entries.id as id,title,
2422 SUBSTRING(updated,1,16) as updated,
2424 marked,link,last_read,
2425 SUBSTRING(last_read,1,19) as last_read_noms,
2428 SUBSTRING(updated,1,19) as updated_noms
2430 ttrss_entries,ttrss_user_entries,ttrss_tags
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
2437 $query_strategy_part ORDER BY $order_by
2438 $limit_query_part");
2441 return array($result, $feed_title, $feed_site_url, $last_error);
2445 function generate_syndicated_feed($link, $feed, $is_cat,
2446 $search, $search_mode, $match_on) {
2448 $qfh_ret = queryFeedHeadlines($link, $feed,
2449 30, false, $is_cat, $search, $search_mode, $match_on, "updated DESC");
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];
2456 print "<rss version=\"2.0\">
2458 <title>$feed_title</title>
2459 <link>$feed_site_url</link>
2460 <generator>Tiny Tiny RSS v".VERSION
."</generator>";
2462 while ($line = db_fetch_assoc($result)) {
2464 print "<id>" . htmlspecialchars($line["guid"]) . "</id>";
2465 print "<link>" . htmlspecialchars($line["link"]) . "</link>";
2467 $rfc822_date = date('r', strtotime($line["updated"]));
2469 print "<pubDate>$rfc822_date</pubDate>";
2472 htmlspecialchars($line["title"]) . "</title>";
2474 print "<description>" .
2475 htmlspecialchars($line["content_preview"]) . "</description>";
2480 print "</channel></rss>";
2484 function getCategoryTitle($link, $cat_id) {
2486 $result = db_query($link, "SELECT title FROM ttrss_feed_categories WHERE
2489 if (db_num_rows($result) == 1) {
2490 return db_fetch_result($result, 0, "title");
2492 return "Uncategorized";
2496 function sanitize_rss($str) {
2499 $res = preg_replace('/<script.*?>/i',
2500 "<p class=\"scriptWarn\">Disabled script: ", $res);
2502 $res = preg_replace('/<\/script.*?>/i', "</p>", $res);
2504 /* $res = preg_replace('/<embed.*?>/i', "", $res);
2506 $res = preg_replace('/<object.*?>.*?<\/object>/i',
2507 "<p class=\"objectWarn\">(Disabled html object
2508 - flash or other embedded content)</p>", $res); */
2513 function send_headlines_digests($link, $limit = 100) {
2515 if (!DIGEST_ENABLE
) return false;
2517 $user_limit = DIGEST_EMAIL_LIMIT
;
2520 print "Sending digests, batch of max $user_limit users, days = $days, headline limit = $limit\n\n";
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)";
2528 $result = db_query($link, "SELECT id,email FROM ttrss_users
2529 WHERE email != '' AND (last_digest_sent IS NULL OR $interval_query)");
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"] . " ... ";
2535 $tuple = prepare_headlines_digest($link, $line["id"], $days, $limit);
2536 $digest = $tuple[0];
2537 $headlines_count = $tuple[1];
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");
2546 db_query($link, "UPDATE ttrss_users SET last_digest_sent = NOW()
2547 WHERE id = " . $line["id"]);
2549 print "No headlines\n";
2554 // $digest = prepare_headlines_digest($link, $user_id, $days, $limit);
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";
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)";
2568 $result = db_query($link, "SELECT ttrss_entries.title,
2569 ttrss_feeds.title AS feed_title,
2572 SUBSTRING(last_updated,1,19) AS last_updated
2574 ttrss_user_entries,ttrss_entries,ttrss_feeds
2576 ref_id = ttrss_entries.id AND feed_id = ttrss_feeds.id
2577 AND include_in_digest = true
2579 AND ttrss_user_entries.owner_uid = $user_id
2580 AND unread = true ORDER BY ttrss_feeds.title, date_entered DESC
2583 $cur_feed_title = "";
2585 $headlines_count = db_num_rows($result);
2587 while ($line = db_fetch_assoc($result)) {
2588 $updated = smart_date_time(strtotime($line["last_updated"]));
2589 $feed_title = $line["feed_title"];
2591 if ($cur_feed_title != $feed_title) {
2592 $cur_feed_title = $feed_title;
2594 $tmp .= "$feed_title\n\n";
2597 $tmp .= " * " . trim($line["title"]) . " - $updated\n";
2598 $tmp .= " " . trim($line["link"]) . "\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";
2608 return array($tmp, $headlines_count);
2611 function check_for_update($link) {
2612 $releases_feed = "http://tt-rss.spb.ru/releases.rss";
2614 if (!CHECK_FOR_NEW_VERSION ||
$_SESSION["access_level"] < 10) {
2619 $rss = fetch_rss($releases_feed);
2620 error_reporting (DEFAULT_ERROR_LEVEL
);
2624 $items = $rss->items
;
2626 if (!$items ||
!is_array($items)) $items = $rss->entries
;
2627 if (!$items ||
!is_array($items)) $items = $rss;
2629 if (!is_array($items) ||
count($items) == 0) {
2633 $latest_item = $items[0];
2635 $latest_version = trim(preg_replace("/(Milestone)|(completed)/", "", $latest_item["title"]));
2637 $release_url = sanitize_rss($latest_item["link"]);
2638 $content = sanitize_rss($latest_item["description"]);
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>";
2648 function markArticlesById($link, $ids, $cmode) {
2652 foreach ($ids as $id) {
2653 array_push($tmp_ids, "ref_id = '$id'");
2656 $ids_qpart = join(" OR ", $tmp_ids);
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
2665 WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
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"]);
2673 function catchupArticlesById($link, $ids, $cmode) {
2677 foreach ($ids as $id) {
2678 array_push($tmp_ids, "ref_id = '$id'");
2681 $ids_qpart = join(" OR ", $tmp_ids);
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
2690 WHERE ($ids_qpart) AND owner_uid = " . $_SESSION["uid"]);
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"]);
2698 function escape_for_form($s) {
2699 return htmlspecialchars(db_unescape_string($s));
2702 function make_guid_from_title($title) {
2703 return preg_replace("/[ \"\',.:;]/", "-",
2704 mb_strtolower(strip_tags($title)));
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) {
2713 $class = "headlinesSubToolbar";
2714 $tid = "headlineActionsTop";
2716 $class = "headlinesSubToolbar";
2717 $tid = "headlineActionsBottom";
2720 print "<table class=\"$class\" id=\"$tid\"
2721 width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tr>";
2729 if (!get_pref($link, 'COMBINED_DISPLAY_MODE')) {
2731 print "<td class=\"headlineActions$rtl_cpart\">
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>
2737 Toggle: <a href=\"javascript:selectionToggleUnread()\">Unread</a>,
2738 <a href=\"javascript:selectionToggleMarked()\">Starred</a>
2741 <a href=\"#\" onclick=\"catchupPage()\">Page</a>,
2742 <a href=\"#\" onclick=\"catchupCurrentFeed()\">Feed</a>";
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>";
2754 print "<td class=\"headlineActions$rtl_cpart\">
2756 <a href=\"javascript:cdmSelectArticles('all')\">All</a>,
2757 <a href=\"javascript:cdmSelectArticles('unread')\">Unread</a>,
2758 <a href=\"javascript:cdmSelectArticles('none')\">None</a>
2760 Toggle: <a href=\"javascript:selectionToggleUnread(true)\">Unread</a>,
2761 <a href=\"javascript:selectionToggleMarked(true)\">Starred</a>
2764 <a href=\"#\" onclick=\"catchupPage()\">Page</a>,
2765 <a href=\"#\" onclick=\"catchupCurrentFeed()\">Feed</a>";
2771 print "<td class=\"headlineTitle$rtl_cpart\">";
2773 if ($feed_site_url) {
2775 $target = "target=\"_blank\"";
2777 print "<a $target href=\"$feed_site_url\">$feed_title</a>";
2783 $search_q = "&q=$search&m=$match_on&smode=$search_mode";
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\">
2796 print "</tr></table>";
2800 function outputFeedList($link, $tags = false) {
2802 print "<ul class=\"feedList\" id=\"feedList\">\n";
2804 $owner_uid = $_SESSION["uid"];
2808 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2809 print "<li class=\"feedCat\">Special</li>";
2810 print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
2813 $num_starred = getFeedUnread($link, -1);
2817 if ($num_starred > 0) $class .= "Unread";
2819 printFeedEntry(-1, $class, "Starred articles", $num_starred,
2820 "images/mark_set.png", $link);
2822 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2828 if (GLOBAL_ENABLE_LABELS
&& get_pref($link, 'ENABLE_LABELS')) {
2830 $result = db_query($link, "SELECT id,sql_exp,description FROM
2831 ttrss_labels WHERE owner_uid = '$owner_uid' ORDER by description");
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\">";
2838 print "<li><hr></li>";
2842 while ($line = db_fetch_assoc($result)) {
2844 error_reporting (0);
2846 $label_id = -$line['id'] - 11;
2847 $count = getFeedUnread($link, $label_id);
2855 error_reporting (DEFAULT_ERROR_LEVEL
);
2857 printFeedEntry($label_id,
2858 $class, db_unescape_string($line["description"]),
2859 $count, "images/label.png", $link);
2863 if (db_num_rows($result) > 0) {
2864 if (get_pref($link, 'ENABLE_FEED_CATS')) {
2871 if (!get_pref($link, 'ENABLE_FEED_CATS')) {
2872 print "<li><hr></li>";
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";
2879 $order_by_qpart = "category,title";
2882 if (get_pref($link, "FEEDS_SORT_BY_UNREAD")) {
2883 $order_by_qpart = "unread DESC,title";
2885 $order_by_qpart = "title";
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,
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)
2901 ttrss_feeds.hidden = false AND
2902 ttrss_feeds.owner_uid = '$owner_uid' AND parent_feed IS NULL
2903 ORDER BY $order_by_qpart");
2905 $actid = $_GET["actid"];
2915 $short_date = get_pref($link, 'SHORT_DATE_FORMAT');
2917 while ($line = db_fetch_assoc($result)) {
2919 $feed = db_unescape_string($line["title"]);
2920 $feed_id = $line["id"];
2922 $subop = $_GET["subop"];
2924 $unread = $line["unread"];
2926 if (get_pref($link, 'HEADLINES_SMART_DATE')) {
2927 $last_updated = smart_date_time(strtotime($line["last_updated_noms"]));
2929 $last_updated = date($short_date, strtotime($line["last_updated_noms"]));
2932 $rtl_content = sql_bool_to_bool($line["rtl_content"]);
2935 $rtl_tag = "dir=\"RTL\"";
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");
2947 if (db_num_rows($tmp_result) > 0) {
2948 while ($l = db_fetch_assoc($tmp_result)) {
2949 $unread +
= $l["unread"];
2953 $cat_id = $line["cat_id"];
2955 $tmp_category = $line["category"];
2957 if (!$tmp_category) {
2958 $tmp_category = "Uncategorized";
2961 // $class = ($lnum % 2) ? "even" : "odd";
2963 if ($line["last_error"]) {
2969 if ($unread > 0) $class .= "Unread";
2971 if ($actid == $feed_id) {
2972 $class .= "Selected";
2975 $total_unread +
= $unread;
2977 if ($category != $tmp_category && get_pref($link, 'ENABLE_FEED_CATS')) {
2983 $category = $tmp_category;
2985 $collapsed = $line["collapsed"];
2987 // workaround for NULL category
2988 if ($category == "Uncategorized") {
2989 if ($_COOKIE["ttrss_vf_uclps"] == 1) {
2994 if ($collapsed == "t" ||
$collapsed == "1") {
2995 $holder_class = "invisible";
3002 $cat_id = sprintf("%d", $cat_id);
3004 $cat_unread = getCategoryUnread($link, $cat_id);
3006 $catctr_class = ($cat_unread > 0) ?
"catCtrHasUnread" : "catCtrNoUnread";
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
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\">";
3020 printFeedEntry($feed_id, $class, $feed, $unread,
3021 "icons/$feed_id.ico", $link, $rtl_content,
3022 $last_updated, $line["last_error"]);
3027 if (db_num_rows($result) == 0) {
3028 print "<li>No feeds to display.</li>";
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
3041 select tag_name,0 as count FROM ttrss_tags WHERE owner_uid = '$owner_uid'
3042 ORDER BY tag_name"); */
3044 if (get_pref($link, 'ENABLE_FEED_CATS')) {
3045 print "<li class=\"feedCat\">Tags</li>";
3046 print "<li id=\"feedCatHolder\"><ul class=\"feedCatList\">";
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");
3056 while ($line = db_fetch_assoc($result)) {
3057 $tags[$line["tag_name"]] +
= $line["count"];
3060 foreach (array_keys($tags) as $tag) {
3062 $unread = $tags[$tag];
3070 printFeedEntry($tag, $class, $tag, $unread, "images/tag.png", $link);
3074 if (db_num_rows($result) == 0) {
3075 print "<li>No tags to display.</li>";
3078 if (get_pref($link, 'ENABLE_FEED_CATS')) {
3088 function get_article_tags($link, $id) {
3090 $a_id = db_escape_string($id);
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");
3098 while ($tmp_line = db_fetch_assoc($tmp_result)) {
3099 array_push($tags, $tmp_line["tag_name"]);
3105 function trim_value(&$value) {
3106 $value = trim($value);
3109 function trim_array($array) {
3111 array_walk($tmp, 'trim_value');