submit news A small pseudo-CAPTCHA is built in, which asks users to calculate something. Division asks for integers only (but will accept reals in submissions). It will hinder generic link spam bots, but not targetted attacks. Enabling the more difficult arithmetic riddles would just irritate users. */ #-- config define("RSS_INTERNAL_BLOG_CID", 5000); #-- register hooks if (defined("GREGARIUS_HOME")) { rss_set_hook("rss.plugins.admin.activate", "g_plugins_internalblog_install"); rss_set_hook("rss.plugins.configuration", "g_plugin_internalblog_settings"); #-- link to InternalBlog in sidemenu rss_set_hook("rss.plugins.sidemenu", "g_plugin_internalblog_link_sidemenu"); #-- put link into top/head nav menu (BROKEN) rss_set_hook("rss.plugins.navelements", "g_plugins_internalblog_link_topmenu"); } #-- script got invoked directly else { chdir(".."); require_once("init.php"); g_plugin_internalblog_interface(); } #-- admin page function g_plugin_internalblog_settings() { #-- config ($cid = rss_plugins_get_option("intblog.cid")) or ($cid = RSS_INTERNAL_BLOG_CID); #-- save/action if (rss_plugins_is_submit()) { #-- item deletion foreach ($_REQUEST["delete"] as $guid) { $guid = rss_real_escape_string($guid); rss_query("DELETE FROM ".getTable("item")." WHERE (cid=$cid) AND (guid='$guid')"); } // #-- store submitted channel_id for InternalBlog // if ($cid = (int)$_REQUEST["cid"]) { // rss_plugins_add_option("intblog.cid", $cid, "string", "", "channel_id for internal blog"); // } } #-- list blog posts print<< To modify items, you currently have to use a SQL table editor. This interface does not provide anything overkill and beyond simple item deletion.

END; $sqlres = rss_query("SELECT title, added, url, description, guid FROM ".getTable("item")." WHERE (cid=$cid) ORDER BY added DESC"); while ($row = rss_fetch_row($sqlres)) { list($title, $added, $url, $desc, $guid) = $row; $title = htmlentities($title); $link = htmlentities($link); $desc = htmlentities(substr($desc, 0, 50)); print<< END; } print "
deletetitledescription
$title $desc
\n"; return; #-- edit channel_id print<< Leave as is, unless you know what you are doing.

END; } #-- install function g_plugins_internalblog_install($activatethis) { print_r($activatethis); ($cid = rss_plugins_get_option("intblog.cid")) or ($cid = RSS_INTERNAL_BLOG_CID); $sql = "INSERT INTO ".getTable("channels") . " (id, title, url, siteurl, parent, descr, icon, mode) " . " VALUES ($cid, 'InternalBlog', 'http://gregarius-plugin-itemfilter.googlecode.com/svn/trunk/empty.rss.xml', '', 0, 'Local link blog', '', 0)"; rss_query($sql); } #-- link ourselves function g_plugin_internalblog_link_sidemenu($null) { echo '
  • submit
  • '."\n"; } function g_plugin_internalblog_link_topmenu($text) { $GLOBALS->appendNavItem(getPath().'plugins/InternalBlog.php', "submit", 5); # return $text . '
  • Submit
  • '; } #-- submit UI function g_plugin_internalblog_interface() { ($cid = rss_plugins_get_option("intblog.cid")) or ($cid = RSS_INTERNAL_BLOG_CID); $url = $_SERVER["REQUEST_URI"]; #-- save --------------------------------------------------------------- if ($_REQUEST["save"]) { #-- input $description = $_REQUEST["description"]; $title = $_REQUEST["title"]; $link = $_REQUEST["link"]; #-- "solve" captcha # (it actually only prevents generic submit bots, not those specifically crafted against this simple form variation - one only had to extract the right text snippet to overcome it) $formula = preg_replace("#[^-+*/\d]#", "", $_REQUEST["captcha_formula"]); $val = g_plugin_internalblog_solve_formula($formula); #-- check if (g_plugin_internalblog_used_captcha($formula)) { $ERROR = "This CAPTCHA has been used already. Rejected. Please go back and reload the submit page. This is an error."; } elseif (((int)$val) != ((int)($_REQUEST["captcha"]))) { $ERROR = "Your CAPTCHA solution was wrong."; } elseif (strlen($title)<3) { $ERROR = "No title was provided."; } elseif (strlen($description)<15) { $ERROR = "Text tooooooo short."; } elseif (!preg_match("#^http://\w+\.\w+#", $link)) { $ERROR = "Invalid or missing URL."; } #-- ok else { #-- filter list($cid, $title, $url, $description) = rss_plugin_hook('rss.plugins.items.new', array($cid, $title, $url, $description)); #-- SQL $mode = 0; $db_title = rss_real_escape_string($title); $db_link = rss_real_escape_string($link); $db_desc = rss_real_escape_string($description); $client_ip = isset($_SERVER["X_FORWARDED_FOR"]) ? "$_SERVER[X_FORWARDED_FOR]" : "$_SERVER[REMOTE_ADDR]:$_SERVER[REMOTE_PORT]"; $db_author = rss_real_escape_string($client_ip." ($formula)"); $md5sum = md5($link); $guid = "x-local:intblog:$md5sum"; # $sql = "INSERT INTO " . getTable("item") . " (cid, added, title, url, enclosure, description, author, unread, pubdate, md5sum, guid) " . " VALUES (" . " $cid, now(), '$db_title', '$db_link', '', '$db_desc', '$db_author', $mode, now(), '$md5sum', '$guid' " . ")"; # rss_query($sql); #-- show success message $ERROR = <<

    Entry has been successfully saved.

    Go back to the front page to see it.

    Or you can now submit another one.

     

    END; $title = $link = $description = $_REQUEST["captcha"] = ""; } } #-- page / form -------------------------------------------------------- if (true) { #-- prepare vars $sqlres = rss_query("SELECT title, descr FROM ".getTable("channels")." WHERE id=$cid"); list($page_title, $page_title2) = rss_fetch_row($sqlres); #-- get fresh captcha do { $formula = g_plugin_internalblog_new_captcha(); } while (g_plugin_internalblog_used_captcha($formula)); #-- output if ($ERROR) { $html_ERROR = "

    $ERROR

    "; } $title = htmlentities($title); ($link = htmlentities($link)) || ($link = "http://"); $description = htmlentities($description); echo << $page_title

    $page_title2

    You can use this page to submit news items into the local site. They get displayed in the according category. This is meant for link items primarily, and therefore will reject anything without an URL.

    Post Item

    $html_ERROR

    =

    END; } } #-- make new captcha formula string function g_plugin_internalblog_new_captcha() { $formula = array( rand(20,100) . " / " . rand(1,11), rand(50,150) . " - " . rand(1,100), rand( 1,100) . " + " . rand(1,100), rand( 1, 15) . " * " . rand(1,12), rand( 5, 10) . " * " . rand(5,10) . " - " . rand(1,20), rand(30,100) . " + " . rand(5,99) . " - " . rand(1,50), // rand(20,100) . " / " . rand(2,10) . " + " . rand(1,50), ); return $formula[rand(0,count($formula)-1)]; } #-- "solve" simple calculations function g_plugin_internalblog_solve_formula($formula) { preg_match("#^(\d+)([-+/*])(\d+)([-+/*])?(\d+)?$#", $formula, $uu); list($uu, $X, $op1, $Y, $op2, $Z) = $uu; if ($Y) $calc = array( "/" => $X / $Y, // PHP+ZendVM catches division by zero already, and CAPTCHA "attacker" would get no advantage herefrom anyhow "*" => $X * $Y, "+" => $X + $Y, "-" => $X - $Y, "*-" => $X * $Y - $Z, "+-" => $X + $Y - $Z, "/+" => $X / $Y + $Z, ); return( $calc[$op1.$op2] ? $calc[$op1.$op2] : rand(0,1<<23) ); } #-- check database for used calculations (important to prevent CAPTCHA replays) function g_plugin_internalblog_used_captcha($formula) { $formula = rss_real_escape_string(preg_replace("#[^-+*/\d]#", "", $formula)); $r = rss_query("SELECT guid, author FROM ".getTable("item")." WHERE author LIKE '%($formula)%'"); return rss_fetch_row($r); } ?>