/** * Send POST request to API server * * @param string API method to call * @param array Variables to post * * @return string Response to this request from remote server */ private static function sendRequest($method, $params) { require_once DIR . '/includes/class_vurl.php'; $vurl = new vB_vURL(self::$registry); $vurl->set_option(VURL_URL, self::POSTURL . $method); $vurl->set_option(VURL_POST, 1); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, true); $vurl->set_option(VURL_POSTFIELDS, http_build_query($params, '', '&')); return $vurl->exec(); }
function send_ping($pingurl, $url, $title = '', $excerpt = '', $blog_title = '') { $params = array( 'url' => $url, 'title' => $title, 'excerpt' => $excerpt, 'blog_title' => $blog_title, ); foreach($params AS $key => $val) { if (!empty($val)) { $query[] = $key . '=' . urlencode($val); } } $vurl = new vB_vURL($this->registry); $vurl->set_option(VURL_URL, $pingurl); $vurl->set_option(VURL_POST, 1); $vurl->set_option(VURL_HEADER, 1); $vurl->set_option(VURL_ENCODING, 'gzip'); $vurl->set_option(VURL_POSTFIELDS, implode('&', $query)); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); return $vurl->exec(); }
/** * Verify is supplied token/reponse is valid * * @param array Values given by user 'input' and 'hash' * * @return bool */ function verify_token($input) { if (!isset($input['recaptcha_challenge_field'])) { $input['recaptcha_challenge_field'] = ''; } if (!isset($input['recaptcha_response_field'])) { $input['recaptcha_response_field'] = ''; } if ($input['recaptcha_response_field'] and $input['recaptcha_challenge_field']) { // Contact recaptcha.net $private_key = $this->registry->options['hv_recaptcha_privatekey'] ? $this->registry->options['hv_recaptcha_privatekey'] : '6LfHsgMAAAAAACYsFwZz6cqcG-WWnfay7NIrciyU'; $query = array('privatekey=' . urlencode($private_key), 'remoteip=' . urlencode(IPADDRESS), 'challenge=' . urlencode($input['recaptcha_challenge_field']), 'response=' . urlencode($input['recaptcha_response_field'])); $vurl = new vB_vURL(); $vurl->set_option(VURL_URL, 'http://api-verify.recaptcha.net/verify'); $vurl->set_option(VURL_USERAGENT, 'vBulletin ' . FILE_VERSION); $vurl->set_option(VURL_POST, 1); $vurl->set_option(VURL_POSTFIELDS, implode('&', $query)); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); if (($result = $vurl->exec()) === false) { $this->error = 'humanverify_recaptcha_unreachable'; return false; } else { $result = explode("\n", $result); if ($result[0] === 'true') { return true; } switch ($result[1]) { case 'invalid-site-public-key': $this->error = 'humanverify_recaptcha_publickey'; break; case 'invalid-site-private-key': $this->error = 'humanverify_recaptcha_privatekey'; break; case 'invalid-referrer': $this->error = 'humanverify_recaptcha_referrer'; break; case 'invalid-request-cookie': $this->error = 'humanverify_recaptcha_challenge'; break; case 'verify-params-incorrect': $this->error = 'humanverify_recaptcha_parameters'; break; default: $this->error = 'humanverify_image_wronganswer'; } return false; } } else { $this->error = 'humanverify_image_wronganswer'; return false; } }
/** * Overrides the Facebook API request methods, so we can use vUrl * * @param String $url the URL to make the request to * @param Array $params the parameters to use for the POST body * @param CurlHandler $ch optional initialized curl handle * @return String the response text */ protected function makeRequest($url, $params, $ch = null) { global $vbulletin; $opts = self::$CURL_OPTS; require_once(DIR . '/includes/class_vurl.php'); $vurl = new vB_vURL($vbulletin); $vurl->set_option(VURL_URL, $url); $vurl->set_option(VURL_CONNECTTIMEOUT, $opts[CURLOPT_CONNECTTIMEOUT]); $vurl->set_option(VURL_TIMEOUT, $opts[CURLOPT_TIMEOUT]); $vurl->set_option(VURL_POST, 1); // If we want to use more advanced features such as uploading pictures // to facebook, we may need to remove http_build_query and refactor // vB_vURL to accept an array of POST data and send the multipart/form-data // Content-Type header. $vurl->set_option(VURL_POSTFIELDS, http_build_query($params, '', '&')); $vurl->set_option(VURL_RETURNTRANSFER, $opts[CURLOPT_RETURNTRANSFER]); $vurl->set_option(VURL_CLOSECONNECTION, $opts[CURLOPT_RETURNTRANSFER]); $vurl->set_option(VURL_USERAGENT, $opts[CURLOPT_USERAGENT]); return $vurl->exec(); }
/** * Overrides the Facebook API request methods, so we can use vUrl * * @param String $url the URL to make the request to * @param Array $params the parameters to use for the POST body * @param CurlHandler $ch optional initialized curl handle * @return String the response text */ protected function makeRequest($url, $params, $ch = null) { // try Facebook's cURL implementation (including the new bundled certificates) if (function_exists('curl_init')) { try { $result = parent::makeRequest($url, $params, $ch); } catch (Exception $e) { $result = false; } if ($result) { return $result; } } // use vB_vURL implmentation global $vbulletin; $opts = self::$CURL_OPTS; require_once DIR . '/includes/class_vurl.php'; $vurl = new vB_vURL($vbulletin); $vurl->set_option(VURL_URL, $url); $vurl->set_option(VURL_CONNECTTIMEOUT, $opts[CURLOPT_CONNECTTIMEOUT]); $vurl->set_option(VURL_TIMEOUT, $opts[CURLOPT_TIMEOUT]); $vurl->set_option(VURL_POST, 1); // If we want to use more advanced features such as uploading pictures // to facebook, we may need to remove http_build_query and refactor // vB_vURL to accept an array of POST data and send the multipart/form-data // Content-Type header. $vurl->set_option(VURL_POSTFIELDS, http_build_query($params, '', '&')); $vurl->set_option(VURL_RETURNTRANSFER, $opts[CURLOPT_RETURNTRANSFER]); $vurl->set_option(VURL_CLOSECONNECTION, $opts[CURLOPT_RETURNTRANSFER]); $vurl->set_option(VURL_USERAGENT, $opts[CURLOPT_USERAGENT]); $result = $vurl->exec(); // TODO: add some error checking here // particularly check if $vurl->fetch_error() returns VURL_ERROR_SSL, meaning the server // does not have access to TLS/SSL with which to communicate with facebook return $result; }
/** * Parse HTML Page and get its title/meta and images * * @param string URL of the Page * * @return array */ public function parsePage($url) { // Validate url if (!preg_match('|^http(s)?://[a-z0-9-]+(\\.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $url)) { throw new vB_Exception_Api('upload_invalid_url'); } if (($urlparts = vB_String::parseUrl($url)) === false) { throw new vB_Exception_Api('upload_invalid_url'); } // Try to fetch the url $vurl = new vB_vURL(); $vurl->set_option(VURL_URL, $url); // Use IE8's User-Agent for the best compatibility $vurl->set_option(VURL_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)'); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); $vurl->set_option(VURL_FOLLOWLOCATION, 1); $vurl->set_option(VURL_HEADER, 1); $page = $vurl->exec(); return $this->extractData($page, $urlparts); }
/** * Requests headers of remote file to retrieve size without downloading the file * * @param string URL of remote file to retrieve size from */ function fetch_remote_filesize($url) { if (!preg_match('#^((http|ftp)s?):\\/\\/#i', $url, $check)) { $this->set_error('upload_invalid_url'); return false; } require_once DIR . '/includes/class_vurl.php'; $vurl = new vB_vURL($this->registry); $vurl->set_option(VURL_URL, $url); $vurl->set_option(VURL_HEADER, 1); $vurl->set_option(VURL_NOBODY, 1); $vurl->set_option(VURL_USERAGENT, 'vBulletin via PHP'); $vurl->set_option(VURL_CUSTOMREQUEST, 'HEAD'); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); if ($result = $vurl->exec2() and $length = intval($result['content-length'])) { return $length; } else { return false; } }
/** * Submits a request to the Stop Forum Post service * * @access private * * @param string URL to submit to * * @return string Data returned by Stop Forum Spam */ protected function _submit($url) { $vurl = new vB_vURL(); $vurl->set_option(VURL_URL, $url); $vurl->set_option(VURL_USERAGENT, 'vBulletin/' . SIMPLE_VERSION); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); return $vurl->exec(); }
} if (substr($avatar['avatarpath'], 0, 7) == 'http://') { if ($vbulletin->options['safeupload']) { $imagepath = $vbulletin->options['tmppath'] . '/' . md5(uniqid(microtime()) . $avatar['avatarid']); } else { $imagepath = tempnam(ini_get('upload_tmp_dir'), 'vbthumb'); } if ($filenum = @fopen($imagepath, 'wb')) { require_once(DIR . '/includes/class_vurl.php'); $vurl = new vB_vURL($vbulletin); $vurl->set_option(VURL_URL, $avatar['avatarpath']); $vurl->set_option(VURL_HEADER, true); $vurl->set_option(VURL_RETURNTRANSFER, true); if ($result = $vurl->exec()) { @fwrite($filenum, $result['body']); } unset($vurl); @fclose($filenum); $remotefile = true; } } if (!file_exists($imagepath)) { echo " ... <span class=\"modsincethirtydays\">$vbphrase[unable_to_read_avatar]</span><br />\n";
/** * Submits a request to the Akismet service (POST) * * @access private * * @param string URL to submit to * @param array Array of data to submit * * @return string Data returned by Akismet */ function _submit($url, $params) { $query = array(); $params['blog'] = $this->akismet_board; foreach ($params as $key => $val) { if (!empty($val)) { $query[] = $key . '=' . urlencode($val); } } $vurl = new vB_vURL($this->registry); $vurl->set_option(VURL_URL, $url); $vurl->set_option(VURL_USERAGENT, 'vBulletin/' . FILE_VERSION . ' | Akismet/1.0'); $vurl->set_option(VURL_POST, 1); $vurl->set_option(VURL_POSTFIELDS, implode('&', $query)); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); return $vurl->exec(); }
/** * Ping the search engines * @param object A vB_vURL object * * @return none A blind call, no return currently parsed */ public function ping_search_engines() { if (!$this->registry->options['sitemap_se_submit']) { // value of 0 in bitfield means all search engines are disabled return; } require_once DIR . '/includes/class_vurl.php'; $vurl = new vB_vURL($this->registry); $vurl->set_option(VURL_HEADER, true); $vurl->set_option(VURL_RETURNTRANSFER, true); $map_url = urlencode($this->registry->options['bburl'] . "/xmlsitemap.php"); foreach ($this->search_engines as $bit_option => $callback_url) { if ($this->registry->options['sitemap_se_submit'] & $bit_option) { $vurl->set_option(VURL_URL, $callback_url . $map_url); $vurl->exec(); } } }
/** * Requests headers of remote file to retrieve size without downloading the file * * @param string URL of remote file to retrieve size from */ function fetch_remote_filesize($url) { if (!preg_match('#^((http|ftp)s?):\\/\\/#i', $url, $check)) { $this->set_error('upload_invalid_url'); return false; } require_once DIR . '/includes/class_vurl.php'; $vurl = new vB_vURL($this->registry); $vurl->set_option(VURL_URL, $url); $vurl->set_option(VURL_FOLLOWLOCATION, 1); $vurl->set_option(VURL_HEADER, 1); $vurl->set_option(VURL_NOBODY, 1); $vurl->set_option(VURL_USERAGENT, 'vBulletin via PHP'); $vurl->set_option(VURL_CUSTOMREQUEST, 'HEAD'); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); $result = $vurl->exec2(); if ($result and $length = intval($result['content-length'])) { return $length; } else { if ($result['http-response']['statuscode'] == "200") { // We have an HTTP 200 OK, but no content-length, return -1 and let VURL handle the max fetch size return -1; } else { return false; } } }
/** * Perform verification of the payment, this is called from the payment gatewa * * @return bool Whether the payment is valid */ public function verify_payment() { $this->registry->input->clean_array_gpc('p', array('serial-number' => vB_Cleaner::TYPE_NOHTML)); if (!$this->registry->GPC['serial-number']) { $this->sendHeader(false); $this->error_code = 'missing_serial_number'; return false; } if (!$this->test()) { $this->sendHeader(false); $this->error_code = 'Payment processor not configured'; return false; } $xml = new vB_XML_Builder(); $xml->add_group('notification-history-request', array('xmlns' => 'http://checkout.google.com/schema/2')); $xml->add_tag('serial-number', $this->registry->GPC['serial-number']); $xml->close_group('notification-history-request'); $xmlString = $xml->fetch_xml(); $submitUrl = ($this->settings['sandbox'] ? $this->sandboxNotifyUrl : $this->productionNotifyUrl) . trim($this->settings['google_merchant_id']); $headers = array('Authorization: Basic ' . base64_encode(trim($this->settings['google_merchant_id']) . ':' . trim($this->settings['google_merchant_key'])), 'Content-Type: application/xml; charset=UTF-8', 'Accept: application/xml; charset=UTF-8'); $vurl = new vB_vURL(); $vurl->set_option(VURL_URL, $submitUrl); $vurl->set_option(VURL_USERAGENT, 'vBulletin/' . SIMPLE_VERSION); $vurl->set_option(VURL_HTTPHEADER, $headers); $vurl->set_option(VURL_POST, 1); $vurl->set_option(VURL_POSTFIELDS, $xmlString); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); $result = $vurl->exec(); $xmlobj = new vB_XML_Parser($result); $xmlobj->include_first_tag = true; $parsed_xml = $xmlobj->parse(); if ($parsed_xml === false or !is_array($parsed_xml)) { $this->error_code = 'xml_parse_failed'; $this->sendHeader(false); return false; } $data = each($parsed_xml); $notificationType = $data['key']; $parsed_xml = $data['value']; $this->transaction_id = isset($parsed_xml['google-order-number']) ? $parsed_xml['google-order-number'] : false; $hash = isset($parsed_xml['order-summary']['shopping-cart']['items']['item']['merchant-item-id']) ? $parsed_xml['order-summary']['shopping-cart']['items']['item']['merchant-item-id'] : false; $order_state = isset($parsed_xml['order-summary']['financial-order-state']) ? $parsed_xml['order-summary']['financial-order-state'] : false; $totalcost = isset($parsed_xml['order-summary']['total-charge-amount']['value']) ? floatval($parsed_xml['order-summary']['total-charge-amount']['value']) : 0; $tax = isset($parsed_xml['order-summary']['order-adjustment']['total-tax']['value']) ? floatval($parsed_xml['order-summary']['order-adjustment']['total-tax']['value']) : 0; $currency = isset($parsed_xml['order-summary']['total-charge-amount']['currency']) ? strtolower($parsed_xml['order-summary']['total-charge-amount']['currency']) : 0; $cost = $totalcost - $tax; if ($this->transaction_id and $hash) { $this->paymentinfo = vB::getDbAssertor()->getRow('vBForum:getPaymentinfo', array('hash' => $hash)); if (!empty($this->paymentinfo)) { $sub = vB::getDbAssertor()->getRow('vBForum:subscription', array('subscriptionid' => $this->paymentinfo['subscriptionid'])); $subcost = unserialize($sub['cost']); if ($subcost) { $this->paymentinfo['currency'] = $currency; $this->paymentinfo['amount'] = $cost; switch ($notificationType) { case 'charge-amount-notification': if ($cost == floatval($subcost["{$this->paymentinfo[subscriptionsubid]}"]['cost'][$currency])) { $this->type = 1; } else { $this->error_code = 'invalid_payment_amount - XML: ' . $result . htmlspecialchars_uni(' SubmitURL: ' . $submitUrl . ' Headers: ' . implode(' ', $headers)); } break; case 'refund-amount-notification': case 'chargeback-amount-notification': $this->type = 2; break; case 'new-order-notification': case 'risk-information-notification': case 'authorization-amount-notification': $this->error_code = 'ignored_status_update'; $this->type = 3; break; default: } if ($this->type == 0 and $this->error_code == '') { switch ($order_state) { case 'CANCELLED': case 'CANCELLED_BY_GOOGLE': $this->type = 2; break; // Ignore these states // Ignore these states case 'PAYMENT_DECLINED': case 'REVIEWING': case 'CHARGEABLE': case 'CHARGING': case 'CHARGED': $this->type = 3; $this->error_code = 'ignored_status_update'; default: } } } else { $this->error_code = 'invalid_subscription - XML: ' . $result . htmlspecialchars_uni(' SubmitURL: ' . $submitUrl . ' Headers: ' . implode(' ', $headers)); } } else { $this->error_code = 'invalid_payment - XML: ' . $result . htmlspecialchars_uni(' SubmitURL: ' . $submitUrl . ' Headers: ' . implode(' ', $headers)); } $this->sendHeader(true); } else { $this->error_code = 'invalid_XML_response - XML: ' . $result . htmlspecialchars_uni(' SubmitURL: ' . $submitUrl . ' Headers: ' . implode(' ', $headers)); $this->sendHeader(false); return false; } $xml = new vB_XML_Builder(); $xml->add_group('notification-acknowledgment', array('xmlns' => 'http://checkout.google.com/schema/2', 'serial-number' => $this->registry->GPC['serial-number'])); $xml->close_group(); $xml->send_content_type_header(); $xml->send_content_length_header(); echo $xml->fetch_xml(); return $this->type > 0 and $this->type < 3; }
/** * Submits a request to the Akismet service (POST) * * @access private * * @param string URL to submit to * @param array Array of data to submit * * @return string Data returned by Akismet */ protected function _submit($submitUrl, $params) { //$params['is_test'] = 1; $query = array(); foreach ($params as $key => $val) { if (!empty($val)) { $query[] = $key . '=' . urlencode($val); } } $vurl = new vB_vURL(); $vurl->set_option(VURL_URL, $submitUrl); $vurl->set_option(VURL_USERAGENT, 'vBulletin/' . SIMPLE_VERSION . ' | Akismet/1.1'); $vurl->set_option(VURL_POST, 1); $vurl->set_option(VURL_POSTFIELDS, implode('&', $query)); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); return $vurl->exec(); }
/** * Public * Output the XML-RPC Call via HTTP POST * */ function send_xml_call($url) { if ($this->outputtype != 'call') { trigger_error('vB_XMLRPC_Client::send_xml_call() Must call build_xml_call() before send_xml_call()', E_USER_ERROR); } $vurl = new vB_vURL($this->registry); $vurl->set_option(VURL_URL, $url); $vurl->set_option(VURL_POST, 1); $vurl->set_option(VURL_HEADER, 1); $vurl->set_option(VURL_ENCODING, 'gzip'); $vurl->set_option(VURL_HTTPHEADER, array( $this->xml_object->fetch_content_type_header(), )); $vurl->set_option(VURL_MAXREDIRS, 1); $vurl->set_option(VURL_FOLLOWLOCATION, 1); $vurl->set_option(VURL_POSTFIELDS, $this->xml_object->fetch_xml_tag() . $this->xml_object->output()); $vurl->set_option(VURL_RETURNTRANSFER, 1); $vurl->set_option(VURL_CLOSECONNECTION, 1); return $vurl->exec(); }