pref_feeds.php 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536
  1. <?php
  2. class Pref_Feeds extends Protected_Handler {
  3. function csrf_ignore($method) {
  4. $csrf_ignored = array("index", "getfeedtree", "add", "editcats", "editfeed");
  5. return array_search($method, $csrf_ignored) !== false;
  6. }
  7. function batch_edit_cbox($elem, $label = false) {
  8. print "<input type=\"checkbox\" title=\"".__("Check to enable field")."\"
  9. onchange=\"dijit.byId('feedEditDlg').toggleField(this, '$elem', '$label')\">";
  10. }
  11. function renamecat() {
  12. $title = db_escape_string($_REQUEST['title']);
  13. $id = db_escape_string($_REQUEST['id']);
  14. if ($title) {
  15. db_query($this->link, "UPDATE ttrss_feed_categories SET
  16. title = '$title' WHERE id = '$id' AND owner_uid = " . $_SESSION["uid"]);
  17. }
  18. return;
  19. }
  20. function remtwitterinfo() {
  21. db_query($this->link, "UPDATE ttrss_users SET twitter_oauth = NULL
  22. WHERE id = " . $_SESSION['uid']);
  23. return;
  24. }
  25. function getfeedtree() {
  26. $search = $_SESSION["prefs_feed_search"];
  27. if ($search) $search_qpart = " AND LOWER(title) LIKE LOWER('%$search%')";
  28. $root = array();
  29. $root['id'] = 'root';
  30. $root['name'] = __('Feeds');
  31. $root['items'] = array();
  32. $root['type'] = 'category';
  33. if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
  34. $result = db_query($this->link, "SELECT id, title FROM ttrss_feed_categories
  35. WHERE owner_uid = " . $_SESSION["uid"] . " ORDER BY order_id, title");
  36. while ($line = db_fetch_assoc($result)) {
  37. $cat = array();
  38. $cat['id'] = 'CAT:' . $line['id'];
  39. $cat['bare_id'] = $feed_id;
  40. $cat['name'] = $line['title'];
  41. $cat['items'] = array();
  42. $cat['checkbox'] = false;
  43. $cat['type'] = 'category';
  44. $feed_result = db_query($this->link, "SELECT id, title, last_error,
  45. ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
  46. FROM ttrss_feeds
  47. WHERE cat_id = '".$line['id']."' AND owner_uid = ".$_SESSION["uid"].
  48. "$search_qpart ORDER BY order_id, title");
  49. while ($feed_line = db_fetch_assoc($feed_result)) {
  50. $feed = array();
  51. $feed['id'] = 'FEED:' . $feed_line['id'];
  52. $feed['bare_id'] = $feed_line['id'];
  53. $feed['name'] = $feed_line['title'];
  54. $feed['checkbox'] = false;
  55. $feed['error'] = $feed_line['last_error'];
  56. $feed['icon'] = getFeedIcon($feed_line['id']);
  57. $feed['param'] = make_local_datetime($this->link,
  58. $feed_line['last_updated'], true);
  59. array_push($cat['items'], $feed);
  60. }
  61. $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
  62. if (count($cat['items']) > 0)
  63. array_push($root['items'], $cat);
  64. $root['param'] += count($cat['items']);
  65. }
  66. /* Uncategorized is a special case */
  67. $cat = array();
  68. $cat['id'] = 'CAT:0';
  69. $cat['bare_id'] = 0;
  70. $cat['name'] = __("Uncategorized");
  71. $cat['items'] = array();
  72. $cat['type'] = 'category';
  73. $cat['checkbox'] = false;
  74. $feed_result = db_query($this->link, "SELECT id, title,last_error,
  75. ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
  76. FROM ttrss_feeds
  77. WHERE cat_id IS NULL AND owner_uid = ".$_SESSION["uid"].
  78. "$search_qpart ORDER BY order_id, title");
  79. while ($feed_line = db_fetch_assoc($feed_result)) {
  80. $feed = array();
  81. $feed['id'] = 'FEED:' . $feed_line['id'];
  82. $feed['bare_id'] = $feed_line['id'];
  83. $feed['name'] = $feed_line['title'];
  84. $feed['checkbox'] = false;
  85. $feed['error'] = $feed_line['last_error'];
  86. $feed['icon'] = getFeedIcon($feed_line['id']);
  87. $feed['param'] = make_local_datetime($this->link,
  88. $feed_line['last_updated'], true);
  89. array_push($cat['items'], $feed);
  90. }
  91. $cat['param'] = T_sprintf('(%d feeds)', count($cat['items']));
  92. if (count($cat['items']) > 0)
  93. array_push($root['items'], $cat);
  94. $root['param'] += count($cat['items']);
  95. $root['param'] = T_sprintf('(%d feeds)', $root['param']);
  96. } else {
  97. $feed_result = db_query($this->link, "SELECT id, title, last_error,
  98. ".SUBSTRING_FOR_DATE."(last_updated,1,19) AS last_updated
  99. FROM ttrss_feeds
  100. WHERE owner_uid = ".$_SESSION["uid"].
  101. "$search_qpart ORDER BY order_id, title");
  102. while ($feed_line = db_fetch_assoc($feed_result)) {
  103. $feed = array();
  104. $feed['id'] = 'FEED:' . $feed_line['id'];
  105. $feed['bare_id'] = $feed_line['id'];
  106. $feed['name'] = $feed_line['title'];
  107. $feed['checkbox'] = false;
  108. $feed['error'] = $feed_line['last_error'];
  109. $feed['icon'] = getFeedIcon($feed_line['id']);
  110. $feed['param'] = make_local_datetime($this->link,
  111. $feed_line['last_updated'], true);
  112. array_push($root['items'], $feed);
  113. }
  114. $root['param'] = T_sprintf('(%d feeds)', count($root['items']));
  115. }
  116. $fl = array();
  117. $fl['identifier'] = 'id';
  118. $fl['label'] = 'name';
  119. $fl['items'] = array($root);
  120. print json_encode($fl);
  121. return;
  122. }
  123. function catsortreset() {
  124. db_query($this->link, "UPDATE ttrss_feed_categories
  125. SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
  126. return;
  127. }
  128. function feedsortreset() {
  129. db_query($this->link, "UPDATE ttrss_feeds
  130. SET order_id = 0 WHERE owner_uid = " . $_SESSION["uid"]);
  131. return;
  132. }
  133. function savefeedorder() {
  134. $data = json_decode($_POST['payload'], true);
  135. if (is_array($data) && is_array($data['items'])) {
  136. $cat_order_id = 0;
  137. $data_map = array();
  138. foreach ($data['items'] as $item) {
  139. if ($item['id'] != 'root') {
  140. if (is_array($item['items'])) {
  141. if (isset($item['items']['_reference'])) {
  142. $data_map[$item['id']] = array($item['items']);
  143. } else {
  144. $data_map[$item['id']] =& $item['items'];
  145. }
  146. }
  147. }
  148. }
  149. foreach ($data['items'][0]['items'] as $item) {
  150. $id = $item['_reference'];
  151. $bare_id = substr($id, strpos($id, ':')+1);
  152. ++$cat_order_id;
  153. if ($bare_id > 0) {
  154. db_query($this->link, "UPDATE ttrss_feed_categories
  155. SET order_id = '$cat_order_id' WHERE id = '$bare_id' AND
  156. owner_uid = " . $_SESSION["uid"]);
  157. }
  158. $feed_order_id = 0;
  159. if (is_array($data_map[$id])) {
  160. foreach ($data_map[$id] as $feed) {
  161. $id = $feed['_reference'];
  162. $feed_id = substr($id, strpos($id, ':')+1);
  163. if ($bare_id != 0)
  164. $cat_query = "cat_id = '$bare_id'";
  165. else
  166. $cat_query = "cat_id = NULL";
  167. db_query($this->link, "UPDATE ttrss_feeds
  168. SET order_id = '$feed_order_id',
  169. $cat_query
  170. WHERE id = '$feed_id' AND
  171. owner_uid = " . $_SESSION["uid"]);
  172. ++$feed_order_id;
  173. }
  174. }
  175. }
  176. }
  177. return;
  178. }
  179. function removeicon() {
  180. $feed_id = db_escape_string($_REQUEST["feed_id"]);
  181. $result = db_query($this->link, "SELECT id FROM ttrss_feeds
  182. WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
  183. if (db_num_rows($result) != 0) {
  184. unlink(ICONS_DIR . "/$feed_id.ico");
  185. }
  186. return;
  187. }
  188. function uploadicon() {
  189. $icon_file = $_FILES['icon_file']['tmp_name'];
  190. $feed_id = db_escape_string($_REQUEST["feed_id"]);
  191. if (is_file($icon_file) && $feed_id) {
  192. if (filesize($icon_file) < 20000) {
  193. $result = db_query($this->link, "SELECT id FROM ttrss_feeds
  194. WHERE id = '$feed_id' AND owner_uid = ". $_SESSION["uid"]);
  195. if (db_num_rows($result) != 0) {
  196. unlink(ICONS_DIR . "/$feed_id.ico");
  197. move_uploaded_file($icon_file, ICONS_DIR . "/$feed_id.ico");
  198. $rc = 0;
  199. } else {
  200. $rc = 2;
  201. }
  202. } else {
  203. $rc = 1;
  204. }
  205. } else {
  206. $rc = 2;
  207. }
  208. print "<script type=\"text/javascript\">";
  209. print "parent.uploadIconHandler($rc);";
  210. print "</script>";
  211. return;
  212. }
  213. function editfeed() {
  214. global $purge_intervals;
  215. global $update_intervals;
  216. global $update_methods;
  217. $feed_id = db_escape_string($_REQUEST["id"]);
  218. $result = db_query($this->link,
  219. "SELECT * FROM ttrss_feeds WHERE id = '$feed_id' AND
  220. owner_uid = " . $_SESSION["uid"]);
  221. $title = htmlspecialchars(db_fetch_result($result,
  222. 0, "title"));
  223. print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"id\" value=\"$feed_id\">";
  224. print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
  225. print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"editSave\">";
  226. print "<div class=\"dlgSec\">".__("Feed")."</div>";
  227. print "<div class=\"dlgSecCont\">";
  228. /* Title */
  229. print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
  230. placeHolder=\"".__("Feed Title")."\"
  231. style=\"font-size : 16px; width: 20em\" name=\"title\" value=\"$title\">";
  232. /* Feed URL */
  233. $feed_url = db_fetch_result($result, 0, "feed_url");
  234. $feed_url = htmlspecialchars(db_fetch_result($result,
  235. 0, "feed_url"));
  236. print "<hr/>";
  237. print __('URL:') . " ";
  238. print "<input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\"
  239. placeHolder=\"".__("Feed URL")."\"
  240. regExp='^(http|https)://.*' style=\"width : 20em\"
  241. name=\"feed_url\" value=\"$feed_url\">";
  242. $last_error = db_fetch_result($result, 0, "last_error");
  243. if ($last_error) {
  244. print "&nbsp;<span title=\"".htmlspecialchars($last_error)."\"
  245. class=\"feed_error\">(error)</span>";
  246. }
  247. /* Category */
  248. if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
  249. $cat_id = db_fetch_result($result, 0, "cat_id");
  250. print "<hr/>";
  251. print __('Place in category:') . " ";
  252. print_feed_cat_select($this->link, "cat_id", $cat_id,
  253. 'dojoType="dijit.form.Select"');
  254. }
  255. print "</div>";
  256. print "<div class=\"dlgSec\">".__("Update")."</div>";
  257. print "<div class=\"dlgSecCont\">";
  258. /* Update Interval */
  259. $update_interval = db_fetch_result($result, 0, "update_interval");
  260. print_select_hash("update_interval", $update_interval, $update_intervals,
  261. 'dojoType="dijit.form.Select"');
  262. /* Update method */
  263. $update_method = db_fetch_result($result, 0, "update_method",
  264. 'dojoType="dijit.form.Select"');
  265. print " " . __('using') . " ";
  266. print_select_hash("update_method", $update_method, $update_methods,
  267. 'dojoType="dijit.form.Select"');
  268. $purge_interval = db_fetch_result($result, 0, "purge_interval");
  269. /* Purge intl */
  270. print "<hr/>";
  271. print __('Article purging:') . " ";
  272. print_select_hash("purge_interval", $purge_interval, $purge_intervals,
  273. 'dojoType="dijit.form.Select" ' .
  274. ((FORCE_ARTICLE_PURGE == 0) ? "" : 'disabled="1"'));
  275. print "</div>";
  276. print "<div class=\"dlgSec\">".__("Authentication")."</div>";
  277. print "<div class=\"dlgSecCont\">";
  278. $auth_login = htmlspecialchars(db_fetch_result($result, 0, "auth_login"));
  279. print "<input dojoType=\"dijit.form.TextBox\" id=\"feedEditDlg_login\"
  280. placeHolder=\"".__("Login")."\"
  281. name=\"auth_login\" value=\"$auth_login\"><hr/>";
  282. $auth_pass = htmlspecialchars(db_fetch_result($result, 0, "auth_pass"));
  283. print "<input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
  284. placeHolder=\"".__("Password")."\"
  285. value=\"$auth_pass\">";
  286. print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedEditDlg_login\" position=\"below\">
  287. ".__('<b>Hint:</b> you need to fill in your login information if your feed requires authentication, except for Twitter feeds.')."
  288. </div>";
  289. print "</div>";
  290. print "<div class=\"dlgSec\">".__("Options")."</div>";
  291. print "<div class=\"dlgSecCont\">";
  292. $private = sql_bool_to_bool(db_fetch_result($result, 0, "private"));
  293. if ($private) {
  294. $checked = "checked=\"1\"";
  295. } else {
  296. $checked = "";
  297. }
  298. print "<input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" name=\"private\" id=\"private\"
  299. $checked>&nbsp;<label for=\"private\">".__('Hide from Popular feeds')."</label>";
  300. $rtl_content = sql_bool_to_bool(db_fetch_result($result, 0, "rtl_content"));
  301. if ($rtl_content) {
  302. $checked = "checked=\"1\"";
  303. } else {
  304. $checked = "";
  305. }
  306. print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
  307. $checked>&nbsp;<label for=\"rtl_content\">".__('Right-to-left content')."</label>";
  308. $include_in_digest = sql_bool_to_bool(db_fetch_result($result, 0, "include_in_digest"));
  309. if ($include_in_digest) {
  310. $checked = "checked=\"1\"";
  311. } else {
  312. $checked = "";
  313. }
  314. print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"include_in_digest\"
  315. name=\"include_in_digest\"
  316. $checked>&nbsp;<label for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
  317. $always_display_enclosures = sql_bool_to_bool(db_fetch_result($result, 0, "always_display_enclosures"));
  318. if ($always_display_enclosures) {
  319. $checked = "checked";
  320. } else {
  321. $checked = "";
  322. }
  323. print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"always_display_enclosures\"
  324. name=\"always_display_enclosures\"
  325. $checked>&nbsp;<label for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
  326. $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images"));
  327. if ($cache_images) {
  328. $checked = "checked=\"1\"";
  329. } else {
  330. $checked = "";
  331. }
  332. print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"cache_images\"
  333. name=\"cache_images\"
  334. $checked>&nbsp;<label for=\"cache_images\">".
  335. __('Cache images locally')."</label>";
  336. $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update"));
  337. if ($mark_unread_on_update) {
  338. $checked = "checked";
  339. } else {
  340. $checked = "";
  341. }
  342. print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"mark_unread_on_update\"
  343. name=\"mark_unread_on_update\"
  344. $checked>&nbsp;<label for=\"mark_unread_on_update\">".__('Mark updated articles as unread')."</label>";
  345. $update_on_checksum_change = sql_bool_to_bool(db_fetch_result($result, 0, "update_on_checksum_change"));
  346. if ($update_on_checksum_change) {
  347. $checked = "checked";
  348. } else {
  349. $checked = "";
  350. }
  351. print "<hr/><input dojoType=\"dijit.form.CheckBox\" type=\"checkbox\" id=\"update_on_checksum_change\"
  352. name=\"update_on_checksum_change\"
  353. $checked>&nbsp;<label for=\"update_on_checksum_change\">".__('Mark posts as updated on content change')."</label>";
  354. print "</div>";
  355. /* Icon */
  356. print "<div class=\"dlgSec\">".__("Icon")."</div>";
  357. print "<div class=\"dlgSecCont\">";
  358. print "<iframe name=\"icon_upload_iframe\"
  359. style=\"width: 400px; height: 100px; display: none;\"></iframe>";
  360. print "<form style='display : block' target=\"icon_upload_iframe\"
  361. enctype=\"multipart/form-data\" method=\"POST\"
  362. action=\"backend.php\">
  363. <input id=\"icon_file\" size=\"10\" name=\"icon_file\" type=\"file\">
  364. <input type=\"hidden\" name=\"op\" value=\"pref-feeds\">
  365. <input type=\"hidden\" name=\"feed_id\" value=\"$feed_id\">
  366. <input type=\"hidden\" name=\"method\" value=\"uploadicon\">
  367. <button dojoType=\"dijit.form.Button\" onclick=\"return uploadFeedIcon();\"
  368. type=\"submit\">".__('Replace')."</button>
  369. <button dojoType=\"dijit.form.Button\" onclick=\"return removeFeedIcon($feed_id);\"
  370. type=\"submit\">".__('Remove')."</button>
  371. </form>";
  372. print "</div>";
  373. $title = htmlspecialchars($title, ENT_QUOTES);
  374. print "<div class='dlgButtons'>
  375. <div style=\"float : left\">
  376. <button dojoType=\"dijit.form.Button\" onclick='return unsubscribeFeed($feed_id, \"$title\")'>".
  377. __('Unsubscribe')."</button>";
  378. if (PUBSUBHUBBUB_ENABLED) {
  379. $pubsub_state = db_fetch_result($result, 0, "pubsub_state");
  380. $pubsub_btn_disabled = ($pubsub_state == 2) ? "" : "disabled=\"1\"";
  381. print "<button dojoType=\"dijit.form.Button\" id=\"pubsubReset_Btn\" $pubsub_btn_disabled
  382. onclick='return resetPubSub($feed_id, \"$title\")'>".__('Resubscribe to push updates').
  383. "</button>";
  384. }
  385. print "</div>";
  386. print "<div dojoType=\"dijit.Tooltip\" connectId=\"pubsubReset_Btn\" position=\"below\">".
  387. __('Resets PubSubHubbub subscription status for push-enabled feeds.')."</div>";
  388. print "<button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').execute()\">".__('Save')."</button>
  389. <button dojoType=\"dijit.form.Button\" onclick=\"return dijit.byId('feedEditDlg').hide()\">".__('Cancel')."</button>
  390. </div>";
  391. return;
  392. }
  393. function editfeeds() {
  394. global $purge_intervals;
  395. global $update_intervals;
  396. global $update_methods;
  397. $feed_ids = db_escape_string($_REQUEST["ids"]);
  398. print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"ids\" value=\"$feed_ids\">";
  399. print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"op\" value=\"pref-feeds\">";
  400. print "<input dojoType=\"dijit.form.TextBox\" style=\"display : none\" name=\"method\" value=\"batchEditSave\">";
  401. print "<div class=\"dlgSec\">".__("Feed")."</div>";
  402. print "<div class=\"dlgSecCont\">";
  403. /* Title */
  404. print "<input dojoType=\"dijit.form.ValidationTextBox\"
  405. disabled=\"1\" style=\"font-size : 16px; width : 20em;\" required=\"1\"
  406. name=\"title\" value=\"$title\">";
  407. $this->batch_edit_cbox("title");
  408. /* Feed URL */
  409. print "<br/>";
  410. print __('URL:') . " ";
  411. print "<input dojoType=\"dijit.form.ValidationTextBox\" disabled=\"1\"
  412. required=\"1\" regExp='^(http|https)://.*' style=\"width : 20em\"
  413. name=\"feed_url\" value=\"$feed_url\">";
  414. $this->batch_edit_cbox("feed_url");
  415. /* Category */
  416. if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
  417. print "<br/>";
  418. print __('Place in category:') . " ";
  419. print_feed_cat_select($this->link, "cat_id", $cat_id,
  420. 'disabled="1" dojoType="dijit.form.Select"');
  421. $this->batch_edit_cbox("cat_id");
  422. }
  423. print "</div>";
  424. print "<div class=\"dlgSec\">".__("Update")."</div>";
  425. print "<div class=\"dlgSecCont\">";
  426. /* Update Interval */
  427. print_select_hash("update_interval", $update_interval, $update_intervals,
  428. 'disabled="1" dojoType="dijit.form.Select"');
  429. $this->batch_edit_cbox("update_interval");
  430. /* Update method */
  431. print " " . __('using') . " ";
  432. print_select_hash("update_method", $update_method, $update_methods,
  433. 'disabled="1" dojoType="dijit.form.Select"');
  434. $this->batch_edit_cbox("update_method");
  435. /* Purge intl */
  436. if (FORCE_ARTICLE_PURGE == 0) {
  437. print "<br/>";
  438. print __('Article purging:') . " ";
  439. print_select_hash("purge_interval", $purge_interval, $purge_intervals,
  440. 'disabled="1" dojoType="dijit.form.Select"');
  441. $this->batch_edit_cbox("purge_interval");
  442. }
  443. print "</div>";
  444. print "<div class=\"dlgSec\">".__("Authentication")."</div>";
  445. print "<div class=\"dlgSecCont\">";
  446. print "<input dojoType=\"dijit.form.TextBox\"
  447. placeHolder=\"".__("Login")."\" disabled=\"1\"
  448. name=\"auth_login\" value=\"$auth_login\">";
  449. $this->batch_edit_cbox("auth_login");
  450. print "<br/><input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\"
  451. placeHolder=\"".__("Password")."\" disabled=\"1\"
  452. value=\"$auth_pass\">";
  453. $this->batch_edit_cbox("auth_pass");
  454. print "</div>";
  455. print "<div class=\"dlgSec\">".__("Options")."</div>";
  456. print "<div class=\"dlgSecCont\">";
  457. print "<input disabled=\"1\" type=\"checkbox\" name=\"private\" id=\"private\"
  458. dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"private_l\" class='insensitive' for=\"private\">".__('Hide from Popular feeds')."</label>";
  459. print "&nbsp;"; $this->batch_edit_cbox("private", "private_l");
  460. print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"rtl_content\" name=\"rtl_content\"
  461. dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"rtl_content_l\" for=\"rtl_content\">".__('Right-to-left content')."</label>";
  462. print "&nbsp;"; $this->batch_edit_cbox("rtl_content", "rtl_content_l");
  463. print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"include_in_digest\"
  464. name=\"include_in_digest\"
  465. dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"include_in_digest_l\" class='insensitive' for=\"include_in_digest\">".__('Include in e-mail digest')."</label>";
  466. print "&nbsp;"; $this->batch_edit_cbox("include_in_digest", "include_in_digest_l");
  467. print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"always_display_enclosures\"
  468. name=\"always_display_enclosures\"
  469. dojoType=\"dijit.form.CheckBox\">&nbsp;<label id=\"always_display_enclosures_l\" class='insensitive' for=\"always_display_enclosures\">".__('Always display image attachments')."</label>";
  470. print "&nbsp;"; $this->batch_edit_cbox("always_display_enclosures", "always_display_enclosures_l");
  471. print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"cache_images\"
  472. name=\"cache_images\"
  473. dojoType=\"dijit.form.CheckBox\">&nbsp;<label class='insensitive' id=\"cache_images_l\"
  474. for=\"cache_images\">".
  475. __('Cache images locally')."</label>";
  476. print "&nbsp;"; $this->batch_edit_cbox("cache_images", "cache_images_l");
  477. print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"mark_unread_on_update\"
  478. name=\"mark_unread_on_update\"
  479. 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>";
  480. print "&nbsp;"; $this->batch_edit_cbox("mark_unread_on_update", "mark_unread_on_update_l");
  481. print "<br/><input disabled=\"1\" type=\"checkbox\" id=\"update_on_checksum_change\"
  482. name=\"update_on_checksum_change\"
  483. 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>";
  484. print "&nbsp;"; $this->batch_edit_cbox("update_on_checksum_change", "update_on_checksum_change_l");
  485. print "</div>";
  486. print "<div class='dlgButtons'>
  487. <button dojoType=\"dijit.form.Button\"
  488. onclick=\"return dijit.byId('feedEditDlg').execute()\">".
  489. __('Save')."</button>
  490. <button dojoType=\"dijit.form.Button\"
  491. onclick=\"return dijit.byId('feedEditDlg').hide()\">".
  492. __('Cancel')."</button>
  493. </div>";
  494. return;
  495. }
  496. function batchEditSave() {
  497. return $this->editsaveops(true);
  498. }
  499. function editSave() {
  500. return $this->editsaveops(false);
  501. }
  502. function editsaveops($batch) {
  503. $feed_title = db_escape_string(trim($_POST["title"]));
  504. $feed_link = db_escape_string(trim($_POST["feed_url"]));
  505. $upd_intl = (int) db_escape_string($_POST["update_interval"]);
  506. $purge_intl = (int) db_escape_string($_POST["purge_interval"]);
  507. $feed_id = (int) db_escape_string($_POST["id"]); /* editSave */
  508. $feed_ids = db_escape_string($_POST["ids"]); /* batchEditSave */
  509. $cat_id = (int) db_escape_string($_POST["cat_id"]);
  510. $auth_login = db_escape_string(trim($_POST["auth_login"]));
  511. $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
  512. $private = checkbox_to_sql_bool(db_escape_string($_POST["private"]));
  513. $rtl_content = checkbox_to_sql_bool(db_escape_string($_POST["rtl_content"]));
  514. $include_in_digest = checkbox_to_sql_bool(
  515. db_escape_string($_POST["include_in_digest"]));
  516. $cache_images = checkbox_to_sql_bool(
  517. db_escape_string($_POST["cache_images"]));
  518. $update_method = (int) db_escape_string($_POST["update_method"]);
  519. $always_display_enclosures = checkbox_to_sql_bool(
  520. db_escape_string($_POST["always_display_enclosures"]));
  521. $mark_unread_on_update = checkbox_to_sql_bool(
  522. db_escape_string($_POST["mark_unread_on_update"]));
  523. $update_on_checksum_change = checkbox_to_sql_bool(
  524. db_escape_string($_POST["update_on_checksum_change"]));
  525. if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
  526. if ($cat_id && $cat_id != 0) {
  527. $category_qpart = "cat_id = '$cat_id',";
  528. $category_qpart_nocomma = "cat_id = '$cat_id'";
  529. } else {
  530. $category_qpart = 'cat_id = NULL,';
  531. $category_qpart_nocomma = 'cat_id = NULL';
  532. }
  533. } else {
  534. $category_qpart = "";
  535. $category_qpart_nocomma = "";
  536. }
  537. $cache_images_qpart = "cache_images = $cache_images,";
  538. if (!$batch) {
  539. $result = db_query($this->link, "UPDATE ttrss_feeds SET
  540. $category_qpart
  541. title = '$feed_title', feed_url = '$feed_link',
  542. update_interval = '$upd_intl',
  543. purge_interval = '$purge_intl',
  544. auth_login = '$auth_login',
  545. auth_pass = '$auth_pass',
  546. private = $private,
  547. rtl_content = $rtl_content,
  548. $cache_images_qpart
  549. include_in_digest = $include_in_digest,
  550. always_display_enclosures = $always_display_enclosures,
  551. mark_unread_on_update = $mark_unread_on_update,
  552. update_on_checksum_change = $update_on_checksum_change,
  553. update_method = '$update_method'
  554. WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]);
  555. } else {
  556. $feed_data = array();
  557. foreach (array_keys($_POST) as $k) {
  558. if ($k != "op" && $k != "method" && $k != "ids") {
  559. $feed_data[$k] = $_POST[$k];
  560. }
  561. }
  562. db_query($this->link, "BEGIN");
  563. foreach (array_keys($feed_data) as $k) {
  564. $qpart = "";
  565. switch ($k) {
  566. case "title":
  567. $qpart = "title = '$feed_title'";
  568. break;
  569. case "feed_url":
  570. $qpart = "feed_url = '$feed_link'";
  571. break;
  572. case "update_interval":
  573. $qpart = "update_interval = '$upd_intl'";
  574. break;
  575. case "purge_interval":
  576. $qpart = "purge_interval = '$purge_intl'";
  577. break;
  578. case "auth_login":
  579. $qpart = "auth_login = '$auth_login'";
  580. break;
  581. case "auth_pass":
  582. $qpart = "auth_pass = '$auth_pass'";
  583. break;
  584. case "private":
  585. $qpart = "private = '$private'";
  586. break;
  587. case "include_in_digest":
  588. $qpart = "include_in_digest = '$include_in_digest'";
  589. break;
  590. case "always_display_enclosures":
  591. $qpart = "always_display_enclosures = '$always_display_enclosures'";
  592. break;
  593. case "mark_unread_on_update":
  594. $qpart = "mark_unread_on_update = '$mark_unread_on_update'";
  595. break;
  596. case "update_on_checksum_change":
  597. $qpart = "update_on_checksum_change = '$update_on_checksum_change'";
  598. break;
  599. case "cache_images":
  600. $qpart = "cache_images = '$cache_images'";
  601. break;
  602. case "rtl_content":
  603. $qpart = "rtl_content = '$rtl_content'";
  604. break;
  605. case "update_method":
  606. $qpart = "update_method = '$update_method'";
  607. break;
  608. case "cat_id":
  609. $qpart = $category_qpart_nocomma;
  610. break;
  611. }
  612. if ($qpart) {
  613. db_query($this->link,
  614. "UPDATE ttrss_feeds SET $qpart WHERE id IN ($feed_ids)
  615. AND owner_uid = " . $_SESSION["uid"]);
  616. print "<br/>";
  617. }
  618. }
  619. db_query($this->link, "COMMIT");
  620. }
  621. return;
  622. }
  623. function resetPubSub() {
  624. $ids = db_escape_string($_REQUEST["ids"]);
  625. db_query($this->link, "UPDATE ttrss_feeds SET pubsub_state = 0 WHERE id IN ($ids)
  626. AND owner_uid = " . $_SESSION["uid"]);
  627. return;
  628. }
  629. function remove() {
  630. $ids = split(",", db_escape_string($_REQUEST["ids"]));
  631. foreach ($ids as $id) {
  632. remove_feed($this->link, $id, $_SESSION["uid"]);
  633. }
  634. return;
  635. }
  636. function clear() {
  637. $id = db_escape_string($_REQUEST["id"]);
  638. clear_feed_articles($this->link, $id);
  639. }
  640. function rescore() {
  641. $ids = split(",", db_escape_string($_REQUEST["ids"]));
  642. foreach ($ids as $id) {
  643. $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
  644. $result = db_query($this->link, "SELECT
  645. title, content, link, ref_id, author,".
  646. SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
  647. FROM
  648. ttrss_user_entries, ttrss_entries
  649. WHERE ref_id = id AND feed_id = '$id' AND
  650. owner_uid = " .$_SESSION['uid']."
  651. ");
  652. $scores = array();
  653. while ($line = db_fetch_assoc($result)) {
  654. $tags = get_article_tags($this->link, $line["ref_id"]);
  655. $article_filters = get_article_filters($filters, $line['title'],
  656. $line['content'], $line['link'], strtotime($line['updated']),
  657. $line['author'], $tags);
  658. $new_score = calculate_article_score($article_filters);
  659. if (!$scores[$new_score]) $scores[$new_score] = array();
  660. array_push($scores[$new_score], $line['ref_id']);
  661. }
  662. foreach (array_keys($scores) as $s) {
  663. if ($s > 1000) {
  664. db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
  665. marked = true WHERE
  666. ref_id IN (" . join(',', $scores[$s]) . ")");
  667. } else if ($s < -500) {
  668. db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
  669. unread = false WHERE
  670. ref_id IN (" . join(',', $scores[$s]) . ")");
  671. } else {
  672. db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
  673. ref_id IN (" . join(',', $scores[$s]) . ")");
  674. }
  675. }
  676. }
  677. print __("All done.");
  678. }
  679. function rescoreAll() {
  680. $result = db_query($this->link,
  681. "SELECT id FROM ttrss_feeds WHERE owner_uid = " . $_SESSION['uid']);
  682. while ($feed_line = db_fetch_assoc($result)) {
  683. $id = $feed_line["id"];
  684. $filters = load_filters($this->link, $id, $_SESSION["uid"], 6);
  685. $tmp_result = db_query($this->link, "SELECT
  686. title, content, link, ref_id, author,".
  687. SUBSTRING_FOR_DATE."(updated, 1, 19) AS updated
  688. FROM
  689. ttrss_user_entries, ttrss_entries
  690. WHERE ref_id = id AND feed_id = '$id' AND
  691. owner_uid = " .$_SESSION['uid']."
  692. ");
  693. $scores = array();
  694. while ($line = db_fetch_assoc($tmp_result)) {
  695. $tags = get_article_tags($this->link, $line["ref_id"]);
  696. $article_filters = get_article_filters($filters, $line['title'],
  697. $line['content'], $line['link'], strtotime($line['updated']),
  698. $line['author'], $tags);
  699. $new_score = calculate_article_score($article_filters);
  700. if (!$scores[$new_score]) $scores[$new_score] = array();
  701. array_push($scores[$new_score], $line['ref_id']);
  702. }
  703. foreach (array_keys($scores) as $s) {
  704. if ($s > 1000) {
  705. db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s',
  706. marked = true WHERE
  707. ref_id IN (" . join(',', $scores[$s]) . ")");
  708. } else {
  709. db_query($this->link, "UPDATE ttrss_user_entries SET score = '$s' WHERE
  710. ref_id IN (" . join(',', $scores[$s]) . ")");
  711. }
  712. }
  713. }
  714. print __("All done.");
  715. }
  716. function add() {
  717. $feed_url = db_escape_string(trim($_REQUEST["feed_url"]));
  718. $cat_id = db_escape_string($_REQUEST["cat_id"]);
  719. $p_from = db_escape_string($_REQUEST["from"]);
  720. /* only read authentication information from POST */
  721. $auth_login = db_escape_string(trim($_POST["auth_login"]));
  722. $auth_pass = db_escape_string(trim($_POST["auth_pass"]));
  723. if ($p_from != 'tt-rss') {
  724. header("Content-Type: text/html");
  725. print "<html>
  726. <head>
  727. <title>Tiny Tiny RSS</title>
  728. <link rel=\"stylesheet\" type=\"text/css\" href=\"utility.css\">
  729. </head>
  730. <body>
  731. <img class=\"floatingLogo\" src=\"images/ttrss_logo.png\"
  732. alt=\"Tiny Tiny RSS\"/>
  733. <h1>Subscribe to feed...</h1>";
  734. }
  735. $rc = subscribe_to_feed($this->link, $feed_url, $cat_id, $auth_login, $auth_pass);
  736. switch ($rc) {
  737. case 1:
  738. print_notice(T_sprintf("Subscribed to <b>%s</b>.", $feed_url));
  739. break;
  740. case 2:
  741. print_error(T_sprintf("Could not subscribe to <b>%s</b>.", $feed_url));
  742. break;
  743. case 3:
  744. print_error(T_sprintf("No feeds found in <b>%s</b>.", $feed_url));
  745. break;
  746. case 0:
  747. print_warning(T_sprintf("Already subscribed to <b>%s</b>.", $feed_url));
  748. break;
  749. case 4:
  750. print_notice("Multiple feed URLs found.");
  751. $feed_urls = get_feeds_from_html($feed_url);
  752. break;
  753. case 5:
  754. print_error(T_sprintf("Could not subscribe to <b>%s</b>.<br>Can't download the Feed URL.", $feed_url));
  755. break;
  756. }
  757. if ($p_from != 'tt-rss') {
  758. if ($feed_urls) {
  759. print "<form action=\"backend.php\">";
  760. print "<input type=\"hidden\" name=\"op\" value=\"pref-feeds\">";
  761. print "<input type=\"hidden\" name=\"quiet\" value=\"1\">";
  762. print "<input type=\"hidden\" name=\"method\" value=\"add\">";
  763. print "<select name=\"feed_url\">";
  764. foreach ($feed_urls as $url => $name) {
  765. $url = htmlspecialchars($url);
  766. $name = htmlspecialchars($name);
  767. print "<option value=\"$url\">$name</option>";
  768. }
  769. print "<input type=\"submit\" value=\"".__("Subscribe to selected feed").
  770. "\">";
  771. print "</form>";
  772. }
  773. $tp_uri = get_self_url_prefix() . "/prefs.php";
  774. $tt_uri = get_self_url_prefix();
  775. if ($rc <= 2){
  776. $result = db_query($this->link, "SELECT id FROM ttrss_feeds WHERE
  777. feed_url = '$feed_url' AND owner_uid = " . $_SESSION["uid"]);
  778. $feed_id = db_fetch_result($result, 0, "id");
  779. } else {
  780. $feed_id = 0;
  781. }
  782. print "<p>";
  783. if ($feed_id) {
  784. print "<form method=\"GET\" style='display: inline'
  785. action=\"$tp_uri\">
  786. <input type=\"hidden\" name=\"tab\" value=\"feedConfig\">
  787. <input type=\"hidden\" name=\"method\" value=\"editFeed\">
  788. <input type=\"hidden\" name=\"methodparam\" value=\"$feed_id\">
  789. <input type=\"submit\" value=\"".__("Edit subscription options")."\">
  790. </form>";
  791. }
  792. print "<form style='display: inline' method=\"GET\" action=\"$tt_uri\">
  793. <input type=\"submit\" value=\"".__("Return to Tiny Tiny RSS")."\">
  794. </form></p>";
  795. print "</body></html>";
  796. return;
  797. }
  798. }
  799. function categorize() {
  800. $ids = split(",", db_escape_string($_REQUEST["ids"]));
  801. $cat_id = db_escape_string($_REQUEST["cat_id"]);
  802. if ($cat_id == 0) {
  803. $cat_id_qpart = 'NULL';
  804. } else {
  805. $cat_id_qpart = "'$cat_id'";
  806. }
  807. db_query($this->link, "BEGIN");
  808. foreach ($ids as $id) {
  809. db_query($this->link, "UPDATE ttrss_feeds SET cat_id = $cat_id_qpart
  810. WHERE id = '$id'
  811. AND owner_uid = " . $_SESSION["uid"]);
  812. }
  813. db_query($this->link, "COMMIT");
  814. }
  815. function editCats() {
  816. $action = $_REQUEST["action"];
  817. if ($action == "save") {
  818. $cat_title = db_escape_string(trim($_REQUEST["value"]));
  819. $cat_id = db_escape_string($_REQUEST["cid"]);
  820. db_query($this->link, "BEGIN");
  821. $result = db_query($this->link, "SELECT title FROM ttrss_feed_categories
  822. WHERE id = '$cat_id' AND owner_uid = ".$_SESSION["uid"]);
  823. if (db_num_rows($result) == 1) {
  824. $old_title = db_fetch_result($result, 0, "title");
  825. if ($cat_title != "") {
  826. $result = db_query($this->link, "UPDATE ttrss_feed_categories SET
  827. title = '$cat_title' WHERE id = '$cat_id' AND
  828. owner_uid = ".$_SESSION["uid"]);
  829. print $cat_title;
  830. } else {
  831. print $old_title;
  832. }
  833. } else {
  834. print $_REQUEST["value"];
  835. }
  836. db_query($this->link, "COMMIT");
  837. return;
  838. }
  839. if ($action == "add") {
  840. $feed_cat = db_escape_string(trim($_REQUEST["cat"]));
  841. if (!add_feed_category($this->link, $feed_cat))
  842. print_warning(T_sprintf("Category <b>$%s</b> already exists in the database.", $feed_cat));
  843. }
  844. if ($action == "remove") {
  845. $ids = split(",", db_escape_string($_REQUEST["ids"]));
  846. foreach ($ids as $id) {
  847. remove_feed_category($this->link, $id, $_SESSION["uid"]);
  848. }
  849. }
  850. print "<div dojoType=\"dijit.Toolbar\">
  851. <input dojoType=\"dijit.form.ValidationTextBox\" required=\"1\" name=\"newcat\">
  852. <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedCatEditDlg').addCategory()\">".
  853. __('Create category')."</button></div>";
  854. $result = db_query($this->link, "SELECT title,id FROM ttrss_feed_categories
  855. WHERE owner_uid = ".$_SESSION["uid"]."
  856. ORDER BY title");
  857. if (db_num_rows($result) != 0) {
  858. print "<div class=\"prefFeedCatHolder\">";
  859. print "<table width=\"100%\" class=\"prefFeedCatList\"
  860. cellspacing=\"0\" id=\"prefFeedCatList\">";
  861. $lnum = 0;
  862. while ($line = db_fetch_assoc($result)) {
  863. $class = ($lnum % 2) ? "even" : "odd";
  864. $cat_id = $line["id"];
  865. $this_row_id = "id=\"FCATR-$cat_id\"";
  866. print "<tr class=\"\" $this_row_id>";
  867. $edit_title = htmlspecialchars($line["title"]);
  868. print "<td width='5%' align='center'><input
  869. onclick='toggleSelectRow2(this);' dojoType=\"dijit.form.CheckBox\"
  870. type=\"checkbox\"></td>";
  871. print "<td>";
  872. print "<span dojoType=\"dijit.InlineEditBox\"
  873. width=\"300px\" autoSave=\"false\"
  874. cat-id=\"$cat_id\">" . $edit_title .
  875. "<script type=\"dojo/method\" event=\"onChange\" args=\"item\">
  876. var elem = this;
  877. dojo.xhrPost({
  878. url: 'backend.php',
  879. content: {op: 'pref-feeds', method: 'editCats',
  880. action: 'save',
  881. value: this.value,
  882. cid: this.srcNodeRef.getAttribute('cat-id')},
  883. load: function(response) {
  884. elem.attr('value', response);
  885. updateFeedList();
  886. }
  887. });
  888. </script>
  889. </span>";
  890. print "</td></tr>";
  891. ++$lnum;
  892. }
  893. print "</table>";
  894. print "</div>";
  895. } else {
  896. print "<p>".__('No feed categories defined.')."</p>";
  897. }
  898. print "<div class='dlgButtons'>
  899. <div style='float : left'>
  900. <button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedCatEditDlg').removeSelected()\">".
  901. __('Remove selected categories')."</button>
  902. </div>";
  903. print "<button dojoType=\"dijit.form.Button\" onclick=\"dijit.byId('feedCatEditDlg').hide()\">".
  904. __('Close this window')."</button></div>";
  905. return;
  906. }
  907. function index() {
  908. print "<div dojoType=\"dijit.layout.AccordionContainer\" region=\"center\">";
  909. print "<div id=\"pref-feeds-feeds\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Feeds')."\">";
  910. $result = db_query($this->link, "SELECT COUNT(id) AS num_errors
  911. FROM ttrss_feeds WHERE last_error != '' AND owner_uid = ".$_SESSION["uid"]);
  912. $num_errors = db_fetch_result($result, 0, "num_errors");
  913. if ($num_errors > 0) {
  914. $error_button = "<button dojoType=\"dijit.form.Button\"
  915. onclick=\"showFeedsWithErrors()\" id=\"errorButton\">" .
  916. __("Feeds with errors") . "</button>";
  917. }
  918. if (DB_TYPE == "pgsql") {
  919. $interval_qpart = "NOW() - INTERVAL '3 months'";
  920. } else {
  921. $interval_qpart = "DATE_SUB(NOW(), INTERVAL 3 MONTH)";
  922. }
  923. $result = db_query($this->link, "SELECT COUNT(*) AS num_inactive FROM ttrss_feeds WHERE
  924. (SELECT MAX(updated) FROM ttrss_entries, ttrss_user_entries WHERE
  925. ttrss_entries.id = ref_id AND
  926. ttrss_user_entries.feed_id = ttrss_feeds.id) < $interval_qpart AND
  927. ttrss_feeds.owner_uid = ".$_SESSION["uid"]);
  928. $num_inactive = db_fetch_result($result, 0, "num_inactive");
  929. if ($num_inactive > 0) {
  930. $inactive_button = "<button dojoType=\"dijit.form.Button\"
  931. onclick=\"showInactiveFeeds()\">" .
  932. __("Inactive feeds") . "</button>";
  933. }
  934. $feed_search = db_escape_string($_REQUEST["search"]);
  935. if (array_key_exists("search", $_REQUEST)) {
  936. $_SESSION["prefs_feed_search"] = $feed_search;
  937. } else {
  938. $feed_search = $_SESSION["prefs_feed_search"];
  939. }
  940. print '<div dojoType="dijit.layout.BorderContainer" gutters="false">';
  941. print "<div region='top' dojoType=\"dijit.Toolbar\">"; #toolbar
  942. print "<div style='float : right; padding-right : 4px;'>
  943. <input dojoType=\"dijit.form.TextBox\" id=\"feed_search\" size=\"20\" type=\"search\"
  944. value=\"$feed_search\">
  945. <button dojoType=\"dijit.form.Button\" onclick=\"updateFeedList()\">".
  946. __('Search')."</button>
  947. </div>";
  948. print "<div dojoType=\"dijit.form.DropDownButton\">".
  949. "<span>" . __('Select')."</span>";
  950. print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
  951. print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(true)\"
  952. dojoType=\"dijit.MenuItem\">".__('All')."</div>";
  953. print "<div onclick=\"dijit.byId('feedTree').model.setAllChecked(false)\"
  954. dojoType=\"dijit.MenuItem\">".__('None')."</div>";
  955. print "</div></div>";
  956. print "<div dojoType=\"dijit.form.DropDownButton\">".
  957. "<span>" . __('Feeds')."</span>";
  958. print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
  959. print "<div onclick=\"quickAddFeed()\"
  960. dojoType=\"dijit.MenuItem\">".__('Subscribe to feed')."</div>";
  961. print "<div onclick=\"editSelectedFeed()\"
  962. dojoType=\"dijit.MenuItem\">".__('Edit selected feeds')."</div>";
  963. print "<div onclick=\"resetFeedOrder()\"
  964. dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
  965. print "</div></div>";
  966. if (get_pref($this->link, 'ENABLE_FEED_CATS')) {
  967. print "<div dojoType=\"dijit.form.DropDownButton\">".
  968. "<span>" . __('Categories')."</span>";
  969. print "<div dojoType=\"dijit.Menu\" style=\"display: none;\">";
  970. print "<div onclick=\"editFeedCats()\"
  971. dojoType=\"dijit.MenuItem\">".__('Edit categories')."</div>";
  972. print "<div onclick=\"resetCatOrder()\"
  973. dojoType=\"dijit.MenuItem\">".__('Reset sort order')."</div>";
  974. print "</div></div>";
  975. }
  976. print $error_button;
  977. print $inactive_button;
  978. print "<button dojoType=\"dijit.form.Button\" onclick=\"removeSelectedFeeds()\">"
  979. .__('Unsubscribe')."</button dojoType=\"dijit.form.Button\"> ";
  980. if (defined('_ENABLE_FEED_DEBUGGING')) {
  981. print "<select id=\"feedActionChooser\" onchange=\"feedActionChange()\">
  982. <option value=\"facDefault\" selected>".__('More actions...')."</option>";
  983. if (FORCE_ARTICLE_PURGE == 0) {
  984. print
  985. "<option value=\"facPurge\">".__('Manual purge')."</option>";
  986. }
  987. print "
  988. <option value=\"facClear\">".__('Clear feed data')."</option>
  989. <option value=\"facRescore\">".__('Rescore articles')."</option>";
  990. print "</select>";
  991. }
  992. print "</div>"; # toolbar
  993. //print '</div>';
  994. print '<div dojoType="dijit.layout.ContentPane" region="center">';
  995. print "<div id=\"feedlistLoading\">
  996. <img src='images/indicator_tiny.gif'>".
  997. __("Loading, please wait...")."</div>";
  998. print "<div dojoType=\"fox.PrefFeedStore\" jsId=\"feedStore\"
  999. url=\"backend.php?op=pref-feeds&method=getfeedtree\">
  1000. </div>
  1001. <div dojoType=\"lib.CheckBoxStoreModel\" jsId=\"feedModel\" store=\"feedStore\"
  1002. query=\"{id:'root'}\" rootId=\"root\" rootLabel=\"Feeds\"
  1003. childrenAttrs=\"items\" checkboxStrict=\"false\" checkboxAll=\"false\">
  1004. </div>
  1005. <div dojoType=\"fox.PrefFeedTree\" id=\"feedTree\"
  1006. dndController=\"dijit.tree.dndSource\"
  1007. betweenThreshold=\"5\"
  1008. model=\"feedModel\" openOnClick=\"false\">
  1009. <script type=\"dojo/method\" event=\"onClick\" args=\"item\">
  1010. var id = String(item.id);
  1011. var bare_id = id.substr(id.indexOf(':')+1);
  1012. if (id.match('FEED:')) {
  1013. editFeed(bare_id);
  1014. } else if (id.match('CAT:')) {
  1015. editCat(bare_id, item);
  1016. }
  1017. </script>
  1018. <script type=\"dojo/method\" event=\"onLoad\" args=\"item\">
  1019. Element.hide(\"feedlistLoading\");
  1020. </script>
  1021. </div>";
  1022. print "<div dojoType=\"dijit.Tooltip\" connectId=\"feedTree\" position=\"below\">
  1023. ".__('<b>Hint:</b> you can drag feeds and categories around.')."
  1024. </div>";
  1025. print '</div>';
  1026. print '</div>';
  1027. print "</div>"; # feeds pane
  1028. print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('OPML')."\">";
  1029. print "<p>" . __("Using OPML you can export and import your feeds, filters, labels and Tiny Tiny RSS settings.") . " ";
  1030. print "<span class=\"insensitive\">" . __("Note: Only main settings profile can be migrated using OPML.") . "</span>";
  1031. print "</p>";
  1032. print "<h3>" . __("Import") . "</h3>";
  1033. print "<br/><iframe id=\"upload_iframe\"
  1034. name=\"upload_iframe\" onload=\"opmlImportComplete(this)\"
  1035. style=\"width: 400px; height: 100px; display: none;\"></iframe>";
  1036. print "<form name=\"opml_form\" style='display : block' target=\"upload_iframe\"
  1037. enctype=\"multipart/form-data\" method=\"POST\"
  1038. action=\"backend.php\">
  1039. <input id=\"opml_file\" name=\"opml_file\" type=\"file\">&nbsp;
  1040. <input type=\"hidden\" name=\"op\" value=\"dlg\">
  1041. <input type=\"hidden\" name=\"method\" value=\"importOpml\">
  1042. <button dojoType=\"dijit.form.Button\" onclick=\"return opmlImport();\" type=\"submit\">" .
  1043. __('Import') . "</button>";
  1044. print "<h3>" . __("Export") . "</h3>";
  1045. print "<p>" . __('Filename:') .
  1046. " <input type=\"text\" id=\"filename\" value=\"TinyTinyRSS.opml\" />&nbsp;" .
  1047. __('Include settings') . "<input type=\"checkbox\" id=\"settings\" CHECKED />" .
  1048. "<button dojoType=\"dijit.form.Button\"
  1049. onclick=\"gotoExportOpml(document.opml_form.filename.value, document.opml_form.settings.checked)\" >" .
  1050. __('Export') . "</button></p></form>";
  1051. print "<h3>" . __("Publish") . "</h3>";
  1052. print "<p>".__('Your OPML can be published publicly and can be subscribed by anyone who knows the URL below.') . " ";
  1053. print "<span class=\"insensitive\">" . __("Note: Published OPML does not include your Tiny Tiny RSS settings, feeds that require authentication or feeds hidden from Popular feeds.") . "</span>" . "</p>";
  1054. print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('pubOPMLUrl')\">".
  1055. __('Display URL')."</button> ";
  1056. print "</div>"; # pane
  1057. if (strpos($_SERVER['HTTP_USER_AGENT'], "Firefox") !== false) {
  1058. print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Firefox integration')."\">";
  1059. print "<p>" . __('This Tiny Tiny RSS site can be used as a Firefox Feed Reader by clicking the link below.') . "</p>";
  1060. print "<p>";
  1061. print "<button onclick='window.navigator.registerContentHandler(" .
  1062. "\"application/vnd.mozilla.maybe.feed\", " .
  1063. "\"" . add_feed_url() . "\", " . " \"Tiny Tiny RSS\")'>" .
  1064. __('Click here to register this site as a feed reader.') .
  1065. "</button>";
  1066. print "</p>";
  1067. print "</div>"; # pane
  1068. }
  1069. print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Subscribing using bookmarklet')."\">";
  1070. 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>";
  1071. $bm_subscribe_url = str_replace('%s', '', add_feed_url());
  1072. $confirm_str = __('Subscribe to %s in Tiny Tiny RSS?');
  1073. $bm_url = htmlspecialchars("javascript:{if(confirm('$confirm_str'.replace('%s',window.location.href)))window.location.href='$bm_subscribe_url'+window.location.href}");
  1074. print "<a href=\"$bm_url\" class='bookmarklet'>" . __('Subscribe in Tiny Tiny RSS'). "</a>";
  1075. print "</div>"; #pane
  1076. print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Published & shared articles and generated feeds')."\">";
  1077. print "<h3>" . __("Published articles and generated feeds") . "</h3>";
  1078. print "<p>".__('Published articles are exported as a public RSS feed and can be subscribed by anyone who knows the URL specified below.')."</p>";
  1079. $rss_url = '-2::' . htmlspecialchars(get_self_url_prefix() .
  1080. "/public.php?op=rss&id=-2&view-mode=all_articles");;
  1081. print "<button dojoType=\"dijit.form.Button\" onclick=\"return displayDlg('generatedFeed', '$rss_url')\">".
  1082. __('Display URL')."</button> ";
  1083. print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearFeedAccessKeys()\">".
  1084. __('Clear all generated URLs')."</button> ";
  1085. print "<h3>" . __("Articles shared by URL") . "</h3>";
  1086. print "<p>" . __("You can disable all articles shared by unique URLs here.") . "</p>";
  1087. print "<button dojoType=\"dijit.form.Button\" onclick=\"return clearArticleAccessKeys()\">".
  1088. __('Unshare all articles')."</button> ";
  1089. print "</div>"; #pane
  1090. if (defined('CONSUMER_KEY') && CONSUMER_KEY != '') {
  1091. print "<div id=\"pref-feeds-twitter\" dojoType=\"dijit.layout.AccordionPane\" title=\"".__('Twitter')."\">";
  1092. $result = db_query($this->link, "SELECT COUNT(*) AS cid FROM ttrss_users
  1093. WHERE twitter_oauth IS NOT NULL AND twitter_oauth != '' AND
  1094. id = " . $_SESSION['uid']);
  1095. $is_registered = db_fetch_result($result, 0, "cid") != 0;
  1096. if (!$is_registered) {
  1097. print_notice(__('Before you can update your Twitter feeds, you must register this instance of Tiny Tiny RSS with Twitter.com.'));
  1098. } else {
  1099. print_notice(__('You have been successfully registered with Twitter.com and should be able to access your Twitter feeds.'));
  1100. }
  1101. print "<button dojoType=\"dijit.form.Button\" onclick=\"window.location.href = 'twitter.php?op=register'\">".
  1102. __("Register with Twitter.com")."</button>";
  1103. print " ";
  1104. print "<button dojoType=\"dijit.form.Button\"
  1105. onclick=\"return clearTwitterCredentials()\">".
  1106. __("Clear stored credentials")."</button>";
  1107. print "</div>"; # pane
  1108. }
  1109. print "</div>"; #container
  1110. }
  1111. }
  1112. ?>