]> git.wh0rd.org Git - tt-rss.git/blob - backend.php
allow onclick editing of categories and drag-reordering of feeds and categories
[tt-rss.git] / backend.php
1 <?php
2         /* remove ill effects of magic quotes */
3
4         if (get_magic_quotes_gpc()) {
5                 function stripslashes_deep($value) {
6                         $value = is_array($value) ? 
7                                 array_map('stripslashes_deep', $value) : stripslashes($value);
8                                 return $value;
9                 }
10
11                 $_POST = array_map('stripslashes_deep', $_POST);
12                 $_GET = array_map('stripslashes_deep', $_GET);
13                 $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
14                 $_REQUEST = array_map('stripslashes_deep', $_REQUEST);
15         }
16
17         require_once "functions.php";
18         require_once "sessions.php";
19         require_once "modules/backend-rpc.php";
20         require_once "sanity_check.php";
21         require_once "config.php";
22         require_once "db.php";
23         require_once "db-prefs.php";
24
25         no_cache_incantation();
26
27         if (ENABLE_TRANSLATIONS == true) { 
28                 startup_gettext();
29         }
30
31         $script_started = getmicrotime();
32
33         $link = db_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME); 
34
35         if (!$link) {
36                 if (DB_TYPE == "mysql") {
37                         print mysql_error();
38                 }
39                 // PG seems to display its own errors just fine by default.             
40                 return;
41         }
42
43         init_connection($link);
44
45         $op = $_REQUEST["op"];
46         $subop = $_REQUEST["subop"];
47         $mode = $_REQUEST["mode"];
48
49         $print_exec_time = false;
50
51         if ((!$op || $op == "rpc" || $op == "rss" || 
52                         ($op == "view" && $mode != "zoom") || 
53                         $op == "digestSend" || $op == "dlg" || 
54                         $op == "viewfeed" || $op == "publish" ||
55                         $op == "globalUpdateFeeds") && !$_REQUEST["noxml"]) {
56                                 header("Content-Type: application/xml; charset=utf-8");
57
58                                 if (ENABLE_GZIP_OUTPUT) {
59                                         ob_start("ob_gzhandler");
60                                 }
61                                 
62                 } else {
63                 if (!$_REQUEST["noxml"]) {
64                         header("Content-Type: text/html; charset=utf-8");
65                 } else {
66                         header("Content-Type: text/plain; charset=utf-8");
67                 }
68         }
69
70         if (!$op) {
71                 header("Content-Type: application/xml");
72                 print_error_xml(7); exit;
73         }
74
75         if (SINGLE_USER_MODE) {
76                 authenticate_user($link, "admin", null);
77         }
78
79         if (!($_SESSION["uid"] && validate_session($link)) && $op != "globalUpdateFeeds" 
80                 && $op != "rss" && $op != "getUnread" && $op != "publish" && $op != "getProfiles") {
81
82                 if ($op == "rpc" || $op == "viewfeed" || $op == "view") {
83                         print_error_xml(6); die;
84                 } else {
85                         print "
86                         <html><body>
87                                 <p>Error: Not logged in.</p>
88                                 <script type=\"text/javascript\">
89                                         if (parent.window != 'undefined') {
90                                                 parent.window.location = \"tt-rss.php\";                
91                                         } else {
92                                                 window.location = \"tt-rss.php\";
93                                         }
94                                 </script>
95                         </body></html>
96                         ";
97                 }
98                 exit;
99         }
100
101         $purge_intervals = array(
102                 0  => __("Use default"),
103                 -1 => __("Never purge"),
104                 5  => __("1 week old"),
105                 14 => __("2 weeks old"),
106                 31 => __("1 month old"),
107                 60 => __("2 months old"),
108                 90 => __("3 months old"));
109
110         $update_intervals = array(
111                 0   => __("Default interval"),
112                 -1  => __("Disable updates"),
113                 15  => __("Each 15 minutes"),
114                 30  => __("Each 30 minutes"),
115                 60  => __("Hourly"),
116                 240 => __("Each 4 hours"),
117                 720 => __("Each 12 hours"),
118                 1440 => __("Daily"),
119                 10080 => __("Weekly"));
120
121         $update_intervals_nodefault = array(
122                 -1  => __("Disable updates"),
123                 15  => __("Each 15 minutes"),
124                 30  => __("Each 30 minutes"),
125                 60  => __("Hourly"),
126                 240 => __("Each 4 hours"),
127                 720 => __("Each 12 hours"),
128                 1440 => __("Daily"),
129                 10080 => __("Weekly"));
130
131         $update_methods = array(
132                 0   => __("Default"),
133                 1   => __("Magpie"),
134                 2   => __("SimplePie"));
135
136         if (DEFAULT_UPDATE_METHOD == "1") {
137                 $update_methods[0] .= ' (SimplePie)';
138         } else {
139                 $update_methods[0] .= ' (Magpie)';
140         }
141
142         $access_level_names = array(
143                 0 => __("User"), 
144                 5 => __("Power User"),
145                 10 => __("Administrator"));
146
147         require_once "modules/pref-prefs.php";
148         require_once "modules/popup-dialog.php";
149         require_once "modules/help.php";
150         require_once "modules/pref-feeds.php";
151         require_once "modules/pref-filters.php";
152         require_once "modules/pref-labels.php";
153         require_once "modules/pref-users.php";
154
155         if (!sanity_check($link)) { return; }
156
157         switch($op) { // Select action according to $op value.
158                 case "rpc":
159                         // Handle remote procedure calls.
160                         handle_rpc_request($link);
161                 break; // rpc
162
163                 case "feeds":
164                         $subop = $_REQUEST["subop"];
165                         $root = (bool)$_REQUEST["root"];
166
167                         switch($subop) {
168                                 case "catchupAll":
169                                         db_query($link, "UPDATE ttrss_user_entries SET 
170                                                 last_read = NOW(),unread = false WHERE owner_uid = " . $_SESSION["uid"]);
171                                         ccache_zero_all($link, $_SESSION["uid"]);
172
173                                 break;
174
175                                 case "collapse":
176                                         $cat_id = db_escape_string($_REQUEST["cid"]);
177                                         $mode = (int) db_escape_string($_REQUEST['mode']);
178                                         toggle_collapse_cat($link, $cat_id, $mode);
179                                         return;
180                                 break;
181                         }
182
183                         if (!$root) {
184                                 print json_encode(outputFeedList($link));
185                         } else {
186
187                                 $feeds = outputFeedList($link, false);
188
189                                 $root = array();
190                                 $root['id'] = 'root';
191                                 $root['name'] = __('Feeds');
192                                 $root['items'] = $feeds['items'];
193
194                                 $fl = array();
195                                 $fl['identifier'] = 'id';
196                                 $fl['label'] = 'name';
197                                 $fl['items'] = array($root);
198
199                                 print json_encode($fl);
200                         }
201
202                 break; // feeds
203
204                 case "view":
205
206                         $id = db_escape_string($_REQUEST["id"]);
207                         $cids = split(",", db_escape_string($_REQUEST["cids"]));
208                         $mode = db_escape_string($_REQUEST["mode"]);
209                         $omode = db_escape_string($_REQUEST["omode"]);
210
211                         if ($mode != "zoom") print "<reply>";
212
213                         // in prefetch mode we only output requested cids, main article 
214                         // just gets marked as read (it already exists in client cache)
215
216                         if ($mode == "") {
217                                 outputArticleXML($link, $id, false);
218                         } else if ($mode == "zoom") {
219                                 outputArticleXML($link, $id, false, true, true);
220                         } else {
221                                 catchupArticleById($link, $id, 0);
222                         }
223
224                         if (!$_SESSION["bw_limit"]) {
225                                 foreach ($cids as $cid) {
226                                         if ($cid) {
227                                                 outputArticleXML($link, $cid, false, false);
228                                         }
229                                 }
230                         }
231
232                         /* if ($mode == "prefetch") {
233                                 print "<counters><![CDATA[";
234                                 print json_encode(getAllCounters($link, $omode));
235                                 print "]]></counters>";
236                         } */
237
238                         if ($mode != "zoom") print "</reply>";
239                 break; // view
240
241                 case "viewfeed":
242
243                         $print_exec_time = true;
244                         $timing_info = getmicrotime();
245
246                         print "<reply>";
247
248                         if ($_REQUEST["debug"]) $timing_info = print_checkpoint("0", $timing_info);
249
250                         $omode = db_escape_string($_REQUEST["omode"]);
251
252                         $feed = db_escape_string($_REQUEST["feed"]);
253                         $subop = db_escape_string($_REQUEST["subop"]);
254                         $view_mode = db_escape_string($_REQUEST["view_mode"]);
255                         $limit = (int) get_pref($link, "DEFAULT_ARTICLE_LIMIT");
256                         @$cat_view = db_escape_string($_REQUEST["cat"]);
257                         @$next_unread_feed = db_escape_string($_REQUEST["nuf"]);
258                         @$offset = db_escape_string($_REQUEST["skip"]);
259                         @$vgroup_last_feed = db_escape_string($_REQUEST["vgrlf"]);
260                         $order_by = db_escape_string($_REQUEST["order_by"]);
261
262                         /* Feed -5 is a special case: it is used to display auxiliary information
263                          * when there's nothing to load - e.g. no stuff in fresh feed */
264
265                         if ($feed == -5) {
266                                 generate_dashboard_feed($link);
267                                 print "</reply>";
268                                 return;
269                         }
270
271                         /* Updating a label ccache means recalculating all of the caches
272                          * so for performance reasons we don't do that here */
273
274                         if ($feed >= 0) {
275                                 ccache_update($link, $feed, $_SESSION["uid"], $cat_view);
276                         }
277
278                         set_pref($link, "_DEFAULT_VIEW_MODE", $view_mode);
279                         set_pref($link, "_DEFAULT_VIEW_LIMIT", $limit);
280                         set_pref($link, "_DEFAULT_VIEW_ORDER_BY", $order_by);
281
282                         if (!$cat_view && preg_match("/^[0-9][0-9]*$/", $feed)) {
283                                 db_query($link, "UPDATE ttrss_feeds SET last_viewed = NOW()
284                                         WHERE id = '$feed' AND owner_uid = ".$_SESSION["uid"]);
285                         }
286
287                         if (!$next_unread_feed) {
288                                 print "<headlines id=\"$feed\" is_cat=\"$cat_view\">";
289                         } else {
290                                 print "<headlines id=\"$next_unread_feed\" is_cat=\"$cat_view\">";
291                         }
292                 
293                         $override_order = false;
294
295                         if (get_pref($link, "SORT_HEADLINES_BY_FEED_DATE", $owner_uid)) {
296                                 $date_sort_field = "updated";
297                         } else {
298                                 $date_sort_field = "date_entered";
299                         }
300
301                         switch ($order_by) {
302                                 case "date":
303                                         if (get_pref($link, 'REVERSE_HEADLINES', $owner_uid)) {
304                                                 $override_order = "$date_sort_field";
305                                         } else {        
306                                                 $override_order = "$date_sort_field DESC";
307                                         }
308                                         break;
309
310                                 case "title":
311                                         if (get_pref($link, 'REVERSE_HEADLINES', $owner_uid)) {
312                                                 $override_order = "title DESC, $date_sort_field";
313                                         } else {
314                                                 $override_order = "title, $date_sort_field DESC";
315                                         }
316                                         break;
317
318                                 case "score":
319                                         if (get_pref($link, 'REVERSE_HEADLINES', $owner_uid)) {
320                                                 $override_order = "score, $date_sort_field";
321                                         } else {
322                                                 $override_order = "score DESC, $date_sort_field DESC";
323                                         }
324                                         break;
325                         }
326
327                         if ($_REQUEST["debug"]) $timing_info = print_checkpoint("04", $timing_info);
328
329                         $ret = outputHeadlinesList($link, $feed, $subop, 
330                                 $view_mode, $limit, $cat_view, $next_unread_feed, $offset, 
331                                 $vgroup_last_feed, $override_order);
332
333                         $topmost_article_ids = $ret[0];
334                         $headlines_count = $ret[1];
335                         $returned_feed = $ret[2];
336                         $disable_cache = $ret[3];
337                         $vgroup_last_feed = $ret[4];
338
339                         print "</headlines>";
340
341                         if ($_REQUEST["debug"]) $timing_info = print_checkpoint("05", $timing_info);
342
343                         //print "<headlines-count value=\"$headlines_count\"/>";
344                         //print "<vgroup-last-feed value=\"$vgroup_last_feed\"/>";
345
346                         $headlines_unread = ccache_find($link, $returned_feed, $_SESSION["uid"],
347                                         $cat_view, true);
348
349                         if ($headlines_unread == -1) {
350                                 $headlines_unread = getFeedUnread($link, $returned_feed, $cat_view);
351
352                         }
353
354                         //print "<headlines-unread value=\"$headlines_unread\"/>";
355                         //printf("<disable-cache value=\"%d\"/>", $disable_cache);
356
357                         print "<headlines-info><![CDATA[";
358
359                         $info = array("count" => (int) $headlines_count,
360                                 "vgroup_last_feed" => $vgroup_last_feed,
361                                 "unread" => (int) $headlines_unread,
362                                 "disable_cache" => (bool) $disable_cache);
363
364                         print json_encode($info);
365
366                         print "]]></headlines-info>";
367
368                         if ($_REQUEST["debug"]) $timing_info = print_checkpoint("10", $timing_info);
369
370                         if (is_array($topmost_article_ids) && !get_pref($link, 'COMBINED_DISPLAY_MODE') && !$_SESSION["bw_limit"]) {
371                                 print "<articles>";
372                                 foreach ($topmost_article_ids as $id) {
373                                         outputArticleXML($link, $id, $feed, false);
374                                 }
375                                 print "</articles>";
376                         }
377
378                         if ($_REQUEST["debug"]) $timing_info = print_checkpoint("20", $timing_info);
379
380                         //if (get_pref($link, 'COMBINED_DISPLAY_MODE') || $subop) {
381                         if ($subop) {
382                                 print "<counters><![CDATA[";
383                                 print json_encode(getAllCounters($link, $omode, $feed));
384                                 print "]]></counters>";
385                         } 
386
387                         if ($_REQUEST["debug"]) $timing_info = print_checkpoint("30", $timing_info);
388
389                         print_runtime_info($link);
390
391                         print "</reply>";
392                 break; // viewfeed
393
394                 case "pref-feeds":
395                         module_pref_feeds($link);
396                 break; // pref-feeds
397
398                 case "pref-filters":
399                         module_pref_filters($link);
400                 break; // pref-filters
401
402                 case "pref-labels":
403                         module_pref_labels($link);
404                 break; // pref-labels
405
406                 case "pref-prefs":
407                         module_pref_prefs($link);
408                 break; // pref-prefs
409
410                 case "pref-users":
411                         module_pref_users($link);
412                 break; // prefs-users
413
414                 case "help":
415                         module_help($link);
416                 break; // help
417
418                 case "dlg":
419                         module_popup_dialog($link);
420                 break; // dlg
421
422                 case "pref-pub-items":
423                         module_pref_pub_items($link);
424                 break; // pref-pub-items
425
426                 case "globalUpdateFeeds":
427                         // update feeds of all users, may be used anonymously
428
429                         print "<!--";
430                         // Update all feeds needing a update.
431                         update_daemon_common($link, 0, true, true);
432                         print " -->";
433
434                         print "<rpc-reply>
435                                 <message msg=\"All feeds updated\"/>
436                         </rpc-reply>";
437                 break; // globalUpdateFeeds
438
439                 case "pref-feed-browser":
440                         module_pref_feed_browser($link);
441                 break; // pref-feed-browser
442
443                 case "rss":
444                         $feed = db_escape_string($_REQUEST["id"]);
445                         $key = db_escape_string($_REQUEST["key"]);
446                         $is_cat = $_REQUEST["is_cat"] != false;
447                         $limit = (int)db_escape_string($_REQUEST["limit"]);
448
449                         $search = db_escape_string($_REQUEST["q"]);
450                         $match_on = db_escape_string($_REQUEST["m"]);
451                         $search_mode = db_escape_string($_REQUEST["smode"]);
452                         $view_mode = db_escape_string($_REQUEST["view-mode"]);
453
454                         if (SINGLE_USER_MODE) {
455                                 authenticate_user($link, "admin", null);
456                         }
457
458                         if ($key && !$_SESSION["uid"]) {
459                                 $result = db_query($link, "SELECT owner_uid FROM
460                                         ttrss_access_keys WHERE access_key = '$key' AND feed_id = '$feed'");
461
462                                 if (db_num_rows($result) == 1)
463                                         $_SESSION["uid"] = db_fetch_result($result, 0, "owner_uid");
464
465                         }
466
467                         if ($_SESSION["uid"]) {
468                                 generate_syndicated_feed($link, 0, $feed, $is_cat, $limit,
469                                         $search, $search_mode, $match_on, $view_mode);
470                         }
471                 break; // rss
472
473                 case "getUnread":
474                         $login = db_escape_string($_REQUEST["login"]);
475                         $fresh = $_REQUEST["fresh"] == "1";
476
477                         header("Content-Type: text/plain; charset=utf-8");
478
479                         $result = db_query($link, "SELECT id FROM ttrss_users WHERE login = '$login'");
480
481                         if (db_num_rows($result) == 1) {
482                                 $uid = db_fetch_result($result, 0, "id");
483
484                                 print getGlobalUnread($link, $uid);
485
486                                 if ($fresh) {
487                                         print ";";
488                                         print getFeedArticles($link, -3, false, true, $uid);
489                                 }
490
491                         } else {
492                                 print "-1;User not found";
493                         }
494
495                         $print_exec_time = false;
496                 break; // getUnread
497
498                 case "digestTest":
499                         header("Content-Type: text/plain");
500                         print_r(prepare_headlines_digest($link, $_SESSION["uid"]));
501                         $print_exec_time = false;
502                 break; // digestTest
503
504                 case "digestSend":
505                         header("Content-Type: text/plain");
506                         send_headlines_digests($link);
507                         $print_exec_time = false;
508                 break; // digestSend
509
510                 case "getProfiles":
511                         $login = db_escape_string($_REQUEST["login"]);
512                         $password = db_escape_string($_REQUEST["password"]);
513
514                         if (authenticate_user($link, $login, $password)) {
515                                 $result = db_query($link, "SELECT * FROM ttrss_settings_profiles
516                                         WHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY title");
517
518                                 print "<select style='width: 100%' name='profile'>";
519
520                                 print "<option value='0'>" . __("Default profile") . "</option>";
521
522                                 while ($line = db_fetch_assoc($result)) {
523                                         $id = $line["id"];
524                                         $title = $line["title"];
525
526                                         print "<option value='$id'>$title</option>";
527                                 }
528
529                                 print "</select>";
530
531                                 $_SESSION = array();
532                         }
533                 break;
534
535         } // Select action according to $op value.
536
537         // We close the connection to database.
538         db_close($link);
539 ?>
540
541 <?php if ($print_exec_time) { ?>
542 <!-- <?php echo sprintf("Backend execution time: %.4f seconds", getmicrotime() - $script_started) ?> -->
543 <?php } ?>