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