Browse Source

Support proxy for server-side HTTP requests #7658 (#7659)

Co-authored-by: Andrzej Talarek <andrzej.talarek@efinity.com>
pull/7743/head
ATA 5 years ago
committed by GitHub
parent
commit
8f81fda450
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      config/defaults.inc.php
  2. 41
      program/actions/utils/modcss.php
  3. 6
      program/include/rcmail_utils.php
  4. 85
      program/lib/Roundcube/spellchecker/googie.php

25
config/defaults.inc.php

@ -75,7 +75,7 @@ $config['db_max_allowed_packet'] = null;
$config['log_driver'] = 'file';
// date format for log entries
// (read http://php.net/manual/en/function.date.php for all format characters)
// (read http://php.net/manual/en/function.date.php for all format characters)
$config['log_date_format'] = 'd-M-Y H:i:s O';
// length of the session ID to prepend each log line with
@ -292,9 +292,9 @@ $config['smtp_auth_cid'] = null;
// Optional SMTP authentication password to be used for smtp_auth_cid
$config['smtp_auth_pw'] = null;
// SMTP HELO host
// Hostname to give to the remote server for SMTP 'HELO' or 'EHLO' messages
// Leave this blank and you will get the server variable 'server_name' or
// SMTP HELO host
// Hostname to give to the remote server for SMTP 'HELO' or 'EHLO' messages
// Leave this blank and you will get the server variable 'server_name' or
// localhost if that isn't defined.
$config['smtp_helo_host'] = '';
@ -795,6 +795,11 @@ $config['assets_path'] = '';
// PHP code about the location of asset files in filesystem
$config['assets_dir'] = '';
// options passed when creating Guzzle http_client, used to fetch remote content
$config['http_client'] = array(
// 'timeout' => 10,
// 'proxy' => 'tcp://localhost:8125',
);
// ----------------------------------
// PLUGINS
@ -807,7 +812,7 @@ $config['plugins'] = array();
// USER INTERFACE
// ----------------------------------
// default messages sort column. Use empty value for default server's sorting,
// default messages sort column. Use empty value for default server's sorting,
// or 'arrival', 'date', 'subject', 'from', 'to', 'fromto', 'size', 'cc'
$config['message_sort_col'] = '';
@ -869,7 +874,7 @@ $config['protect_default_folders'] = true;
// Disable localization of the default folder names listed above
$config['show_real_foldernames'] = false;
// if in your system 0 quota means no limit set this option to true
// if in your system 0 quota means no limit set this option to true
$config['quota_zero_as_unlimited'] = false;
// Make use of the built-in spell checker. It is based on GoogieSpell.
@ -959,7 +964,7 @@ $config['address_book_type'] = 'sql';
// Array key must contain only safe characters, ie. a-zA-Z0-9_
$config['ldap_public'] = array();
// If you are going to use LDAP for individual address books, you will need to
// If you are going to use LDAP for individual address books, you will need to
// set 'user_specific' to true and use the variables to generate the appropriate DNs to access it.
//
// The recommended directory structure for LDAP is to store all the address book entries
@ -972,7 +977,7 @@ $config['ldap_public'] = array();
//
// So the base_dn would be uid=%fu,ou=people,o=root
// The bind_dn would be the same as based_dn or some super user login.
/*
/*
* example config for Verisign directory
*
$config['ldap_public']['Verisign'] = array(
@ -1078,7 +1083,7 @@ $config['ldap_public']['Verisign'] = array(
'sub_fields' => array(),
// Generate values for the following LDAP attributes automatically when creating a new record
'autovalues' => array(
// 'uid' => 'md5(microtime())', // You may specify PHP code snippets which are then eval'ed
// 'uid' => 'md5(microtime())', // You may specify PHP code snippets which are then eval'ed
// 'mail' => '{givenname}.{sn}@mydomain.com', // or composite strings with placeholders for existing attributes
),
'sort' => 'cn', // The field to sort the listing by.
@ -1279,7 +1284,7 @@ $config['logout_purge'] = false;
// Compact INBOX on logout
$config['logout_expunge'] = false;
// Display attached images below the message body
// Display attached images below the message body
$config['inline_images'] = true;
// Encoding of long/non-ascii attachment names:

41
program/actions/utils/modcss.php

@ -40,42 +40,15 @@ class rcmail_action_utils_modcss extends rcmail_action
exit("Invalid URL");
}
if (ini_get('allow_url_fopen')) {
$scheme = strtolower($matches[1]);
$options = [
$scheme => [
'method' => 'GET',
'timeout' => 15,
]
];
$context = stream_context_create($options);
$source = @file_get_contents($realurl, false, $context);
// php.net/manual/en/reserved.variables.httpresponseheader.php
$headers = implode("\n", (array) $http_response_header);
}
else if (function_exists('curl_init')) {
$curl = curl_init($realurl);
curl_setopt($curl, CURLOPT_TIMEOUT, 15);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_setopt($curl, CURLOPT_ENCODING, '');
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($curl);
if ($data !== false) {
list($headers, $source) = explode("\r\n\r\n", $data, 2);
}
else {
$headers = false;
$source = false;
}
$client = rcmail_utils::get_http_client();
$response = $client->get($url);
if (!empty($response)) {
$headers = $response->getHeaders();
$source = $response->getBody();
}
else {
header('HTTP/1.1 403 Forbidden');
exit("HTTP connections disabled");
$headers = false;
$source = false;
}
$ctype_regexp = '~Content-Type:\s+text/(css|plain)~i';

6
program/include/rcmail_utils.php

@ -387,4 +387,10 @@ class rcmail_utils
}
}
}
public static function get_http_client($options = [])
{
$rc = rcube::get_instance();
return new \GuzzleHttp\Client($options + $rc->config->get('http_client'));
}
}

85
program/lib/Roundcube/spellchecker/googie.php

@ -26,8 +26,7 @@
*/
class rcube_spellchecker_googie extends rcube_spellchecker_engine
{
const GOOGIE_HOST = 'ssl://spell.roundcube.net';
const GOOGIE_PORT = 443;
const GOOGIE_HOST = 'https://spell.roundcube.net';
private $matches = array();
private $content;
@ -55,74 +54,58 @@ class rcube_spellchecker_googie extends rcube_spellchecker_engine
function check($text)
{
$this->content = $text;
$matches = array();
if (empty($text)) {
return $this->matches = array();
return $this->matches = $matches;
}
// spell check uri is configured
$url = rcube::get_instance()->config->get('spellcheck_uri');
if ($url) {
$a_uri = parse_url($url);
$ssl = ($a_uri['scheme'] == 'https' || $a_uri['scheme'] == 'ssl');
$port = $a_uri['port'] ? $a_uri['port'] : ($ssl ? 443 : 80);
$host = ($ssl ? 'ssl://' : '') . $a_uri['host'];
$path = $a_uri['path'] . ($a_uri['query'] ? '?'.$a_uri['query'] : '') . $this->lang;
if (!$url) {
$url = self::GOOGIE_HOST . '/tbproxy/spell?lang=';
}
else {
$host = self::GOOGIE_HOST;
$port = self::GOOGIE_PORT;
$path = '/tbproxy/spell?lang=' . $this->lang;
}
$path .= sprintf('&key=%06d', $_SESSION['user_id']);
$url .= $this->lang;
$url .= sprintf('&key=%06d', $_SESSION['user_id']);
$gtext = '<?xml version="1.0" encoding="utf-8" ?>'
.'<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">'
.'<text>' . htmlspecialchars($text, ENT_QUOTES, RCUBE_CHARSET) . '</text>'
.'</spellrequest>';
$store = '';
if ($fp = fsockopen($host, $port, $errno, $errstr, 30)) {
$out = "POST $path HTTP/1.0\r\n";
$out .= "Host: " . str_replace('ssl://', '', $host) . "\r\n";
$out .= "User-Agent: Roundcube Webmail/" . RCUBE_VERSION . " (Googiespell Wrapper)\r\n";
$out .= "Content-Length: " . strlen($gtext) . "\r\n";
$out .= "Content-Type: text/xml\r\n";
$out .= "Connection: Close\r\n\r\n";
$out .= $gtext;
fwrite($fp, $out);
while (!feof($fp))
$store .= fgets($fp, 128);
fclose($fp);
}
// parse HTTP response
if (preg_match('!^HTTP/1.\d (\d+)(.+)!', $store, $m)) {
$http_status = $m[1];
if ($http_status != '200') {
$this->error = 'HTTP ' . $m[1] . rtrim($m[2]);
}
}
if (!$store) {
$client = rcmail_utils::get_http_client();
$response = $client->post($url, [
'headers' => [
'User-Agent' => "Roundcube Webmail/" . RCUBE_VERSION . " (Googiespell Wrapper)",
'Content-type' => 'text/xml'
],
'body' => $gtext
]
);
if (empty($response)) {
$this->error = "Empty result from spelling engine";
}
else if (preg_match('/<spellresult error="([^"]+)"/', $store, $m) && $m[1]) {
$this->error = "Error code $m[1] returned";
$this->error .= preg_match('/<errortext>([^<]+)/', $store, $m) ? ": " . html_entity_decode($m[1]) : '';
else if ($response->getStatusCode() != 200) {
$this->error = 'HTTP ' . $response->getReasonPhrase();
}
else {
$response_body = $response->getBody();
if (preg_match('/<spellresult error="([^"]+)"/', $response_body, $m) && $m[1]) {
$this->error = "Error code $m[1] returned";
$this->error .= preg_match('/<errortext>([^<]+)/', $response_body, $m) ? ": " . html_entity_decode($m[1]) : '';
}
preg_match_all('/<c o="([^"]*)" l="([^"]*)" s="([^"]*)">([^<]*)<\/c>/', $store, $matches, PREG_SET_ORDER);
preg_match_all('/<c o="([^"]*)" l="([^"]*)" s="([^"]*)">([^<]*)<\/c>/', $response_body, $matches, PREG_SET_ORDER);
// skip exceptions (if appropriate options are enabled)
foreach ($matches as $idx => $m) {
$word = mb_substr($text, $m[1], $m[2], RCUBE_CHARSET);
// skip exceptions
if ($this->dictionary->is_exception($word)) {
unset($matches[$idx]);
// skip exceptions (if appropriate options are enabled)
foreach ($matches as $idx => $m) {
$word = mb_substr($text, $m[1], $m[2], RCUBE_CHARSET);
// skip exceptions
if ($this->dictionary->is_exception($word)) {
unset($matches[$idx]);
}
}
}

Loading…
Cancel
Save