function GetXMLTree($file) { require_once S9Y_PEAR_PATH . 'HTTP/Request2.php'; serendipity_request_start(); $options = array(); if (version_compare(PHP_VERSION, '5.6.0', '<')) { // On earlier PHP versions, the certificate validation fails. We deactivate it on them to restore the functionality we had with HTTP/Request1 $options['ssl_verify_peer'] = false; } $req = new HTTP_Request2($file, HTTP_Request2::METHOD_GET, $options); try { $response = $req->send(); if ($response->getStatus() != '200') { throw new HTTP_Request2_Exception('Status code not 200, xml file not fetched'); } $data = $response->getBody(); } catch (HTTP_Request2_Exception $e) { $data = file_get_contents($file); } serendipity_request_end(); // Global replacements // by: waldo@wh-e.com - trim space around tags not within $data = preg_replace('@>[[:space:]]+<@', '><', $data); // Flatten the input opml file to not have nested categories $data = preg_replace('@<outline[^>]+[^/]>@imsU', '', $data); $data = str_replace('</outline>', '', $data); // XML functions $xml_string = '<?xml version="1.0" encoding="UTF-8" ?>'; if (preg_match('@(<\\?xml.+\\?>)@imsU', $data, $xml_head)) { $xml_string = $xml_head[1]; } $encoding = 'UTF-8'; if (preg_match('@encoding="([^"]+)"@', $xml_string, $xml_encoding)) { $encoding = $xml_encoding[1]; } $p = xml_parser_create($encoding); // by: anony@mous.com - meets XML 1.0 specification @xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0); xml_parser_set_option($p, XML_OPTION_TARGET_ENCODING, LANG_CHARSET); xml_parse_into_struct($p, $data, $vals, $index); xml_parser_free($p); $i = 0; $tree = array(); $tree[] = array('tag' => $vals[$i]['tag'], 'attributes' => $vals[$i]['attributes'], 'value' => $vals[$i]['value'], 'children' => $this->GetChildren($vals, $i)); return $tree; }
/** * Fetches additional comment data from the page that sent the pingback * @access private * @param array comment array to be filled */ function fetchPingbackData(&$comment) { global $serendipity; // Don't fetch remote page, if not explicitly allowed in serendipity_config_local.php: if (empty($serendipity['pingbackFetchPage'])) { return; } // If we don't have a comment or a commentors url, stop it. if (!isset($comment) || !is_array($comment) || !isset($comment['url'])) { return; } // Max amount of characters fetched from the page doing a pingback: $fetchPageMaxLength = 200; if (isset($serendipity['pingbackFetchPageMaxLength'])) { $fetchPageMaxLength = $serendipity['pingbackFetchPageMaxLength']; } require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; $url = $comment['url']; if (function_exists('serendipity_request_start')) { serendipity_request_start(); } // Request the page $req = new HTTP_Request($url, array('allowRedirects' => true, 'maxRedirects' => 5, 'timeout' => 20, 'readTimeout' => array(5, 0))); // code 200: OK, code 30x: REDIRECTION $responses = "/(200 OK)|(30[0-9] Found)/"; // |(30[0-9] Moved) if (PEAR::isError($req->sendRequest()) || preg_match($responses, $req->getResponseCode())) { // nothing to do, } else { $fContent = $req->getResponseBody(); // Get a title if (preg_match('@<head[^>]*>.*?<title[^>]*>(.*?)</title>.*?</head>@is', $fContent, $matches)) { $comment['title'] = serendipity_entity_decode(strip_tags($matches[1]), ENT_COMPAT, LANG_CHARSET); } // Try to get content from first <p> tag on: if (preg_match('@<p[^>]*>(.*?)</body>@is', $fContent, $matches)) { $body = $matches[1]; } if (empty($body) && preg_match('@<body[^>]*>(.*?)</body>@is', $fContent, $matches)) { $body = $matches[1]; } // Get a part of the article if (!empty($body)) { $body = trackback_body_strip($body); // truncate the text to 200 chars $arr = str_split($body, $fetchPageMaxLength); $body = $arr[0]; $comment['comment'] = $body . '[..]'; } } if (function_exists('serendipity_request_end')) { serendipity_request_end(); } }
function mod_time($uri) { if (function_exists('version_compare') && version_compare(phpversion(), '4.3.0') >= 0) { require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; serendipity_request_start(); $req = new HTTP_Request($uri); if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') { serendipity_request_end(); return false; } $fHeader = $req->getResponseHeader(); if (isset($fHeader['last-modified'])) { $modtime = $fHeader['last-modified']; } serendipity_request_end(); } else { $parts = parse_url($uri); $host = $parts['host']; $path = $parts['path']; if (!($fp = @fsockopen($host, 80))) { return false; } $req = "HEAD {$path} HTTP/1.1\r\nUser-Agent: PHP/" . phpversion(); $req .= "\r\nHost: {$host}\r\nAccept: */*\r\n\r\n"; fputs($fp, $req); while (!feof($fp)) { $str = fgets($fp, 4096); if (strpos(strtolower($str), 'last-modified') !== false) { $modtime = substr($str, 15); break; } } fclose($fp); } return isset($modtime) ? $modtime : 0; }
function &importFeeds() { // Used by ImportOPML routine global $serendipity; $file = $serendipity['POST']['aggregatorOPML']; require_once (defined('S9Y_PEAR_PATH') ? S9Y_PEAR_PATH : S9Y_INCLUDE_PATH . 'bundled-libs/') . 'HTTP/Request.php'; if (function_exists('serendipity_request_start')) { serendipity_request_start(); } $req = new HTTP_Request($file); if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') { $data = file_get_contents($file); if (empty($data)) { return false; } } else { // Fetch file $data = $req->getResponseBody(); } if (function_exists('serendipity_request_end')) { serendipity_request_end(); } // XML functions $xml_string = '<?xml version="1.0" encoding="UTF-8" ?>'; if (preg_match('@(<\\?xml.+\\?>)@imsU', $data, $xml_head)) { $xml_string = $xml_head[1]; } $encoding = 'UTF-8'; if (preg_match('@encoding="([^"]+)"@', $xml_string, $xml_encoding)) { $encoding = $xml_encoding[1]; } // Global replacements // by: waldo@wh-e.com - trim space around tags not within $data = preg_replace('@>[[:space:]]+<@i', '><', $data); switch (strtolower($encoding)) { case 'iso-8859-1': case 'utf-8': $p = xml_parser_create($encoding); break; default: $p = xml_parser_create(''); } // by: anony@mous.com - meets XML 1.0 specification xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0); @xml_parser_set_option($p, XML_OPTION_TARGET_ENCODING, LANG_CHARSET); xml_parse_into_struct($p, $data, $vals, $index); xml_parser_free($p); $i = 0; $tree = array(); $tree[] = array('tag' => $vals[$i]['tag'], 'attributes' => $vals[$i]['attributes'], 'value' => $vals[$i]['value'], 'children' => $this->GetChildren($vals, $i)); return $tree; }
function serendipity_request_url($uri, $method = 'GET', $contenttype = null, $data = null, $extra_options = null, $addData = null, $auth = null) { global $serendipity; require_once S9Y_PEAR_PATH . 'HTTP/Request2.php'; $options = array('follow_redirects' => true, 'max_redirects' => 5); if (is_array($extra_options)) { foreach ($extra_options as $okey => $oval) { $options[$okey] = $oval; } } serendipity_plugin_api::hook_event('backend_http_request', $options, $addData); serendipity_request_start(); if (version_compare(PHP_VERSION, '5.6.0', '<')) { // On earlier PHP versions, the certificate validation fails. We deactivate it on them to restore the functionality we had with HTTP/Request1 $options['ssl_verify_peer'] = false; } switch (strtoupper($method)) { case 'GET': $http_method = HTTP_Request2::METHOD_GET; break; case 'PUT': $http_method = HTTP_Request2::METHOD_PUT; break; case 'OPTIONS': $http_method = HTTP_Request2::METHOD_OPTIONS; break; case 'HEAD': $http_method = HTTP_Request2::METHOD_HEAD; break; case 'DELETE': $http_method = HTTP_Request2::METHOD_DELETE; break; case 'TRACE': $http_method = HTTP_Request2::METHOD_TRACE; break; case 'CONNECT': $http_method = HTTP_Request2::METHOD_CONNECT; break; default: case 'POST': $http_method = HTTP_Request2::METHOD_POST; break; } $req = new HTTP_Request2($uri, $http_method, $options); if (isset($contenttype) && $contenttype !== null) { $req->setHeader('Content-Type', $contenttype); } if (is_array($auth)) { $req->setAuth($auth['user'], $auth['pass']); } if ($data != null) { if (is_array($data)) { $req->addPostParameter($data); } else { $req->setBody($data); } } try { $res = $req->send(); } catch (HTTP_Request2_Exception $e) { serendipity_request_end(); return false; } $fContent = $res->getBody(); $serendipity['last_http_request'] = array('responseCode' => $res->getStatus(), 'effectiveUrl' => $res->getEffectiveUrl(), 'reasonPhrase' => $res->getReasonPhrase(), 'isRedirect' => $res->isRedirect(), 'cookies' => $res->getCookies(), 'version' => $res->getVersion(), 'header' => $res->getHeader(), 'object' => $res); serendipity_request_end(); return $fContent; }
function get_gg_status($numer_gg, $haslo_gg, $szukany_numer, &$error, &$gg_status_widocznosc) { define("GG_WELCOME", 0x1); define("GG_LOGIN", 0xc); define("GG_LOGIN60", 0x15); define("GG_LOGIN_OK", 0x3); define("GG_LOGIN_FAILED", 0x9); define("GG_NEW_STATUS", 0x2); define("GG_STATUS", 0x2); define("GG_STATUS_NOT_AVAIL", 0x1); define("GG_STATUS_NOT_AVAIL_DESCR", 0x15); define("GG_STATUS_AVAIL", 0x2); define("GG_STATUS_AVAIL_DESCR", 0x4); define("GG_STATUS_BUSY", 0x3); define("GG_STATUS_BUSY_DESCR", 0x5); define("GG_STATUS_INVISIBLE", 0x14); define("GG_NOTIFY", 0x10); define("GG_NOTIFY_REPLY", 0xc); define("GG_NOTIFY_REPLY60", 0x11); define("GG_USER_NORMAL", 0x3); define("GG_USER_BLOCKED", 0x4); define("GG_SEND_MSG", 0xb); define("GG_CLASS_MSG", 0x4); define("GG_CLASS_CHAT", 0x8); define("GG_CLASS_ACK", 0x20); define("GG_SEND_MSG_ACK", 0x5); define("GG_ACK_DELIVERED", 0x2); define("GG_ACK_QUEUED", 0x3); define("GG_RECV_MSG", 0xa); define("GG_LOGIN_FAILED2", 0xb); define("GG_ACK_MBOXFULL", 0x4); define("DISCONNECTED", 0x100); define("GG_PUBDIR50_REQUEST", 0x14); define("GG_PUBDIR50_REPLY", 0xe); define("GG_PUBDIR50_SEARCH", 0x3); // // Getting a logon server // require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; serendipity_request_start(); $req = new HTTP_Request('http://appmsg.gadu-gadu.pl:80/appsvc/appmsg.asp?fmnumber=<' . $numer_gg . '>'); if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') { $error = PLUGIN_GGOPIS_MSG_NOCONNTOAPPMSG . $errno . " - " . $errstr . "\n"; serendipity_request_end(); return false; } else { $buf = $req->getResponseBody(); preg_match("/\\s([\\d\\.]{8,16})\\:([\\d]{1,5})\\s/", $buf, $adres); $host = $adres[1]; $port = $adres[2]; serendipity_request_end(); } // // Connecting to a server // require_once S9Y_PEAR_PATH . 'Net/Socket.php'; $conn = new Net_Socket(); if (!$conn->connect($host, $port, null, 10)) { $error = PLUGIN_GGOPIS_MSG_CONNERROR . ": {$errno} - {$errstr}\n\n"; return false; } // // Getting data from a server - // receiving a key needed to calculate // a hash from your password // if (!($data = $conn->read(12))) { $error = PLUGIN_GGOPIS_MSG_CONNUNEXPCLOSED . "\n\n"; $conn->disconnect(); return false; } $tab = unpack("Vtyp/Vrozmiar/Vklucz", $data); // Calculating a password hash $hash = $this->calculate_hash($haslo_gg, $tab['klucz']); $data = pack("VVVVVVvVvVvCCa" . strlen(""), GG_LOGIN60, 0x20 + strlen(""), $numer_gg, $hash, GG_STATUS_AVAIL, 0x20, 0, 0, 0, 0, 0, 0x14, 0xbe, ""); // Sending a password hash - logging to a GG server $conn->write($data); if (!($data1 = $conn->read(8))) { $error = PLUGIN_GGOPIS_MSG_UNKNOWNERROR . "\n"; $conn->disconnect(); return false; } // Checking a login status $tab = unpack("Vlogin_status/Vrozmiar", $data1); if ($tab['login_status'] != GG_LOGIN_OK) { $error = PLUGIN_GGOPIS_MSG_INCORRPASSWD . "\n\n"; $conn->disconnect(); return false; } // Sending a contact list with one contact $data = pack("VVVC", GG_NOTIFY, 5, $szukany_numer, GG_USER_NORMAL); if (!$conn->write($data)) { $error = PLUGIN_GGOPIS_MSG_SENDCONTACTSERROR . "\n\n"; $conn->disconnect(); return false; } // Receiving a packet with the next packet specification $gg_opis = ''; $data = $conn->read(8); if (strlen($data) > 0) { $tab = unpack("Vtyp/Vrozmiar", $data); // Pobranie pakietu opisu // DEBUG: echo $tab['rozmiar']; $data = $conn->read($tab['rozmiar']); if ($tab['rozmiar'] > 14) { $tablica = unpack("Iuin/Cstatus/Iremoteip/Sremoteport/Cversion/Cimagesize/Cunknown/Cdescription_size/a*description", $data); // Getting a status description, and converting it from CP1250 (that's how it's encoded) to UTF8 $gg_opis = $this->cp1250_to_utf8($tablica['description']); // Getting a status itself $gg_status_flaga = $tablica['status']; } else { $tablica = unpack("Iuin/Cstatus", $data); // Getting a status $gg_status_flaga = $tablica['status']; } if (empty($gg_opis)) { $gg_opis = PLUGIN_GGOPIS_MSG_NOSTATUSDESC; } // Choosing a status icon to display switch ($gg_status_flaga) { case GG_STATUS_NOT_AVAIL: case GG_STATUS_NOT_AVAIL_DESCR: $gg_status_widocznosc = 'gg11'; break; case GG_STATUS_AVAIL: case GG_STATUS_AVAIL_DESCR: $gg_status_widocznosc = 'gg12'; break; case GG_STATUS_BUSY: case GG_STATUS_BUSY_DESCR: $gg_status_widocznosc = 'gg13'; break; default: $gg_status_widocznosc = 'gg11'; } } else { $gg_opis = PLUGIN_GGOPIS_MSG_NOSTATUSDESC; } // Closing a connection to the server $conn->disconnect(); return $gg_opis; }
function event_hook($event, &$bag, &$eventData, $addData = null) { global $serendipity; $debug = true; $hooks =& $bag->get('event_hooks'); if (isset($hooks[$event])) { $captchas_ttl = $this->get_config('captchas_ttl', 7); $_captchas = $this->get_config('captchas', 'yes'); $captchas = $_captchas !== 'no' && ($_captchas === 'yes' || $_captchas === 'scramble' || serendipity_db_bool($_captchas)); // Check if the entry is older than the allowed amount of time. Enforce kaptchas if that is true // of if kaptchas are activated for every entry $show_captcha = $captchas && isset($eventData['timestamp']) && ($captchas_ttl < 1 || $eventData['timestamp'] < time() - $captchas_ttl * 60 * 60 * 24) ? true : false; // Plugins can override with custom captchas if (isset($serendipity['plugins']['disable_internal_captcha'])) { $show_captcha = false; } $forcemoderation = $this->get_config('forcemoderation', 60); $forcemoderation_treat = $this->get_config('forcemoderation_treat', 'moderate'); $forcemoderationt = $this->get_config('forcemoderationt', 60); $forcemoderationt_treat = $this->get_config('forcemoderationt_treat', 'moderate'); $links_moderate = $this->get_config('links_moderate', 10); $links_reject = $this->get_config('links_reject', 20); if (function_exists('imagettftext') && function_exists('imagejpeg')) { $max_char = 5; $min_char = 3; $use_gd = true; } else { $max_char = $min_char = 5; $use_gd = false; } switch ($event) { case 'fetchcomments': if (is_array($eventData) && !$_SESSION['serendipityAuthedUser'] && serendipity_db_bool($this->get_config('hide_email', false))) { // Will force emails to be not displayed in comments and RSS feed for comments. Will not apply to logged in admins (so not in the backend as well) @reset($eventData); while (list($idx, $comment) = each($eventData)) { $eventData[$idx]['no_email'] = true; } } break; case 'frontend_saveComment': /* $fp = fopen('/tmp/spamblock2.log', 'a'); fwrite($fp, date('Y-m-d H:i') . "\n" . print_r($eventData, true) . "\n" . print_r($addData, true) . "\n"); fclose($fp); */ if (!is_array($eventData) || serendipity_db_bool($eventData['allow_comments'])) { $this->checkScheme(); $serendipity['csuccess'] = 'true'; $logfile = $this->logfile = $this->get_config('logfile', $serendipity['serendipityPath'] . 'spamblock.log'); $required_fields = $this->get_config('required_fields', ''); $checkmail = $this->get_config('checkmail'); // Check CSRF [comments only, cannot be applied to trackbacks] if ($addData['type'] == 'NORMAL' && serendipity_db_bool($this->get_config('csrf', true))) { if (!serendipity_checkFormToken(false)) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_CSRF_REASON, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_CSRF_REASON; } } // Check required fields if ($addData['type'] == 'NORMAL' && !empty($required_fields)) { $required_field_list = explode(',', $required_fields); foreach ($required_field_list as $required_field) { $required_field = trim($required_field); if (empty($addData[$required_field])) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_REQUIRED_FIELD, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_REQUIRED_FIELD, $required_field); return false; } } } /* if ($addData['type'] != 'NORMAL' && empty($addData['name'])) { $eventData = array('allow_coments' => false); $this->log($logfile, $eventData['id'], 'INVALIDGARV', 'INVALIDGARV', $addData); return false; } */ // Check whether to allow comments from registered authors if (serendipity_userLoggedIn() && $this->inGroup()) { return true; } // Check if the user has verified himself via email already. if ($addData['type'] == 'NORMAL' && (string) $checkmail === 'verify_once') { $auth = serendipity_db_query("SELECT *\n FROM {$serendipity['dbPrefix']}options\n WHERE okey = 'mail_confirm'\n AND name = '" . serendipity_db_escape_string($addData['email']) . "'\n AND value = '" . serendipity_db_escape_string($addData['name']) . "'", true); if (!is_array($auth)) { // Filter authors names, Filter URL, Filter Content, Filter Emails, Check for maximum number of links before rejecting // moderate false if (false === $this->wordfilter($logfile, $eventData, $wordmatch, $addData, true)) { // already there #$this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_FILTER_WORDS, $addData); // already there #$eventData = array('allow_comments' => false); // already there #$serendipity['messagestack']['emails'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; return false; } elseif (serendipity_db_bool($this->get_config('killswitch', false)) === true) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_KILLSWITCH, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_KILLSWITCH; return false; } else { $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_CHECKMAIL_VERIFICATION_MAIL, $addData); $eventData['moderate_comments'] = true; $eventData['status'] = 'confirm1'; $serendipity['csuccess'] = 'moderate'; $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_CHECKMAIL_VERIFICATION_MAIL; return false; } } else { // User is allowed to post message, bypassing other checks as if he were logged in. return true; } } // Check if entry title is the same as comment body if (serendipity_db_bool($this->get_config('entrytitle')) && trim($eventData['title']) == trim($addData['comment'])) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_TITLE, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; return false; } // Check for global emergency moderation if (serendipity_db_bool($this->get_config('killswitch', false)) === true) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_KILLSWITCH, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_KILLSWITCH; return false; } // Check for not allowing trackbacks/pingbacks/wfwcomments if (($addData['type'] != 'NORMAL' || $addData['source'] == 'API') && $this->get_config('disable_api_comments', 'none') != 'none') { if ($this->get_config('disable_api_comments') == 'reject') { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_API, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_API; return false; } elseif ($this->get_config('disable_api_comments') == 'moderate') { $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_API, $addData); $eventData['moderate_comments'] = true; $serendipity['csuccess'] = 'moderate'; $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_API; } } // Check if sender ip is matching trackback/pingback ip (ip validation) $trackback_ipvalidation_option = $this->get_config('trackback_ipvalidation', 'moderate'); if (($addData['type'] == 'TRACKBACK' || $addData['type'] == 'PINGBACK') && $trackback_ipvalidation_option != 'no') { $this->IsHardcoreSpammer(); $exclude_urls = explode(';', $this->get_config('trackback_ipvalidation_url_exclude', $this->get_default_exclude_urls())); $found_exclude_url = false; foreach ($exclude_urls as $exclude_url) { $exclude_url = trim($exclude_url); if (empty($exclude_url)) { continue; } $found_exclude_url = preg_match('@' . $exclude_url . '@', $addData['url']); if ($found_exclude_url) { break; } } if (!$found_exclude_url) { $parts = @parse_url($addData['url']); $tipval_method = $trackback_ipvalidation_option == 'reject' ? 'REJECTED' : 'MODERATE'; // Getting host from url successfully? if (!is_array($parts)) { // not a valid URL $this->log($logfile, $eventData['id'], $tipval_method, sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_IPVALIDATION, $addData['url'], '', ''), $addData); if ($trackback_ipvalidation_option == 'reject') { $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_IPVALIDATION, $addData['url']); return false; } else { $eventData['moderate_comments'] = true; $serendipity['csuccess'] = 'moderate'; $serendipity['moderate_reason'] = sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_IPVALIDATION, $addData['url']); } } $trackback_ip = preg_replace('/[^0-9.]/', '', gethostbyname($parts['host'])); $sender_ip = preg_replace('/[^0-9.]/', '', $_SERVER['REMOTE_ADDR']); $sender_ua = $debug ? ', ua="' . $_SERVER['HTTP_USER_AGENT'] . '"' : ''; // Is host ip and sender ip matching? if ($trackback_ip != $sender_ip) { $this->log($logfile, $eventData['id'], $tipval_method, sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_IPVALIDATION, $parts['host'], $trackback_ip, $sender_ip . $sender_ua), $addData); if ($trackback_ipvalidation_option == 'reject') { $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_IPVALIDATION, $parts['host'], $trackback_ip, $sender_ip . $sender_ua); return false; } else { $eventData['moderate_comments'] = true; $serendipity['csuccess'] = 'moderate'; $serendipity['moderate_reason'] = sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_IPVALIDATION, $parts['host'], $trackback_ip, $sender_ip . $sender_ua); } } } } // Filter Akismet Blacklist? $akismet_apikey = $this->get_config('akismet'); $akismet = $this->get_config('akismet_filter'); if (!empty($akismet_apikey) && ($akismet == 'moderate' || $akismet == 'reject') && !isset($addData['skip_akismet'])) { $spam = $this->getBlacklist('akismet.com', $akismet_apikey, $eventData, $addData); if ($spam['is_spam'] !== false) { $this->IsHardcoreSpammer(); if ($akismet == 'moderate') { $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_AKISMET_SPAMLIST . ': ' . $spam['message'], $addData); $eventData['moderate_comments'] = true; $serendipity['csuccess'] = 'moderate'; $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY . ' (Akismet)'; } else { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_AKISMET_SPAMLIST . ': ' . $spam['message'], $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; return false; } } } // Check Trackback URLs? if (($addData['type'] == 'TRACKBACK' || $addData['type'] == 'PINGBACK') && serendipity_db_bool($this->get_config('trackback_check_url'))) { require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; if (function_exists('serendipity_request_start')) { serendipity_request_start(); } $req = new HTTP_Request($addData['url'], array('allowRedirects' => true, 'maxRedirects' => 5, 'readTimeout' => array(5, 0))); $is_valid = false; if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') { $is_valid = false; } else { $fdata = $req->getResponseBody(); // Check if the target page contains a link to our blog if (preg_match('@' . preg_quote($serendipity['baseURL'], '@') . '@i', $fdata)) { $is_valid = true; } else { $is_valid = false; } } if (function_exists('serendipity_request_end')) { serendipity_request_end(); } if ($is_valid === false) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_TRACKBACKURL, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_TRACKBACKURL; return false; } } if (false === $this->wordfilter($logfile, $eventData, $wordmatch, $addData)) { return false; } // Check for maximum number of links before rejecting $link_count = substr_count(strtolower($addData['comment']), 'http://'); if ($links_reject > 0 && $link_count > $links_reject) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_REJECT, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; return false; } // Captcha checking if ($show_captcha && $addData['type'] == 'NORMAL') { if (!isset($_SESSION['spamblock']['captcha']) || !isset($serendipity['POST']['captcha']) || strtolower($serendipity['POST']['captcha']) != strtolower($_SESSION['spamblock']['captcha'])) { $this->log($logfile, $eventData['id'], 'REJECTED', sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_CAPTCHAS, $serendipity['POST']['captcha'], $_SESSION['spamblock']['captcha']), $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_CAPTCHAS; return false; } else { // DEBUG // $this->log($logfile, $eventData['id'], 'REJECTED', 'Captcha passed: ' . $serendipity['POST']['captcha'] . ' / ' . $_SESSION['spamblock']['captcha'] . ' // Source: ' . $_SERVER['REQUEST_URI'], $addData); } } else { // DEBUG // $this->log($logfile, $eventData['id'], 'REJECTED', 'Captcha not needed: ' . $serendipity['POST']['captcha'] . ' / ' . $_SESSION['spamblock']['captcha'] . ' // Source: ' . $_SERVER['REQUEST_URI'], $addData); } // Check for forced comment moderation (X days) if ($addData['type'] == 'NORMAL' && $forcemoderation > 0 && $eventData['timestamp'] < time() - $forcemoderation * 60 * 60 * 24) { $this->log($logfile, $eventData['id'], $forcemoderation_treat, PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION, $addData); if ($forcemoderation_treat == 'reject') { $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION; return false; } else { $eventData['moderate_comments'] = true; $serendipity['csuccess'] = 'moderate'; $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION; } } // Check for forced trackback moderation if ($addData['type'] != 'NORMAL' && $forcemoderationt > 0 && $eventData['timestamp'] < time() - $forcemoderationt * 60 * 60 * 24) { $this->log($logfile, $eventData['id'], $forcemoderationt_treat, PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION, $addData); if ($forcemoderationt_treat == 'reject') { $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION; return false; } else { $eventData['moderate_comments'] = true; $serendipity['csuccess'] = 'moderate'; $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION; } } // Check for maximum number of links before forcing moderation if ($links_moderate > 0 && $link_count > $links_moderate) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_MODERATE, $addData); $eventData['moderate_comments'] = true; $serendipity['csuccess'] = 'moderate'; $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_MODERATE; } // Check for identical comments. We allow to bypass trackbacks from our server to our own blog. if ($this->get_config('bodyclone', true) === true && $_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR'] && $addData['type'] != 'PINGBACK') { $query = "SELECT count(id) AS counter FROM {$serendipity['dbPrefix']}comments WHERE type = '" . $addData['type'] . "' AND body = '" . serendipity_db_escape_string($addData['comment']) . "'"; $row = serendipity_db_query($query, true); if (is_array($row) && $row['counter'] > 0) { $this->IsHardcoreSpammer(); $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_BODYCLONE, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; return false; } } // Check last IP if ($addData['type'] == 'NORMAL' && $this->get_config('ipflood', 2) != 0) { $query = "SELECT max(timestamp) AS last_post FROM {$serendipity['dbPrefix']}comments WHERE ip = '" . serendipity_db_escape_string($_SERVER['REMOTE_ADDR']) . "'"; $row = serendipity_db_query($query, true); if (is_array($row) && $row['last_post'] > time() - $this->get_config('ipflood', 2) * 60) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_IPFLOOD, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_IP; return false; } } if ($addData['type'] == 'NORMAL' && (string) $checkmail === 'verify_always') { $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_CHECKMAIL_VERIFICATION_MAIL, $addData); $eventData['moderate_comments'] = true; $eventData['status'] = 'confirm'; $serendipity['csuccess'] = 'moderate'; $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_CHECKMAIL_VERIFICATION_MAIL; return false; } // Check invalid email if ($addData['type'] == 'NORMAL' && serendipity_db_bool($this->get_config('checkmail', false))) { if (!empty($addData['email']) && strstr($addData['email'], '@') === false) { $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_CHECKMAIL, $addData); $eventData = array('allow_comments' => false); $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_CHECKMAIL; return false; } } if ($eventData['moderate_comments'] == true) { return false; } } return true; break; case 'frontend_comment': if (serendipity_db_bool($this->get_config('hide_email', false))) { echo '<div class="serendipity_commentDirection serendipity_comment_spamblock">' . PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_NOTICE . '</div>'; } if ((string) $this->get_config('checkmail') === 'verify_always' || (string) $this->get_config('checkmail') === 'verify_once') { echo '<div class="serendipity_commentDirection serendipity_comment_spamblock">' . PLUGIN_EVENT_SPAMBLOCK_CHECKMAIL_VERIFICATION_INFO . '</div>'; } if (serendipity_db_bool($this->get_config('csrf', true))) { echo serendipity_setFormToken('form'); } // Check whether to allow comments from registered authors if (serendipity_userLoggedIn() && $this->inGroup()) { return true; } if ($show_captcha) { echo '<div class="serendipity_commentDirection serendipity_comment_captcha">'; if (!isset($serendipity['POST']['preview']) || strtolower($serendipity['POST']['captcha'] != strtolower($_SESSION['spamblock']['captcha']))) { echo '<br />' . PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC . '<br />'; echo $this->show_captcha($use_gd); echo '<br />'; echo '<label for="captcha">' . PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC3 . '</label><br /><input class="input_textbox" type="text" size="5" name="serendipity[captcha]" value="" id="captcha" />'; } elseif (isset($serendipity['POST']['captcha'])) { echo '<input type="hidden" name="serendipity[captcha]" value="' . serendipity_specialchars($serendipity['POST']['captcha']) . '" />'; } echo '</div>'; } return true; break; case 'external_plugin': $parts = explode('_', (string) $eventData); if (!empty($parts[1])) { $param = (int) $parts[1]; } else { $param = null; } $methods = array('captcha'); if (!in_array($parts[0], $methods)) { return; } list($musec, $msec) = explode(' ', microtime()); $srand = (double) $msec + (double) $musec * 100000; srand($srand); mt_srand($srand); $width = 120; $height = 40; $bgcolors = explode(',', $this->get_config('captcha_color', '255,255,255')); $fontfiles = array('Vera.ttf', 'VeraSe.ttf', 'chumbly.ttf', '36daysago.ttf'); if ($use_gd) { $strings = $this->random_string($max_char, $min_char); $fontname = $fontfiles[array_rand($fontfiles)]; $font = $serendipity['serendipityPath'] . 'plugins/serendipity_event_spamblock/' . $fontname; if (!file_exists($font)) { // Search in shared plugin directory $font = S9Y_INCLUDE_PATH . 'plugins/serendipity_event_spamblock/' . $fontname; } if (!file_exists($font)) { die(PLUGIN_EVENT_SPAMBLOCK_ERROR_NOTTF); } header('Content-Type: image/jpeg'); $image = imagecreate($width, $height); // recommended use of imagecreatetruecolor() returns a black backgroundcolor $bgcol = imagecolorallocate($image, trim($bgcolors[0]), trim($bgcolors[1]), trim($bgcolors[2])); // imagettftext($image, 10, 1, 1, 15, imagecolorallocate($image, 255, 255, 255), $font, 'String: ' . $string); $pos_x = 5; foreach ($strings as $idx => $charidx) { $color = imagecolorallocate($image, mt_rand(50, 235), mt_rand(50, 235), mt_rand(50, 235)); $size = mt_rand(15, 21); $angle = mt_rand(-20, 20); $pos_y = ceil($height - mt_rand($size / 3, $size / 2)); imagettftext($image, $size, $angle, $pos_x, $pos_y, $color, $font, $this->chars[$charidx]); $pos_x = $pos_x + $size + 2; } if ($_captchas === 'scramble') { $line_diff = mt_rand(5, 15); $pixel_col = imagecolorallocate($image, trim($bgcolors[0]) - mt_rand(10, 50), trim($bgcolors[1]) - mt_rand(10, 50), trim($bgcolors[2]) - mt_rand(10, 50)); for ($y = $line_diff; $y < $height; $y += $line_diff) { $row_diff = mt_rand(5, 15); for ($x = $row_diff; $x < $width; $x += $row_diff) { imagerectangle($image, $x, $y, $x + 1, $y + 1, $pixel_col); } } } imagejpeg($image, NULL, 90); // NULL fixes https://bugs.php.net/bug.php?id=63920 imagedestroy($image); } else { header('Content-Type: image/png'); $output_char = strtolower($_SESSION['spamblock']['captcha'][$parts[1] - 1]); $cap = $serendipity['serendipityPath'] . 'plugins/serendipity_event_spamblock/captcha_' . $output_char . '.png'; if (!file_exists($cap)) { $cap = S9Y_INCLUDE_PATH . 'plugins/serendipity_event_spamblock/captcha_' . $output_char . '.png'; } if (file_exists($cap)) { echo file_get_contents($cap); } } return true; break; case 'backend_comments_top': // Tell Akismet about spam or not spam $tell_id = null; if (isset($serendipity['GET']['spamIsSpam'])) { $tell_spam = true; $tell_id = $serendipity['GET']['spamIsSpam']; } if (isset($serendipity['GET']['spamNotSpam'])) { $tell_spam = false; $tell_id = $serendipity['GET']['spamNotSpam']; } if ($tell_id !== null) { $akismet_apikey = $this->get_config('akismet'); $akismet = $this->get_config('akismet_filter'); if (!empty($akismet_apikey)) { $this->tellAboutComment('akismet.com', $akismet_apikey, $tell_id, $tell_spam); } } // Add Author to blacklist. If already filtered, it will be removed from the filter. (AKA "Toggle") if (isset($serendipity['GET']['spamBlockAuthor'])) { $item = $this->getComment('author', $serendipity['GET']['spamBlockAuthor']); $items =& $this->checkFilter('authors', $item, true); $this->set_config('contentfilter_authors', implode(';', $items)); } // Add URL to blacklist. If already filtered, it will be removed from the filter. (AKA "Toggle") if (isset($serendipity['GET']['spamBlockURL'])) { $item = $this->getComment('url', $serendipity['GET']['spamBlockURL']); $items =& $this->checkFilter('urls', $item, true); $this->set_config('contentfilter_urls', implode(';', $items)); } // Add E-mail to blacklist. If already filtered, it will be removed from the filter. (AKA "Toggle") if (isset($serendipity['GET']['spamBlockEmail'])) { $item = $this->getComment('email', $serendipity['GET']['spamBlockEmail']); $items =& $this->checkFilter('emails', $item, true); $this->set_config('contentfilter_emails', implode(';', $items)); } echo '<a class="button_link" title="' . PLUGIN_EVENT_SPAMBLOCK_CONFIG . '" href="serendipity_admin.php?serendipity[adminModule]=plugins&serendipity[plugin_to_conf]=' . $this->instance . '"><span class="icon-medkit"></span><span class="visuallyhidden"> ' . PLUGIN_EVENT_SPAMBLOCK_CONFIG . '</span></a>'; return true; break; case 'backend_view_comment': $author_is_filtered = $this->checkFilter('authors', $eventData['author']); $clink = 'comment_' . $eventData['id']; $randomString = '&random=' . substr(sha1(rand()), 0, 10); # the random string will force browser to reload the page, # so the server knows who to block/unblock when clicking again on the same link, # see http://stackoverflow.com/a/2573986/2508518, http://stackoverflow.com/a/14043346/2508518 $akismet_apikey = $this->get_config('akismet'); $akismet = $this->get_config('akismet_filter'); if (!empty($akismet_apikey)) { $eventData['action_more'] .= ' <a class="button_link actions_extra" title="' . PLUGIN_EVENT_SPAMBLOCK_SPAM . '" href="serendipity_admin.php?serendipity[adminModule]=comments&serendipity[spamIsSpam]=' . $eventData['id'] . $addData . '#' . $clink . '"><span class="icon-block"></span><span class="visuallyhidden"> ' . PLUGIN_EVENT_SPAMBLOCK_SPAM . '</span></a>'; $eventData['action_more'] .= ' <a class="button_link actions_extra" title="' . PLUGIN_EVENT_SPAMBLOCK_NOT_SPAM . '" href="serendipity_admin.php?serendipity[adminModule]=comments&serendipity[spamNotSpam]=' . $eventData['id'] . $addData . '#' . $clink . '"><span class="icon-ok-circled"></span><span class="visuallyhidden"> ' . PLUGIN_EVENT_SPAMBLOCK_NOT_SPAM . '</span></a>'; } $eventData['action_author'] .= ' <a class="button_link" title="' . ($author_is_filtered ? PLUGIN_EVENT_SPAMBLOCK_REMOVE_AUTHOR : PLUGIN_EVENT_SPAMBLOCK_ADD_AUTHOR) . '" href="serendipity_admin.php?serendipity[adminModule]=comments&serendipity[spamBlockAuthor]=' . $eventData['id'] . $addData . $randomString . '#' . $clink . '"><span class="icon-' . ($author_is_filtered ? 'ok-circled' : 'block') . '"></span><span class="visuallyhidden"> ' . ($author_is_filtered ? PLUGIN_EVENT_SPAMBLOCK_REMOVE_AUTHOR : PLUGIN_EVENT_SPAMBLOCK_ADD_AUTHOR) . '</span></a>'; if (!empty($eventData['url'])) { $url_is_filtered = $this->checkFilter('urls', $eventData['url']); $eventData['action_url'] .= ' <a class="button_link" title="' . ($url_is_filtered ? PLUGIN_EVENT_SPAMBLOCK_REMOVE_URL : PLUGIN_EVENT_SPAMBLOCK_ADD_URL) . '" href="serendipity_admin.php?serendipity[adminModule]=comments&serendipity[spamBlockURL]=' . $eventData['id'] . $addData . $randomString . '#' . $clink . '"><span class="icon-' . ($url_is_filtered ? 'ok-circled' : 'block') . '"></span><span class="visuallyhidden"> ' . ($url_is_filtered ? PLUGIN_EVENT_SPAMBLOCK_REMOVE_URL : PLUGIN_EVENT_SPAMBLOCK_ADD_URL) . '</span></a>'; } if (!empty($eventData['email'])) { $email_is_filtered = $this->checkFilter('emails', $eventData['email']); $eventData['action_email'] .= ' <a class="button_link" title="' . ($email_is_filtered ? PLUGIN_EVENT_SPAMBLOCK_REMOVE_EMAIL : PLUGIN_EVENT_SPAMBLOCK_ADD_EMAIL) . '" href="serendipity_admin.php?serendipity[adminModule]=comments&serendipity[spamBlockEmail]=' . $eventData['id'] . $addData . $randomString . '#' . $clink . '"><span class="icon-' . ($email_is_filtered ? 'ok-circled' : 'block') . '"></span><span class="visuallyhidden"> ' . ($email_is_filtered ? PLUGIN_EVENT_SPAMBLOCK_REMOVE_EMAIL : PLUGIN_EVENT_SPAMBLOCK_ADD_EMAIL) . '</span></a>'; } return true; break; case 'backend_sidebar_admin_appearance': echo '<li><a href="serendipity_admin.php?serendipity[adminModule]=plugins&serendipity[plugin_to_conf]=' . $this->instance . '">' . PLUGIN_EVENT_SPAMBLOCK_TITLE . '</a></li>'; return true; break; default: return false; break; } } else { return false; } }
function updateTwitterTimelineCache($cachefile) { global $serendipity; $cachetime = (int) $this->get_config('cachetime', 300); if (!file_exists($cachefile) || filemtime($cachefile) < time() - $cachetime) { require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; $service = $this->get_config('service'); $username = $this->get_config('username'); $number = $this->get_config('number'); if (serendipity_db_bool($this->get_config('toall_only', false))) { $number = 50; // Fetch many in the hope, that there are enough globals with it. } if ($service == 'identi.ca') { $service_url = 'http://identi.ca/api'; $status_url = 'http://identi.ca/notice/'; $search_twitter_uri = $service_url . '/statuses/user_timeline/' . $username . '.json?count=' . $number; } else { $followme_url = 'https://twitter.com/' . $username; $service_url = 'https://api.twitter.com'; $status_url = 'https://twitter.com/' . $username . '/statuses/'; $search_twitter_uri = 'https://api.twitter.com/1/statuses/user_timeline.json?screen_name=' . $username . '&count=' . $number; } serendipity_request_start(); $req = new HTTP_Request($search_twitter_uri); $req->sendRequest(); $response = trim($req->getResponseBody()); $error = $req->getResponseCode(); serendipity_request_end(); if ($error == 200 && !empty($response)) { $fp = fopen($cachefile, 'w'); fwrite($fp, serialize($response)); fflush($fp); fclose($fp); } } }
function &fetchfile($url, $target, $cacheTimeout = 0, $decode_utf8 = false, $sub = 'plugins') { global $serendipity; static $error = false; // Fix double URL strings. $url = preg_replace('@http(s)?:/@i', 'http\\1://', str_replace('//', '/', $url)); // --JAM: Get the URL's IP in the most error-free way possible $url_parts = @parse_url($url); $url_hostname = 'localhost'; if (is_array($url_parts)) { $url_hostname = $url_parts['host']; } $url_ip = gethostbyname($url_hostname); if (is_object($serendipity['logger'])) { $serendipity['logger']->debug(sprintf(PLUGIN_EVENT_SPARTACUS_FETCHING, '<a target="_blank" href="' . $url . '">' . basename($url) . '</a>')); } if (file_exists($target) && filesize($target) > 0 && filemtime($target) >= time() - $cacheTimeout) { $data = file_get_contents($target); if (is_object($serendipity['logger'])) { $serendipity['logger']->debug(sprintf(PLUGIN_EVENT_SPARTACUS_FETCHED_BYTES_CACHE, strlen($data), $target)); } } else { require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; $options = array('allowRedirects' => true, 'maxRedirects' => 5); serendipity_plugin_api::hook_event('backend_http_request', $options, 'spartacus'); serendipity_request_start(); $req = new HTTP_Request($url, $options); if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') { $resolved_url = $url . ' (IP ' . $url_ip . ')'; $this->outputMSG('error', sprintf(PLUGIN_EVENT_SPARTACUS_FETCHERROR, $resolved_url)); //--JAM: START FIREWALL DETECTION if ($req->getResponseCode()) { $this->outputMSG('error', sprintf(PLUGIN_EVENT_SPARTACUS_REPOSITORY_ERROR, $req->getResponseCode())); } $check_health = true; if (function_exists('curl_init')) { $this->outputMSG('notice', PLUGIN_EVENT_SPARTACUS_TRYCURL); $curl_handle = curl_init(); curl_setopt($curl_handle, CURLOPT_URL, $url); curl_setopt($curl_handle, CURLOPT_HEADER, 0); $curl_result = curl_exec($curl_handle); curl_close($curl_handle); if ($curl_result) { $check_health = false; } else { $this->outputMSG('error', PLUGIN_EVENT_SPARTACUS_CURLFAIL . "\n"); } } } if ($check_health) { /*--JAM: Useful for later, when we have a health monitor for SPARTACUS $propbag = new serendipity_property_bag; $this->introspect($propbag); $health_url = 'http://spartacus.s9y.org/spartacus_health.php?version=' . $propbag->get('version'); */ // Garvin: Temporary health. Better than nothing, eh? $health_url = $url; $matches = array(); preg_match('#http://[^/]*/#', $url, $matches); if ($matches[0]) { $health_url = $matches[0]; } $mirrors = $this->getMirrors('files_health', true); $health_url = $mirrors[$health_url]; $this->outputMSG('notice', sprintf(PLUGIN_EVENT_SPARTACUS_HEALTHCHECK, $health_url)); $health_options = $options; serendipity_plugin_api::hook_event('backend_http_request', $health_options, 'spartacus_health'); $health_req = new HTTP_Request($health_url, $health_options); $health_result = $health_req->sendRequest(); if (PEAR::isError($health_result)) { $fp = @fsockopen('www.google.com', 80, $errno, $errstr); if (!$fp) { $this->outputMSG('error', sprintf(PLUGIN_EVENT_SPARTACUS_HEALTHBLOCKED, $errno, $errstr)); } else { $this->outputMSG('error', PLUGIN_EVENT_SPARTACUS_HEALTHDOWN); $this->outputMSG('notice', sprintf(PLUGIN_EVENT_SPARTACUS_HEALTHLINK, $health_url)); fclose($fp); } } else { if ($health_req->getResponseCode() != '200') { $this->outputMSG('error', sprintf(PLUGIN_EVENT_SPARTACUS_HEALTHERROR, $health_req->getResponseCode())); $this->outputMSG('notice', sprintf(PLUGIN_EVENT_SPARTACUS_HEALTHLINK, $health_url)); } else { $this->outputMSG('error', PLUGIN_EVENT_SPARTACUS_HEALTFIREWALLED); //--JAM: Parse response and display it. } } //--JAM: END FIREWALL DETECTION if (file_exists($target) && filesize($target) > 0) { $data = file_get_contents($target); $this->outputMSG('success', sprintf(PLUGIN_EVENT_SPARTACUS_FETCHED_BYTES_CACHE, strlen($data), $target)); } } else { // Fetch file if (!$data) { $data = $req->getResponseBody(); } if (is_object($serendipity['logger'])) { $serendipity['logger']->debug(sprintf(PLUGIN_EVENT_SPARTACUS_FETCHED_BYTES_URL, strlen($data), $target)); } $tdir = dirname($target); if (!is_dir($tdir) && !$this->rmkdir($tdir, $sub)) { $this->outputMSG('error', sprintf(FILE_WRITE_ERROR, $tdir)); return $error; } $fp = @fopen($target, 'w'); if (!$fp) { $this->outputMSG('error', sprintf(FILE_WRITE_ERROR, $target)); return $error; } if ($decode_utf8) { $data = str_replace('<?xml version="1.0" encoding="UTF-8" ?>', '<?xml version="1.0" encoding="' . LANG_CHARSET . '" ?>', $data); $this->decode($data, true); } fwrite($fp, $data); fclose($fp); $this->fileperm($target, false); $this->purgeCache = true; } serendipity_request_end(); } return $data; }
/** * Caches an avatar and streams it back to the browser. */ function saveAndResponseAvatar($eventData, $url, $allow_redirection = 3) { require_once S9Y_PEAR_PATH . 'HTTP/Request2.php'; global $serendipity; $fContent = null; if (function_exists('serendipity_request_start')) { serendipity_request_start(); } if ($allow_redirection) { $request_pars['follow_redirects'] = true; $request_pars['max_redirects'] = $allow_redirection; } else { $request_pars['follow_redirects'] = false; } if (version_compare(PHP_VERSION, '5.6.0', '<')) { // On earlier PHP versions, the certificate validation fails. We deactivate it on them to restore the functionality we had with HTTP/Request1 $request_pars['ssl_verify_peer'] = false; } $req = new HTTP_Request2($url, HTTP_Request2::METHOD_GET, $request_pars); try { $response = $req->send(); if ($response->getStatus() != '200') { throw new HTTP_Request2_Exception("Could not search on identica"); } // Allow only images as Avatar! $mime = $response->getHeader("content-type"); $this->avatarConfiguration['mime-type'] = $mime; $this->log("Avatar fetch mimetype: {$mime}" . " for url=" . $url); $mimeparts = explode('/', $mime); if (count($mimeparts) == 2 && $mimeparts[0] == 'image') { $fContent = $response->getBody(); } } catch (HTTP_Request2_Exception $e) { $fContent = null; $this->log("Avatar fetch error: " . $e); } if (function_exists('serendipity_request_start')) { serendipity_request_end(); } // if no content was fetched, return false if (!isset($fContent) || empty($fContent)) { $this->log("Avatar fetch: no Content!"); return false; } $cache_file = $this->cacheAvatar($eventData, $fContent); if ($cache_file) { $this->show($cache_file); } else { if ($this->supportDefaultAvatar()) { $this->fetchDefault(); } } return true; }
function updateTwitterTimelineCache($parts) { global $serendipity; require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; if (count($parts) < 5) { return time() + 60 * 60; } // params corrupted next try allowed one minute later // Do we need to do OAuth? if (count($parts) > 6) { $idx_twitter = $parts[5]; $idxmd5 = $parts[6]; $idxmd5_test = md5(serendipity_event_twitter::pluginSecret() . "_{$idx_twitter}"); if ($idxmd5_test != $idxmd5) { // Seems to be a hack! return time() + 60 * 60; // params corrupted next try allowed one minute later } } $show_rt = false; if (count($parts) > 7) { $features = $parts[7]; $show_rt = strpos($features, 'r') !== false; } $cachetime = (int) $parts[4]; $service = $parts[1]; $username = str_replace('!', '_', $parts[2]); $cache_user = md5($service) . md5($username); $cachefile = $serendipity['serendipityPath'] . PATH_SMARTY_COMPILE . "/twitterresult.{$cache_user}.json"; $nextcheck = time() + (int) $cachetime; if (file_exists($cachefile)) { $nextcheck = filemtime($cachefile) + $cachetime; } if (!file_exists($cachefile) || filemtime($cachefile) < time() - $cachetime) { $number = str_replace("!", "_", $parts[3]); $error = 200; // Default is: All OK if (!empty($idx_twitter)) { $search_twitter_uri = 'https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=' . $username . '&count=' . $number . '&trim_user=true'; if (!$show_rt) { $search_twitter_uri .= '&include_rts=false'; } if ($idx_twitter == '1') { $idx_twitter = ''; } // First cfg is saved with empty suffix! $connection = $this->twitteroa_connect($idx_twitter); $connection->decode_json = false; $response = $connection->get($search_twitter_uri); } else { if ($service == 'identi.ca') { $followme_url = 'http://identi.ca/' . $username; $status_url = 'http://identi.ca/notice/'; $JSONcallback = 'identicaCallback2'; $service_url = 'http://identi.ca/api'; $search_twitter_uri = $service_url . '/statuses/user_timeline/' . $username . '.json?count=' . $number; } else { $followme_url = 'https://twitter.com/' . $username; $service_url = 'https://twitter.com'; $status_url = 'https://twitter.com/' . $username . '/statuses/'; $JSONcallback = 'twitterCallback2'; $search_twitter_uri = 'https://api.twitter.com/1/statuses/user_timeline.json?screen_name=' . $username . '&count=' . $number; } serendipity_request_start(); $req = new HTTP_Request($search_twitter_uri); $req->sendRequest(); $response = trim($req->getResponseBody()); $error = $req->getResponseCode(); serendipity_request_end(); } $this->log("error: {$error}"); if ($error == 200 && !empty($response)) { $this->log("Writing response into cache."); $fp = fopen($cachefile, 'w'); fwrite($fp, serialize($response)); fflush($fp); fclose($fp); $nextcheck = time() + (int) $cachetime; $this->log("Writing response into cache. DONE"); } } return $nextcheck; }
function userinfo($screenname) { if (empty($screenname)) { echo "screenname empty"; return; } require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; $requrl = $this->get_api_url() . 'users/show.json?screen_name=' . $screenname; if (function_exists('serendipity_request_start')) { serendipity_request_start(); } $req = new HTTP_Request($requrl); $req->sendRequest(); $response = trim($req->getResponseBody()); if (function_exists('serendipity_request_start')) { serendipity_request_end(); } return @json_decode($response); }
/** * Fetches additional comment data from the page that sent the pingback * @access private * @param array comment array to be filled */ function fetchPingbackData(&$comment) { global $serendipity; // Don't fetch remote page, if not explicitly allowed in serendipity_config_local.php: if (empty($serendipity['pingbackFetchPage'])) { return; } // If we don't have a comment or a commentors url, stop it. if (!isset($comment) || !is_array($comment) || !isset($comment['url'])) { return; } // Max amount of characters fetched from the page doing a pingback: $fetchPageMaxLength = 200; if (isset($serendipity['pingbackFetchPageMaxLength'])) { $fetchPageMaxLength = $serendipity['pingbackFetchPageMaxLength']; } require_once S9Y_PEAR_PATH . 'HTTP/Request2.php'; $url = $comment['url']; if (function_exists('serendipity_request_start')) { serendipity_request_start(); } // Request the page $options = array('follow_redirects' => true, 'max_redirects' => 5, 'timeout' => 20); if (version_compare(PHP_VERSION, '5.6.0', '<')) { // On earlier PHP versions, the certificate validation fails. We deactivate it on them to restore the functionality we had with HTTP/Request1 $options['ssl_verify_peer'] = false; } $req = new HTTP_Request2($url, HTTP_Request2::METHOD_GET, $options); // code 200: OK, code 30x: REDIRECTION $responses = "/(200)|(30[0-9])/"; // |(30[0-9] Moved) try { $response = $req->send(); if (preg_match($responses, $response->getStatus())) { } $fContent = $response->getBody(); // Get a title if (preg_match('@<head[^>]*>.*?<title[^>]*>(.*?)</title>.*?</head>@is', $fContent, $matches)) { $comment['title'] = serendipity_entity_decode(strip_tags($matches[1]), ENT_COMPAT, LANG_CHARSET); } // Try to get content from first <p> tag on: if (preg_match('@<p[^>]*>(.*?)</body>@is', $fContent, $matches)) { $body = $matches[1]; } if (empty($body) && preg_match('@<body[^>]*>(.*?)</body>@is', $fContent, $matches)) { $body = $matches[1]; } // Get a part of the article if (!empty($body)) { $body = trackback_body_strip($body); // truncate the text to 200 chars $arr = str_split($body, $fetchPageMaxLength); $body = $arr[0]; $comment['comment'] = $body . '[..]'; } } catch (HTTP_Request2_Exception $e) { } if (function_exists('serendipity_request_end')) { serendipity_request_end(); } }
/** * Make an HTTP request * * @return API results */ function http($url, $method, $postfields = NULL) { $this->http_info = array(); if (function_exists('curl_init')) { $ci = curl_init(); /* Curl settings */ curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent); curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout); curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout); curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:')); curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer); curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader')); curl_setopt($ci, CURLOPT_HEADER, FALSE); switch ($method) { case 'POST': curl_setopt($ci, CURLOPT_POST, TRUE); if (!empty($postfields)) { curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields); } break; case 'DELETE': curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE'); if (!empty($postfields)) { $url = "{$url}?{$postfields}"; } } curl_setopt($ci, CURLOPT_URL, $url); $response = curl_exec($ci); $this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE); $this->http_info = array_merge($this->http_info, curl_getinfo($ci)); $this->url = $url; curl_close($ci); } else { require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; serendipity_request_start(); $req = new HTTP_Request($url); switch ($method) { case 'POST': $req->setMethod(HTTP_REQUEST_METHOD_POST); if (!empty($postfields)) { $fields = explode('&', $postfields); foreach ($fields as $field) { $data = explode('=', $field); $req->addPostData($data[0], $data[1], true); } } break; case 'DELETE': $req->setMethod(HTTP_REQUEST_METHOD_DELETE); if (!empty($postfields)) { $url = "{$url}?{$postfields}"; } } $req->sendRequest(); $response = trim($req->getResponseBody()); $this->url = $url; $this->http_code = $req->getResponseCode(); serendipity_event_twitter::twitteroalog($url . " - " . $postfields . " (Code: " . $this->http_code . ")\n" . $response); serendipity_request_end(); } return $response; }
function urlcheck($uri) { // These two substring comparisons are faster than one regexp. if ('http://' != substr($uri, 0, 7) && 'https://' != substr($uri, 0, 8)) { return false; } // Disabled by now. May get enabled in the future, but for now the extra HTTP call isn't worth trying. return true; require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; serendipity_request_start(); $req = new HTTP_Request($uri); if (PEAR::isError($req->sendRequest()) || !preg_match('@^[23]..@', $req->getResponseCode())) { serendipity_request_end(); return false; } else { serendipity_request_end(); return true; } }
/** * Caches a map and streams it back to the browser. */ function saveAndResponseMap($url, $lat, $long, $isArticle) { require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; global $serendipity; $fContent = null; if (function_exists('serendipity_request_start')) { serendipity_request_start(); } $request_pars['allowRedirects'] = TRUE; $req = new HTTP_Request($url, $request_pars); // if the request leads to an error we don't want to have it: return false if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') { $fContent = null; } else { // Allow only images! $mime = $req->getResponseHeader("content-type"); $mimeparts = explode('/', $mime); if (count($mimeparts) == 2 && $mimeparts[0] == 'image') { $fContent = $req->getResponseBody(); } } if (function_exists('serendipity_request_start')) { serendipity_request_end(); } // if no content was fetched, return false if (!isset($fContent)) { return false; } $cache_file = $this->cacheMap($lat, $long, $isArticle, $fContent, $req); if ($cache_file) { $this->showMap($cache_file); } return true; }
function event_hook($event, &$bag, &$eventData) { global $serendipity; $hooks =& $bag->get('event_hooks'); if (isset($hooks[$event])) { switch ($event) { case 'backend_display': ?> <fieldset style="margin: 5px"> <legend><?php echo PLUGIN_EVENT_WEBLOGPING_PING; ?> </legend> <?php $noneclick = ''; foreach ($this->services as $index => $service) { // Detect if the current checkbox needs to be saved. We use the field chk_timestamp to see, // if the form has already been submitted and individual changes shall be preserved $selected = $serendipity['POST']['chk_timestamp'] && $serendipity['POST']['announce_entries_' . $service['name']] || !isset($serendipity['POST']['chk_timestamp']) && $this->get_config($service['name']) == 'true' ? 'checked="checked"' : ''; $noneclick .= 'document.getElementById(\'serendipity[announce_entries_' . $service['name'] . ']\').checked = false; '; $onclick = ''; if (!empty($service['supersedes'])) { $onclick = 'onclick="'; $supersedes = explode(', ', $service['supersedes']); foreach ($supersedes as $sid => $servicename) { $onclick .= 'document.getElementById(\'serendipity[announce_entries_' . $servicename . ']\').checked = false; '; } $onclick .= '"'; } $title = sprintf(PLUGIN_EVENT_WEBLOGPING_SENDINGPING, $service['name']) . (!empty($service['supersedes']) ? ' ' . sprintf(PLUGIN_EVENT_WEBLOGPING_SUPERSEDES, $service['supersedes']) : ''); ?> <input <?php echo $onclick; ?> class="input_checkbox" style="margin: 0px; padding: 0px; vertical-align: bottom;" type="checkbox" name="serendipity[announce_entries_<?php echo $service['name']; ?> ]" id="serendipity[announce_entries_<?php echo $service['name']; ?> ]" value="true" <?php echo $selected; ?> /> <label title="<?php echo $title; ?> " style="vertical-align: bottom; margin: 0px; padding: 0px;" for="serendipity[announce_entries_<?php echo $service['name']; ?> ]"> <?php echo $service['name']; ?> </label><br /> <?php } ?> <input onclick="<?php echo $noneclick; ?> " class="input_checkbox" style="margin: 0px; padding: 0px; vertical-align: bottom;" type="checkbox" value="none" id="serendipity[announce_entries_none]" /> <label title="<?php echo NONE; ?> " style="vertical-align: bottom; margin: 0px; padding: 0px;" for="serendipity[announce_entries_none]"> <?php echo NONE; ?> </label><br /> </fieldset> <?php return true; break; case 'backend_publish': if (!class_exists('XML_RPC_Base')) { include_once S9Y_PEAR_PATH . "XML/RPC.php"; } // First cycle through list of services to remove superseding services which may have been checked foreach ($this->services as $index => $service) { if (!empty($service['supersedes']) && isset($serendipity['POST']['announce_entries_' . $service['name']])) { $supersedes = explode(', ', $service['supersedes']); foreach ($supersedes as $sid => $servicename) { // A service has been checked that is superseded by another checked meta-service. Remove that service from the list of services to be ping'd unset($serendipity['POST']['announce_entries_' . $servicename]); } } } foreach ($this->services as $index => $service) { if (isset($serendipity['POST']['announce_entries_' . $service['name']]) || defined('SERENDIPITY_IS_XMLRPC') && serendipity_db_bool($this->get_config($service['name']))) { if (!defined('SERENDIPITY_IS_XMLRPC') || defined('SERENDIPITY_XMLRPC_VERBOSE')) { printf(PLUGIN_EVENT_WEBLOGPING_SENDINGPING . '...', $service['host']); } flush(); # XXX append $serendipity['indexFile'] to baseURL? $args = array(new XML_RPC_Value($serendipity['blogTitle'], 'string'), new XML_RPC_Value($serendipity['baseURL'], 'string')); if ($service['extended']) { # the checkUrl: for when the main page is not really the main page $args[] = new XML_RPC_Value('', 'string'); # the rssUrl $args[] = new XML_RPC_Value($serendipity['baseURL'] . 'rss.php?version=2.0', 'string'); } $message = new XML_RPC_Message($service['extended'] ? 'weblogUpdates.extendedPing' : 'weblogUpdates.ping', $args); $client = new XML_RPC_Client(trim($service['path']), trim($service['host'])); # 15 second timeout may not be long enough for weblogs.com $message->createPayload(); $options = array(); serendipity_plugin_api::hook_event('backend_http_request', $options, 'weblogping'); serendipity_request_start(); $req = new HTTP_Request("http://" . $service['host'] . $service['path'], $options); $req->setMethod(HTTP_REQUEST_METHOD_POST); $req->addHeader("Content-Type", "text/xml"); if (strtoupper(LANG_CHARSET) != 'UTF-8') { $payload = utf8_encode($message->payload); } else { $payload = $message->payload; } $req->addRawPostData($payload); $http_result = $req->sendRequest(); $http_response = $req->getResponseBody(); $xmlrpc_result = $message->parseResponse($http_response); if ($xmlrpc_result->faultCode()) { $out = sprintf(PLUGIN_EVENT_WEBLOGPING_SEND_FAILURE . "<br />", htmlspecialchars($xmlrpc_result->faultString())); } else { $out = PLUGIN_EVENT_WEBLOGPING_SEND_SUCCESS . "<br />"; } serendipity_request_end(); if (!defined('SERENDIPITY_IS_XMLRPC') || defined('SERENDIPITY_XMLRPC_VERBOSE')) { echo $out; } } } return true; break; case 'external_plugin': if ($eventData == 'xmlrpc_ping') { echo "XMLRPC START\n"; @define('SERENDIPITY_IS_XMLRPC', true); @define('SERENDIPITY_XMLRPC_VERBOSE', true); $this->event_hook('backend_publish', $bag, $eventData); echo "XMLRPC DONE\n"; } return true; case 'frontend_display': case 'backend_insert': case 'backend_update': case 'backend_draft': default: return false; break; } } else { return false; } }
function fetchFacebook() { global $serendipity; $this->install(); if ($this->debug) { $fp = fopen('/tmp/facebook.log', 'a'); fwrite($fp, date('d.m.Y H:i') . 'Facebook run'); fclose($fp); } header('Content-Type: text/plain; charset=' . LANG_CHARSET); require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; $users = explode(',', $this->get_config('facebook_users')); foreach ($users as $user) { $user = trim($user); if (empty($user)) { continue; } $url = 'http://graph.facebook.com/' . $user . '/posts?limit=' . $this->get_config('limit'); serendipity_request_start(); $req = new HTTP_Request($url, array('allowRedirects' => true, 'maxRedirects' => 3)); // code 200: OK, code 30x: REDIRECTION if (PEAR::isError($req->sendRequest()) || !preg_match('/200/', $req->getResponseCode())) { if ($this->debug) { echo "Request failed. (" . $req->getResponseCode() . ")"; } serendipity_request_end(); continue; } else { $data = $req->getResponseBody(); serendipity_request_end(); $fb = json_decode($data); #print_r($fb); foreach ($fb->data as $idx => $fb_item) { #if ($fb_item-> // Check each Graph API item. If it's an empty link or the link points to facebook, // we cannot read it. Also, the URL might not directly point to our own blog postings // to match up, so we need to follow the HTTP request to see if Location: redirects // take place to our final link. if ($fb_item->type != 'link' || empty($fb_item->link) || preg_match('@/www.facebook.com/@i', $fb_item->link)) { continue; } // Skip some links that we can be sure are not to be requested if (preg_match('@/(www\\.)?(facebook.com|foursquare.com)/@i', $fb_item->link)) { continue; } if ($this->debug) { echo "\nRequesting Link " . $fb_item->link . "\n"; } // Check if we already have metadata about this link. $meta = serendipity_db_query("SELECT entryid, resolved_url FROM {$serendipity['dbPrefix']}facebook WHERE base_url = '" . serendipity_db_escape_string($fb_item->link) . "'"); if ($meta[0]['resolved_url'] != '') { // YES, link is stored. if ($this->debug) { echo "(Metadata exists)\n"; } // Check if stored link is no blog entry of ours. if ((int) $meta[0]['entryid'] == 0) { continue; } $entry_id = $meta[0]['entryid']; if ($this->debug) { echo "(Resolved to: {$entry_id})\n"; } } else { // NO, link not yet stored. Request final location. if ($this->debug) { echo "(No metadata yet)\n"; } serendipity_request_start(); $subreq = new HTTP_Request($fb_item->link, array('allowRedirects' => true, 'maxRedirects' => 3)); $ret = $subreq->sendRequest(); serendipity_request_end(); $check_url = $subreq->_url->url; $entry_id = $this->linkmatch($check_url); if ($this->debug) { echo "(Resolved to: {$entry_id})\n"; } serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}facebook \n (entryid, base_url, resolved_url)\n VALUES \n (" . (int) $entry_id . ", '" . serendipity_db_escape_string($fb_item->link) . "', '" . serendipity_db_escape_string($check_url) . "')"); // Check if stored link is no blog entry of ours if (empty($entry_id)) { continue; } } list($user_id, $post_id) = explode('_', $fb_item->id); // The comments inside the main API graph may not contain everything, so fetch each comment uniquely. $curl = 'http://graph.facebook.com/' . $fb_item->id . '/comments'; if ($this->debug) { echo $curl . "\n"; } serendipity_request_start(); $subreq = new HTTP_Request($curl, array('allowRedirects' => true, 'maxRedirects' => 3)); $ret = $subreq->sendRequest(); $cdata = $subreq->getResponseBody(); serendipity_request_end(); $cfb = json_decode($cdata); #print_r($cfb); // Iterate existing comments. foreach ($cfb->data as $dataidx => $comment) { // Check if comment is already saved. $c = serendipity_db_query("SELECT id\n FROM {$serendipity['dbPrefix']}comments \n WHERE entry_id = " . (int) $entry_id . " \n AND title = 'facebook_" . $comment->id . "'"); if ($c[0]['id'] > 0) { if ($this->debug) { echo "Comment already fetched.\n"; } continue; } $this->addComment($entry_id, $user, $post_id, $comment); if ($this->debug) { echo "comment added.\n"; } } } } } }
if (serendipity_checkMediaSize($target)) { $thumbs = array(array('thumbSize' => $serendipity['thumbSize'], 'thumb' => $serendipity['thumbSuffix'])); serendipity_plugin_api::hook_event('backend_media_makethumb', $thumbs); foreach ($thumbs as $thumb) { // Create thumbnail if ($created_thumbnail = serendipity_makeThumbnail($tfile, $serendipity['POST']['target_directory'][$tindex], $thumb['thumbSize'], $thumb['thumb'])) { $messages[] = '<span class="msg_success"><span class="icon-ok-circled"></span> ' . THUMB_CREATED_DONE . '</span>'; } } // Insert into database $image_id = serendipity_insertImageInDatabase($tfile, $serendipity['POST']['target_directory'][$tindex], $authorid, null, $realname); serendipity_plugin_api::hook_event('backend_image_add', $target); $new_media[] = array('image_id' => $image_id, 'target' => $target, 'created_thumbnail' => $created_thumbnail); } } serendipity_request_end(); } } else { if (!is_array($_FILES['serendipity']['name']['userfile'])) { break; } foreach ($_FILES['serendipity']['name']['userfile'] as $idx => $uploadfiles) { if (!is_array($uploadfiles)) { $uploadfiles = array($uploadfiles); } $uploadFileCounter = -1; foreach ($uploadfiles as $uploadfile) { $uploadFileCounter++; $target_filename = $serendipity['POST']['target_filename'][$idx]; $uploadtmp = $_FILES['serendipity']['tmp_name']['userfile'][$idx]; if (is_array($uploadtmp)) {
function mod_time($uri) { if (function_exists('version_compare') && version_compare(phpversion(), '4.3.0') >= 0) { require_once S9Y_PEAR_PATH . 'HTTP/Request2.php'; serendipity_request_start(); $options = array(); if (version_compare(PHP_VERSION, '5.6.0', '<')) { // On earlier PHP versions, the certificate validation fails. We deactivate it on them to restore the functionality we had with HTTP/Request1 $options['ssl_verify_peer'] = false; } $req = new HTTP_Request2($uri, HTTP_Request2::METHOD_GET, $options); try { $response = $req->send(); if ($response->getStatus() != '200') { throw new HTTP_Request2_Exception('could not fetch url: status code != 200'); } } catch (HTTP_Request2_Exception $e) { serendipity_request_end(); return false; } $fHeader = $response->getHeader(); if (isset($fHeader['last-modified'])) { $modtime = $fHeader['last-modified']; } serendipity_request_end(); } else { $parts = parse_url($uri); $host = $parts['host']; $path = $parts['path']; if (!($fp = @fsockopen($host, 80))) { return false; } $req = "HEAD {$path} HTTP/1.1\r\nUser-Agent: PHP/" . phpversion(); $req .= "\r\nHost: {$host}\r\nAccept: */*\r\n\r\n"; fputs($fp, $req); while (!feof($fp)) { $str = fgets($fp, 4096); if (strpos(strtolower($str), 'last-modified') !== false) { $modtime = substr($str, 15); break; } } fclose($fp); } return isset($modtime) ? $modtime : 0; }
function saveAndResponseMyBlogAvatar($eventData, $url) { global $serendipity; $request_pars['allowRedirects'] = false; $this->log("saveAndResponseMyBlogAvatar: " . $url); // First a dummy icon is fetched. This is done by fetching a MyBlog Avatar for a not existing domain. // If we have done this before, the dummy_md5 is already set, so we can skip this fetching here. if (!isset($this->mybloglog_dummy_md5)) { $cachefilename = '_mybloglogdummy.md5'; $cache_file = $this->getCacheDirectory() . '/' . $cachefilename; // Look up the cache for the md5 of the MyBlogLog dummy icon saved earlier: if (file_exists($cache_file) && time() - filemtime($cache_file) < $this->cache_seconds) { $fp = fopen($cache_file, 'rb'); $this->mybloglog_dummy_md5 = fread($fp, filesize($cache_file)); fclose($fp); $this->log("Loaded dummy MD5: " . $this->mybloglog_dummy_md5); } else { // dummy MD5 file was not cached or was too old. We have to fetch the dummy icon now $dummyurl = 'http://pub.mybloglog.com/coiserv.php?href=http://grunz.grunz.grunz&n=*'; $this->log("trying dummyUrl: " . $dummyurl); if (function_exists('serendipity_request_start')) { serendipity_request_start(); } $reqdummy = new HTTP_Request($dummyurl, $request_pars); if (PEAR::isError($reqdummy->sendRequest()) || $reqdummy->getResponseCode() != '200') { if (function_exists('serendipity_request_start')) { serendipity_request_end(); } $this->avatarConfiguration["mybloglog_dummy_error!"] = $reqdummy->getResponseCode(); // unable to fetch a dummy picture! $this->log("unable to fetch a dummy picture!" . $dummyurl); return false; // what can we say else.. } else { // Allow only images as Avatar! $mime = $reqdummy->getResponseHeader("content-type"); $this->log("MyBlogLog Avatar fetch mimetype: {$mime}"); $mimeparts = explode('/', $mime); if (count($mimeparts) != 2 || $mimeparts[0] != 'image') { // unable to fetch a dummy picture! $this->log("unable to fetch a dummy picture!" . $dummyurl); if (function_exists('serendipity_request_start')) { serendipity_request_end(); } return false; // what can we say else.. } $fContent = $reqdummy->getResponseBody(); $this->mybloglog_dummy_md5 = md5($fContent); // Save MD5 of dummy icon for later runs $fp = fopen($cache_file, 'wb'); fwrite($fp, $this->mybloglog_dummy_md5); fclose($fp); $this->log("dummy MD5 saved: " . $this->mybloglog_dummy_md5); } if (function_exists('serendipity_request_start')) { serendipity_request_end(); } } } // Fetch the correct icon and compare: if (isset($this->mybloglog_dummy_md5)) { $cachefilename = $this->getCacheFilePath($eventData); // fetch the icon if (function_exists('serendipity_request_start')) { serendipity_request_start(); } $this->log("Fetching mbl: " . $url); $req = new HTTP_Request($url, $request_pars); if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') { if (function_exists('serendipity_request_start')) { serendipity_request_end(); } $this->log("Unable to fetch the correct image!"); // Unable to fetch the correct image! return false; } else { // Test, if this realy is an image! $mime_type = $req->getResponseHeader('content-type'); if (!empty($mime_type)) { $mt_parts = explode('/', $mime_type); } if (isset($mt_parts) && is_array($mt_parts) && $mt_parts[0] == 'image') { $fContent = $req->getResponseBody(); $avtmd5 = md5($fContent); $this->log("mbl image fetched, MD5: " . $avtmd5); if ($this->mybloglog_dummy_md5 != $avtmd5) { $this->log("caching mbl image: " . $cachefilename); $this->cacheAvatar($eventData, $fContent, $req); } } else { $this->log("MyBlogLog did not return an image: " . $mime_type); $avtmd5 = $this->mybloglog_dummy_md5; // Declare it as dummy in order not to save it. } } if (function_exists('serendipity_request_start')) { serendipity_request_end(); } if ($this->mybloglog_dummy_md5 == $avtmd5) { // This seems to be a dummy avatar! return false; } else { $this->show($cachefilename); return true; } } return false; }
function import_wpxrss() { // TODO: Backtranscoding to NATIVE charset. Currently only works with UTF-8. $dry_run = false; $serendipity['noautodiscovery'] = 1; $uri = $this->data['url']; require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; serendipity_request_start(); $req = new HTTP_Request($uri, array('allowRedirects' => true, 'maxRedirects' => 5)); $res = $req->sendRequest(); if (PEAR::isError($res) || $req->getResponseCode() != '200') { serendipity_request_end(); echo IMPORT_FAILED . ': ' . htmlspecialchars($this->data['url']); echo "<br />\n"; return false; } $fContent = $req->getResponseBody(); serendipity_request_end(); echo strlen($fContent) . " Bytes<br />\n"; if (version_compare(PHP_VERSION, '5.0') === -1) { printf(UNMET_REQUIREMENTS, 'PHP >= 5.0'); echo "<br />\n"; return false; } $xml = simplexml_load_string($fContent); unset($fContent); /* ************* USERS **********************/ $_s9y_users = serendipity_fetchUsers(); $s9y_users = array(); if (is_array($s9y_users)) { foreach ($_s9y_users as $v) { $s9y_users[$v['realname']] = $v; } } /* ************* CATEGORIES **********************/ $_s9y_cat = serendipity_fetchCategories('all'); $s9y_cat = array(); if (is_array($s9y_cat)) { foreach ($_s9y_cat as $v) { $s9y_cat[$v['category_name']] = $v['categoryid']; } } $wp_ns = 'http://wordpress.org/export/1.0/'; $dc_ns = 'http://purl.org/dc/elements/1.1/'; $content_ns = 'http://purl.org/rss/1.0/modules/content/'; $wp_core = $xml->channel->children($wp_ns); foreach ($wp_core->category as $idx => $cat) { //TODO: Parent generation unknown. $cat_name = (string) $cat->cat_name; if (!isset($s9y_cat[$cat_name])) { $cat = array('category_name' => $cat_name, 'category_description' => '', 'parentid' => 0, 'category_left' => 0, 'category_right' => 0); printf(CREATE_CATEGORY, htmlspecialchars($cat_name)); echo "<br />\n"; if ($dry_run) { $s9y_cat[$cat_name] = time(); } else { serendipity_db_insert('category', $cat); $s9y_cat[$cat_name] = serendipity_db_insert_id('category', 'categoryid'); } } } /* ************* ITEMS **********************/ foreach ($xml->channel->item as $idx => $item) { $wp_items = $item->children($wp_ns); $dc_items = $item->children($dc_ns); $content_items = $item->children($content_ns); // TODO: Attachments not handled if ((string) $wp_items->post_type == 'attachment' or (string) $wp_items->post_type == 'page') { continue; } $entry = array('title' => (string) $item->title, 'isdraft' => (string) $wp_items->status == 'publish' ? 'false' : 'true', 'allow_comments' => (string) $wp_items->comment_status == 'open' ? true : false, 'categories' => array(), 'body' => (string) $content_items->encoded); if (preg_match('@^([0-9]{4})\\-([0-9]{2})\\-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})$@', (string) $wp_items->post_date, $timematch)) { $entry['timestamp'] = mktime($timematch[4], $timematch[5], $timematch[6], $timematch[2], $timematch[3], $timematch[1]); } else { $entry['timestamp'] = time(); } if (isset($item->category[1])) { foreach ($item->category as $idx => $category) { $cstring = (string) $category; if (!isset($s9y_cat[$cstring])) { echo "WARNING: {$category} unset!<br />\n"; } else { $entry['categories'][] = $s9y_cat[$cstring]; } } } else { $cstring = (string) $item->category; $entry['categories'][] = $s9y_cat[$cstring]; } $wp_user = (string) $dc_items->creator; if (!isset($s9y_users[$wp_user])) { if ($dry_run) { $s9y_users[$wp_user]['authorid'] = time(); } else { $s9y_users[$wp_user]['authorid'] = serendipity_addAuthor($wp_user, md5(time()), $wp_user, '', USERLEVEL_EDITOR); } printf(CREATE_AUTHOR, htmlspecialchars($wp_user)); echo "<br />\n"; } $entry['authorid'] = $s9y_users[$wp_user]['authorid']; if ($dry_run) { $id = time(); } else { $id = serendipity_updertEntry($entry); } $s9y_cid = array(); // Holds comment ids to s9y ids association. $c_i = 0; foreach ($wp_items->comment as $comment) { $c_i++; $c_id = (string) $comment->comment_id; $c_pid = (string) $comment->comment_parent; $c_type = (string) $comment->comment_type; if ($c_type == 'pingback') { $c_type2 = 'PINGBACK'; } elseif ($c_type == 'trackback') { $c_type2 = 'TRACKBACK'; } else { $c_type2 = 'NORMAL'; } $s9y_comment = array('entry_id ' => $id, 'parent_id' => $s9y_cid[$c_pd], 'author' => (string) $comment->comment_author, 'email' => (string) $comment->comment_author_email, 'url' => (string) $comment->comment_author_url, 'ip' => (string) $comment->comment_author_IP, 'status' => empty($comment->comment_approved) || $comment->comment_approved == '1' ? 'approved' : 'pending', 'subscribed' => 'false', 'body' => (string) $comment->comment_content, 'type' => $c_type2); if (preg_match('@^([0-9]{4})\\-([0-9]{2})\\-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})$@', (string) $comment->comment_date, $timematch)) { $s9y_comment['timestamp'] = mktime($timematch[4], $timematch[5], $timematch[6], $timematch[2], $timematch[3], $timematch[1]); } else { $s9y_comment['timestamp'] = time(); } if ($dry_run) { $cid = time(); } else { serendipity_db_insert('comments', $s9y_comment); $cid = serendipity_db_insert_id('comments', 'id'); if ($s9y_comment['status'] == 'approved') { serendipity_approveComment($cid, $id, true); } } $s9y_cid[$c_id] = $cid; } echo "Entry '" . htmlspecialchars($entry['title']) . "' ({$c_i} comments) imported.<br />\n"; } return true; }
/** * Calculates infos on the given file and returns an array containing these infos */ function GetFileInfo($url) { global $serendipity; $this->log("GetFileInfo for {$url}"); $fileInfo = array(); //caching metadata $cacheOptions = array('lifeTime' => '2592000', 'automaticSerialization' => true, 'cacheDir' => $serendipity['serendipityPath'] . 'templates_c/'); if (serendipity_db_bool($this->get_config('use_cache', 'true'))) { $this->log("GetFileInfo: Trying cached infos"); //md5 for not having strange characters in that id.. $cacheId = md5($url) . '.2'; include_once S9Y_PEAR_PATH . "Cache/Lite.php"; $cache = new Cache_Lite($cacheOptions); if ($fileInfo = $cache->get($cacheId)) { $this->log("GetFileInfo: Cached infos found in file {$cacheId}"); //return directly on cache hit return $fileInfo; } } //cache miss! -> get data, store it in cache and return. // translate pontential relative url to absolute url if (preg_match('@https?://@', $url)) { $absolute_url = $url; } else { $absolute_url = $this->GetHostUrl() . $url; } if ($this->debug) { $fileInfo['absolute_url'] = $absolute_url; } // Now remove configured base URL $rel_path = str_replace($serendipity['baseURL'], "", $absolute_url); if ($this->debug) { $fileInfo['rel_path'] = $rel_path; } // do we have a local file here? //$localMediaFile = $serendipity['serendipityPath'] . $urlParts['path']; $localMediaFile = $serendipity['serendipityPath'] . $rel_path; $fileInfo['localMediaFile'] = $localMediaFile; $this->log("Absolute_url: {$absolute_url} - Relative: {$localMediaFile}"); // Remember extension of file list($sName, $fileInfo['extension']) = serendipity_parseFileName($localMediaFile); if (file_exists($localMediaFile)) { $this->log("GetFileInfo: Local file exists"); $fileInfo['length'] = filesize($localMediaFile); $fileInfo['md5'] = md5_file($localMediaFile); $this->GetID3Infos($localMediaFile, $fileInfo); $this->log(print_r($fileInfo, true)); // Set default $fileInfo['mime'] = $this->getFileMime($fileInfo['extension'], $fileInfo['mime']); } elseif (preg_match('@https?://@', $url)) { include_once S9Y_PEAR_PATH . 'HTTP/Request.php'; if (function_exists('serendipity_request_start')) { serendipity_request_start(); } $this->Log("Execute HTTP_Request for {$url}"); $http = new HTTP_Request($url); $http->setMethod(HTTP_REQUEST_METHOD_HEAD); if (!PEAR::isError($http->sendRequest(false))) { $fileInfo['length'] = intval($http->getResponseHeader('content-length')); $fileInfo['md5'] = $http->getResponseHeader('content-md5'); //will return false if not present $fileInfo['mime'] = $http->getResponseHeader('content-type'); $this->Log("Filling MIME with HTTP Header: " . print_r($fileInfo, true)); } if (function_exists('serendipity_request_end')) { serendipity_request_end(); } } else { // Not found locally and no URL $fileInfo['notfound'] = true; } if (serendipity_db_bool($this->get_config('use_cache', 'true'))) { $cache->save($fileInfo, $cacheId); } return $fileInfo; }
function shorten_via_delivr($url, &$shorturls) { require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; // if we already evaluated the shorturl, stop here if (!empty($shorturls['delivr'])) { return; } $login = '******'; $apikey = '8bbce762-971e-45d6-a0e1-cbf5730252ea'; $url = urlencode($url); $req_url = "http://api.delivr.com/shorten?username={$login}&apiKey={$apikey}&format=xml&url=" . $url; serendipity_request_start(); $req = new HTTP_Request($req_url, array('timeout' => 20, 'readTimeout' => array(5, 0))); $req->sendRequest(); $xml = $req->getResponseBody(); serendipity_request_end(); if ($req->getResponseCode() == 200) { $vals = array(); $index = array(); $parser = xml_parser_create(); xml_parse_into_struct($parser, $xml, $vals, $index); xml_parser_free($parser); $short_url = 'http://delivr.com/' . $vals[$index['DELIVRID'][0]][value]; $shorturls['delivr'] = trim($short_url); } }