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