if (file_exists($componentdir)) { require_once "{$componentdir}/rsslib.php"; $functionname = $plugin . '_rss_get_feed'; if (function_exists($functionname)) { // $pathname will be null if there was a problem (eg user doesn't have the necessary capabilities) // NOTE:the component providing the feed must do its own capability checks and security try { $pathname = $functionname($context, $args); } catch (Exception $e) { rss_error('rsserror'); } } } // Check that file exists if (empty($pathname) || !file_exists($pathname)) { rss_error(); } // Send the RSS file to the user! send_file($pathname, 'rss.xml', 3600); // Cached by browsers for 1 hour /** * Sends an error formatted as an rss file and then exits * * @package core_rss * @category rss * * @param string $error the error type, default is rsserror * @param string $filename the name of the file to create (NOT USED) * @param int $lifetime UNSURE (NOT USED) * @uses exit */
function tags() { // Fix for #16: Admin (et al.) should not rely on l10n labels for actions: // Look for a meta-action first, which should be the (untranslated) *name* of // the (translated) action constant. // Fixme: should replace 'action's with a constant if (array_key_exists(CST_ADMIN_METAACTION, $_REQUEST)) { $__action__ = $_REQUEST[CST_ADMIN_METAACTION]; } elseif (array_key_exists('action', $_REQUEST)) { $__action__ = $_REQUEST['action']; } else { $__action__ = ""; } if (isset($_REQUEST['id'])) { $tid = sanitize($_REQUEST['id'], RSS_SANITIZER_NUMERIC); } $ret__ = CST_ADMIN_DOMAIN_TAGS; switch ($__action__) { case CST_ADMIN_EDIT_ACTION: tag_edit($tid); $ret__ = CST_ADMIN_DOMAIN_NONE; break; case CST_ADMIN_DELETE_ACTION: if (array_key_exists(CST_ADMIN_CONFIRMED, $_POST) && $_POST[CST_ADMIN_CONFIRMED] == __('Yes')) { $sql = "delete from " . getTable("tag") . " where id={$tid}"; rss_query($sql); $sql = "delete from " . getTable("metatag") . " where tid={$tid}"; rss_query($sql); rss_invalidate_cache(); } elseif (array_key_exists(CST_ADMIN_CONFIRMED, $_REQUEST) && $_REQUEST[CST_ADMIN_CONFIRMED] == __('No')) { // nop; } elseif (array_key_exists('me_delete', $_REQUEST)) { if (array_key_exists('me_do_delete', $_REQUEST) && "1" == $_REQUEST['me_do_delete']) { $ids = array(); foreach ($_REQUEST as $key => $val) { if (preg_match('/^tcb([0-9]+)$/', $key, $match)) { if (($id = (int) $_REQUEST[$key]) > 0) { $ids[] = $id; } } } if (count($ids) > 0) { $sql = "delete from " . getTable("tag") . " where id in (" . implode(',', $ids) . ")"; rss_query($sql); $sql = "delete from " . getTable("metatag") . " where tid in (" . implode(',', $ids) . ")"; rss_query($sql); rss_invalidate_cache(); } } } else { list($tname) = rss_fetch_row(rss_query("select tag from " . getTable("tag") . " where id = {$tid}")); echo "<form class=\"box\" method=\"post\" action=\"" . $_SERVER['PHP_SELF'] . "\">\n" . "<p class=\"error\">"; printf(__("Are you sure you wish to delete '%s'?"), $tname); echo "</p>\n" . "<p><input type=\"submit\" name=\"" . CST_ADMIN_CONFIRMED . "\" value=\"" . __('No') . "\"/>\n" . "<input type=\"submit\" name=\"" . CST_ADMIN_CONFIRMED . "\" value=\"" . __('Yes') . "\"/>\n" . "<input type=\"hidden\" name=\"id\" value=\"{$tid}\"/>\n" . "<input type=\"hidden\" name=\"" . CST_ADMIN_DOMAIN . "\" value=\"" . CST_ADMIN_DOMAIN_TAGS . "\"/>\n" . "<input type=\"hidden\" name=\"action\" value=\"" . CST_ADMIN_DELETE_ACTION . "\"/>\n" . "</p>\n</form>\n"; $ret__ = CST_ADMIN_DOMAIN_NONE; } break; case CST_ADMIN_SUBMIT_EDIT: // TBD $new_label = preg_replace(ALLOWED_TAGS_REGEXP, '', $_REQUEST['t_name']); // also replace whitespaces $new_label = str_replace(' ', '', $new_label); if (is_numeric($tid) && strlen($new_label) > 0) { $res = rss_query("select count(*) as cnt from " . getTable("tag") . " where binary tag='" . rss_real_escape_string($new_label) . "'"); list($cnt) = rss_fetch_row($res); if ($cnt > 0) { rss_error(sprintf(__("You can't rename this item '%s' because such an item already exists."), $new_label), RSS_ERROR_ERROR, true); break; } rss_query("update " . getTable("tag") . " set tag='" . rss_real_escape_string($new_label) . "' where id={$tid}"); rss_invalidate_cache(); } break; default: break; } echo "<script type=\"text/javascript\">\n" . "//<!--\n" . "function cbtoggle() {\n" . "var c=document.getElementById('mastercb').checked;\n" . "var cs=document.getElementById('tagtable').getElementsByTagName('input');\n" . "for(i=0;i<cs.length;i++) {\n" . "if (cs[i].type == 'checkbox') cs[i].checked = c;\n" . "}\n" . "}\n" . "</script>\n"; echo "<form method=\"post\" action=\"" . $_SERVER['PHP_SELF'] . "\">\n" . "<h2 class=\"trigger\">" . __('Tags') . "</h2>\n" . "<div id=\"admin_tags\" class=\"trigger\">" . "<table id=\"tagtable\">\n" . "<tr>\n" . "\t<th><input type=\"checkbox\" id=\"mastercb\" onclick=\"cbtoggle();\" /></th>\n" . "\t<th class=\"cntr\">" . __('Tags') . "</th>\n" . "\t<th>" . __('Action') . "</th>\n" . "</tr>\n"; $sql = sprintf("select id, tag from %s t left join %s m on (t.id = m.tid) where m.ttype = 'item'", getTable("tag"), getTable("metatag")); $res = rss_query($sql); $cntr = 0; while (list($id, $tag) = rss_fetch_row($res)) { $class_ = $cntr++ % 2 == 0 ? "even" : "odd"; echo "<tr class=\"{$class_}\">\n" . "\t<td><input type=\"checkbox\" name=\"tcb{$id}\" value=\"{$id}\" id=\"scb_{$id}\" /></td>\n" . "\t<td><label for=\"scb_{$id}\">" . htmlspecialchars($tag) . "</label></td>\n" . "\t<td><a href=\"" . $_SERVER['PHP_SELF'] . "?" . CST_ADMIN_DOMAIN . "=" . CST_ADMIN_DOMAIN_TAGS . "&action=" . CST_ADMIN_EDIT_ACTION . "&id={$id}\">" . __('edit') . "</a>\n" . "|<a href=\"" . $_SERVER['PHP_SELF'] . "?" . CST_ADMIN_DOMAIN . "=" . CST_ADMIN_DOMAIN_TAGS . "&action=" . CST_ADMIN_DELETE_ACTION . "&id={$id}\">" . __('delete') . "</a>\n" . "|<a href=\"" . getPath('tag/' . htmlspecialchars($tag)) . "\">" . __('view') . "</a>\n" . "</td>\n" . "</tr>\n"; } echo "</table>\n"; echo "<fieldset>\n" . "<legend>" . __('Selected') . "...</legend>\n" . "<p>\n" . "<input type=\"submit\" id=\"me_delete\" name=\"me_delete\" value=\"" . __('Delete') . "\" />\n" . "<input type=\"checkbox\" name=\"me_do_delete\" id=\"me_do_delete\" value=\"1\" />\n" . "<label for=\"me_do_delete\">" . __("I'm sure!") . "</label>\n" . "<input type=\"hidden\" name=\"action\" value=\"" . CST_ADMIN_DELETE_ACTION . "\" />\n" . "<input type=\"hidden\" name=\"" . CST_ADMIN_DOMAIN . "\" value=\"" . CST_ADMIN_DOMAIN_TAGS . "\" />\n" . "</fieldset>\n" . "</form>\n" . "</div>\n"; }
function theme_getThemesUpdate(&$themes) { $themesxml = array(); global $themesxml; $xml = getUrl('http://themes.gregarius.net/api.php'); $xml = str_replace("\r", '', $xml); $xml = str_replace("\n", '', $xml); $xp = xml_parser_create() or rss_error("couldn't create parser"); xml_set_element_handler($xp, 'themes_xml_startElement', 'themes_xml_endElement') or rss_error("couldnt set XML handlers"); xml_parse($xp, $xml, true) or rss_error("failed parsing xml"); xml_parser_free($xp) or rss_error("failed freeing the parser"); if (is_array($themesxml)) { foreach ($themesxml as $theme => $data) { list($tversion, $turl) = $data; if (isset($themes[$theme]) && $themes[$theme]['version'] < $tversion) { $themes[$theme]['updateVersion'] = $tversion; $themes[$theme]['updateUrl'] = $turl; } } } }
function xml_error($error_msg) { rss_error($error_msg, RSS_ERROR_ERROR, true); echo "\n</div>\n</body></html>\n"; die; }
/** * Performs all the feed-related admin actions */ function channel_admin() { // Fix for #16: Admin (et al.) should not rely on l10n labels for actions: // Look for a meta-action first, which should be the (untranslated) *name* of // the (translated) action constant. // Fixme: should replace 'action's with a constant if (array_key_exists(CST_ADMIN_METAACTION, $_REQUEST)) { $__action__ = $_REQUEST[CST_ADMIN_METAACTION]; } elseif (array_key_exists('action', $_REQUEST)) { $__action__ = $_REQUEST['action']; } else { $__action__ = ""; } $ret__ = CST_ADMIN_DOMAIN_NONE; switch ($__action__) { case __('Add'): case 'ACT_ADMIN_ADD': case 'Add': $label = trim(sanitize($_REQUEST['new_channel'], RSS_SANITIZER_URL)); $fid = trim(sanitize($_REQUEST['add_channel_to_folder'], RSS_SANITIZER_NUMERIC)); list($flabel) = rss_fetch_row(rss_query("select name from " . getTable('folders') . " where id={$fid}")); // handle "feed:" urls if (substr($label, 0, 5) == 'feed:') { if (substr($label, 0, 11) == "feed://http") { $label = substr($label, 5); } else { // handle feed://example.com/rss.xml urls $label = "http:" . substr($label, 5); } } if ($label != 'http://' && substr($label, 0, 4) == "http") { $tags = @$_REQUEST['channel_tags']; $ret = add_channel($label, $fid, null, null, $tags); //var_dump($ret); if (is_array($ret) && $ret[0] > -1) { update($ret[0]); rss_invalidate_cache(); // feedback $newCid = $ret[0]; rss_error(sprintf(__('Adding %s to %s... '), htmlentities($label), "/{$flabel}") . __('OK') . " [<a href=\"" . getPath() . "admin/index.php?domain=" . CST_ADMIN_DOMAIN_CHANNEL . "&action=edit&cid={$newCid}\">" . __('edit') . "</a>]", RSS_ERROR_ERROR, true); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; } elseif (is_array($ret) && $ret[0] > -2) { // okay, something went wrong, maybe thats a html url after all? // let's try and see if we can extract some feeds $feeds = extractFeeds($label); if (!is_array($feeds) || sizeof($feeds) == 0) { rss_error($ret[1], RSS_ERROR_ERROR, true); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; } else { //one single feed in the html doc, add that if (is_array($feeds) && sizeof($feeds) == 1 && array_key_exists('href', $feeds[0])) { $ret = add_channel($feeds[0]['href'], $fid); if (is_array($ret) && $ret[0] > -1) { update($ret[0]); rss_invalidate_cache(); // feedback $newCid = $ret[0]; rss_error(sprintf(__('Adding %s to %s... '), htmlentities($label), "/{$flabel}") . __('OK') . " [<a href=\"" . getPath() . "admin/index.php?domain=" . CST_ADMIN_DOMAIN_CHANNEL . "&action=edit&cid={$newCid}\">" . __('edit') . "</a>]", RSS_ERROR_ERROR, true); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; } else { // failure rss_error($ret[1], RSS_ERROR_ERROR, true); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; } } else { // multiple feeds in the channel echo "<form method=\"post\" action=\"" . $_SERVER['PHP_SELF'] . "\">\n" . "<p>" . sprintf(__('The following feeds were found in <a href="%s">%s</a>, which one would you like to subscribe?'), $label, $label) . "</p>\n"; $cnt = 0; while (list($id, $feedarr) = each($feeds)) { // we need an URL if (!array_key_exists('href', $feedarr)) { continue; } else { $href = $feedarr['href']; } if (array_key_exists('type', $feedarr)) { $typeLbl = " [<a href=\"{$href}\">" . $feedarr['type'] . "</a>]"; } $cnt++; if (array_key_exists('title', $feedarr)) { $lbl = $feedarr['title']; } elseif (array_key_exists('type', $feedarr)) { $lbl = $feedarr['type']; $typeLbl = ""; } elseif (array_key_exists('href', $feedarr)) { $lbl = $feedarr['href']; } else { $lbl = "Resource {$cnt}"; } echo "<p>\n\t<input class=\"indent\" type=\"radio\" id=\"fd_{$cnt}\" name=\"new_channel\" " . " value=\"{$href}\" />\n" . "\t<label for=\"fd_{$cnt}\">{$lbl} {$typeLbl}</label>\n" . "</p>\n"; } echo "<p><input type=\"hidden\" name=\"add_channel_to_folder\" value=\"{$fid}\" />\n" . "<input type=\"hidden\" name=\"" . CST_ADMIN_DOMAIN . "\" value=\"" . CST_ADMIN_DOMAIN_CHANNEL . "\" />\n" . "<input type=\"hidden\" name=\"" . CST_ADMIN_METAACTION . "\" value=\"ACT_ADMIN_ADD\" />\n" . "<input type=\"submit\" class=\"indent\" name=\"action\" value=\"" . __('Add') . "\" />\n" . "</p>\n</form>\n\n"; } } } elseif (is_array($ret)) { rss_error($ret[1], RSS_ERROR_ERROR, true); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; } else { rss_error(sprintf(__("I'm sorry, I don't think I can handle this URL: '%s'"), $label), RSS_ERROR_ERROR, true); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; } } else { rss_error(sprintf(__("I'm sorry, I don't think I can handle this URL: '%s'"), $label), RSS_ERROR_ERROR, true); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; } break; case CST_ADMIN_EDIT_ACTION: $id = sanitize($_REQUEST['cid'], RSS_SANITIZER_NUMERIC); channel_edit_form($id); break; case CST_ADMIN_DELETE_ACTION: $id = sanitize($_REQUEST['cid'], RSS_SANITIZER_NUMERIC); if (array_key_exists(CST_ADMIN_CONFIRMED, $_POST) && $_POST[CST_ADMIN_CONFIRMED] == __('Yes')) { $rs = rss_query("select distinct id from " . getTable("item") . " where cid={$id}"); $ids = array(); while (list($did) = rss_fetch_row($rs)) { $ids[] = $did; } if (count($ids)) { $sqldel = "delete from " . getTable('metatag') . " where fid in (" . implode(",", $ids) . ")"; rss_query($sqldel); } $sql = "delete from " . getTable("item") . " where cid={$id}"; rss_query($sql); $sql = "delete from " . getTable("channels") . " where id={$id}"; rss_query($sql); // Delete properties deleteProperty($id, 'rss.input.allowupdates'); deleteProperty($id, 'rss.config.refreshinterval'); deleteProperty($id, 'rss.config.refreshdate'); // Invalidate cache rss_invalidate_cache(); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; } elseif (array_key_exists(CST_ADMIN_CONFIRMED, $_REQUEST) && $_REQUEST[CST_ADMIN_CONFIRMED] == __('No')) { $ret__ = CST_ADMIN_DOMAIN_CHANNEL; } else { list($cname) = rss_fetch_row(rss_query("select title from " . getTable("channels") . " where id = {$id}")); echo "<form class=\"box\" method=\"post\" action=\"" . $_SERVER['PHP_SELF'] . "\">\n" . "<p class=\"error\">"; printf(__("Are you sure you wish to delete '%s'?"), $cname); echo "</p>\n" . "<p><input type=\"submit\" name=\"" . CST_ADMIN_CONFIRMED . "\" value=\"" . __('No') . "\" />\n" . "<input type=\"submit\" name=\"" . CST_ADMIN_CONFIRMED . "\" value=\"" . __('Yes') . "\" />\n" . "<input type=\"hidden\" name=\"cid\" value=\"{$id}\" />\n" . "<input type=\"hidden\" name=\"" . CST_ADMIN_DOMAIN . "\" value=\"" . CST_ADMIN_DOMAIN_CHANNEL . "\" />\n" . "<input type=\"hidden\" name=\"action\" value=\"" . CST_ADMIN_DELETE_ACTION . "\" />\n" . "</p>\n</form>\n"; } break; case __('Import'): case 'ACT_ADMIN_IMPORT': if (array_key_exists('opml', $_POST) && strlen(trim($_POST['opml'])) > 7) { $url = trim(sanitize($_POST['opml'], RSS_SANITIZER_NO_SPACES)); } elseif (array_key_exists('opmlfile', $_FILES) && $_FILES['opmlfile']['tmp_name']) { if (is_uploaded_file($_FILES['opmlfile']['tmp_name'])) { $url = $_FILES['opmlfile']['tmp_name']; } else { $url = ''; } } else { $url = ''; } if (!$url) { $ret__ = CST_ADMIN_DOMAIN_OPML; break; } if (array_key_exists('opml_import_option', $_POST)) { $import_opt = $_POST['opml_import_option']; } else { $import_opt = CST_ADMIN_OPML_IMPORT_MERGE; } if ($import_opt == CST_ADMIN_OPML_IMPORT_FOLDER) { $opmlfid = sanitize($_POST['opml_import_to_folder'], RSS_SANITIZER_NUMERIC); } else { $opmlfid = getRootFolder(); } @set_time_limit(0); @ini_set('max_execution_time', 300); // Parse into and OPML object $opml = getOpml($url); if (sizeof($opml) > 0) { if ($import_opt == CST_ADMIN_OPML_IMPORT_WIPE) { rss_query("delete from " . getTable("metatag")); rss_query("delete from " . getTable("channels")); rss_query("delete from " . getTable("item")); rss_query("delete from " . getTable("folders") . " where id > 0"); } if ($import_opt == CST_ADMIN_OPML_IMPORT_FOLDER) { $fid = $opmlfid; list($prev_folder) = rss_fetch_row(rss_query("select name from " . getTable('folders') . " where id= {$opmlfid} ")); } else { $prev_folder = __('Root'); $fid = 0; } echo "<div class=\"frame\" style=\"background-color:#eee;font-size:small\"><ul>\n"; while (list($folder, $items) = each($opml)) { if ($folder != $prev_folder && $import_opt != CST_ADMIN_OPML_IMPORT_FOLDER) { $fid = create_folder(strip_tags($folder), false); $prev_folder = strip_tags($folder); } for ($i = 0; $i < sizeof($opml[$folder]); $i++) { $url_ = isset($opml[$folder][$i]['XMLURL']) ? trim($opml[$folder][$i]['XMLURL']) : null; $title_ = isset($opml[$folder][$i]['TEXT']) ? trim($opml[$folder][$i]['TEXT']) : null; // support for title attribute (optional) $title_ = isset($opml[$folder][$i]['TITLE']) ? trim($opml[$folder][$i]['TITLE']) : $title_; $descr_ = isset($opml[$folder][$i]['DESCRIPTION']) ? trim($opml[$folder][$i]['DESCRIPTION']) : null; $cats_ = isset($opml[$folder][$i]['CATEGORY']) ? trim($opml[$folder][$i]['CATEGORY']) : ""; $t__ = strip_tags($title_); $d__ = strip_tags($descr_); $f__ = strip_tags($prev_folder); $u__ = sanitize($url_, RSS_SANITIZER_URL); $c__ = $cats_; //preg_replace(ALLOWED_TAGS_REGEXP,' ',$cats_); if ($u__) { echo "<li><p>" . sprintf(__('Adding %s to %s... '), $t__, $f__); flush(); list($retcde, $retmsg) = add_channel($u__, $fid, $t__, $d__); if ($retcde && count($c__)) { __exp__submitTag($retcde, utf8_encode($c__), "'channel'"); } echo ($retcde < 0 ? $retmsg : " OK") . "</p></li>\n"; flush(); } } } echo "</ul>\n<p><b>" . __('Updating') . "...</b></p>\n"; echo "</div>\n"; flush(); //update all the feeds update(""); rss_invalidate_cache(); } $ret__ = CST_ADMIN_DOMAIN_CHANNEL; break; case CST_ADMIN_SUBMIT_EDIT: $cid = sanitize($_POST['cid'], RSS_SANITIZER_NUMERIC); rss_plugin_hook('rss.plugins.admin.feed.properties.submit', null); // TBD $title = strip_tags(rss_real_escape_string(real_strip_slashes($_POST['c_name']))); $url = rss_real_escape_string($_POST['c_url']); $siteurl = rss_real_escape_string($_POST['c_siteurl']); $parent = rss_real_escape_string($_POST['c_parent']); $descr = strip_tags(rss_real_escape_string(real_strip_slashes($_POST['c_descr']))); $icon = rss_real_escape_string($_POST['c_icon']); $priv = array_key_exists('c_private', $_POST) && $_POST['c_private'] == '1'; $tags = rss_real_escape_string($_POST['c_tags']); $old_priv = $_POST['old_priv'] == '1'; // Feed Properties $prop_rss_input_allowupdates = rss_real_escape_string($_POST['prop_rss_input_allowupdates']); if ($prop_rss_input_allowupdates == 'default') { deleteProperty($cid, 'rss.input.allowupdates'); } else { setProperty($cid, 'rss.input.allowupdates', 'feed', $prop_rss_input_allowupdates == 1); } deleteProperty($cid, 'rss.config.refreshinterval'); $rss_config_refreshinterval = rss_real_escape_string($_POST['rss_config_refreshinterval']); if ($rss_config_refreshinterval > 60) { setProperty($cid, 'rss.config.refreshinterval', 'feed', $rss_config_refreshinterval); } if ($priv != $old_priv) { $mode = ", mode = mode "; if ($priv) { $mode .= " | " . RSS_MODE_PRIVATE_STATE; rss_query('update ' . getTable('item') . " set unread = unread | " . RSS_MODE_PRIVATE_STATE . " where cid={$cid}"); } else { $mode .= " & " . SET_MODE_PUBLIC_STATE; rss_query('update ' . getTable('item') . " set unread = unread & " . SET_MODE_PUBLIC_STATE . " where cid={$cid}"); } rss_invalidate_cache(); } else { $mode = ""; } $del = array_key_exists('c_deleted', $_POST) && $_POST['c_deleted'] == '1'; $old_del = $_POST['old_del'] == '1'; if ($del != $old_del) { if ($mode == "") { $mode = ", mode = mode "; } if ($del) { $mode .= " | " . RSS_MODE_DELETED_STATE; } else { $mode .= " & " . SET_MODE_AVAILABLE_STATE; } } if ($url == '' || substr($url, 0, 4) != "http") { rss_error(sprintf(__("I'm sorry, I don't think I can handle this URL: '%s'"), $url), RSS_ERROR_ERROR, true); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; break; } if ($icon && cacheFavicon($icon)) { $icon = 'blob:' . $icon; } $sql = "update " . getTable("channels") . " set title='{$title}', url='{$url}', siteurl='{$siteurl}', " . " parent={$parent}, descr='{$descr}', icon='{$icon}', " . " daterefreshed = 1, etag = '' " . " {$mode} where id={$cid}"; rss_query($sql); __exp__submitTag($cid, utf8_decode($tags), "'channel'"); rss_invalidate_cache(); $ret__ = CST_ADMIN_DOMAIN_CHANNEL; break; case CST_ADMIN_MOVE_UP_ACTION: case CST_ADMIN_MOVE_DOWN_ACTION: $id = sanitize($_REQUEST['cid'], RSS_SANITIZER_NUMERIC); $res = rss_query("select parent,position from " . getTable("channels") . " where id={$id}"); list($parent, $position) = rss_fetch_row($res); if ($_REQUEST['action'] == CST_ADMIN_MOVE_UP_ACTION) { $res = rss_query("select id, position from " . getTable("channels") . " where parent={$parent} and id != {$id} and position<{$position} " . " order by abs({$position}-position) limit 1"); } else { $res = rss_query("select id, position from " . getTable("channels") . " where parent={$parent} and id != {$id} and position>{$position} " . " order by abs({$position}-position) limit 1"); } list($switch_with_id, $switch_with_position) = rss_fetch_row($res); //If this is already the first or last item in a folder we won't get any results from the query above if ($switch_with_position != "") { // right, lets! if ($switch_with_position != $position) { rss_query("update " . getTable("channels") . " set position = {$switch_with_position} where id={$id}"); rss_query("update " . getTable("channels") . " set position = {$position} where id={$switch_with_id}"); rss_invalidate_cache(); } } $ret__ = CST_ADMIN_DOMAIN_CHANNEL; break; case CST_ADMIN_MULTIEDIT: $ret__ = CST_ADMIN_DOMAIN_CHANNEL; $ids = array(); foreach ($_REQUEST as $key => $val) { if (preg_match('/^fcb([0-9]+)$/', $key, $match)) { if (($id = (int) $_REQUEST[$key]) > 0) { $ids[] = $id; } } } // no feed selected? if (count($ids) == 0) { break; } else { $sqlids = " (" . implode(',', $ids) . ")"; } // MOVE TO FOLDER if (array_key_exists('me_move_to_folder', $_REQUEST)) { $fid = sanitize($_REQUEST['me_folder'], RSS_SANITIZER_NUMERIC); $sql = "update " . getTable('channels') . " set parent={$fid} where id in {$sqlids}"; rss_query($sql); /// STATE } elseif (array_key_exists('me_state', $_REQUEST)) { $deprecated = array_key_exists('me_deprecated', $_REQUEST) ? $_REQUEST['me_deprecated'] : false; $private = array_key_exists('me_private', $_REQUEST) ? $_REQUEST['me_private'] : false; if ($private) { rss_query('update ' . getTable('channels') . " set mode = mode | " . RSS_MODE_PRIVATE_STATE . " where id in {$sqlids}"); rss_query('update ' . getTable('item') . " set unread = unread | " . RSS_MODE_PRIVATE_STATE . " where cid in {$sqlids}"); } else { rss_query('update ' . getTable('channels') . " set mode = mode & " . SET_MODE_PUBLIC_STATE . " where id in {$sqlids}"); rss_query('update ' . getTable('item') . " set unread = unread & " . SET_MODE_PUBLIC_STATE . " where cid in {$sqlids}"); } if ($deprecated) { rss_query('update ' . getTable('channels') . " set mode = mode | " . RSS_MODE_DELETED_STATE . " where id in {$sqlids}"); } else { rss_query('update ' . getTable('channels') . " set mode = mode & " . SET_MODE_AVAILABLE_STATE . " where id in {$sqlids}"); } // DELETE } elseif (array_key_exists('me_delete', $_REQUEST)) { if (array_key_exists('me_do_delete', $_REQUEST) && $_REQUEST['me_do_delete'] == "1") { $sql = "delete from " . getTable('channels') . " where id in {$sqlids}"; rss_query($sql); } } elseif (array_key_exists('me_set_categories', $_POST)) { $tags = utf8_decode(trim(rss_real_escape_string($_POST['me_categories']))); if ($tags) { foreach ($ids as $id) { __exp__submitTag($id, $tags, '"channel"'); } } } rss_invalidate_cache(); break; case 'dump': // Make sure this is a POST if (!isset($_POST['dumpact'])) { die('Sorry, you can\'t access this via a GET'); } $tbl = array('"', '"'); error_reporting(E_ALL); rss_require('schema.php'); $tables = getExpectedTables(); unset($tables['cache']); //$tables=array('channels','tag','config'); $bfr = ''; $bfr .= '<' . '?xml version="1.0" encoding="UTF-8"?' . '>' . "\n"; $bfr .= '<dump prefix="' . getTable('') . '" date="' . date('r') . '">' . "\n"; foreach ($tables as $table => $prefixed) { $rs = rss_query("select * from {$prefixed}"); $bfr .= "<{$table}>\n"; while ($row = rss_fetch_assoc($rs)) { $r = "<row "; foreach ($row as $key => $val) { $val = htmlspecialchars($val); $r .= " {$key}=\"{$val}\" "; } $r .= "/>\n"; $bfr .= $r; } $bfr .= "</{$table}>\n"; } $bfr .= '</dump>' . "\n"; $gzdata = gzencode($bfr, 9); // Delete the output buffer. This is probably a bad thing to do, if the ob'ing is turned off. // e.g. data was already sent to the brwoser. while (@ob_end_clean()) { } // Send the dump to the browser: header("Pragma: public"); // required header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Connection: close"); header("Content-Transfer-Encoding: binary"); header("Content-Length: " . strlen($gzdata)); header('Content-type: application/x-gzip'); header('Content-disposition: inline; filename="gregarius.dump.' . date('MjSY') . '.xml.gz"'); die($gzdata); break; default: break; } return $ret__; }
/** * main function. checks for authorization and renders the * required admin section. */ function admin_main($authorised) { echo "\n<div id=\"channel_admin\" class=\"frame\">"; if ($authorised) { admin_menu(); if (array_key_exists(CST_ADMIN_DOMAIN, $_REQUEST)) { switch ($_REQUEST[CST_ADMIN_DOMAIN]) { case CST_ADMIN_DOMAIN_FOLDER: $show = folder_admin(); break; case CST_ADMIN_DOMAIN_CHANNEL: $show = channel_admin(); break; case CST_ADMIN_DOMAIN_CONFIG: $show = config_admin(); break; case CST_ADMIN_DOMAIN_ITEM: $show = item_admin(); break; case CST_ADMIN_DOMAIN_PLUGINS: $show = plugins_admin(); break; case CST_ADMIN_DOMAIN_THEMES: $show = themes_admin(); break; case CST_ADMIN_DOMAIN_TAGS: $show = tags_admin(); break; case CST_ADMIN_DOMAIN_PLUGIN_OPTIONS: $show = plugin_options_admin(); break; case CST_ADMIN_DOMAIN_THEME_OPTIONS: $show = theme_options_admin(); break; default: break; } } if (array_key_exists(CST_ADMIN_VIEW, $_REQUEST) || isset($show)) { if (!isset($show)) { $show = $_REQUEST[CST_ADMIN_VIEW]; } switch ($show) { case CST_ADMIN_DOMAIN_CONFIG: config(); break; case CST_ADMIN_DOMAIN_CHANNEL: channels(); break; case CST_ADMIN_DOMAIN_FOLDER: folders(); break; case CST_ADMIN_DOMAIN_OPML: opml(); break; case CST_ADMIN_DOMAIN_NONE: break; case CST_ADMIN_DOMAIN_ITEM: items(); break; case CST_ADMIN_DOMAIN_SYSINFO: sysinfo(); break; case CST_ADMIN_DOMAIN_DASHBOARD: dashboard(); break; case CST_ADMIN_DOMAIN_PLUGINS: plugins(); break; case CST_ADMIN_DOMAIN_THEMES: themes(); break; case CST_ADMIN_DOMAIN_TAGS: tags(); break; case CST_ADMIN_DOMAIN_PLUGIN_OPTIONS: plugin_options(); break; case CST_ADMIN_DOMAIN_THEME_OPTIONS: theme_options(); break; default: } } else { if (true == getConfig('rss.config.defaultdashboard')) { dashboard(); } else { channels(); } } echo "\n<div class=\"clearer\"></div>\n"; } else { rss_error(sprintf(__('<h1>Not Authorized!</h1>You are not authorized to access the administration interface. Please follow <a href="%s">this link</a> back to the main page. Have a nice day!'), getPath()), RSS_ERROR_ERROR, true); } echo "</div>\n"; }
function _init_properties() { $table = getTable('properties'); rss_query_wrapper('DROP TABLE IF EXISTS ' . $table, true, true); $sql_create = str_replace('__table__', $table, <<<_SQL_ \t\tCREATE TABLE __table__ ( \t\t fk_ref_object_id text NOT NULL, \t\t proptype enum('item','feed','folder','category','plugin','tag','theme','misc') NOT NULL default 'item', \t\t property varchar(128) NOT NULL default '', \t\t value text NOT NULL \t\t) ENGINE=MyISAM \t\t _SQL_ ); rss_query_wrapper($sql_create, false, true); if (!rss_is_sql_error(RSS_SQL_ERROR_NO_ERROR)) { rss_error('The ' . $table . 'table doesn\'t exist and I couldn\'t create it! Please create it manually.', RSS_ERROR_ERROR); return 0; } else { $idSql = "alter table {$table} add UNIQUE KEY uniq (fk_ref_object_id(180),property,proptype)"; rss_query_wrapper($idSql, false, true); return rss_is_sql_error(RSS_SQL_ERROR_NO_ERROR); } }
function config_admin() { $ret__ = CST_ADMIN_DOMAIN_CONFIG; if (isset($_REQUEST[CST_ADMIN_METAACTION])) { $action = $_REQUEST[CST_ADMIN_METAACTION]; } else { $action = $_REQUEST['action']; } switch ($action) { case CST_ADMIN_DEFAULT_ACTION: case 'CST_ADMIN_DEFAULT_ACTION': if (!array_key_exists('key', $_REQUEST)) { rss_error(__('Invalid config key specified.'), RSS_ERROR_ERROR, true); break; } $key = sanitize($_REQUEST['key'], RSS_SANITIZER_NO_SPACES | RSS_SANITIZER_SIMPLE_SQL); $res = rss_query("select value_,default_,type_ from " . getTable('config') . " where key_='{$key}'"); list($value, $default, $type) = rss_fetch_row($res); $value = real_strip_slashes($value); $default = real_strip_slashes($default); if ($value == $default) { rss_error(__("The value for '{$key}' is the same as its default value!"), RSS_ERROR_ERROR, true); break; } if (array_key_exists(CST_ADMIN_CONFIRMED, $_POST) && $_POST[CST_ADMIN_CONFIRMED] == __('Yes')) { rss_query("update " . getTable('config') . " set value_=default_ where key_='{$key}'"); rss_invalidate_cache(); } elseif (array_key_exists(CST_ADMIN_CONFIRMED, $_REQUEST) && $_REQUEST[CST_ADMIN_CONFIRMED] == __('No')) { //nop } else { echo "<form class=\"box\" method=\"post\" action=\"" . $_SERVER['PHP_SELF'] . "\">\n"; config_default_form($key, $type, $default, CST_ADMIN_DOMAIN_CONFIG); echo "</form>\n"; $ret = CST_ADMIN_DOMAIN_NONE; } break; case CST_ADMIN_EDIT_ACTION: case 'CST_ADMIN_EDIT_ACTION': $key_ = sanitize($_REQUEST['key'], RSS_SANITIZER_NO_SPACES | RSS_SANITIZER_SIMPLE_SQL); $res = rss_query("select * from " . getTable('config') . " where key_ ='{$key_}'"); list($key, $value, $default, $type, $desc, $export) = rss_fetch_row($res); echo "<div>\n"; echo "\n\n<h2>Edit '{$key}'</h2>\n"; echo "<form style=\"display:inline\" id=\"cfg\" method=\"post\" action=\"" . $_SERVER['PHP_SELF'] . "\">\n"; $onclickaction = null; config_edit_form($key, $value, $default, $type, $desc, $export, $onclickaction); echo "<p style=\"display:inline\">\n"; echo isset($preview) ? "<input type=\"submit\" name=\"action\" value=\"" . __('Preview') . "\"" . ($onclickaction ? " onclick=\"{$onclickaction}\"" : "") . " />\n" : ""; echo "<input type=\"hidden\" name=\"" . CST_ADMIN_METAACTION . "\" value=\"ACT_ADMIN_SUBMIT_CHANGES\" />"; echo "<input type=\"submit\" name=\"action\" value=\"" . __('Submit Changes') . "\"" . ($onclickaction ? " onclick=\"{$onclickaction}\"" : "") . " /><input type=\"hidden\" name=\"" . CST_ADMIN_DOMAIN . "\" value=\"" . CST_ADMIN_DOMAIN_CONFIG . "\"/>\n</p></form>\n"; echo "<form style=\"display:inline\" method=\"post\" action=\"" . $_SERVER['PHP_SELF'] . "\">\n" . "<p style=\"display:inline\">\n<input type=\"hidden\" name=\"" . CST_ADMIN_DOMAIN . "\" value=\"" . CST_ADMIN_DOMAIN_CONFIG . "\"/>\n" . "<input type=\"hidden\" name=\"" . CST_ADMIN_METAACTION . "\" value=\"ACT_ADMIN_SUBMIT_CANCEL\" />" . "<input type=\"submit\" name=\"action\" value=\"" . __('Cancel') . "\"/></p></form>\n" . "\n\n</div>\n"; $ret__ = CST_ADMIN_DOMAIN_NONE; break; case __('Preview'): case 'ACT_ADMIN_PREVIEW_CHANGES': rss_error('fixme: preview not yet implemented', RSS_ERROR_ERROR, true); break; case __('Submit Changes'): case 'ACT_ADMIN_SUBMIT_CHANGES': $key = sanitize($_POST['key'], RSS_SANITIZER_NO_SPACES | RSS_SANITIZER_SIMPLE_SQL); $type = sanitize($_POST['type'], RSS_SANITIZER_CHARACTERS); $value = sanitize($_POST['value'], RSS_SANITIZER_SIMPLE_SQL); // sanitizine routines for values switch ($key) { case 'rss.output.title': $value = strip_tags($value); break; case 'rss.config.robotsmeta': $value = preg_replace('#[^a-zA-Z,\\s]#', '', $value); break; } switch ($key) { case 'rss.input.allowed': $ret = array(); $tmp = explode(' ', $value); foreach ($tmp as $key__) { if (preg_match('|^[a-zA-Z]+$|', $key__)) { $ret[$key__] = array(); } else { $tmp2 = array(); $attrs = explode(',', $key__); $key__ = array_shift($attrs); foreach ($attrs as $attr) { $tmp2[$attr] = 1; } $ret[$key__] = $tmp2; } } $sql = "update " . getTable('config') . " set value_='" . serialize($ret) . "' where key_='{$key}'"; break; case 'rss.output.lang': $langs = getLanguages(); $codes = array_keys($langs); $out_val = implode(',', $codes); $cntr = 0; $idx = "0"; foreach ($codes as $code) { if ($code == $value) { $idx = $cntr; } $cntr++; } $out_val .= ",{$idx}"; $sql = "update " . getTable('config') . " set value_='{$out_val}' where key_='{$key}'"; break; default: switch ($type) { case 'string': $sql = "update " . getTable('config') . " set value_='{$value}' where key_='{$key}'"; break; case 'num': if (!is_numeric($value)) { rss_error(__("Oops, I was expecting a numeric value, got '{$value}' instead!"), RSS_ERROR_ERROR, true); break; } $sql = "update " . getTable('config') . " set value_='{$value}' where key_='{$key}'"; break; case 'boolean': if ($value != __('True') && $value != __('False')) { rss_error(__("Oops, invalid value for {$key} : {$value}"), RSS_ERROR_ERROR, true); break; } $sql = "update " . getTable('config') . " set value_='" . ($value == __('True') ? 'true' : 'false') . "'" . " where key_='{$key}'"; break; case 'enum': $res = rss_query("select value_ from " . getTable('config') . " where key_='{$key}'"); list($oldvalue) = rss_fetch_row($res); if (strstr($oldvalue, $value) === FALSE) { rss_error(__("Oops, invalid value '{$value}' for this config key"), RSS_ERROR_ERROR, true); break; } $arr = explode(',', $oldvalue); $idx = array_pop($arr); $newkey = -1; foreach ($arr as $i => $val) { if ($val == $value) { $newkey = $i; } } reset($arr); if ($newkey > -1) { array_push($arr, $newkey); $sql = "update " . getTable('config') . " set value_='" . implode(',', $arr) . "'" . " where key_='{$key}'"; } else { rss_error(__("Oops, invalid value '{$value}' for this config key"), RSS_ERROR_ERROR, true); } break; default: rss_error(__('Ooops, unknown config type: ') . $type, RSS_ERROR_ERROR, true); //var_dump($_REQUEST); break; } } if (isset($sql)) { rss_query($sql); rss_invalidate_cache(); } break; default: break; } return $ret__; }
/** * performs pruning action */ function item_admin() { $ret__ = CST_ADMIN_DOMAIN_NONE; switch ($_REQUEST['action']) { case __('Delete'): $req = rss_query('select count(*) as cnt from ' . getTable('item') . " where not(unread & " . RSS_MODE_DELETED_STATE . ")"); list($cnt) = rss_fetch_row($req); $prune_older = sanitize($_REQUEST['prune_older'], RSS_SANITIZER_NUMERIC); if (array_key_exists('prune_older', $_REQUEST) && strlen($_REQUEST['prune_older']) && is_numeric($_REQUEST['prune_older'])) { switch ($_REQUEST['prune_period']) { case __('days'): $period = 'day'; break; case __('months'): $period = 'month'; break; case __('years'): $period = 'year'; break; default: rss_error(__('Invalid pruning period'), RSS_ERROR_ERROR, true); return CST_ADMIN_DOMAIN_ITEM; break; } $sql = " from " . getTable('item') . " i inner join " . getTable('channels') . " c on c.id=i.cid " . " where 1=1 "; if (array_key_exists('prune_channel', $_REQUEST)) { if (ALL_CHANNELS_ID != $_REQUEST['prune_channel']) { $sql .= " and c.id = " . $_REQUEST['prune_channel'] . ""; } } if ($prune_older > 0) { $prune_older_date = date("Y-m-d H:i:s", strtotime("-{$prune_older} {$period}")); $sql .= " and ifnull(i.pubdate, i.added) < '{$prune_older_date}'"; } if (!array_key_exists('prune_include_sticky', $_REQUEST) || $_REQUEST['prune_include_sticky'] != '1') { $sql .= " and not(unread & " . RSS_MODE_STICKY_STATE . ") "; } if (!array_key_exists('prune_include_flag', $_REQUEST) || $_REQUEST['prune_include_flag'] != '1') { $sql .= " and not(unread & " . RSS_MODE_FLAG_STATE . ") "; } if (!array_key_exists('prune_include_unread', $_REQUEST) || $_REQUEST['prune_include_unread'] != '1') { $sql .= " and not(unread & " . RSS_MODE_UNREAD_STATE . ") "; } if (array_key_exists('prune_exclude_tags', $_REQUEST) && trim($_REQUEST['prune_exclude_tags'])) { if (trim($_REQUEST['prune_exclude_tags']) == '*') { $tsql = " select distinct fid from " . getTable('metatag'); } else { $exclude_tags = explode(" ", $_REQUEST['prune_exclude_tags']); $trimmed_exclude_tags = array(); foreach ($exclude_tags as $etag) { if ($tetag = rss_real_escape_string(trim($etag))) { $trimmed_exclude_tags[] = $tetag; } } $tsql = " select distinct fid from " . getTable('metatag') . " m " . " inner join " . getTable('tag') . " t" . " on t.id = m.tid " . " where t.tag in ('" . implode("', '", $trimmed_exclude_tags) . "')"; } $tres = rss_query($tsql); $fids = array(); while (list($fid) = rss_fetch_row($tres)) { $fids[] = $fid; } if (count($fids)) { $sql .= " and i.id not in (" . implode(",", $fids) . ") "; } } if (array_key_exists(CST_ADMIN_CONFIRMED, $_REQUEST)) { // Possible fix for #207: max out execution time // to avoid timeouts @set_time_limit(0); @ini_set('max_execution_time', 60 * 10); //echo "<pre>\n"; //delete the tags for these items $sqlids = "select distinct i.id,i.cid " . $sql . " order by i.cid, i.id desc"; $rs = rss_query($sqlids); $ids = array(); $cids = array(); //echo "to be deleted\n"; while (list($id, $cid) = rss_fetch_row($rs)) { $cids[$cid][] = $id; //echo "cid=$cid, $id\n"; } //echo "\n\n"; if (count($cids)) { // Righto. Lets check which of these ids still is in cache: $cacheIds = array(); // now, sort the ids to be deleted into two lists: in cache / to trash $in_cache = array(); $to_trash = array(); foreach ($cids as $cid => $ids) { $rsCache = rss_query("select itemsincache from " . getTable('channels') . " where id={$cid}"); list($idString) = rss_fetch_row($rsCache); if ($idString) { $cacheIds = unserialize($idString); } else { $cacheIds = array(); } foreach ($ids as $iid) { //echo "examining: $iid (cid $cid) ->"; if (array_search($iid, $cacheIds) !== FALSE) { $in_cache[] = $iid; //echo " in cache!\n"; } else { $to_trash[] = $iid; //echo " not in cache!\n"; } } } // cheers, we're set. Now delete the metatag links for *all* // items to be deleted if (count($ids)) { $sqldel = "delete from " . getTable('metatag') . " where fid in (" . implode(",", array_merge($in_cache, $to_trash)) . ")"; rss_query($sqldel); } // finally, delete the actual items if (count($to_trash)) { rss_query("delete from " . getTable('item') . " where id in (" . implode(", ", $to_trash) . ")"); } if (count($in_cache)) { rss_query("update " . getTable('item') . " set unread = unread | " . RSS_MODE_DELETED_STATE . ", description='' " . " where id in (" . implode(", ", $in_cache) . ")"); } rss_invalidate_cache(); } $ret__ = CST_ADMIN_DOMAIN_ITEM; } else { list($cnt_d) = rss_fetch_row(rss_query("select count(distinct(i.id)) as cnt " . $sql . " and not(i.unread & " . RSS_MODE_DELETED_STATE . ")")); rss_error(sprintf(__('Warning: you are about to delete %s items (of %s)'), $cnt_d, $cnt), RSS_ERROR_ERROR, true); echo "<form action=\"\" method=\"post\">\n" . "<p><input type=\"hidden\" name=\"" . CST_ADMIN_DOMAIN . "\" value=\"" . CST_ADMIN_DOMAIN_ITEM . "\" />\n" . "<input type=\"hidden\" name=\"prune_older\" value=\"" . $_REQUEST['prune_older'] . "\" />\n" . "<input type=\"hidden\" name=\"prune_period\" value=\"" . $_REQUEST['prune_period'] . "\" />\n" . "<input type=\"hidden\" name=\"" . CST_ADMIN_CONFIRMED . "\" value=\"1\" />\n" . "<input type=\"submit\" name=\"action\" value=\"" . __('Delete') . "\" />\n" . "<input type=\"submit\" name=\"action\" value=\"" . __('Cancel') . "\"/>\n" . "</p>\n" . "</form>\n"; } } else { rss_error(__('oops, no period specified'), RSS_ERROR_ERROR, true); $ret__ = CST_ADMIN_DOMAIN_ITEM; } break; default: $ret__ = CST_ADMIN_DOMAIN_ITEM; break; } return $ret__; }
function plugins_check_for_updates() { $pluginsxml = array(); global $pluginsxml; $xml = getUrl('http://plugins.gregarius.net/api.php'); $xml = str_replace("\r", '', $xml); $xml = str_replace("\n", '', $xml); $xp = xml_parser_create() or rss_error("couldn't create parser"); xml_set_element_handler($xp, 'plugins_xml_startElement', 'plugins_xml_endElement') or rss_error("couldnt set XML handlers"); xml_parse($xp, $xml, true) or rss_error("failed parsing xml"); xml_parser_free($xp) or rss_error("failed freeing the parser"); return $pluginsxml; }
/** * Creates a folder with the given name. Does some sanity check, * creates the folder, then returns the */ function create_folder($label, $complainonerror = true) { $res = rss_query("select count(*) from " . getTable("folders") . " where name='" . rss_real_escape_string($label) . "'"); list($exists) = rss_fetch_row($res); if ($exists > 0 && $complainonerror) { rss_error(sprintf(__("Looks like you already have a folder called '%s'!"), $label), RSS_ERROR_ERROR, true); return; } elseif ($exists == 0) { $res = rss_query("select 1+max(position) as np from " . getTable("folders")); list($np) = rss_fetch_row($res); if (!$np) { $np = "0"; } rss_query("insert into " . getTable("folders") . " (name,position) values ('" . rss_real_escape_string($label) . "', {$np})"); rss_invalidate_cache(); } list($fid) = rss_fetch_row(rss_query("select id from " . getTable("folders") . " where name='" . rss_real_escape_string($label) . "'")); return $fid; }