]> git.wh0rd.org - tt-rss.git/blame - classes/pref_feeds.php
small tweak for loadMoreHeadlines() algorithm
[tt-rss.git] / classes / pref_feeds.php
CommitLineData
afcfe6ca 1<?php
46da73c2 2class Pref_Feeds extends Protected_Handler {
8484ce22
AD
3
4 function csrf_ignore($method) {
f6cd767b 5 $csrf_ignored = array("index", "getfeedtree", "add", "editcats", "editfeed",
35b9844b 6 "savefeedorder", "uploadicon");
8484ce22
AD
7
8 return array_search($method, $csrf_ignored) !== false;
9 }
10
afcfe6ca
AD
11 function batch_edit_cbox($elem, $label = false) {
12 print "<input type=\"checkbox\" title=\"".__("Check to enable field")."\"
13 onchange=\"dijit.byId('feedEditDlg').toggleField(this, '$elem', '$label')\">";
14 }
15
16 function renamecat() {
17 $title = db_escape_string($_REQUEST['title']);
18 $id = db_escape_string($_REQUEST['id']);
19
20 if ($title) {
21 db_query($this->link, "UPDATE ttrss_feed_categories SET
22 title = '$title' WHERE id = '$id' AND owner_uid = " . $_SESSION["uid"]);
23 }
24 return;
25 }
26
27 function remtwitterinfo() {
28
29 db_query($this->link, "UPDATE ttrss_users SET twitter_oauth = NULL
30 WHERE id = " . $_SESSION['uid']);
31
32 return;
33 }
34
2a060a94 35 private function get_category_items($cat_id) {
fbf85cf6
AD
36 $show_empty_cats = $_REQUEST['mode'] != 2 &&
37 get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS');
2a060a94
AD
38
39 $items = array();
40
2ecd2df5 41 $result = db_query($this->link, "SELECT id, title, collapsed FROM ttrss_feed_categories
2a060a94
AD
42 WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat = '$cat_id' ORDER BY order_id, title");
43
44 while ($line = db_fetch_assoc($result)) {
45
46 $cat = array();
47 $cat['id'] = 'CAT:' . $line['id'];
2ecd2df5 48 $cat['bare_id'] = (int)$line['id'];
2a060a94
AD
49 $cat['name'] = $line['title'];
50 $cat['items'] = array();
51 $cat['checkbox'] = false;
2ecd2df5 52 $cat['hidden'] = sql_bool_to_bool($line['collapsed']);
2a060a94 53 $cat['type'] = 'category';
2ecd2df5 54 $cat['unread'] = 0;
2c5f231e 55 $cat['child_unread'] = 0;
2a060a94
AD
56
57 $cat['items'] = $this->get_category_items($line['id']);
58
59 $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
60
61 if (count($cat['items']) > 0 || $show_empty_cats)
62 array_push($items, $cat);
63
64 }
65
66 $feed_result = db_query($this->link, "SELECT id, title, last_error,
67 ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
68 FROM ttrss_feeds
69 WHERE cat_id = '$cat_id' AND owner_uid = ".$_SESSION["uid"].
70 "$search_qpart ORDER BY order_id, title");
71
72 while ($feed_line = db_fetch_assoc($feed_result)) {
73 $feed = array();
74 $feed['id'] = 'FEED:' . $feed_line['id'];
2ecd2df5 75 $feed['bare_id'] = (int)$feed_line['id'];
2a060a94
AD
76 $feed['name'] = $feed_line['title'];
77 $feed['checkbox'] = false;
2ecd2df5 78 $feed['unread'] = 0;
2a060a94
AD
79 $feed['error'] = $feed_line['last_error'];
80 $feed['icon'] = getFeedIcon($feed_line['id']);
81 $feed['param'] = make_local_datetime($this->link,
82 $feed_line['last_updated'], true);
83
84 array_push($items, $feed);
85 }
86
87 return $items;
88 }
89
afcfe6ca
AD
90 function getfeedtree() {
91
92 $search = $_SESSION["prefs_feed_search"];
93
94 if ($search) $search_qpart = " AND LOWER(title) LIKE LOWER('%$search%')";
95
96 $root = array();
97 $root['id'] = 'root';
98 $root['name'] = __('Feeds');
99 $root['items'] = array();
100 $root['type'] = 'category';
101
2ecd2df5
AD
102 $enable_cats = get_pref($this->link, 'ENABLE_FEED_CATS');
103
104 if ($_REQUEST['mode'] == 2) {
105
106 if ($enable_cats) {
107 $cat_hidden = get_pref($this->link, "_COLLAPSED_SPECIAL");
108 $cat = $this->feedlist_init_cat(-1, $cat_hidden);
109 } else {
110 $cat['items'] = array();
111 }
112
113 foreach (array(-4, -3, -1, -2, 0) as $i) {
114 array_push($cat['items'], $this->feedlist_init_feed($i));
115 }
116
117 if ($enable_cats) {
118 array_push($root['items'], $cat);
119 } else {
120 $root['items'] = array_merge($root['items'], $cat['items']);
121 }
afcfe6ca 122
2ecd2df5
AD
123 $result = db_query($this->link, "SELECT * FROM
124 ttrss_labels2 WHERE owner_uid = ".$_SESSION['uid']." ORDER by caption");
125
126 if (db_num_rows($result) > 0) {
127
128 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
129 $cat_hidden = get_pref($this->link, "_COLLAPSED_LABELS");
130 $cat = $this->feedlist_init_cat(-2, $cat_hidden);
131 } else {
132 $cat['items'] = array();
133 }
134
135 while ($line = db_fetch_assoc($result)) {
136
137 $label_id = -$line['id'] - 11;
138 $count = getFeedUnread($this->link, $label_id);
139
140 $feed = $this->feedlist_init_feed($label_id, false, $count);
141
142 $feed['fg_color'] = $line['fg_color'];
143 $feed['bg_color'] = $line['bg_color'];
144
145 array_push($cat['items'], $feed);
146 }
147
148 if ($enable_cats) {
149 array_push($root['items'], $cat);
150 } else {
151 $root['items'] = array_merge($root['items'], $cat['items']);
152 }
153 }
154 }
155
156 if ($enable_cats) {
157 $show_empty_cats = $_REQUEST['mode'] != 2 &&
158 get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS');
159
160 $result = db_query($this->link, "SELECT id, title, collapsed FROM ttrss_feed_categories
2a060a94 161 WHERE owner_uid = " . $_SESSION["uid"] . " AND parent_cat IS NULL ORDER BY order_id, title");
afcfe6ca
AD
162
163 while ($line = db_fetch_assoc($result)) {
164 $cat = array();
165 $cat['id'] = 'CAT:' . $line['id'];
2ecd2df5 166 $cat['bare_id'] = (int)$line['id'];
afcfe6ca
AD
167 $cat['name'] = $line['title'];
168 $cat['items'] = array();
169 $cat['checkbox'] = false;
2ecd2df5 170 $cat['hidden'] = sql_bool_to_bool($line['collapsed']);
afcfe6ca 171 $cat['type'] = 'category';
2ecd2df5 172 $cat['unread'] = 0;
2c5f231e 173 $cat['child_unread'] = 0;
afcfe6ca 174
2a060a94 175 $cat['items'] = $this->get_category_items($line['id']);
afcfe6ca
AD
176
177 $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
178
5b7bd238 179 if (count($cat['items']) > 0 || $show_empty_cats)
afcfe6ca
AD
180 array_push($root['items'], $cat);
181
182 $root['param'] += count($cat['items']);
183 }
184
185 /* Uncategorized is a special case */
186
187 $cat = array();
188 $cat['id'] = 'CAT:0';
189 $cat['bare_id'] = 0;
190 $cat['name'] = __("Uncategorized");
191 $cat['items'] = array();
2ecd2df5 192 $cat['hidden'] = get_pref($this->link, "_COLLAPSED_UNCAT");
afcfe6ca
AD
193 $cat['type'] = 'category';
194 $cat['checkbox'] = false;
2ecd2df5 195 $cat['unread'] = 0;
2c5f231e 196 $cat['child_unread'] = 0;
afcfe6ca
AD
197
198 $feed_result = db_query($this->link, "SELECT id, title,last_error,
199 ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
200 FROM ttrss_feeds
201 WHERE cat_id IS NULL AND owner_uid = ".$_SESSION["uid"].
202 "$search_qpart ORDER BY order_id, title");
203
204 while ($feed_line = db_fetch_assoc($feed_result)) {
205 $feed = array();
206 $feed['id'] = 'FEED:' . $feed_line['id'];
2ecd2df5 207 $feed['bare_id'] = (int)$feed_line['id'];
afcfe6ca
AD
208 $feed['name'] = $feed_line['title'];
209 $feed['checkbox'] = false;
210 $feed['error'] = $feed_line['last_error'];
211 $feed['icon'] = getFeedIcon($feed_line['id']);
212 $feed['param'] = make_local_datetime($this->link,
213 $feed_line['last_updated'], true);
2ecd2df5
AD
214 $feed['unread'] = 0;
215 $feed['type'] = 'feed';
afcfe6ca
AD
216
217 array_push($cat['items'], $feed);
218 }
219
220 $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
221
5b7bd238 222 if (count($cat['items']) > 0 || $show_empty_cats)
afcfe6ca
AD
223 array_push($root['items'], $cat);
224
225 $root['param'] += count($cat['items']);
226 $root['param'] = T_sprintf('(%d feeds)', $root['param']);
227
228 } else {
229 $feed_result = db_query($this->link, "SELECT id, title, last_error,
230 ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
231 FROM ttrss_feeds
232 WHERE owner_uid = ".$_SESSION["uid"].
233 "$search_qpart ORDER BY order_id, title");
234
235 while ($feed_line = db_fetch_assoc($feed_result)) {
236 $feed = array();
237 $feed['id'] = 'FEED:' . $feed_line['id'];
2ecd2df5 238 $feed['bare_id'] = (int)$feed_line['id'];
afcfe6ca
AD
239 $feed['name'] = $feed_line['title'];
240 $feed['checkbox'] = false;
241 $feed['error'] = $feed_line['last_error'];
242 $feed['icon'] = getFeedIcon($feed_line['id']);
243 $feed['param'] = make_local_datetime($this->link,
244 $feed_line['last_updated'], true);
2ecd2df5
AD
245 $feed['unread'] = 0;
246 $feed['type'] = 'feed';
afcfe6ca
AD
247
248 array_push($root['items'], $feed);
249 }
250
251 $root['param'] = T_sprintf('(%d feeds)', count($root['items']));
afcfe6ca
AD
252 }
253
254 $fl = array();
255 $fl['identifier'] = 'id';
256 $fl['label'] = 'name';
2ecd2df5
AD
257
258 if ($_REQUEST['mode'] != 2) {
259 $fl['items'] = array($root);
260 } else {
261 $fl['items'] =& $root['items'];
262 }
afcfe6ca
AD
263
264 print json_encode($fl);
265 return;
266 }
267
268 function catsortreset() {
269 db_query($this->link, "UPDATE ttrss_feed_categories
270 SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
271 return;
272 }
273
274 function feedsortreset() {
275 db_query($this->link, "UPDATE ttrss_feeds
276 SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
277 return;
278 }
279
5b7bd238
AD
280 function togglehiddenfeedcats() {
281 set_pref($this->link, '_PREFS_SHOW_EMPTY_CATS',
282 (get_pref($this->link, '_PREFS_SHOW_EMPTY_CATS') ? 'false' : 'true'));
283 }
284
95ee44b3
AD
285 private function process_category_order(&$data_map, $item_id, $parent_id = false, $nest_level = 0) {
286 $debug = isset($_REQUEST["debug"]);
287
288 $prefix = "";
289 for ($i = 0; $i < $nest_level; $i++)
290 $prefix .= " ";
291
292 if ($debug) _debug("$prefix C: $item_id P: $parent_id");
293
294 $bare_item_id = substr($item_id, strpos($item_id, ':')+1);
2a060a94
AD
295
296 if ($item_id != 'root') {
297 if ($parent_id && $parent_id != 'root') {
298 $parent_bare_id = substr($parent_id, strpos($parent_id, ':')+1);
299 $parent_qpart = db_escape_string($parent_bare_id);
300 } else {
301 $parent_qpart = 'NULL';
302 }
303
304 db_query($this->link, "UPDATE ttrss_feed_categories
95ee44b3 305 SET parent_cat = $parent_qpart WHERE id = '$bare_item_id' AND
2a060a94
AD
306 owner_uid = " . $_SESSION["uid"]);
307 }
308
309 $order_id = 0;
310
311 $cat = $data_map[$item_id];
312
313 if ($cat && is_array($cat)) {
314 foreach ($cat as $item) {
315 $id = $item['_reference'];
316 $bare_id = substr($id, strpos($id, ':')+1);
317
95ee44b3 318 if ($debug) _debug("$prefix [$order_id] $id/$bare_id");
2a060a94
AD
319
320 if ($item['_reference']) {
321
322 if (strpos($id, "FEED") === 0) {
323
95ee44b3
AD
324 $cat_id = ($item_id != "root") ?
325 db_escape_string($bare_item_id) : "NULL";
326
2a060a94 327 db_query($this->link, "UPDATE ttrss_feeds
95ee44b3
AD
328 SET order_id = $order_id, cat_id = '$cat_id'
329 WHERE id = '$bare_id' AND
2a060a94
AD
330 owner_uid = " . $_SESSION["uid"]);
331
332 } else if (strpos($id, "CAT:") === 0) {
95ee44b3
AD
333 $this->process_category_order($data_map, $item['_reference'], $item_id,
334 $nest_level+1);
2a060a94
AD
335
336 if ($item_id != 'root') {
337 $parent_qpart = db_escape_string($bare_id);
338 } else {
339 $parent_qpart = 'NULL';
340 }
341
342 db_query($this->link, "UPDATE ttrss_feed_categories
343 SET order_id = '$order_id' WHERE id = '$bare_id' AND
344 owner_uid = " . $_SESSION["uid"]);
345 }
346 }
347
348 ++$order_id;
349 }
350 }
351 }
352
afcfe6ca
AD
353 function savefeedorder() {
354 $data = json_decode($_POST['payload'], true);
355
2a060a94
AD
356 #file_put_contents("/tmp/saveorder.json", $_POST['payload']);
357 #$data = json_decode(file_get_contents("/tmp/saveorder.json"), true);
a26f57e6 358
95ee44b3
AD
359 if (!is_array($data['items']))
360 $data['items'] = json_decode($data['items'], true);
361
362# print_r($data['items']);
2a060a94 363
afcfe6ca
AD
364 if (is_array($data) && is_array($data['items'])) {
365 $cat_order_id = 0;
366
367 $data_map = array();
2a060a94 368 $root_item = false;
afcfe6ca
AD
369
370 foreach ($data['items'] as $item) {
371
2a060a94 372# if ($item['id'] != 'root') {
afcfe6ca
AD
373 if (is_array($item['items'])) {
374 if (isset($item['items']['_reference'])) {
375 $data_map[$item['id']] = array($item['items']);
376 } else {
377 $data_map[$item['id']] =& $item['items'];
378 }
379 }
2a060a94
AD
380 if ($item['id'] == 'root') {
381 $root_item = $item['id'];
afcfe6ca
AD
382 }
383 }
384
d04f8c82 385 $this->process_category_order($data_map, $root_item);
2a060a94
AD
386
387 /* foreach ($data['items'][0]['items'] as $item) {
afcfe6ca
AD
388 $id = $item['_reference'];
389 $bare_id = substr($id, strpos($id, ':')+1);
390
391 ++$cat_order_id;
392
393 if ($bare_id > 0) {
394 db_query($this->link, "UPDATE ttrss_feed_categories
395 SET order_id = '$cat_order_id' WHERE id = '$bare_id' AND
396 owner_uid = " . $_SESSION["uid"]);
397 }
398
399 $feed_order_id = 0;
400
401 if (is_array($data_map[$id])) {
402 foreach ($data_map[$id] as $feed) {
403 $id = $feed['_reference'];
404 $feed_id = substr($id, strpos($id, ':')+1);
405
406 if ($bare_id != 0)
407 $cat_query = "cat_id = '$bare_id'";
408 else
409 $cat_query = "cat_id = NULL";
410
411 db_query($this->link, "UPDATE ttrss_feeds
412 SET order_id = '$feed_order_id',
413 $cat_query
414 WHERE id = '$feed_id' AND
415 owner_uid = " . $_SESSION["uid"]);
416
417 ++$feed_order_id;
418 }
419 }
2a060a94 420 } */
afcfe6ca
AD
421 }
422
423 return;
424 }
425
426 function removeicon() {
427 $feed_id = db_escape_string($_REQUEST["feed_id"]);
428
429 $result = db_query($this->link, "SELECT id FROM ttrss_feeds
430 WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
431
432 if (db_num_rows($result) != 0) {
433 unlink(ICONS_DIR . "/$feed_id.ico");
434 }
435
436 return;
437 }
438
439 function uploadicon() {
440 $icon_file = $_FILES['icon_file']['tmp_name'];
441 $feed_id = db_escape_string($_REQUEST["feed_id"]);
442
443 if (is_file($icon_file) && $feed_id) {
444 if (filesize($icon_file) < 20000) {
445
446 $result = db_query($this->link, "SELECT id FROM ttrss_feeds
447 WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
448
449 if (db_num_rows($result) != 0) {
450 unlink(ICONS_DIR . "/$feed_id.ico");
451 move_uploaded_file($icon_file, ICONS_DIR . "/$feed_id.ico");
452 $rc = 0;
453 } else {
454 $rc = 2;
455 }
456 } else {
457 $rc = 1;
458 }
459 } else {
460 $rc = 2;
461 }
462
463 print "<script type=\"text/javascript\">";
464 print "parent.uploadIconHandler($rc);";
465 print "</script>";
466 return;
467 }
468
469 function editfeed() {
470 global $purge_intervals;
471 global $update_intervals;
472 global $update_methods;
473
474 $feed_id = db_escape_string($_REQUEST["id"]);
475
476 $result = db_query($this->link,
477 "SELECT * FROM ttrss_feeds WHERE id = '$feed_id' AND
478 owner_uid = " . $_SESSION["uid"]);
479
480 $title = htmlspecialchars(db_fetch_result($result,
481 0, "title"));
482
483 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$feed_id\">";
484 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
485 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"editSave\">";
486
487 print "<div class=\"dlgSec\">".__("Feed")."</div>";
488 print "<div class=\"dlgSecCont\">";
489
490 /* Title */
491
492 print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
493 placeHolder=\"".__("Feed Title")."\"
494 style=\"font-size : 16px; width: 20em\" name=\"title\" value=\"$title\">";
495
496 /* Feed URL */
497
498 $feed_url = db_fetch_result($result, 0, "feed_url");
499 $feed_url = htmlspecialchars(db_fetch_result($result,
500 0, "feed_url"));
501
502 print "<hr/>";
503
504 print __('URL:') . " ";
505 print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
506 placeHolder=\"".__("Feed URL")."\"
507 regExp='^(http|https)://.*' style=\"width : 20em\"
508 name=\"feed_url\" value=\"$feed_url\">";
509
510 $last_error = db_fetch_result($result, 0, "last_error");
511
512 if ($last_error) {
513 print "&nbsp;<span title=\"".htmlspecialchars($last_error)."\"
514 class=\"feed_error\">(error)</span>";
515
516 }
517
518 /* Category */
519
520 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
521
522 $cat_id = db_fetch_result($result, 0, "cat_id");
523
524 print "<hr/>";
525
526 print __('Place in category:') . " ";
527
528 print_feed_cat_select($this->link, "cat_id", $cat_id,
529 'dojoType="dijit.form.Select"');
530 }
531
532 print "</div>";
533
534 print "<div class=\"dlgSec\">".__("Update")."</div>";
535 print "<div class=\"dlgSecCont\">";
536
537 /* Update Interval */
538
539 $update_interval = db_fetch_result($result, 0, "update_interval");
540
541 print_select_hash("update_interval", $update_interval, $update_intervals,
542 'dojoType="dijit.form.Select"');
543
544 /* Update method */
545
546 $update_method = db_fetch_result($result, 0, "update_method",
547 'dojoType="dijit.form.Select"');
548
549 print " " . __('using') . " ";
550 print_select_hash("update_method", $update_method, $update_methods,
551 'dojoType="dijit.form.Select"');
552
553 $purge_interval = db_fetch_result($result, 0, "purge_interval");
554
555
556 /* Purge intl */
557
558 print "<hr/>";
559 print __('Article purging:') . " ";
560
561 print_select_hash("purge_interval", $purge_interval, $purge_intervals,
562 'dojoType="dijit.form.Select" ' .
563 ((FORCE_ARTICLE_PURGE == 0) ? "" : 'disabled="1"'));
564
565 print "</div>";
566 print "<div class=\"dlgSec\">".__("Authentication")."</div>";
567 print "<div class=\"dlgSecCont\">";
568
569 $auth_login = htmlspecialchars(db_fetch_result($result, 0, "auth_login"));
570
571 print "<input dojoType=\"dijit.form.TextBox\" id=\"feedEditDlg_login\"
572 placeHolder=\"".__("Login")."\"
573 name=\"auth_login\" value=\"$auth_login\"><hr/>";
574
575 $auth_pass = htmlspecialchars(db_fetch_result($result, 0, "auth_pass"));
576
577 print "<input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
578 placeHolder=\"".__("Password")."\"
579 value=\"$auth_pass\">";
580
581 print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedEditDlg_login\" position=\"below\">
582 ".__('<b>Hint:</b> you need to fill in your login information if your feed requires authentication, except for Twitter feeds.')."
583 </div>";
584
585 print "</div>";
586 print "<div class=\"dlgSec\">".__("Options")."</div>";
587 print "<div class=\"dlgSecCont\">";
588
589 $private = sql_bool_to_bool(db_fetch_result($result, 0, "private"));
590
591 if ($private) {
592 $checked = "checked=\"1\"";
593 } else {
594 $checked = "";
595 }
596
597 print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"private\" id=\"private\"
598 $checked>&nbsp;<label for=\"private\">".__('Hide from Popular feeds')."</label>";
599
600 $rtl_content = sql_bool_to_bool(db_fetch_result($result, 0, "rtl_content"));
601
602 if ($rtl_content) {
603 $checked = "checked=\"1\"";
604 } else {
605 $checked = "";
606 }
607
608 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
609 $checked>&nbsp;<label for=\"rtl_content\">".__('Right-to-left content')."</label>";
610
611 $include_in_digest = sql_bool_to_bool(db_fetch_result($result, 0, "include_in_digest"));
612
613 if ($include_in_digest) {
614 $checked = "checked=\"1\"";
615 } else {
616 $checked = "";
617 }
618
619 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"include_in_digest\"
620 name=\"include_in_digest\"
621 $checked>&nbsp;<label for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
622
623
624 $always_display_enclosures = sql_bool_to_bool(db_fetch_result($result, 0, "always_display_enclosures"));
625
626 if ($always_display_enclosures) {
627 $checked = "checked";
628 } else {
629 $checked = "";
630 }
631
632 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"always_display_enclosures\"
633 name=\"always_display_enclosures\"
634 $checked>&nbsp;<label for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
635
636
637 $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
638
639 if ($cache_images) {
640 $checked = "checked=\"1\"";
641 } else {
642 $checked = "";
643 }
644
3c696512
AD
645 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"cache_images\"
646 name=\"cache_images\"
afcfe6ca 647 $checked>&nbsp;<label for=\"cache_images\">".
3c696512 648 __('Cache images locally')."</label>";
afcfe6ca
AD
649
650 $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
651
652 if ($mark_unread_on_update) {
653 $checked = "checked";
654 } else {
655 $checked = "";
656 }
657
658 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"mark_unread_on_update\"
659 name=\"mark_unread_on_update\"
660 $checked>&nbsp;<label for=\"mark_unread_on_update\">".__('Mark updated articles as unread')."</label>";
661
662 $update_on_checksum_change = sql_bool_to_bool(db_fetch_result($result, 0, "update_on_checksum_change"));
663
664 if ($update_on_checksum_change) {
665 $checked = "checked";
666 } else {
667 $checked = "";
668 }
669
670 print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"update_on_checksum_change\"
671 name=\"update_on_checksum_change\"
672 $checked>&nbsp;<label for=\"update_on_checksum_change\">".__('Mark posts as updated on content change')."</label>";
673
674 print "</div>";
675
676 /* Icon */
677
678 print "<div class=\"dlgSec\">".__("Icon")."</div>";
679 print "<div class=\"dlgSecCont\">";
680
681 print "<iframe name=\"icon_upload_iframe\"
682 style=\"width: 400px; height: 100px; display: none;\"></iframe>";
683
684 print "<form style='display : block' target=\"icon_upload_iframe\"
685 enctype=\"multipart/form-data\" method=\"POST\"
686 action=\"backend.php\">
687 <input id=\"icon_file\" size=\"10\" name=\"icon_file\" type=\"file\">
688 <input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
689 <input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
690 <input type=\"hidden\" name=\"method\" value=\"uploadicon\">
691 <button dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
692 type=\"submit\">".__('Replace')."</button>
693 <button dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
694 type=\"submit\">".__('Remove')."</button>
695 </form>";
696
697 print "</div>";
698
699 $title = htmlspecialchars($title, ENT_QUOTES);
700
701 print "<div class='dlgButtons'>
702 <div style=\"float : left\">
703 <button dojoType=\"dijit.form.Button\" onclick='return unsubscribeFeed($feed_id, \"$title\")'>".
704 __('Unsubscribe')."</button>";
705
706 if (PUBSUBHUBBUB_ENABLED) {
707 $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
708 $pubsub_btn_disabled = ($pubsub_state == 2) ? "" : "disabled=\"1\"";
709
710 print "<button dojoType=\"dijit.form.Button\" id=\"pubsubReset_Btn\" $pubsub_btn_disabled
711 onclick='return resetPubSub($feed_id, \"$title\")'>".__('Resubscribe to push updates').
712 "</button>";
713 }
714
715 print "</div>";
716
717 print "<div dojoType=\"dijit.Tooltip\" connectId=\"pubsubReset_Btn\" position=\"below\">".
718 __('Resets PubSubHubbub subscription status for push-enabled feeds.')."</div>";
719
720 print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').execute()\">".__('Save')."</button>
721 <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').hide()\">".__('Cancel')."</button>
722 </div>";
723
724 return;
725 }
726
727 function editfeeds() {
728 global $purge_intervals;
729 global $update_intervals;
730 global $update_methods;
46da73c2 731
afcfe6ca
AD
732 $feed_ids = db_escape_string($_REQUEST["ids"]);
733
ca6a0741
AD
734 print "<div class=\"dialogNotice\">" . __("Enable the options you wish to apply using checkboxes on the right:") . "</div>";
735
afcfe6ca
AD
736 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"ids\" value=\"$feed_ids\">";
737 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
738 print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"batchEditSave\">";
739
740 print "<div class=\"dlgSec\">".__("Feed")."</div>";
741 print "<div class=\"dlgSecCont\">";
742
743 /* Title */
744
745 print "<input dojoType=\"dijit.form.ValidationTextBox\"
746 disabled=\"1\" style=\"font-size : 16px; width : 20em;\" required=\"1\"
747 name=\"title\" value=\"$title\">";
748
749 $this->batch_edit_cbox("title");
750
751 /* Feed URL */
752
753 print "<br/>";
754
755 print __('URL:') . " ";
756 print "<input dojoType=\"dijit.form.ValidationTextBox\" disabled=\"1\"
757 required=\"1\" regExp='^(http|https)://.*' style=\"width : 20em\"
758 name=\"feed_url\" value=\"$feed_url\">";
759
760 $this->batch_edit_cbox("feed_url");
761
762 /* Category */
763
764 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
765
766 print "<br/>";
767
768 print __('Place in category:') . " ";
769
770 print_feed_cat_select($this->link, "cat_id", $cat_id,
771 'disabled="1" dojoType="dijit.form.Select"');
772
773 $this->batch_edit_cbox("cat_id");
774
775 }
776
777 print "</div>";
778
779 print "<div class=\"dlgSec\">".__("Update")."</div>";
780 print "<div class=\"dlgSecCont\">";
781
782 /* Update Interval */
783
784 print_select_hash("update_interval", $update_interval, $update_intervals,
785 'disabled="1" dojoType="dijit.form.Select"');
786
787 $this->batch_edit_cbox("update_interval");
788
789 /* Update method */
790
791 print " " . __('using') . " ";
792 print_select_hash("update_method", $update_method, $update_methods,
793 'disabled="1" dojoType="dijit.form.Select"');
794 $this->batch_edit_cbox("update_method");
795
796 /* Purge intl */
797
798 if (FORCE_ARTICLE_PURGE == 0) {
799
800 print "<br/>";
801
802 print __('Article purging:') . " ";
803
804 print_select_hash("purge_interval", $purge_interval, $purge_intervals,
805 'disabled="1" dojoType="dijit.form.Select"');
806
807 $this->batch_edit_cbox("purge_interval");
808 }
809
810 print "</div>";
811 print "<div class=\"dlgSec\">".__("Authentication")."</div>";
812 print "<div class=\"dlgSecCont\">";
813
814 print "<input dojoType=\"dijit.form.TextBox\"
815 placeHolder=\"".__("Login")."\" disabled=\"1\"
816 name=\"auth_login\" value=\"$auth_login\">";
817
818 $this->batch_edit_cbox("auth_login");
819
820 print "<br/><input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
821 placeHolder=\"".__("Password")."\" disabled=\"1\"
822 value=\"$auth_pass\">";
823
824 $this->batch_edit_cbox("auth_pass");
825
826 print "</div>";
827 print "<div class=\"dlgSec\">".__("Options")."</div>";
828 print "<div class=\"dlgSecCont\">";
829
830 print "<input disabled=\"1\" type=\"checkbox\" name=\"private\" id=\"private\"
831 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"private_l\" class='insensitive' for=\"private\">".__('Hide from Popular feeds')."</label>";
832
833 print "&nbsp;"; $this->batch_edit_cbox("private", "private_l");
834
835 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
836 dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"rtl_content_l\" for=\"rtl_content\">".__('Right-to-left content')."</label>";
837
838 print "&nbsp;"; $this->batch_edit_cbox("rtl_content", "rtl_content_l");
839
840 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"include_in_digest\"
841 name=\"include_in_digest\"
842 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"include_in_digest_l\" class='insensitive' for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
843
844 print "&nbsp;"; $this->batch_edit_cbox("include_in_digest", "include_in_digest_l");
845
846 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"always_display_enclosures\"
847 name=\"always_display_enclosures\"
848 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"always_display_enclosures_l\" class='insensitive' for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
849
850 print "&nbsp;"; $this->batch_edit_cbox("always_display_enclosures", "always_display_enclosures_l");
851
3c696512
AD
852 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"cache_images\"
853 name=\"cache_images\"
854 dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"cache_images_l\"
855 for=\"cache_images\">".
856 __('Cache images locally')."</label>";
afcfe6ca 857
3c696512 858 print "&nbsp;"; $this->batch_edit_cbox("cache_images", "cache_images_l");
afcfe6ca
AD
859
860 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"mark_unread_on_update\"
861 name=\"mark_unread_on_update\"
862 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"mark_unread_on_update_l\" class='insensitive' for=\"mark_unread_on_update\">".__('Mark updated articles as unread')."</label>";
863
864 print "&nbsp;"; $this->batch_edit_cbox("mark_unread_on_update", "mark_unread_on_update_l");
865
866 print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"update_on_checksum_change\"
867 name=\"update_on_checksum_change\"
868 dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"update_on_checksum_change_l\" class='insensitive' for=\"update_on_checksum_change\">".__('Mark posts as updated on content change')."</label>";
869
870 print "&nbsp;"; $this->batch_edit_cbox("update_on_checksum_change", "update_on_checksum_change_l");
871
872 print "</div>";
873
874 print "<div class='dlgButtons'>
875 <button dojoType=\"dijit.form.Button\"
876 onclick=\"return dijit.byId('feedEditDlg').execute()\">".
877 __('Save')."</button>
878 <button dojoType=\"dijit.form.Button\"
879 onclick=\"return dijit.byId('feedEditDlg').hide()\">".
880 __('Cancel')."</button>
881 </div>";
882
883 return;
884 }
885
886 function batchEditSave() {
3a76e2a2 887 return $this->editsaveops(true);
afcfe6ca 888 }
46da73c2 889
afcfe6ca 890 function editSave() {
3a76e2a2 891 return $this->editsaveops(false);
afcfe6ca 892 }
46da73c2
AD
893
894 function editsaveops($batch) {
895
afcfe6ca
AD
896 $feed_title = db_escape_string(trim($_POST["title"]));
897 $feed_link = db_escape_string(trim($_POST["feed_url"]));
898 $upd_intl = (int) db_escape_string($_POST["update_interval"]);
899 $purge_intl = (int) db_escape_string($_POST["purge_interval"]);
900 $feed_id = (int) db_escape_string($_POST["id"]); /* editSave */
901 $feed_ids = db_escape_string($_POST["ids"]); /* batchEditSave */
902 $cat_id = (int) db_escape_string($_POST["cat_id"]);
903 $auth_login = db_escape_string(trim($_POST["auth_login"]));
904 $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
905 $private = checkbox_to_sql_bool(db_escape_string($_POST["private"]));
906 $rtl_content = checkbox_to_sql_bool(db_escape_string($_POST["rtl_content"]));
907 $include_in_digest = checkbox_to_sql_bool(
908 db_escape_string($_POST["include_in_digest"]));
909 $cache_images = checkbox_to_sql_bool(
910 db_escape_string($_POST["cache_images"]));
911 $update_method = (int) db_escape_string($_POST["update_method"]);
912
913 $always_display_enclosures = checkbox_to_sql_bool(
914 db_escape_string($_POST["always_display_enclosures"]));
915
916 $mark_unread_on_update = checkbox_to_sql_bool(
917 db_escape_string($_POST["mark_unread_on_update"]));
918
919 $update_on_checksum_change = checkbox_to_sql_bool(
920 db_escape_string($_POST["update_on_checksum_change"]));
921
922 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
923 if ($cat_id && $cat_id != 0) {
924 $category_qpart = "cat_id = '$cat_id',";
925 $category_qpart_nocomma = "cat_id = '$cat_id'";
926 } else {
927 $category_qpart = 'cat_id = NULL,';
928 $category_qpart_nocomma = 'cat_id = NULL';
929 }
930 } else {
931 $category_qpart = "";
932 $category_qpart_nocomma = "";
933 }
934
3c696512 935 $cache_images_qpart = "cache_images = $cache_images,";
afcfe6ca 936
3a76e2a2 937 if (!$batch) {
afcfe6ca
AD
938
939 $result = db_query($this->link, "UPDATE ttrss_feeds SET
940 $category_qpart
941 title = '$feed_title', feed_url = '$feed_link',
942 update_interval = '$upd_intl',
943 purge_interval = '$purge_intl',
944 auth_login = '$auth_login',
945 auth_pass = '$auth_pass',
946 private = $private,
947 rtl_content = $rtl_content,
948 $cache_images_qpart
949 include_in_digest = $include_in_digest,
950 always_display_enclosures = $always_display_enclosures,
951 mark_unread_on_update = $mark_unread_on_update,
952 update_on_checksum_change = $update_on_checksum_change,
953 update_method = '$update_method'
954 WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
955
3a76e2a2 956 } else {
afcfe6ca
AD
957 $feed_data = array();
958
959 foreach (array_keys($_POST) as $k) {
960 if ($k != "op" && $k != "method" && $k != "ids") {
961 $feed_data[$k] = $_POST[$k];
962 }
963 }
964
965 db_query($this->link, "BEGIN");
966
967 foreach (array_keys($feed_data) as $k) {
968
969 $qpart = "";
970
971 switch ($k) {
972 case "title":
973 $qpart = "title = '$feed_title'";
974 break;
975
976 case "feed_url":
977 $qpart = "feed_url = '$feed_link'";
978 break;
979
980 case "update_interval":
981 $qpart = "update_interval = '$upd_intl'";
982 break;
983
984 case "purge_interval":
985 $qpart = "purge_interval = '$purge_intl'";
986 break;
987
988 case "auth_login":
989 $qpart = "auth_login = '$auth_login'";
990 break;
991
992 case "auth_pass":
993 $qpart = "auth_pass = '$auth_pass'";
994 break;
995
996 case "private":
a498d18b 997 $qpart = "private = $private";
afcfe6ca
AD
998 break;
999
1000 case "include_in_digest":
a498d18b 1001 $qpart = "include_in_digest = $include_in_digest";
afcfe6ca
AD
1002 break;
1003
1004 case "always_display_enclosures":
a498d18b 1005 $qpart = "always_display_enclosures = $always_display_enclosures";
afcfe6ca
AD
1006 break;
1007
1008 case "mark_unread_on_update":
a498d18b 1009 $qpart = "mark_unread_on_update = $mark_unread_on_update";
afcfe6ca
AD
1010 break;
1011
1012 case "update_on_checksum_change":
a498d18b 1013 $qpart = "update_on_checksum_change = $update_on_checksum_change";
afcfe6ca
AD
1014 break;
1015
1016 case "cache_images":
a498d18b 1017 $qpart = "cache_images = $cache_images";
afcfe6ca
AD
1018 break;
1019
1020 case "rtl_content":
a498d18b 1021 $qpart = "rtl_content = $rtl_content";
afcfe6ca
AD
1022 break;
1023
1024 case "update_method":
1025 $qpart = "update_method = '$update_method'";
1026 break;
1027
1028 case "cat_id":
1029 $qpart = $category_qpart_nocomma;
1030 break;
1031
1032 }
1033
1034 if ($qpart) {
1035 db_query($this->link,
1036 "UPDATE ttrss_feeds SET $qpart WHERE id IN ($feed_ids)
1037 AND owner_uid = " . $_SESSION["uid"]);
1038 print "<br/>";
1039 }
1040 }
1041
1042 db_query($this->link, "COMMIT");
1043 }
1044 return;
1045 }
1046
1047 function resetPubSub() {
1048
1049 $ids = db_escape_string($_REQUEST["ids"]);
1050
1051 db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 0 WHERE id IN ($ids)
1052 AND owner_uid = " . $_SESSION["uid"]);
1053
1054 return;
1055 }
1056
1057 function remove() {
1058
1059 $ids = split(",", db_escape_string($_REQUEST["ids"]));
1060
1061 foreach ($ids as $id) {
1062 remove_feed($this->link, $id, $_SESSION["uid"]);
1063 }
1064
1065 return;
1066 }
1067
1068 function clear() {
1069 $id = db_escape_string($_REQUEST["id"]);
1070 clear_feed_articles($this->link, $id);
1071 }
1072
1073 function rescore() {
1074 $ids = split(",", db_escape_string($_REQUEST["ids"]));
1075
1076 foreach ($ids as $id) {
1077
1078 $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
1079
1080 $result = db_query($this->link, "SELECT
1081 title, content, link, ref_id, author,".
1082 SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
1083 FROM
1084 ttrss_user_entries, ttrss_entries
1085 WHERE ref_id = id AND feed_id = '$id' AND
1086 owner_uid = " .$_SESSION['uid']."
1087 ");
1088
1089 $scores = array();
1090
1091 while ($line = db_fetch_assoc($result)) {
1092
1093 $tags = get_article_tags($this->link, $line["ref_id"]);
1094
1095 $article_filters = get_article_filters($filters, $line['title'],
1096 $line['content'], $line['link'], strtotime($line['updated']),
1097 $line['author'], $tags);
1098
1099 $new_score = calculate_article_score($article_filters);
1100
1101 if (!$scores[$new_score]) $scores[$new_score] = array();
1102
1103 array_push($scores[$new_score], $line['ref_id']);
1104 }
1105
1106 foreach (array_keys($scores) as $s) {
1107 if ($s > 1000) {
1108 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
1109 marked = true WHERE
1110 ref_id IN (" . join(',', $scores[$s]) . ")");
1111 } else if ($s < -500) {
1112 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
1113 unread = false WHERE
1114 ref_id IN (" . join(',', $scores[$s]) . ")");
1115 } else {
1116 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
1117 ref_id IN (" . join(',', $scores[$s]) . ")");
1118 }
1119 }
1120 }
1121
1122 print __("All done.");
1123
1124 }
1125
1126 function rescoreAll() {
1127
1128 $result = db_query($this->link,
1129 "SELECT id FROM ttrss_feeds WHERE owner_uid = " . $_SESSION['uid']);
1130
1131 while ($feed_line = db_fetch_assoc($result)) {
1132
1133 $id = $feed_line["id"];
1134
1135 $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
1136
1137 $tmp_result = db_query($this->link, "SELECT
1138 title, content, link, ref_id, author,".
1139 SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
1140 FROM
1141 ttrss_user_entries, ttrss_entries
1142 WHERE ref_id = id AND feed_id = '$id' AND
1143 owner_uid = " .$_SESSION['uid']."
1144 ");
1145
1146 $scores = array();
1147
1148 while ($line = db_fetch_assoc($tmp_result)) {
1149
1150 $tags = get_article_tags($this->link, $line["ref_id"]);
1151
1152 $article_filters = get_article_filters($filters, $line['title'],
1153 $line['content'], $line['link'], strtotime($line['updated']),
1154 $line['author'], $tags);
1155
1156 $new_score = calculate_article_score($article_filters);
1157
1158 if (!$scores[$new_score]) $scores[$new_score] = array();
1159
1160 array_push($scores[$new_score], $line['ref_id']);
1161 }
1162
1163 foreach (array_keys($scores) as $s) {
1164 if ($s > 1000) {
1165 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
1166 marked = true WHERE
1167 ref_id IN (" . join(',', $scores[$s]) . ")");
1168 } else {
1169 db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
1170 ref_id IN (" . join(',', $scores[$s]) . ")");
1171 }
1172 }
1173 }
1174
1175 print __("All done.");
1176
1177 }
1178
1179 function add() {
1180 $feed_url = db_escape_string(trim($_REQUEST["feed_url"]));
1181 $cat_id = db_escape_string($_REQUEST["cat_id"]);
1182 $p_from = db_escape_string($_REQUEST["from"]);
1183
1184 /* only read authentication information from POST */
1185
1186 $auth_login = db_escape_string(trim($_POST["auth_login"]));
1187 $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
1188
1189 if ($p_from != 'tt-rss') {
f4ce1d64 1190 header('Content-Type: text/html; charset=utf-8');
afcfe6ca
AD
1191 print "<html>
1192 <head>
1193 <title>Tiny Tiny RSS</title>
1194 <link rel=\"stylesheet\" type=\"text/css\" href=\"utility.css\">
f4ce1d64 1195 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
afcfe6ca
AD
1196 </head>
1197 <body>
093fae5e 1198 <img class=\"floatingLogo\" src=\"images/logo_wide.png\"
afcfe6ca
AD
1199 alt=\"Tiny Tiny RSS\"/>
1200 <h1>Subscribe to feed...</h1>";
1201 }
1202
1203 $rc = subscribe_to_feed($this->link, $feed_url, $cat_id, $auth_login, $auth_pass);
1204
1205 switch ($rc) {
1206 case 1:
1207 print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
1208 break;
1209 case 2:
1210 print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
1211 break;
1212 case 3:
1213 print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
1214 break;
1215 case 0:
1216 print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
1217 break;
1218 case 4:
d50edb08 1219 print_notice(__("Multiple feed URLs found."));
afcfe6ca
AD
1220
1221 $feed_urls = get_feeds_from_html($feed_url);
1222 break;
1223 case 5:
1224 print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
1225 break;
1226 }
1227
1228 if ($p_from != 'tt-rss') {
1229
1230 if ($feed_urls) {
1231
1232 print "<form action=\"backend.php\">";
1233 print "<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">";
1234 print "<input type=\"hidden\" name=\"quiet\" value=\"1\">";
1235 print "<input type=\"hidden\" name=\"method\" value=\"add\">";
1236
1237 print "<select name=\"feed_url\">";
1238
1239 foreach ($feed_urls as $url => $name) {
1240 $url = htmlspecialchars($url);
1241 $name = htmlspecialchars($name);
1242
1243 print "<option value=\"$url\">$name</option>";
1244 }
1245
1246 print "<input type=\"submit\" value=\"".__("Subscribe to selected feed").
1247 "\">";
1248
1249 print "</form>";
1250 }
1251
1252 $tp_uri = get_self_url_prefix() . "/prefs.php";
1253 $tt_uri = get_self_url_prefix();
1254
1255 if ($rc <= 2){
1256 $result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
1257 feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
1258
1259 $feed_id = db_fetch_result($result, 0, "id");
1260 } else {
1261 $feed_id = 0;
1262 }
1263 print "<p>";
1264
1265 if ($feed_id) {
1266 print "<form method=\"GET\" style='display: inline'
1267 action=\"$tp_uri\">
1268 <input type=\"hidden\" name=\"tab\" value=\"feedConfig\">
1269 <input type=\"hidden\" name=\"method\" value=\"editFeed\">
1270 <input type=\"hidden\" name=\"methodparam\" value=\"$feed_id\">
1271 <input type=\"submit\" value=\"".__("Edit subscription options")."\">
1272 </form>";
1273 }
1274
1275 print "<form style='display: inline' method=\"GET\" action=\"$tt_uri\">
1276 <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
1277 </form></p>";
1278
1279 print "</body></html>";
1280 return;
1281 }
1282 }
1283
1284 function categorize() {
1285 $ids = split(",", db_escape_string($_REQUEST["ids"]));
1286
1287 $cat_id = db_escape_string($_REQUEST["cat_id"]);
1288
1289 if ($cat_id == 0) {
1290 $cat_id_qpart = 'NULL';
1291 } else {
1292 $cat_id_qpart = "'$cat_id'";
1293 }
1294
1295 db_query($this->link, "BEGIN");
1296
1297 foreach ($ids as $id) {
1298
1299 db_query($this->link, "UPDATE ttrss_feeds SET cat_id = $cat_id_qpart
1300 WHERE id = '$id'
1301 AND owner_uid = " . $_SESSION["uid"]);
1302
1303 }
1304
1305 db_query($this->link, "COMMIT");
1306 }
1307
28537341
AD
1308 function removeCat() {
1309 $ids = split(",", db_escape_string($_REQUEST["ids"]));
1310 foreach ($ids as $id) {
1311 remove_feed_category($this->link, $id, $_SESSION["uid"]);
1312 }
1313 }
1314
1315 function addCat() {
1316 $feed_cat = db_escape_string(trim($_REQUEST["cat"]));
1317
1318 add_feed_category($this->link, $feed_cat);
1319 }
1320
afcfe6ca
AD
1321 function index() {
1322
1323 print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
1324 print "<div id=\"pref-feeds-feeds\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Feeds')."\">";
1325
1326 $result = db_query($this->link, "SELECT COUNT(id) AS num_errors
1327 FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]);
1328
1329 $num_errors = db_fetch_result($result, 0, "num_errors");
1330
1331 if ($num_errors > 0) {
1332
1333 $error_button = "<button dojoType=\"dijit.form.Button\"
1334 onclick=\"showFeedsWithErrors()\" id=\"errorButton\">" .
1335 __("Feeds with errors") . "</button>";
1336 }
1337
1338 if (DB_TYPE == "pgsql") {
1339 $interval_qpart = "NOW() - INTERVAL '3 months'";
1340 } else {
1341 $interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
1342 }
1343
1344 $result = db_query($this->link, "SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE
1345 (SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
1346 ttrss_entries.id = ref_id AND
1347 ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart AND
1348 ttrss_feeds.owner_uid = ".$_SESSION["uid"]);
1349
1350 $num_inactive = db_fetch_result($result, 0, "num_inactive");
1351
1352 if ($num_inactive > 0) {
1353 $inactive_button = "<button dojoType=\"dijit.form.Button\"
1354 onclick=\"showInactiveFeeds()\">" .
1355 __("Inactive feeds") . "</button>";
1356 }
1357
1358 $feed_search = db_escape_string($_REQUEST["search"]);
1359
1360 if (array_key_exists("search", $_REQUEST)) {
1361 $_SESSION["prefs_feed_search"] = $feed_search;
1362 } else {
1363 $feed_search = $_SESSION["prefs_feed_search"];
1364 }
1365
1366 print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
1367
1368 print "<div region='top' dojoType=\"dijit.Toolbar\">"; #toolbar
1369
1370 print "<div style='float : right; padding-right : 4px;'>
1371 <input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"
1372 value=\"$feed_search\">
1373 <button dojoType=\"dijit.form.Button\" onclick=\"updateFeedList()\">".
1374 __('Search')."</button>
1375 </div>";
1376
1377 print "<div dojoType=\"dijit.form.DropDownButton\">".
1378 "<span>" . __('Select')."</span>";
1379 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
1380 print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(true)\"
1381 dojoType=\"dijit.MenuItem\">".__('All')."</div>";
1382 print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(false)\"
1383 dojoType=\"dijit.MenuItem\">".__('None')."</div>";
1384 print "</div></div>";
1385
1386 print "<div dojoType=\"dijit.form.DropDownButton\">".
1387 "<span>" . __('Feeds')."</span>";
1388 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
1389 print "<div onclick=\"quickAddFeed()\"
1390 dojoType=\"dijit.MenuItem\">".__('Subscribe to feed')."</div>";
1391 print "<div onclick=\"editSelectedFeed()\"
1392 dojoType=\"dijit.MenuItem\">".__('Edit selected feeds')."</div>";
1393 print "<div onclick=\"resetFeedOrder()\"
1394 dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
33f0fdd0
AD
1395 print "<div onclick=\"batchSubscribe()\"
1396 dojoType=\"dijit.MenuItem\">".__('Batch subscribe')."</div>";
afcfe6ca
AD
1397 print "</div></div>";
1398
1399 if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
1400 print "<div dojoType=\"dijit.form.DropDownButton\">".
1401 "<span>" . __('Categories')."</span>";
1402 print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
5ef071e0
AD
1403 print "<div onclick=\"createCategory()\"
1404 dojoType=\"dijit.MenuItem\">".__('Add category')."</div>";
5b7bd238
AD
1405 print "<div onclick=\"toggleHiddenFeedCats()\"
1406 dojoType=\"dijit.MenuItem\">".__('(Un)hide empty categories')."</div>";
afcfe6ca
AD
1407 print "<div onclick=\"resetCatOrder()\"
1408 dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
1409 print "</div></div>";
1410
1411 }
1412
1413 print $error_button;
1414 print $inactive_button;
1415
1416 print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedFeeds()\">"
1417 .__('Unsubscribe')."</button dojoType=\"dijit.form.Button\"> ";
1418
1419 if (defined('_ENABLE_FEED_DEBUGGING')) {
1420
1421 print "<select id=\"feedActionChooser\" onchange=\"feedActionChange()\">
1422 <option value=\"facDefault\" selected>".__('More actions...')."</option>";
1423
1424 if (FORCE_ARTICLE_PURGE == 0) {
1425 print
1426 "<option value=\"facPurge\">".__('Manual purge')."</option>";
1427 }
1428
1429 print "
1430 <option value=\"facClear\">".__('Clear feed data')."</option>
1431 <option value=\"facRescore\">".__('Rescore articles')."</option>";
1432
1433 print "</select>";
1434
1435 }
1436
1437 print "</div>"; # toolbar
1438
1439 //print '</div>';
1440 print '<div dojoType="dijit.layout.ContentPane" region="center">';
1441
1442 print "<div id=\"feedlistLoading\">
1443 <img src='images/indicator_tiny.gif'>".
1444 __("Loading, please wait...")."</div>";
1445
1446 print "<div dojoType=\"fox.PrefFeedStore\" jsId=\"feedStore\"
1447 url=\"backend.php?op=pref-feeds&method=getfeedtree\">
1448 </div>
1449 <div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"feedModel\" store=\"feedStore\"
1450 query=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"
1451 childrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">
1452 </div>
1453 <div dojoType=\"fox.PrefFeedTree\" id=\"feedTree\"
1454 dndController=\"dijit.tree.dndSource\"
1455 betweenThreshold=\"5\"
1456 model=\"feedModel\" openOnClick=\"false\">
1457 <script type=\"dojo/method\" event=\"onClick\" args=\"item\">
1458 var id = String(item.id);
1459 var bare_id = id.substr(id.indexOf(':')+1);
1460
1461 if (id.match('FEED:')) {
1462 editFeed(bare_id);
1463 } else if (id.match('CAT:')) {
1464 editCat(bare_id, item);
1465 }
1466 </script>
1467 <script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
1468 Element.hide(\"feedlistLoading\");
1469 </script>
1470 </div>";
1471
ba5296a1
AD
1472# print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedTree\" position=\"below\">
1473# ".__('<b>Hint:</b> you can drag feeds and categories around.')."
1474# </div>";
afcfe6ca
AD
1475
1476 print '</div>';
1477 print '</div>';
1478
1479 print "</div>"; # feeds pane
1480
566faa14 1481 print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Import and export')."\">";
afcfe6ca 1482
a1159c01 1483 print "<h3>" . __("OPML") . "</h3>";
afcfe6ca 1484
566faa14 1485 print "<p>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . " ";
afcfe6ca 1486
566faa14 1487 print __("Only main settings profile can be migrated using OPML.") . "</p>";
afcfe6ca 1488
55f34b81 1489 print "<iframe id=\"upload_iframe\"
afcfe6ca
AD
1490 name=\"upload_iframe\" onload=\"opmlImportComplete(this)\"
1491 style=\"width: 400px; height: 100px; display: none;\"></iframe>";
1492
1493 print "<form name=\"opml_form\" style='display : block' target=\"upload_iframe\"
1494 enctype=\"multipart/form-data\" method=\"POST\"
55f34b81 1495 action=\"backend.php\">
afcfe6ca
AD
1496 <input id=\"opml_file\" name=\"opml_file\" type=\"file\">&nbsp;
1497 <input type=\"hidden\" name=\"op\" value=\"dlg\">
c4c74732 1498 <input type=\"hidden\" name=\"method\" value=\"importOpml\">
afcfe6ca 1499 <button dojoType=\"dijit.form.Button\" onclick=\"return opmlImport();\" type=\"submit\">" .
a1159c01 1500 __('Import my OPML') . "</button>";
afcfe6ca 1501
a1159c01 1502 print "<hr>";
afcfe6ca
AD
1503
1504 print "<p>" . __('Filename:') .
1505 " <input type=\"text\" id=\"filename\" value=\"TinyTinyRSS.opml\" />&nbsp;" .
a1159c01 1506 __('Include settings') . "<input type=\"checkbox\" id=\"settings\" checked=\"1\"/>";
afcfe6ca 1507
a1159c01 1508 print "</p><button dojoType=\"dijit.form.Button\"
afcfe6ca 1509 onclick=\"gotoExportOpml(document.opml_form.filename.value, document.opml_form.settings.checked)\" >" .
a1159c01 1510 __('Export OPML') . "</button></p></form>";
afcfe6ca 1511
a1159c01 1512 print "<hr>";
afcfe6ca
AD
1513
1514 print "<p>".__('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.') . " ";
1515
566faa14 1516 print __("Published OPML does not include your Tiny Tiny RSS settings, feeds that require authentication or feeds hidden from Popular feeds.") . "</p>";
afcfe6ca
AD
1517
1518 print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('pubOPMLUrl')\">".
a1159c01 1519 __('Display published OPML URL')."</button> ";
afcfe6ca 1520
55f34b81 1521
a1159c01 1522 print "<h3>" . __("Article archive") . "</h3>";
566faa14 1523
a1159c01 1524 print "<p>" . __("You can export and import your Starred and Archived articles for safekeeping or when migrating between tt-rss instances.") . "</p>";
566faa14
AD
1525
1526 print "<button dojoType=\"dijit.form.Button\" onclick=\"return exportData()\">".
1527 __('Export my data')."</button> ";
1528
a1159c01 1529 print "<hr>";
55f34b81
AD
1530
1531 print "<iframe id=\"data_upload_iframe\"
1532 name=\"data_upload_iframe\" onload=\"dataImportComplete(this)\"
1533 style=\"width: 400px; height: 100px; display: none;\"></iframe>";
1534
41f68571 1535 print "<form name=\"import_form\" style='display : block' target=\"data_upload_iframe\"
55f34b81
AD
1536 enctype=\"multipart/form-data\" method=\"POST\"
1537 action=\"backend.php\">
1538 <input id=\"export_file\" name=\"export_file\" type=\"file\">&nbsp;
1539 <input type=\"hidden\" name=\"op\" value=\"dlg\">
1540 <input type=\"hidden\" name=\"method\" value=\"dataimport\">
1541 <button dojoType=\"dijit.form.Button\" onclick=\"return importData();\" type=\"submit\">" .
1542 __('Import') . "</button>";
1543
1544
afcfe6ca
AD
1545 print "</div>"; # pane
1546
1547 if (strpos($_SERVER['HTTP_USER_AGENT'], "Firefox") !== false) {
1548
1549 print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Firefox integration')."\">";
1550
1551 print "<p>" . __('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.') . "</p>";
1552
1553 print "<p>";
1554
1555 print "<button onclick='window.navigator.registerContentHandler(" .
1556 "\"application/vnd.mozilla.maybe.feed\", " .
1557 "\"" . add_feed_url() . "\", " . " \"Tiny Tiny RSS\")'>" .
1558 __('Click here to register this site as a feed reader.') .
1559 "</button>";
1560
1561 print "</p>";
1562
1563 print "</div>"; # pane
1564 }
1565
1566 print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Subscribing using bookmarklet')."\">";
1567
1568 print "<p>" . __("Drag the link below to your browser toolbar, open the feed you're interested in in your browser and click on the link to subscribe to it.") . "</p>";
1569
1570 $bm_subscribe_url = str_replace('%s', '', add_feed_url());
1571
b1e592d3 1572 $confirm_str = str_replace("'", "\'", __('Subscribe to %s in Tiny Tiny RSS?'));
afcfe6ca
AD
1573
1574 $bm_url = htmlspecialchars("javascript:{if(confirm('$confirm_str'.replace('%s',window.location.href)))window.location.href='$bm_subscribe_url'+window.location.href}");
1575
1576 print "<a href=\"$bm_url\" class='bookmarklet'>" . __('Subscribe in Tiny Tiny RSS'). "</a>";
1577
1578 print "</div>"; #pane
1579
e95e7819 1580 print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Published & shared articles / Generated feeds')."\">";
afcfe6ca
AD
1581
1582 print "<h3>" . __("Published articles and generated feeds") . "</h3>";
1583
1584 print "<p>".__('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.')."</p>";
1585
1586 $rss_url = '-2::' . htmlspecialchars(get_self_url_prefix() .
1587 "/public.php?op=rss&id=-2&view-mode=all_articles");;
1588
1589 print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('generatedFeed', '$rss_url')\">".
1590 __('Display URL')."</button> ";
1591
1592 print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">".
1593 __('Clear all generated URLs')."</button> ";
1594
1595 print "<h3>" . __("Articles shared by URL") . "</h3>";
1596
1597 print "<p>" . __("You can disable all articles shared by unique URLs here.") . "</p>";
1598
1599 print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearArticleAccessKeys()\">".
1600 __('Unshare all articles')."</button> ";
1601
1602 print "</div>"; #pane
1603
1604 if (defined('CONSUMER_KEY') && CONSUMER_KEY != '') {
1605
1606 print "<div id=\"pref-feeds-twitter\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Twitter')."\">";
1607
1608 $result = db_query($this->link, "SELECT COUNT(*) AS cid FROM ttrss_users
1609 WHERE twitter_oauth IS NOT NULL AND twitter_oauth != '' AND
1610 id = " . $_SESSION['uid']);
1611
1612 $is_registered = db_fetch_result($result, 0, "cid") != 0;
1613
1614 if (!$is_registered) {
1615 print_notice(__('Before you can update your Twitter feeds, you must register this instance of Tiny Tiny RSS with Twitter.com.'));
1616 } else {
1617 print_notice(__('You have been successfully registered with Twitter.com and should be able to access your Twitter feeds.'));
1618 }
1619
1620 print "<button dojoType=\"dijit.form.Button\" onclick=\"window.location.href = 'twitter.php?op=register'\">".
1621 __("Register with Twitter.com")."</button>";
1622
1623 print " ";
1624
1625 print "<button dojoType=\"dijit.form.Button\"
1626 onclick=\"return clearTwitterCredentials()\">".
1627 __("Clear stored credentials")."</button>";
1628
1629 print "</div>"; # pane
1630
1631 }
1632
1633 print "</div>"; #container
1634
1635 }
2ecd2df5
AD
1636
1637 private function feedlist_init_cat($cat_id, $hidden = false) {
1638 $obj = array();
1639 $cat_id = (int) $cat_id;
1640
1641 if ($cat_id > 0) {
1642 $cat_unread = ccache_find($this->link, $cat_id, $_SESSION["uid"], true);
1643 } else if ($cat_id == 0 || $cat_id == -2) {
1644 $cat_unread = getCategoryUnread($this->link, $cat_id);
1645 }
1646
1647 $obj['id'] = 'CAT:' . $cat_id;
1648 $obj['items'] = array();
1649 $obj['name'] = getCategoryTitle($this->link, $cat_id);
1650 $obj['type'] = 'category';
1651 $obj['unread'] = (int) $cat_unread;
1652 $obj['hidden'] = $hidden;
1653 $obj['bare_id'] = $cat_id;
1654
1655 return $obj;
1656 }
1657
1658 private function feedlist_init_feed($feed_id, $title = false, $unread = false, $error = '', $updated = '') {
1659 $obj = array();
1660 $feed_id = (int) $feed_id;
1661
1662 if (!$title)
1663 $title = getFeedTitle($this->link, $feed_id, false);
1664
1665 if ($unread === false)
1666 $unread = getFeedUnread($this->link, $feed_id, false);
1667
1668 $obj['id'] = 'FEED:' . $feed_id;
1669 $obj['name'] = $title;
1670 $obj['unread'] = (int) $unread;
1671 $obj['type'] = 'feed';
1672 $obj['error'] = $error;
1673 $obj['updated'] = $updated;
1674 $obj['icon'] = getFeedIcon($feed_id);
1675 $obj['bare_id'] = $feed_id;
1676
1677 return $obj;
1678 }
1679
afcfe6ca
AD
1680}
1681?>