Exemplo n.º 1
0
/**
 * Checks a CSS style sheet.
 *
 * @param  string			The data of the style sheet
 * @return ?map			Error information (NULL: no error)
 */
function _validate_css_sheet($data)
{
    global $CSS_TAG_RANGES, $CSS_VALUE_RANGES, $VALIDATED_ALREADY;
    $CSS_TAG_RANGES = array();
    $CSS_VALUE_RANGES = array();
    $errors = array();
    $len = strlen($data);
    $status = CSS_NO_MANS_LAND;
    $line = 0;
    $class_before_comment = NULL;
    $class = '';
    $at_rule = '';
    $at_rule_block = '';
    //$left_no_mans_land_once=false;
    $brace_level = 0;
    $i = 0;
    $class_start_line = NULL;
    $class_start_i = NULL;
    $class_name = '';
    $in_comment = false;
    $quoting = false;
    while ($i < $len) {
        $next = $data[$i];
        $val = ord($next);
        if ($next == '_' || $next == '.' || $next == '-' || $val >= 65 && $val <= 90 || $val >= 97 && $val <= 122 || $val >= 48 && $val <= 57) {
            $alpha_numeric = true;
            $whitespace = false;
            $comment_starting = false;
        } else {
            $alpha_numeric = false;
            $whitespace = $next == "\t" || $val == 13 || $val == 10 || $next == ' ';
            $comment_starting = $next == '/' && $i < $len - 2 && $data[$i + 1] == '*';
        }
        switch ($status) {
            case CSS_AT_RULE:
                if ($next == '{') {
                    $brace_level = 0;
                    $status = CSS_AT_RULE_BLOCK;
                    $at_rule_block = '';
                } elseif ($next == ';') {
                    $status = CSS_NO_MANS_LAND;
                    if (substr($at_rule, 0, 6) == 'import ') {
                        $count = substr_count($at_rule, '"');
                        $first = strpos($at_rule, '"') + 1;
                        if ($count < 2) {
                            $errors[] = array(0 => 'CSS_UNEXPECTED_CHARACTER', 1 => $next, 2 => number_format($line), 'pos' => $i);
                            return $errors;
                        }
                        $at_file = substr($at_rule, $first, strpos($at_rule, '"', $first) - 1 - $first);
                        if (!isset($VALIDATED_ALREADY[$at_file])) {
                            $at_file = qualify_url($at_file, $GLOBALS['URL_BASE']);
                            if ($at_file != '') {
                                $data2 = http_download_file($at_file, NULL, false);
                                if (!is_null($data2)) {
                                    $css_tag_ranges_backup = $CSS_TAG_RANGES;
                                    $css_value_ranges_backup = $CSS_VALUE_RANGES;
                                    $test = _validate_css_sheet($data2);
                                    $CSS_TAG_RANGES = $css_tag_ranges_backup;
                                    $CSS_VALUE_RANGES = $css_value_ranges_backup;
                                    if (is_array($test)) {
                                        foreach ($test as $error) {
                                            $error['pos'] = $i;
                                            $errors[] = $error;
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else {
                    $at_rule .= $next;
                }
                break;
            case CSS_AT_RULE_BLOCK:
                if ($next == '{') {
                    ++$brace_level;
                    $at_rule_block .= $next;
                } elseif ($next == '}' && $brace_level == 0) {
                    $status = CSS_NO_MANS_LAND;
                    if (substr($at_rule, 0, 6) == 'media ') {
                        $css_tag_ranges_backup = $CSS_TAG_RANGES;
                        $css_value_ranges_backup = $CSS_VALUE_RANGES;
                        $test = _validate_css_sheet($at_rule_block);
                        $CSS_TAG_RANGES = $css_tag_ranges_backup;
                        $CSS_VALUE_RANGES = $css_value_ranges_backup;
                        if (is_array($test)) {
                            foreach ($test as $error) {
                                $error['pos'] = $i;
                                $errors[] = $error;
                            }
                        }
                    }
                } elseif ($next == '}') {
                    $brace_level--;
                    $at_rule_block .= $next;
                } else {
                    $at_rule_block .= $next;
                }
                break;
            case CSS_NO_MANS_LAND:
                if ($whitespace) {
                    // Continuing
                } elseif ($next == '.' || $next == '#' || $alpha_numeric) {
                    $status = CSS_IN_CLASS_NAME;
                    $class_name = '';
                    //$left_no_mans_land_once=true;
                } elseif ($next == '@') {
                    $status = CSS_AT_RULE;
                    $at_rule = '';
                } elseif ($comment_starting) {
                    $status = CSS_IN_COMMENT;
                    $class_before_comment = CSS_NO_MANS_LAND;
                } elseif ($next == '*') {
                    $status = CSS_IN_CLASS_NAME;
                    $class_name = '*';
                    //$left_no_mans_land_once=true;
                } else {
                    $errors[] = array(0 => 'CSS_UNEXPECTED_CHARACTER', 1 => $next, 2 => number_format($line), 'pos' => $i);
                    //					return $errors;
                }
                break;
            case CSS_EXPECTING_CLASS_NAME:
                if ($comment_starting) {
                    $status = CSS_IN_COMMENT;
                    $class_before_comment = CSS_EXPECTING_CLASS_NAME;
                } elseif ($whitespace) {
                    // Continuing
                } elseif ($next == '*') {
                    $status = CSS_IN_CLASS_NAME;
                    $class_name = '*';
                } elseif ($next == '.' || $next == '#' || $alpha_numeric) {
                    $status = CSS_IN_CLASS_NAME;
                    $class_name = $alpha_numeric ? $next : '';
                } else {
                    $errors[] = array(0 => 'CSS_UNEXPECTED_CHARACTER', 1 => $next, 2 => number_format($line), 'pos' => $i);
                    //					return $errors;
                }
                break;
            case CSS_IN_COMMENT:
                if ($next == '*' && $i != $len - 2 && $data[$i + 1] == '/') {
                    $status = $class_before_comment;
                    ++$i;
                }
                break;
            case CSS_IN_CLASS_NAME:
                if ($alpha_numeric || $next == ':' || $next == '#') {
                    $class_name .= $next;
                } else {
                    // Test class name
                    $cnt = substr_count($class_name, ':');
                    if ($cnt > 0) {
                        $pseudo = substr($class_name, strpos($class_name, ':') + 1);
                        if ($GLOBALS['VALIDATION_COMPAT'] && !in_array($pseudo, array('active', 'hover', 'link', 'visited', 'first-letter', 'first-line'))) {
                            $errors[] = array(0 => 'CSS_BAD_PSEUDO_CLASS', 1 => $pseudo, 'pos' => $i);
                        }
                    }
                    if ($whitespace) {
                        $status = CSS_EXPECTING_SEP_OR_CLASS_NAME_OR_CLASS;
                    } elseif ($next == '>') {
                        $status = CSS_EXPECTING_CLASS_NAME;
                        if ($GLOBALS['VALIDATION_COMPAT']) {
                            $errors[] = array(0 => 'CSS_BAD_SELECTOR', 1 => '>', 'pos' => $i);
                        }
                    } elseif ($next == ',') {
                        $status = CSS_EXPECTING_CLASS_NAME;
                    } elseif ($next == '{') {
                        $status = CSS_IN_CLASS;
                        $class_start_line = $line;
                        $class_start_i = $i;
                        $class = '';
                    } else {
                        $matches = array();
                        if ($next == '[' && preg_match('#\\[(\\w+|)?\\w+([$*~|^]?="[^;"]*")?\\]#', substr($data, $i, 50), $matches)) {
                            if ($GLOBALS['VALIDATION_COMPAT']) {
                                $errors[] = array(0 => 'CSS_BAD_SELECTOR', 1 => '(attribute-selectors)', 'pos' => $i);
                            }
                            $i += strlen($matches[0]) - 1;
                        } else {
                            $errors[] = array(0 => 'CSS_UNEXPECTED_CHARACTER', 1 => $next, 2 => number_format($line), 'pos' => $i);
                            //					return $errors;
                        }
                    }
                }
                break;
            case CSS_EXPECTING_SEP_OR_CLASS_NAME_OR_CLASS:
                if ($next == '{') {
                    $status = CSS_IN_CLASS;
                    $class_start_line = $line;
                    $class_start_i = $i;
                    $class = '';
                } elseif ($whitespace || $next == '*') {
                    // Continuing
                } elseif ($comment_starting) {
                    $status = CSS_IN_COMMENT;
                    $class_before_comment = CSS_EXPECTING_SEP_OR_CLASS_NAME_OR_CLASS;
                } elseif ($next == ',' || $next == '>') {
                    $status = CSS_EXPECTING_CLASS_NAME;
                } elseif ($next == '.' || $next == '#' || $alpha_numeric) {
                    $status = CSS_IN_CLASS_NAME;
                    $class_name = '';
                } else {
                    $errors[] = array(0 => 'CSS_UNEXPECTED_CHARACTER', 1 => $next, 2 => number_format($line), 'pos' => $i);
                    //					return $errors;
                }
                break;
            case CSS_IN_CLASS:
                if ($quoting) {
                    if (($next == '"' || $next == "'") && $data[$i - 1] != "\\") {
                        $quoting = !$quoting;
                    }
                    $class .= $next;
                } elseif ($in_comment) {
                    $comment_ending = $next == '*' && $i < $len - 2 && $data[$i + 1] == '/';
                    if ($comment_ending) {
                        $in_comment = false;
                    }
                    $class .= $next;
                } elseif ($next == '}') {
                    $status = CSS_NO_MANS_LAND;
                    $test = _validate_css_class($class, $class_start_i, $class_start_line + 1);
                    if (is_array($test)) {
                        $errors = array_merge($errors, $test);
                    }
                } elseif ($comment_starting) {
                    $in_comment = true;
                    $class .= $next;
                } elseif (($next == '"' || $next == "'") && $data[$i - 1] != "\\") {
                    $quoting = true;
                    $class .= $next;
                } elseif ($next == '{') {
                    $errors[] = array(0 => 'CSS_UNEXPECTED_CHARACTER_CLASS', 1 => $next, 2 => number_format($line), 'pos' => $i);
                    return $errors;
                } else {
                    $class .= $next;
                }
                break;
        }
        if ($val == 10) {
            ++$line;
        }
        ++$i;
    }
    if ($status != CSS_NO_MANS_LAND) {
        $errors[] = array(0 => 'CSS_UNEXPECTED_TERMINATION', 'pos' => $i);
        return $errors;
    }
    return $errors == array() ? NULL : $errors;
}
Exemplo n.º 2
0
/**
 * Take a URL and process it to make a hard include. We'll get the HTML and we'll also load up some global stuff for 'do_header' to use.
 *
 * @param  URLPATH	The URL that we're operating on.
 * @param  URLPATH	We open up linked URLs under this recursively.
 * @return string		The cleaned up contents at the URL, set up for the recursive integrator usage.
 */
function reprocess_url($url, $operation_base_url)
{
    if (url_is_local($url)) {
        return '';
    }
    $trail_end = strrpos($url, '/');
    if ($trail_end !== false) {
        $url_base = substr($url, 0, $trail_end);
    }
    $val = mixed();
    // Cookie relaying from client through to server
    $url_bits = @parse_url($url) or warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER', $url));
    $url_bits_2 = parse_url(get_base_url());
    $cookies_relayed = NULL;
    if (!array_key_exists('host', $url_bits)) {
        $url_bits['host'] = 'localhost';
    }
    if (!array_key_exists('host', $url_bits_2)) {
        $url_bits_2['host'] = 'localhost';
    }
    if ($url_bits['host'] == $url_bits_2['host']) {
        $cookies_relayed = array();
        foreach ($_COOKIE as $key => $val) {
            if (is_array($val)) {
                $cookies_relayed[$key] = array();
                foreach ($val as $_val) {
                    if (get_magic_quotes_gpc()) {
                        $_val = stripslashes($_val);
                    }
                    $cookies_relayed[$key][] = $_val;
                }
            } else {
                if (get_magic_quotes_gpc()) {
                    $val = stripslashes($val);
                }
                $cookies_relayed[$key] = $val;
            }
        }
    }
    // Download the document
    $ua = ocp_srv('HTTP_USER_AGENT');
    if ($ua == '') {
        $ua = 'ocP-integrator';
    }
    $accept = ocp_srv('HTTP_ACCEPT');
    if ($accept == '') {
        $accept = NULL;
    }
    $accept_charset = ocp_srv('HTTP_ACCEPT_CHARSET');
    if ($accept_charset == '') {
        $accept_charset = NULL;
    }
    $accept_language = ocp_srv('HTTP_ACCEPT_LANGUAGE');
    if ($accept_language == '') {
        $accept_language = NULL;
    }
    $post_relayed = NULL;
    if (count($_POST) != 0) {
        $post_relayed = array();
        foreach ($_POST as $key => $val) {
            if (is_array($val)) {
                $post_relayed[$key] = array();
                foreach ($val as $_val) {
                    if (get_magic_quotes_gpc()) {
                        $_val = stripslashes($_val);
                    }
                    $post_relayed[$key] = $val;
                }
            } else {
                if (get_magic_quotes_gpc()) {
                    $val = stripslashes($val);
                }
                $post_relayed[$key] = $val;
            }
        }
    }
    require_code('character_sets');
    $document = convert_to_internal_encoding(http_download_file($url, NULL, true, false, $ua, $post_relayed, $cookies_relayed, $accept, $accept_charset, $accept_language));
    global $HTTP_DOWNLOAD_MIME_TYPE;
    if ($HTTP_DOWNLOAD_MIME_TYPE != 'text/html' && $HTTP_DOWNLOAD_MIME_TYPE != 'application/xhtml+xml') {
        header('Location: ' . str_replace("\r", '', str_replace(chr(10), '', $url)));
        return '';
    }
    // Were we asked to set any cookies?
    if ($url_bits['host'] == $url_bits_2['host']) {
        global $HTTP_NEW_COOKIES;
        if (!is_null($HTTP_NEW_COOKIES)) {
            foreach ($HTTP_NEW_COOKIES as $key => $val) {
                $parts = explode('; ', $val);
                foreach ($parts as $i => $part) {
                    if ($i != 0) {
                        $temp = explode('=', $part, 2);
                        if (array_key_exists(1, $temp)) {
                            $parts[trim($temp[0])] = trim(rawurldecode($temp[1]));
                        }
                    }
                }
                //$parts['domain']=$url_bits_2['host']; // To fix an inconvenience caused by mismatching cookie settings (e.g. cookie on subdomain)
                //echo($key.'->'.trim(rawurldecode($parts[0])));
                //print_r($parts);
                //exit();
                $parts['domain'] = get_cookie_domain();
                setcookie($key, trim(rawurldecode($parts[0])), array_key_exists('expires', $parts) ? strtotime($parts['expires']) : 0, array_key_exists('path', $parts) ? $parts['path'] : '', array_key_exists('domain', $parts) ? $parts['domain'] : '');
            }
        }
    }
    // Sort out title
    $matches = array();
    if (preg_match('#<\\s*title[^>]*>(.*)<\\s*/\\s*title\\s*>#is', $document, $matches) != 0) {
        global $SEO_TITLE;
        $title = str_replace('&bull;', '-', str_replace('&ndash;', '-', str_replace('&mdash;', '-', @html_entity_decode($matches[1], ENT_QUOTES, get_charset()))));
        $SEO_TITLE = $title;
        get_page_title(trim($title), false);
    }
    // Better base?
    $matches = array();
    if (preg_match('#<\\s*base\\s+href\\s*=\\s*["\']?(.*)["\']?\\s*/?\\s*>#is', $document, $matches) != 0) {
        $url_base = trim(@html_entity_decode($matches[1], ENT_QUOTES, get_charset()));
    }
    // Sort out body
    if (preg_match('#<\\s*body[^>]*>(.*)<\\s*/\\s*body\\s*>#is', $document, $matches) != 0) {
        $body = '<div>' . $matches[1] . '</div>';
    } else {
        $body = '<div>' . $document . '</div>';
    }
    // Link filtering, so as to make non-external/non-new-window hyperlinks link through the ocPortal module
    $_self_url = build_url(array('page' => '_SELF'), '_SELF', NULL, false, true);
    $self_url = $_self_url->evaluate();
    $expressions = array('(src)="([^"]*)"', '(src)=\'([^\'])*\'', '(href)="([^"]*)"', '(href)=\'([^\'])*\'', '(data)="([^"]*)"', '(data)=\'([^\']*)\'', '(action)="([^"]*)"', '(action)=\'([^\']*)\'');
    foreach ($expressions as $expression) {
        $all_matches = array();
        $count = preg_match_all('#(<[^>]*)' . $expression . '([^>]*>)#i', $body, $all_matches);
        if ($count != 0) {
            for ($i = 0; $i < count($all_matches[0]); $i++) {
                $m_to_replace = $all_matches[0][$i];
                $m_type = trim(@html_entity_decode($all_matches[2][$i], ENT_QUOTES, get_charset()));
                $m_url = trim(@html_entity_decode($all_matches[3][$i], ENT_QUOTES, get_charset()));
                if (url_is_local($m_url)) {
                    $m_url = qualify_url($m_url, $url_base);
                }
                $non_local = substr($m_url, 0, strlen($operation_base_url)) != $operation_base_url;
                if ($m_type == 'src' || $m_type == 'data' || $non_local) {
                    $new_url = $m_url;
                } else {
                    $new_url = $self_url . '&url=' . rawurlencode($m_url);
                }
                $body = str_replace($m_to_replace, $all_matches[1][$i] . $m_type . '="' . escape_html($new_url) . '"' . $all_matches[4][$i], $body);
            }
        }
    }
    // Moving of CSS sheet imports, etc, into ocPortal's head section
    if (preg_match('#<head[^<>]*>(.*)</head>#is', $document, $matches) != 0) {
        $head = $matches[1];
        // meta
        global $SEO_KEYWORDS, $SEO_DESCRIPTION;
        $count = preg_match_all('#\\<\\s*meta[^\\>]*name=["\']([^"\']*)["\'][^\\>]*content="([^"]*)"[^\\>]*/?\\s*>#i', $head, $all_matches);
        if ($count == 0) {
            $count = preg_match_all('#\\<\\s*meta\\s+[^\\>]*name=["\']([^"\']*)["\']\\s+[^\\>]*content=\'([^\']*)\'[^\\>]*/?\\s*>#i', $head, $all_matches);
        }
        if ($count != 0) {
            for ($i = 0; $i < count($all_matches[0]); $i++) {
                $m_name = trim(@html_entity_decode($all_matches[1][$i], ENT_QUOTES, get_charset()));
                $m_content = trim(@html_entity_decode($all_matches[2][$i], ENT_QUOTES, get_charset()));
                if ($m_name == 'description') {
                    $SEO_DESCRIPTION = $m_content;
                } elseif ($m_name == 'keywords') {
                    $SEO_KEYWORDS = explode(',', $m_content);
                }
            }
        }
        // Stuff to copy
        global $EXTRA_HEAD;
        $head_patterns = array('#<\\s*script.*<\\s*/\\s*script\\s*>#isU', '#<\\s*link[^<>]*>#isU', '#<\\s*style.*<\\s*/\\s*style\\s*>#isU');
        foreach ($head_patterns as $pattern) {
            $num_matches = preg_match_all($pattern, $head, $matches);
            for ($i = 0; $i < $num_matches; $i++) {
                $x = $matches[0][$i];
                $match_x = array();
                if (preg_match('#\\s(src|href)=["\']([^"\']+)["\']#i', $x, $match_x) != 0) {
                    if (url_is_local($match_x[1])) {
                        $url_new = qualify_url($match_x[2], $url_base);
                        $x = str_replace($match_x[0], str_replace($match_x[2], $url_new, $match_x[0]), $x);
                    }
                }
                $EXTRA_HEAD->attach($x);
            }
        }
    }
    return $body;
}
Exemplo n.º 3
0
/**
 * Return the file in the URL by downloading it over HTTP. If a byte limit is given, it will only download that many bytes. It outputs warnings, returning NULL, on error.
 *
 * @param  URLPATH		The URL to download
 * @param  ?integer		The number of bytes to download. This is not a guarantee, it is a minimum (NULL: all bytes)
 * @range  1 max
 * @param  boolean		Whether to throw an ocPortal error, on error
 * @param  boolean		Whether to block redirects (returns NULL when found)
 * @param  string			The user-agent to identify as
 * @param  ?array			An optional array of POST parameters to send; if this is NULL, a GET request is used (NULL: none)
 * @param  ?array			An optional array of cookies to send (NULL: none)
 * @param  ?string		'accept' header value (NULL: don't pass one)
 * @param  ?string		'accept-charset' header value (NULL: don't pass one)
 * @param  ?string		'accept-language' header value (NULL: don't pass one)
 * @param  ?resource		File handle to write to (NULL: do not do that)
 * @param  ?string		The HTTP referer (NULL: none)
 * @param  ?array			A pair: authentication username and password (NULL: none)
 * @param  float			The timeout
 * @param  boolean		Whether to treat the POST parameters as a raw POST (rather than using MIME)
 * @param  ?array			Files to send. Map between field to file path (NULL: none)
 * @return ?string		The data downloaded (NULL: error)
 */
function _http_download_file($url, $byte_limit = NULL, $trigger_error = true, $no_redirect = false, $ua = 'ocPortal', $post_params = NULL, $cookies = NULL, $accept = NULL, $accept_charset = NULL, $accept_language = NULL, $write_to_file = NULL, $referer = NULL, $auth = NULL, $timeout = 6.0, $is_xml = false, $files = NULL)
{
    $url = str_replace(' ', '%20', $url);
    // Prevent DOS loop attack
    if (ocp_srv('HTTP_USER_AGENT') == $ua) {
        $ua = 'ocP-recurse';
    }
    if (ocp_srv('HTTP_USER_AGENT') == 'ocP-recurse') {
        return NULL;
    }
    require_code('urls');
    if (url_is_local($url)) {
        $url = get_custom_base_url() . '/' . $url;
    }
    if (strpos($url, '/') !== false && strrpos($url, '/') < 7) {
        $url .= '/';
    }
    global $DOWNLOAD_LEVEL;
    $DOWNLOAD_LEVEL++;
    global $HTTP_DOWNLOAD_MIME_TYPE;
    $HTTP_DOWNLOAD_MIME_TYPE = NULL;
    global $HTTP_CHARSET;
    $HTTP_CHARSET = NULL;
    global $HTTP_DOWNLOAD_SIZE;
    $HTTP_DOWNLOAD_SIZE = 0;
    global $HTTP_DOWNLOAD_URL;
    $HTTP_DOWNLOAD_URL = $url;
    global $HTTP_MESSAGE;
    $HTTP_MESSAGE = NULL;
    global $HTTP_MESSAGE_B;
    $HTTP_MESSAGE_B = NULL;
    global $HTTP_NEW_COOKIES;
    if ($DOWNLOAD_LEVEL == 0) {
        $HTTP_NEW_COOKIES = array();
    }
    global $HTTP_FILENAME;
    $HTTP_FILENAME = NULL;
    if ($DOWNLOAD_LEVEL == 8) {
        return '';
    }
    //critical_error('FILE_DOS',$url); // Prevent possible DOS attack
    $url_parts = @parse_url($url);
    if ($url_parts === false || !isset($url_parts['host'])) {
        if ($trigger_error) {
            warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL', escape_html($url)));
        } else {
            $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_BAD_URL', escape_html($url));
        }
        $DOWNLOAD_LEVEL--;
        $HTTP_MESSAGE = 'malconstructed-URL';
        return NULL;
    }
    if (!array_key_exists('scheme', $url_parts)) {
        $url_parts['scheme'] = 'http';
    }
    $use_curl = $url_parts['scheme'] != 'http' && function_exists('curl_version') || function_exists('get_value') && get_value('prefer_curl') === '1';
    // Prep cookies and post data
    if (!is_null($post_params)) {
        if ($is_xml) {
            $_postdetails_params = $post_params[0];
        } else {
            $_postdetails_params = '';
            //$url_parts['scheme'].'://'.$url_parts['host'].$url2.'?';
            $first = true;
            if (array_keys($post_params) == array('_')) {
                $_postdetails_params = $post_params['_'];
            } else {
                foreach ($post_params as $param_key => $param_value) {
                    if ($use_curl) {
                        if (substr($param_value, 0, 1) == '@') {
                            $param_value = ' @' . substr($param_value, 1);
                        }
                    }
                    $_postdetails_params .= array_key_exists('query', $url_parts) || !$first ? '&' . $param_key . '=' . rawurlencode($param_value) : $param_key . '=' . rawurlencode($param_value);
                    $first = false;
                }
            }
        }
    } else {
        $_postdetails_params = '';
    }
    if (!is_null($cookies) && count($cookies) != 0) {
        $_cookies = '';
        $done_one_cookie = false;
        foreach ($cookies as $key => $val) {
            if ($done_one_cookie) {
                $_cookies .= '; ';
            }
            if (is_array($val)) {
                foreach ($val as $key2 => $val2) {
                    if (!is_string($key2)) {
                        $key2 = strval($key2);
                    }
                    if ($done_one_cookie) {
                        $_cookies .= '; ';
                    }
                    $_cookies .= $key . '[' . $key2 . ']=' . rawurlencode($val2);
                    $done_one_cookie = true;
                }
            } else {
                $_cookies .= $key . '=' . rawurlencode($val);
            }
            $done_one_cookie = true;
        }
    }
    if ($use_curl) {
        if (!is_null($files)) {
            if (is_null($post_params)) {
                $post_params = array();
            }
            foreach ($files as $upload_field => $file_path) {
                $post_params[$upload_field] = '@' . $file_path;
            }
        }
        // CURL
        if (function_exists('curl_version')) {
            if (function_exists('curl_init')) {
                if (function_exists('curl_setopt')) {
                    if (function_exists('curl_exec')) {
                        if (function_exists('curl_error')) {
                            if (function_exists('curl_close')) {
                                if (function_exists('curl_getinfo')) {
                                    if ($url_parts['scheme'] == 'https' || $url_parts['scheme'] == 'http') {
                                        $curl_version = curl_version();
                                        if (is_string($curl_version) && strpos($curl_version, 'OpenSSL') !== false || is_array($curl_version) && array_key_exists('ssl_version', $curl_version)) {
                                            $ch = curl_init($url);
                                            if (!is_null($post_params)) {
                                                curl_setopt($ch, CURLOPT_POST, true);
                                                if (is_null($files)) {
                                                    curl_setopt($ch, CURLOPT_POSTFIELDS, $_postdetails_params);
                                                } else {
                                                    @curl_setopt($ch, CURLOPT_POSTFIELDS, $post_params);
                                                    // PHP5.5 gives a deprecation warning
                                                }
                                            }
                                            if (!is_null($cookies) && count($cookies) != 0) {
                                                curl_setopt($ch, CURLOPT_COOKIE, $_cookies);
                                            }
                                            $crt_path = get_file_base() . '/data/curl-ca-bundle.crt';
                                            if (ini_get('curl.cainfo') == '') {
                                                curl_setopt($ch, CURLOPT_CAINFO, $crt_path);
                                                curl_setopt($ch, CURLOPT_CAPATH, $crt_path);
                                            }
                                            //curl_setopt($ch,CURLOPT_SSLVERSION,6);
                                            curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1');
                                            //if (!$no_redirect) @curl_setopt($ch,CURLOPT_FOLLOWLOCATION,true); // May fail with safe mode, meaning we can't follow Location headers. But we can do better ourselves anyway and protect against file:// exploits.
                                            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, intval($timeout));
                                            curl_setopt($ch, CURLOPT_TIMEOUT, intval($timeout));
                                            curl_setopt($ch, CURLOPT_USERAGENT, $ua);
                                            $headers = array();
                                            if ($is_xml) {
                                                $headers[] = 'Content-Type: application/xml';
                                            }
                                            if (!is_null($accept)) {
                                                $headers[] = 'Accept: ' . rawurlencode($accept);
                                            }
                                            if (!is_null($accept_charset)) {
                                                $headers[] = 'Accept-Charset: ' . rawurlencode($accept_charset);
                                            }
                                            if (!is_null($accept_language)) {
                                                $headers[] = 'Accept-Language: ' . rawurlencode($accept_language);
                                            }
                                            if (is_null($files)) {
                                                // Breaks file uploads for some reason
                                                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
                                            }
                                            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                                            curl_setopt($ch, CURLOPT_HEADER, true);
                                            if (!is_null($auth)) {
                                                curl_setopt($ch, CURLOPT_USERPWD, implode(':', $auth));
                                            }
                                            if (!is_null($referer)) {
                                                curl_setopt($ch, CURLOPT_REFERER, $referer);
                                            }
                                            $proxy = get_value('proxy', NULL, true);
                                            if ($proxy == '') {
                                                $proxy = NULL;
                                            }
                                            if (!is_null($proxy) && $url_parts['host'] != 'localhost' && $url_parts['host'] != '127.0.0.1') {
                                                $port = get_value('proxy_port', NULL, true);
                                                if (is_null($port)) {
                                                    $port = '8080';
                                                }
                                                curl_setopt($ch, CURLOPT_PROXY, $proxy . ':' . $port);
                                                $proxy_user = get_value('proxy_user', NULL, true);
                                                if (!is_null($proxy_user)) {
                                                    $proxy_password = get_value('proxy_password', NULL, true);
                                                    curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_user . ':' . $proxy_password);
                                                }
                                            }
                                            if (!is_null($byte_limit)) {
                                                curl_setopt($ch, CURLOPT_RANGE, '0-' . strval($byte_limit == 0 ? 0 : $byte_limit - 1));
                                            }
                                            $line = curl_exec($ch);
                                            if ($line === false) {
                                                $error = curl_error($ch);
                                                curl_close($ch);
                                            } else {
                                                if (substr($line, 0, 25) == "HTTP/1.1 100 Continue\r\n\r\n") {
                                                    $line = substr($line, 25);
                                                }
                                                if (substr($line, 0, 25) == "HTTP/1.0 100 Continue\r\n\r\n") {
                                                    $line = substr($line, 25);
                                                }
                                                $HTTP_DOWNLOAD_MIME_TYPE = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
                                                $HTTP_DOWNLOAD_SIZE = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
                                                $HTTP_DOWNLOAD_URL = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
                                                $HTTP_MESSAGE = strval(curl_getinfo($ch, CURLINFO_HTTP_CODE));
                                                if ($HTTP_MESSAGE == '206') {
                                                    $HTTP_MESSAGE = '200';
                                                }
                                                // We don't care about partial-content return code, as ocP implementation gets ranges differently and we check '200' as a return result
                                                if (strpos($HTTP_DOWNLOAD_MIME_TYPE, ';') !== false) {
                                                    $HTTP_CHARSET = substr($HTTP_DOWNLOAD_MIME_TYPE, 8 + strpos($HTTP_DOWNLOAD_MIME_TYPE, 'charset='));
                                                    $HTTP_DOWNLOAD_MIME_TYPE = substr($HTTP_DOWNLOAD_MIME_TYPE, 0, strpos($HTTP_DOWNLOAD_MIME_TYPE, ';'));
                                                }
                                                curl_close($ch);
                                                if (substr($line, 0, strlen('HTTP/1.0 200 Connection Established')) == 'HTTP/1.0 200 Connection Established') {
                                                    $line = substr($line, strpos($line, "\r\n\r\n") + 4);
                                                }
                                                $pos = strpos($line, "\r\n\r\n");
                                                if (substr($line, 0, strlen('HTTP/1.1 100 ')) == 'HTTP/1.1 100 ' || substr($line, 0, strlen('HTTP/1.0 100 ')) == 'HTTP/1.0 100 ') {
                                                    $pos = strpos($line, "\r\n\r\n", $pos + 4);
                                                }
                                                if ($pos === false) {
                                                    $pos = strlen($line);
                                                } else {
                                                    $pos += 4;
                                                }
                                                $lines = explode("\r\n", substr($line, 0, $pos));
                                                foreach ($lines as $lno => $_line) {
                                                    $_line .= "\r\n";
                                                    $matches = array();
                                                    if (preg_match('#^Content-Disposition: [^;]*;\\s*filename="([^"]*)"#i', $_line, $matches) != 0) {
                                                        $HTTP_FILENAME = $matches[1];
                                                    }
                                                    if (preg_match("#^Set-Cookie: ([^\r\n=]*)=([^\r\n]*)\r\n#i", $_line, $matches) != 0) {
                                                        $HTTP_NEW_COOKIES[trim(rawurldecode($matches[1]))] = trim($matches[2]);
                                                    }
                                                    if (preg_match("#^Location: (.*)\r\n#i", $_line, $matches) != 0) {
                                                        if (is_null($HTTP_FILENAME)) {
                                                            $HTTP_FILENAME = basename($matches[1]);
                                                        }
                                                        if (strpos($matches[1], '://') === false) {
                                                            $matches[1] = qualify_url($matches[1], $url);
                                                        }
                                                        if ($matches[1] != $url) {
                                                            $bak = $HTTP_FILENAME;
                                                            $text = $no_redirect ? mixed() : _http_download_file($matches[1], $byte_limit, $trigger_error, false, $ua, NULL, $cookies, $accept, $accept_charset, $accept_language, $write_to_file);
                                                            if (is_null($HTTP_FILENAME)) {
                                                                $HTTP_FILENAME = $bak;
                                                            }
                                                            $DOWNLOAD_LEVEL--;
                                                            return _detect_character_encoding($text);
                                                        }
                                                    }
                                                }
                                                $DOWNLOAD_LEVEL--;
                                                $ret = _detect_character_encoding(substr($line, $pos));
                                                if (!is_null($write_to_file)) {
                                                    fwrite($write_to_file, $ret);
                                                    $ret = '';
                                                }
                                                return $ret;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    $errno = 0;
    $errstr = '';
    if ($url_parts['scheme'] == 'http') {
        if (!array_key_exists('host', $url_parts)) {
            $url_parts['host'] = '127.0.0.1';
        }
        $connect_to = $url_parts['host'];
        $base_url_parsed = parse_url(get_base_url());
        if (!array_key_exists('host', $base_url_parsed)) {
            $base_url_parsed['host'] = '127.0.0.1';
        }
        if ($base_url_parsed['host'] == $connect_to && function_exists('get_option') && get_option('ip_forwarding') == '1') {
            $connect_to = '127.0.0.1';
            // Localhost can fail due to IP6
        } elseif (preg_match('#(\\s|,|^)gethostbyname(\\s|$|,)#i', @ini_get('disable_functions')) == 0) {
            $connect_to = gethostbyname($connect_to);
        }
        // for DNS cacheing
        $proxy = function_exists('get_value') ? get_value('proxy', NULL, true) : NULL;
        if ($proxy == '') {
            $proxy = NULL;
        }
        if (!is_null($proxy) && $connect_to != 'localhost' && $connect_to != '127.0.0.1') {
            $proxy_port = get_value('proxy_port', NULL, true);
            if (is_null($proxy_port)) {
                $proxy_port = '8080';
            }
            $mysock = @fsockopen($proxy, intval($proxy_port), $errno, $errstr, $timeout);
        } else {
            $mysock = @fsockopen($connect_to, array_key_exists('port', $url_parts) ? $url_parts['port'] : 80, $errno, $errstr, $timeout);
        }
        if (is_null($mysock)) {
            $mysock = false;
        }
        // For Quercus #4549
    } else {
        $mysock = false;
    }
    if ($mysock !== false) {
        if (function_exists('stream_set_timeout')) {
            if (@stream_set_timeout($mysock, intval($timeout)) === false) {
                $mysock = false;
            }
        } elseif (function_exists('socket_set_timeout')) {
            if (@socket_set_timeout($mysock, intval($timeout)) === false) {
                $mysock = false;
            }
        }
    }
    if ($mysock !== false) {
        $url2 = array_key_exists('path', $url_parts) ? $url_parts['path'] : '/';
        if (array_key_exists('query', $url_parts)) {
            $url2 .= '?' . $url_parts['query'];
        }
        if (!is_null($proxy) && $connect_to != 'localhost' && $connect_to != '127.0.0.1') {
            $out = '';
            $out .= (is_null($post_params) ? $byte_limit === 0 ? 'HEAD ' : 'GET ' : 'POST ') . str_replace("\r", '', str_replace(chr(10), '', $url)) . " HTTP/1.1\r\n";
            $proxy_user = get_value('proxy_user', NULL, true);
            if (!is_null($proxy_user)) {
                $proxy_password = get_value('proxy_password', NULL, true);
                $out .= 'Proxy-Authorization: Basic ' . base64_encode($proxy_user . ':' . $proxy_password) . "\r\n";
            }
        } else {
            $out = (is_null($post_params) ? $byte_limit === 0 ? 'HEAD ' : 'GET ' : 'POST ') . str_replace("\r", '', str_replace(chr(10), '', $url2)) . " HTTP/1.1\r\n";
        }
        $out .= "Host: " . $url_parts['host'] . "\r\n";
        if (!is_null($cookies) && count($cookies) != 0) {
            $out .= 'Cookie: ' . $_cookies . "\r\n";
        }
        $out .= "User-Agent: " . rawurlencode($ua) . "\r\n";
        if (!is_null($auth)) {
            $out .= "Authorization: Basic " . base64_encode(implode(':', $auth)) . "==\r\n";
        }
        if (!is_null($accept)) {
            $out .= "Accept: " . rawurlencode($accept) . "\r\n";
        } else {
            $out .= "Accept: */*\r\n";
            // There's a mod_security rule that checks for this
        }
        if (!is_null($accept_charset)) {
            $out .= "Accept-Charset: " . rawurlencode($accept_charset) . "\r\n";
        }
        if (!is_null($accept_language)) {
            $out .= "Accept-Language: " . rawurlencode($accept_language) . "\r\n";
        }
        if (!is_null($referer)) {
            $out .= "Referer: " . rawurlencode($referer) . "\r\n";
        }
        if ($_postdetails_params != '') {
            if ($is_xml) {
                $out .= "Content-Type: application/xml\r\n";
                $out .= 'Content-length: ' . strval(strlen($_postdetails_params)) . "\r\n";
                $out .= "\r\n" . $_postdetails_params . "\r\n\r\n";
            } else {
                if (is_null($files)) {
                    $out .= 'Content-type: application/x-www-form-urlencoded; charset=' . get_charset() . "\r\n";
                    $out .= 'Content-length: ' . strval(strlen($_postdetails_params)) . "\r\n";
                    $out .= "\r\n" . $_postdetails_params . "\r\n\r\n";
                } else {
                    $divider = uniqid('', true);
                    $out2 = '';
                    $out .= 'Content-type: multipart/form-data; boundary="--ocp' . $divider . '"; charset=' . get_charset() . "\r\n";
                    foreach ($post_params as $key => $val) {
                        $out2 .= '----ocp' . $divider . "\r\n";
                        $out2 .= 'Content-Disposition: form-data; name="' . urlencode($key) . '"' . "\r\n\r\n";
                        $out2 .= $val . "\r\n";
                    }
                    if (!is_null($files)) {
                        foreach ($files as $upload_field => $file_path) {
                            $out2 .= '----ocp' . $divider . "\r\n";
                            $out2 .= 'Content-Disposition: form-data; name="' . urlencode($upload_field) . '"; filename="' . urlencode(basename($file_path)) . '"' . "\r\n";
                            $out2 .= 'Content-Type: application/octet-stream' . "\r\n\r\n";
                            $out2 .= file_get_contents($file_path) . "\r\n";
                        }
                    }
                    $out2 .= '----ocp' . $divider . "--\r\n";
                    $out .= 'Content-length: ' . strval(strlen($out2)) . "\r\n";
                    $out .= "\r\n" . $out2;
                }
            }
        }
        $out .= "Connection: Close\r\n\r\n";
        @fwrite($mysock, $out);
        $data_started = false;
        $input = '';
        $input_len = 0;
        $first_fail_time = mixed();
        $chunked = false;
        $buffer_unprocessed = '';
        while ($chunked || !@feof($mysock)) {
            $line = @fread($mysock, $chunked && strlen($buffer_unprocessed) > 10 ? 10 : 1024);
            if ($line === false) {
                if (!$chunked || $buffer_unprocessed == '') {
                    break;
                }
                $line = '';
            }
            if ($line == '') {
                if (!is_null($first_fail_time)) {
                    if ($first_fail_time < time() - 5) {
                        break;
                    }
                } else {
                    $first_fail_time = time();
                }
            } else {
                $first_fail_time = NULL;
            }
            if ($data_started) {
                $line = $buffer_unprocessed . $line;
                $buffer_unprocessed = '';
                if ($chunked) {
                    $matches = array();
                    if (preg_match('#^(\\r\\n)?([a-f\\d]+) *(;[^\\r\\n]*)?\\r\\n(.*)$#is', $line, $matches) != 0) {
                        $amount_wanted = hexdec($matches[2]);
                        if (strlen($matches[4]) < $amount_wanted) {
                            $buffer_unprocessed = $line;
                            continue;
                        }
                        $buffer_unprocessed = substr($matches[4], $amount_wanted);
                        // May be some more extra read
                        $line = substr($matches[4], 0, $amount_wanted);
                        if ($line == '') {
                            break;
                        }
                    } else {
                        // Should not happen :S
                    }
                }
                if (is_null($write_to_file)) {
                    $input .= $line;
                } else {
                    fwrite($write_to_file, $line);
                }
                $input_len += strlen($line);
                if (!is_null($byte_limit) && $input_len >= $byte_limit) {
                    $input = substr($input, 0, $byte_limit);
                    break;
                }
            } elseif ($line != '') {
                $old_line = $line;
                $lines = explode("\r\n", $line);
                $tally = 0;
                foreach ($lines as $lno => $line) {
                    $line .= "\r\n";
                    $tally += strlen($line);
                    $matches = array();
                    if (preg_match("#Transfer-Encoding: chunked\r\n#i", $line, $matches) != 0) {
                        $chunked = true;
                    }
                    if (preg_match("#Content-Disposition: [^\r\n]*filename=\"([^;\r\n]*)\"\r\n#i", $line, $matches) != 0) {
                        $HTTP_FILENAME = $matches[1];
                    }
                    if (preg_match("#^Set-Cookie: ([^\r\n=]*)=([^\r\n]*)\r\n#i", $line, $matches) != 0) {
                        $HTTP_NEW_COOKIES[trim(rawurldecode($matches[1]))] = trim($matches[2]);
                    }
                    if (preg_match("#^Content-Length: ([^;\r\n]*)\r\n#i", $line, $matches) != 0) {
                        $HTTP_DOWNLOAD_SIZE = intval($matches[1]);
                    }
                    if (preg_match("#^Content-Type: ([^;\r\n]*)(;[^\r\n]*)?\r\n#i", $line, $matches) != 0) {
                        $HTTP_DOWNLOAD_MIME_TYPE = $matches[1];
                        if (array_key_exists(2, $matches)) {
                            $_ct_more = explode(';', str_replace(' ', '', trim($matches[2])));
                            foreach ($_ct_more as $ct_more) {
                                $ct_bits = explode('=', $ct_more, 2);
                                if (count($ct_bits) == 2 && strtolower($ct_bits[0]) == 'charset') {
                                    $HTTP_CHARSET = trim($ct_bits[1]);
                                }
                            }
                        }
                    }
                    if (preg_match("#^Refresh: (\\d*);(.*)\r\n#i", $line, $matches) != 0) {
                        if (is_null($HTTP_FILENAME)) {
                            $HTTP_FILENAME = basename($matches[1]);
                        }
                        @fclose($mysock);
                        if (strpos($matches[1], '://') === false) {
                            $matches[1] = qualify_url($matches[1], $url);
                        }
                        $bak = $HTTP_FILENAME;
                        $text = $no_redirect ? mixed() : _http_download_file($matches[2], $byte_limit, $trigger_error, false, $ua, NULL, $cookies, $accept, $accept_charset, $accept_language, $write_to_file);
                        if (is_null($HTTP_FILENAME)) {
                            $HTTP_FILENAME = $bak;
                        }
                        $DOWNLOAD_LEVEL--;
                        return _detect_character_encoding($text);
                    }
                    if (preg_match("#^Location: (.*)\r\n#i", $line, $matches) != 0) {
                        if (is_null($HTTP_FILENAME)) {
                            $HTTP_FILENAME = basename($matches[1]);
                        }
                        @fclose($mysock);
                        if (strpos($matches[1], '://') === false) {
                            $matches[1] = qualify_url($matches[1], $url);
                        }
                        if ($matches[1] != $url) {
                            $bak = $HTTP_FILENAME;
                            $text = $no_redirect ? mixed() : _http_download_file($matches[1], $byte_limit, $trigger_error, false, $ua, NULL, $cookies, $accept, $accept_charset, $accept_language, $write_to_file);
                            if (is_null($HTTP_FILENAME)) {
                                $HTTP_FILENAME = $bak;
                            }
                            $DOWNLOAD_LEVEL--;
                            return _detect_character_encoding($text);
                        }
                    }
                    if (preg_match("#HTTP/(\\d*\\.\\d*) (\\d*) #", $line, $matches) != 0) {
                        // 200 = Ok
                        // 301/302 = Redirected: Not good, we should not be here
                        // 401 = Unauthorized
                        // 403 = Forbidden
                        // 404 = Not found
                        // 500 = Internal server error
                        $HTTP_MESSAGE = $matches[2];
                        switch ($matches[2]) {
                            case '302':
                            case '301':
                                // We'll expect a location header
                                break;
                            case '200':
                                // Good
                                break;
                            case '401':
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED', escape_html($url)));
                                } else {
                                    $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED', escape_html($url));
                                }
                                @fclose($mysock);
                                $HTTP_DOWNLOAD_MIME_TYPE = 'security';
                                $DOWNLOAD_LEVEL--;
                                return NULL;
                            case '403':
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED', escape_html($url)));
                                } else {
                                    $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNAUTHORIZED', escape_html($url));
                                }
                                @fclose($mysock);
                                $HTTP_DOWNLOAD_MIME_TYPE = 'security';
                                $DOWNLOAD_LEVEL--;
                                return NULL;
                            case '404':
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_NOT_FOUND', escape_html($url)));
                                }
                                @fclose($mysock);
                                $DOWNLOAD_LEVEL--;
                                return NULL;
                            case '500':
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_SERVER_ERROR', escape_html($url)));
                                }
                                @fclose($mysock);
                                $DOWNLOAD_LEVEL--;
                                return NULL;
                            default:
                                if ($trigger_error) {
                                    warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_STATUS_UNKNOWN', escape_html($url)));
                                }
                        }
                    }
                    if ($line == "\r\n") {
                        $data_started = true;
                        $buffer_unprocessed = substr($old_line, $tally);
                        if ($buffer_unprocessed === false) {
                            $buffer_unprocessed = '';
                        }
                        break;
                    }
                }
            }
        }
        // Process any non-chunked extra buffer (chunked would have been handled in main loop)
        if (!$chunked) {
            if ($buffer_unprocessed != '') {
                if (is_null($write_to_file)) {
                    $input .= $buffer_unprocessed;
                } else {
                    fwrite($write_to_file, $buffer_unprocessed);
                }
                $input_len += strlen($buffer_unprocessed);
                if (!is_null($byte_limit) && $input_len >= $byte_limit) {
                    $input = substr($input, 0, $byte_limit);
                }
            }
        }
        @fclose($mysock);
        if (!$data_started) {
            if ($byte_limit === 0) {
                return '';
            }
            if ($trigger_error) {
                warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER', escape_html($url)));
            } else {
                $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER', escape_html($url));
            }
            $DOWNLOAD_LEVEL--;
            $HTTP_MESSAGE = 'no-data';
            return NULL;
        }
        $size_expected = $HTTP_DOWNLOAD_SIZE;
        if (!is_null($byte_limit)) {
            if ($byte_limit < $HTTP_DOWNLOAD_SIZE) {
                $size_expected = $byte_limit;
            }
        }
        if ($input_len < $size_expected) {
            if ($trigger_error) {
                warn_exit(do_lang_tempcode('HTTP_DOWNLOAD_CUT_SHORT', escape_html($url), escape_html(integer_format($size_expected)), escape_html(integer_format($input_len))));
            } else {
                $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_CUT_SHORT', escape_html($url), escape_html(integer_format($size_expected)), escape_html(integer_format($input_len)));
            }
            $DOWNLOAD_LEVEL--;
            $HTTP_MESSAGE = 'short-data';
            return _detect_character_encoding($input);
        }
        $DOWNLOAD_LEVEL--;
        return _detect_character_encoding($input);
    } else {
        if ($errno != 110 && ($errno != 10060 || @ini_get('default_socket_timeout') == '1') && is_null($post_params)) {
            // Perhaps fsockopen is restricted... try fread/file_get_contents
            @ini_set('allow_url_fopen', '1');
            $timeout_before = @ini_get('default_socket_timeout');
            @ini_set('default_socket_timeout', strval(intval($timeout)));
            if (is_null($byte_limit) && is_null($write_to_file)) {
                $read_file = @file_get_contents($url);
            } else {
                $_read_file = @fopen($url, 'rb');
                if ($_read_file !== false) {
                    $read_file = '';
                    while (!feof($_read_file) && (is_null($byte_limit) || strlen($read_file) < $byte_limit)) {
                        $line = fread($_read_file, 1024);
                        if (is_null($write_to_file)) {
                            $read_file .= $line;
                        } else {
                            fwrite($write_to_file, $line);
                        }
                    }
                    fclose($_read_file);
                } else {
                    $read_file = false;
                }
            }
            @ini_set('allow_url_fopen', '0');
            @ini_set('default_socket_timeout', $timeout_before);
            if ($read_file !== false) {
                $DOWNLOAD_LEVEL--;
                return _detect_character_encoding($read_file);
            }
            $errstr = $php_errormsg;
        }
        if ($trigger_error) {
            if ($errstr == '') {
                $errstr = strval($errno);
            }
            $error = do_lang_tempcode('_HTTP_DOWNLOAD_NO_SERVER', escape_html($url), escape_html($errstr));
            warn_exit($error);
        } else {
            $HTTP_MESSAGE_B = do_lang_tempcode('HTTP_DOWNLOAD_NO_SERVER', escape_html($url));
        }
        $DOWNLOAD_LEVEL--;
        $HTTP_MESSAGE = 'could not connect to host (' . $errstr . ')';
        return NULL;
    }
}
Exemplo n.º 4
0
/**
 * Used by semihtml_to_comcode to fix <a> tag links. preg_replace_callback callback
 *
 * @param  array			Array of matches
 * @return string			Substituted text
 */
function _a_tag_link_fixup($matches)
{
    $referer = post_param('http_referer', ocp_srv('HTTP_REFERER'));
    $caller_url = looks_like_url($referer) ? preg_replace('#/[^/]*$#', '', $referer) : get_base_url();
    $ret = '<a ' . $matches[1] . 'href="' . qualify_url($matches[2], $caller_url) . '"' . $matches[3] . '>';
    return $ret;
}
Exemplo n.º 5
0
function handleParsedElement($parser, $pos, $name, $attrs)
{
    global $tag_stack;
    global $err;
    global $banner;
    global $img_conversion_enabled;
    global $skin;
    global $allow_skin_attribute;
    static $number_of_decks = 0;
    static $number_of_forms = 0;
    static $number_of_linksets = 0;
    static $markup_language = 0;
    static $raw_mode = false;
    if (function_exists("xml_get_current_line_number")) {
        $line = xml_get_current_line_number($parser);
    } else {
        $line = "???";
    }
    switch ($name) {
        case "HAWHAW":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_HAWHAW, $parser);
                $tag_stack->push(0, HAX_TAG_HAWHAW);
            } else {
                // HAX_PARSE_END
                $tag_stack->pop();
            }
            break;
        case "DECK":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_DECK, $parser);
                if ($number_of_decks++ > 0) {
                    error($err[5], $parser, $line);
                }
                // determine contructor arguments of HAW_deck
                if (isset($attrs["TITLE"])) {
                    $title = $attrs["TITLE"];
                } else {
                    $title = HAW_NOTITLE;
                }
                if (isset($attrs["ALIGN"]) && $attrs["ALIGN"] == "center") {
                    $alignment = HAW_ALIGN_CENTER;
                } elseif (isset($attrs["ALIGN"]) && $attrs["ALIGN"] == "right") {
                    $alignment = HAW_ALIGN_RIGHT;
                } else {
                    $alignment = HAW_ALIGN_LEFT;
                }
                $output = HAW_OUTPUT_AUTOMATIC;
                if (isset($attrs["OUTPUT"])) {
                    switch ($attrs["OUTPUT"]) {
                        case "bigscreen":
                            $output = HAW_OUTPUT_BIGSCREEN;
                            break;
                        case "wap":
                            $output = HAW_OUTPUT_WAP;
                            break;
                        case "hdml":
                            $output = HAW_OUTPUT_HDML;
                            break;
                        case "pda":
                            $output = HAW_OUTPUT_PDA;
                            break;
                        case "imode":
                            $output = HAW_OUTPUT_IMODE;
                            break;
                        case "mml":
                            $output = HAW_OUTPUT_MML;
                            break;
                        case "voicexml":
                            $output = HAW_OUTPUT_VOICEXML;
                            break;
                        case "xhtml":
                            $output = HAW_OUTPUT_XHTML;
                            break;
                    }
                }
                // initiate HAW_deck object
                $deck = new HAW_deck($title, $alignment, $output);
                $markup_language = $deck->ml;
                // modify HAW_deck objects according attribute list
                if (isset($attrs["REDIRECTION"])) {
                    $redirection = explode(";", $attrs["REDIRECTION"]);
                    $redirection[0] = trim($redirection[0]);
                    // strip whitespace
                    $redirection[1] = trim($redirection[1]);
                    if (isset($redirection[2])) {
                        $redirection[2] = trim(strtolower($redirection[2]));
                    }
                    if ($redirection[0] < 1 || $redirection[0] > 3600) {
                        error($err[3], $parser, $line);
                    }
                    // invalid time value
                    if (substr(strtolower($redirection[1]), 0, 4) != "url=") {
                        error($err[3], $parser, $line);
                    }
                    // invalid URL declaration
                    if (isset($redirection[2]) && $redirection[2] == "proxy=no") {
                        // redirect directly to target (needed for HawTags)
                        $deck->set_redirection($redirection[0], substr($redirection[1], 4));
                    } else {
                        // redirect via HAWXY
                        $deck->set_redirection($redirection[0], determine_url(qualify_url(substr($redirection[1], 4))));
                    }
                }
                if (isset($attrs["CACHE"]) && strtolower($attrs["CACHE"]) == "no") {
                    $deck->disable_cache();
                }
                if (isset($attrs["CHARSET"])) {
                    $deck->set_charset($attrs["CHARSET"]);
                }
                if (isset($attrs["LANGUAGE"])) {
                    $deck->set_language($attrs["LANGUAGE"]);
                }
                if (isset($attrs["CSS"])) {
                    $deck->set_css($attrs["CSS"]);
                }
                if (isset($attrs["CSS_CLASS"])) {
                    $deck->set_css_class($attrs["CSS_CLASS"]);
                }
                if (isset($attrs["BACKGROUND"])) {
                    $deck->set_background($attrs["BACKGROUND"]);
                }
                if (isset($attrs["BGCOLOR"])) {
                    $deck->set_bgcolor($attrs["BGCOLOR"]);
                }
                if (isset($attrs["SIZE"])) {
                    $deck->set_size($attrs["SIZE"]);
                }
                if (isset($attrs["COLOR"])) {
                    $deck->set_color($attrs["COLOR"]);
                }
                if (isset($attrs["LINK_COLOR"])) {
                    $deck->set_link_color($attrs["LINK_COLOR"]);
                }
                if (isset($attrs["VLINK_COLOR"])) {
                    $deck->set_vlink_color($attrs["VLINK_COLOR"]);
                }
                if (isset($attrs["LINK_BRACKETS"]) && strtolower($attrs["LINK_BRACKETS"]) == "no") {
                    $deck->use_link_brackets(false);
                }
                if (isset($attrs["FACE"])) {
                    $deck->set_face($attrs["FACE"]);
                }
                if (isset($attrs["WAPHOME"])) {
                    $deck->set_waphome($attrs["WAPHOME"]);
                } else {
                    $deck->set_waphome("http://" . getenv("HTTP_HOST") . getenv("REQUEST_URI"));
                }
                if (isset($attrs["VOICE_JINGLE"])) {
                    $deck->set_voice_jingle($attrs["VOICE_JINGLE"]);
                }
                if (isset($attrs["SKIN"]) && $allow_skin_attribute) {
                    if (strtolower($attrs["SKIN"]) == "none") {
                        $deck->use_simulator(HAW_SIM_NONE);
                    } else {
                        if (strtolower($attrs["SKIN"]) == "classic") {
                            $deck->use_simulator(HAW_SIM_CLASSIC);
                        } else {
                            $deck->use_simulator($attrs["SKIN"]);
                        }
                    }
                } else {
                    $deck->use_simulator($skin);
                }
                // display banners on top of simulator device
                while (list($key, $val) = each($banner)) {
                    // edit config file for banner control
                    $top_banner[$key] = new HAW_banner($val["img"], $val["url"], $val["alt"]);
                    $top_banner[$key]->set_size($val["width"], $val["height"]);
                    $deck->add_banner($top_banner[$key], HAW_TOP);
                }
                $tag_stack->push($deck, HAX_TAG_DECK);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                $deck = $element["element"];
                $deck->create_page();
            }
            break;
        case "FORM":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_FORM, $parser);
                if ($number_of_forms++ > 0) {
                    error($err[9], $parser, $line);
                }
                if (!isset($attrs["ACTION"])) {
                    error("<form> " . $err[7] . " action", $parser, $line);
                }
                // action attribute is missing
                // initiate HAW_form object
                if (isset($attrs["PROXY"]) && strtolower($attrs["PROXY"]) == "no") {
                    // send form data to action script (needed for HawTags)
                    $form = new HAW_form($attrs["ACTION"]);
                } else {
                    // send form data to hawxy server
                    $form = new HAW_form($_SERVER['SCRIPT_NAME']);
                    // add info about XML source where form input has to be propagated to
                    $hidden = new HAW_hidden("code", qualify_url($attrs["ACTION"]));
                    $form->add_hidden($hidden);
                }
                $tag_stack->push($form, HAX_TAG_FORM);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_form object
                $form = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck)
                $base_element = $element["element"];
                $base_element->add_form($form);
                // add HAW_form to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "TEXT":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_TEXT, $parser);
                $format = "HAW_TEXTFORMAT_NORMAL";
                if (isset($attrs["BOLD"]) && strtolower($attrs["BOLD"]) == "yes") {
                    $format |= HAW_TEXTFORMAT_BOLD;
                }
                if (isset($attrs["ITALIC"]) && strtolower($attrs["ITALIC"]) == "yes") {
                    $format |= HAW_TEXTFORMAT_ITALIC;
                }
                if (isset($attrs["UNDERLINE"]) && strtolower($attrs["UNDERLINE"]) == "yes") {
                    $format |= HAW_TEXTFORMAT_UNDERLINE;
                }
                if (isset($attrs["BIG"]) && strtolower($attrs["BIG"]) == "yes") {
                    $format |= HAW_TEXTFORMAT_BIG;
                }
                if (isset($attrs["SMALL"]) && strtolower($attrs["SMALL"]) == "yes") {
                    $format |= HAW_TEXTFORMAT_SMALL;
                }
                if (isset($attrs["BOXED"]) && strtolower($attrs["BOXED"]) == "yes") {
                    $format |= HAW_TEXTFORMAT_BOXED;
                }
                $text = new HAW_text("", $format);
                if (isset($attrs["BR"]) && $attrs["BR"] >= 0) {
                    $text->set_br($attrs["BR"] + 0);
                }
                // convert string to int!
                if (isset($attrs["CSS_CLASS"])) {
                    $text->set_css_class($attrs["CSS_CLASS"]);
                }
                if (isset($attrs["COLOR"])) {
                    $textcolor = $attrs["COLOR"];
                    if (isset($attrs["BOXCOLOR"])) {
                        $boxcolor = $attrs["BOXCOLOR"];
                    } else {
                        $boxcolor = "";
                    }
                    $text->set_color($textcolor, $boxcolor);
                }
                $tag_stack->push($text, HAX_TAG_TEXT);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_text object
                $text = $element["element"];
                if (!$text->voice_text) {
                    $text->voice_text = $text->text;
                }
                // update voice_text if not already set
                $element = $tag_stack->pop();
                // pop base object (HAW_deck, HAW_form, ...)
                $base_element = $element["element"];
                if ($element["tag"] == HAX_TAG_TD) {
                    // include HAW_text object in HAX_td pseudo class
                    $base_element->element = $text;
                    $base_element->tag = HAX_TAG_TEXT;
                } else {
                    $base_element->add_text($text);
                }
                // add HAW_text to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "IMG":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_IMAGE, $parser);
                if (!($alt = $attrs["ALT"])) {
                    error("<img> " . $err[7] . " alt", $parser, $line);
                }
                // alt attribute is missing
                if (isset($attrs["SRC"])) {
                    // source attribute ==> perform automatic image conversion
                    if (!$img_conversion_enabled) {
                        error($err[13], $parser, $line);
                    }
                    // image conversion deactivated per config
                    if (!function_exists("ImageTypes")) {
                        error($err[13], $parser, $line);
                    }
                    // GD is not loaded
                    if (!(ImageTypes() & (IMG_PNG | IMG_WBMP))) {
                        error($err[13], $parser, $line);
                    }
                    // not all necessary image types supported
                    $source = $attrs["SRC"];
                    $extension = strtolower(substr($source, -4));
                    $accept = strtolower($_SERVER['HTTP_ACCEPT']);
                    if ($extension == ".gif" && (strstr($accept, "image/gif") || $markup_language == HAW_HTML && !strstr($accept, "image/png")) || $extension == ".png" && (strstr($accept, "image/png") || $markup_language == HAW_HTML) || $extension == "wbmp" && $markup_language == HAW_WML) {
                        // requesting browser accepts given src image file
                        // ==> no conversion required
                        $src_html = $source;
                        $src_wbmp = $source;
                    } else {
                        // session-controlled image conversion
                        // convert images of HAWHAW XML files only
                        // (we don't want to act as conversion server for the whole world!)
                        static $img_counter = 0;
                        $varname = "i" . $img_counter;
                        session_register($varname);
                        $_SESSION[$varname] = $attrs["SRC"];
                        $_SESSION['img_ml'] = $markup_language;
                        //$url = sprintf("%s?index=%d", $_SERVER['PHP_SELF'] , $img_counter);
                        // auto-appending of SID does not work in some environments ?!?!?
                        // PHPSESSID may appear twice in url - and if? ...
                        $url = sprintf("%s?index=%d&amp;%s", $_SERVER['PHP_SELF'], $img_counter, SID);
                        // create image with session ID instead of image URL's
                        // ==> hawxy script will immediately receive a new request
                        //     and will create appropriate image on the fly
                        $src_html = $url;
                        $src_wbmp = $url;
                        $img_counter++;
                    }
                }
                if (!isset($src_wbmp) && !isset($attrs["WBMP"])) {
                    error("<img> " . $err[7] . " wbmp", $parser, $line);
                } elseif (isset($attrs["WBMP"])) {
                    $src_wbmp = $attrs["WBMP"];
                }
                // explicitely given WBMP file has precedence
                if (!isset($src_html) && !isset($attrs["HTML"])) {
                    error("<img> " . $err[7] . " html", $parser, $line);
                } elseif (isset($attrs["HTML"])) {
                    $src_html = $attrs["HTML"];
                }
                // explicitely given HTML file has precedence
                if (isset($attrs["BMP"])) {
                    $image = new HAW_image($src_wbmp, $src_html, $alt, $attrs["BMP"]);
                } else {
                    $image = new HAW_image($src_wbmp, $src_html, $alt);
                }
                if (isset($attrs["HTML"]) && isset($attrs["HTML_WIDTH"])) {
                    $image->set_html_width($attrs["HTML_WIDTH"]);
                }
                if (isset($attrs["HTML"]) && isset($attrs["HTML_HEIGHT"])) {
                    $image->set_html_height($attrs["HTML_HEIGHT"]);
                }
                if (isset($attrs["BR"]) && $attrs["BR"] >= 0) {
                    $image->set_br($attrs["BR"] + 0);
                }
                // convert string to int!
                if (isset($attrs["LOCALSRC"])) {
                    $image->use_localsrc($attrs["LOCALSRC"]);
                }
                if (isset($attrs["CHTML_ICON"])) {
                    $image->use_chtml_icon($attrs["CHTML_ICON"] + 0);
                }
                // convert string to int!
                if (isset($attrs["MML_ICON"]) && strlen($attrs["MML_ICON"]) == 2) {
                    $image->use_mml_icon($attrs["MML_ICON"]);
                }
                $tag_stack->push($image, HAX_TAG_IMAGE);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_image object
                $image = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck, HAW_form, ...)
                $base_element = $element["element"];
                if ($element["tag"] == HAX_TAG_TD) {
                    // include HAW_text object in HAX_td pseudo class
                    $base_element->element = $image;
                    $base_element->tag = HAX_TAG_IMAGE;
                } else {
                    $base_element->add_image($image);
                }
                // add HAW_image to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "INPUT":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_INPUT, $parser);
                if (!($name = $attrs["NAME"])) {
                    error("<input> " . $err[7] . " name", $parser, $line);
                }
                // name attribute is missing
                if (isset($attrs["FORMAT"])) {
                    $input = new HAW_input($name, $attrs["VALUE"], $attrs["LABEL"], $attrs["FORMAT"]);
                } else {
                    $input = new HAW_input($name, $attrs["VALUE"], $attrs["LABEL"]);
                }
                if (isset($attrs["SIZE"])) {
                    $input->set_size($attrs["SIZE"]);
                }
                if (isset($attrs["MAXLENGTH"])) {
                    $input->set_maxlength($attrs["MAXLENGTH"]);
                }
                if (isset($attrs["TYPE"]) && strtolower($attrs["TYPE"]) == "password") {
                    $input->set_type(HAW_INPUT_PASSWORD);
                }
                if (isset($attrs["MODE"])) {
                    if (strtolower($attrs["MODE"]) == "alphabet") {
                        $input->set_mode(HAW_INPUT_ALPHABET);
                    }
                    if (strtolower($attrs["MODE"]) == "katakana") {
                        $input->set_mode(HAW_INPUT_KATAKANA);
                    }
                    if (strtolower($attrs["MODE"]) == "hiragana") {
                        $input->set_mode(HAW_INPUT_HIRAGANA);
                    }
                    if (strtolower($attrs["MODE"]) == "numeric") {
                        $input->set_mode(HAW_INPUT_NUMERIC);
                    }
                }
                if (isset($attrs["BR"]) && $attrs["BR"] >= 0) {
                    $input->set_br($attrs["BR"] + 0);
                }
                // convert string to int!
                if (isset($attrs["VOICE_TYPE"])) {
                    $input->set_voice_type($attrs["VOICE_TYPE"]);
                }
                if (isset($attrs["VOICE_GRAMMAR_SRC"])) {
                    // set external grammar
                    if (isset($attrs["VOICE_GRAMMAR_TYPE"])) {
                        $input->set_voice_grammar($attrs["VOICE_GRAMMAR_SRC"], $attrs["VOICE_GRAMMAR_TYPE"]);
                    } else {
                        $input->set_voice_grammar($attrs["VOICE_GRAMMAR_SRC"]);
                    }
                    // requires HAWHAW V5.5 or higher!
                }
                $tag_stack->push($input, HAX_TAG_INPUT);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_input object
                $input = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_form)
                $base_element = $element["element"];
                $base_element->add_input($input);
                // add HAW_input to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "RADIO":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_RADIO, $parser);
                if (!($name = $attrs["NAME"])) {
                    error("<radio> " . $err[7] . " name", $parser, $line);
                }
                // name attribute is missing
                $radio = new HAW_radio($name);
                $tag_stack->push($radio, HAX_TAG_RADIO);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_radio object
                $radio = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_form)
                $base_element = $element["element"];
                $base_element->add_radio($radio);
                // add HAW_radio to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "BUTTON":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_BUTTON, $parser);
                if (!($label = $attrs["LABEL"])) {
                    error("<button> " . $err[7] . " label", $parser, $line);
                }
                // label attribute is missing
                if (!($value = $attrs["VALUE"])) {
                    error("<button> " . $err[7] . " value", $parser, $line);
                }
                // value attribute is missing
                if (isset($attrs["CHECKED"]) && strtolower($attrs["CHECKED"]) == "yes") {
                    $checked = HAW_CHECKED;
                } else {
                    $checked = HAW_NOTCHECKED;
                }
                $element = $tag_stack->pop();
                // pop base object (HAW_radio)
                $base_element = $element["element"];
                $base_element->add_button($label, $value, $checked);
                // add button properties
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            } else {
                // HAX_PARSE_END
                // nothing to do any more
            }
            break;
        case "CHECKBOX":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_CHECKBOX, $parser);
                if (!($name = $attrs["NAME"])) {
                    error("<checkbox> " . $err[7] . " name", $parser, $line);
                }
                // name attribute is missing
                if (!($value = $attrs["VALUE"])) {
                    error("<checkbox> " . $err[7] . " value", $parser, $line);
                }
                // value attribute is missing
                if (!($label = $attrs["LABEL"])) {
                    error("<checkbox> " . $err[7] . " label", $parser, $line);
                }
                // label attribute is missing
                if (isset($attrs["CHECKED"]) && strtolower($attrs["CHECKED"]) == "yes") {
                    $checked = HAW_CHECKED;
                } else {
                    $checked = HAW_NOTCHECKED;
                }
                $checkbox = new HAW_checkbox($name, $value, $label, $checked);
                $tag_stack->push($checkbox, HAX_TAG_CHECKBOX);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_checkbox object
                $checkbox = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_form)
                $base_element = $element["element"];
                $base_element->add_checkbox($checkbox);
                // add HAW_checkbox to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "SELECT":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_SELECT, $parser);
                if (!($name = $attrs["NAME"])) {
                    error("<select> " . $err[7] . " name", $parser, $line);
                }
                // name attribute is missing
                if (strtolower($attrs["TYPE"]) == "popup") {
                    $select = new HAW_select($name, HAW_SELECT_POPUP);
                } elseif (strtolower($attrs["TYPE"]) == "spin") {
                    $select = new HAW_select($name, HAW_SELECT_SPIN);
                } else {
                    $select = new HAW_select($name);
                }
                $tag_stack->push($select, HAX_TAG_SELECT);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_select object
                $select = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_form)
                $base_element = $element["element"];
                $base_element->add_select($select);
                // add HAW_select to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "OPTION":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_OPTION, $parser);
                if (!($label = $attrs["LABEL"])) {
                    error("<option> " . $err[7] . " label", $parser, $line);
                }
                // label attribute is missing
                if (!($value = $attrs["VALUE"])) {
                    error("<option> " . $err[7] . " value", $parser, $line);
                }
                // value attribute is missing
                if (isset($attrs["SELECTED"]) && strtolower($attrs["SELECTED"]) == "yes") {
                    $selected = HAW_SELECTED;
                } else {
                    $selected = HAW_NOTSELECTED;
                }
                $element = $tag_stack->pop();
                // pop base object (HAW_select)
                $base_element = $element["element"];
                $base_element->add_option($label, $value, $selected);
                // add option properties
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            } else {
                // HAX_PARSE_END
                // nothing to do any more
            }
            break;
        case "HIDDEN":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_HIDDEN, $parser);
                if (!($name = $attrs["NAME"])) {
                    error("<hidden> " . $err[7] . " name", $parser, $line);
                }
                // name attribute is missing
                if (!($value = $attrs["VALUE"])) {
                    error("<hidden> " . $err[7] . " value", $parser, $line);
                }
                // value attribute is missing
                $hidden = new HAW_hidden($name, $value);
                $element = $tag_stack->pop();
                // pop base object (HAW_form)
                $base_element = $element["element"];
                $base_element->add_hidden($hidden);
                // add HAW_hidden to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            } else {
                // HAX_PARSE_END
                // nothing to do any more
            }
            break;
        case "SUBMIT":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_SUBMIT, $parser);
                if (!($label = $attrs["LABEL"])) {
                    error("<submit> " . $err[7] . " label", $parser, $line);
                }
                // label attribute is missing
                if (isset($attrs["NAME"])) {
                    $submit = new HAW_submit($label, $attrs["NAME"]);
                } else {
                    $submit = new HAW_submit($label);
                }
                $tag_stack->push($submit, HAX_TAG_SUBMIT);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_submit object
                $submit = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_form)
                $base_element = $element["element"];
                $base_element->add_submit($submit);
                // add HAW_submit to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "A":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_LINK, $parser);
                if (!isset($attrs["HREF"])) {
                    error("<a> " . $err[7] . " href", $parser, $line);
                }
                // href attribute is missing
                if (isset($attrs["PROXY"]) && strtolower($attrs["PROXY"]) == "no") {
                    $url = $attrs["HREF"];
                } else {
                    $url = determine_url(qualify_url($attrs["HREF"]));
                }
                // let HAWHAW proxy retrieve href
                if (isset($attrs["TITLE"])) {
                    $link = new HAW_link("", $url, $attrs["TITLE"]);
                } else {
                    $link = new HAW_link("", $url);
                }
                if (isset($attrs["BR"]) && $attrs["BR"] >= 0) {
                    $link->set_br($attrs["BR"] + 0);
                }
                // convert string to int!
                if (isset($attrs["CSS_CLASS"])) {
                    $link->set_css_class($attrs["CSS_CLASS"]);
                }
                if (isset($attrs["VOICE_DTMF"])) {
                    $link->set_voice_dtmf($attrs["VOICE_DTMF"]);
                }
                if (isset($attrs["VOICE_INPUT"])) {
                    $link->set_voice_input($attrs["VOICE_INPUT"]);
                } else {
                    unset($link->voice_input);
                }
                // we must destinguish missing attr from empty string
                if (isset($attrs["VOICE_TIMEOUT"])) {
                    $link->set_voice_timeout($attrs["VOICE_TIMEOUT"] + 0);
                }
                // convert string to int!
                $tag_stack->push($link, HAX_TAG_LINK);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_link object
                $link = $element["element"];
                if (!$link->voice_text) {
                    $link->voice_text = $link->label;
                }
                // update voice_text if not already set
                $element = $tag_stack->pop();
                // pop base object (HAW_deck, HAW_linkset, ...)
                $base_element = $element["element"];
                if ($element["tag"] == HAX_TAG_TD) {
                    // include HAW_link object in HAX_td pseudo class
                    $base_element->element = $link;
                    $base_element->tag = HAX_TAG_LINK;
                } else {
                    $base_element->add_link($link);
                }
                // add HAW_link to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "LINKSET":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_LINKSET, $parser);
                if ($number_of_linksets++ > 0) {
                    error($err[8], $parser, $line);
                }
                $linkset = new HAW_linkset();
                $tag_stack->push($linkset, HAX_TAG_LINKSET);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_linkset object
                $linkset = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck)
                $base_element = $element["element"];
                $base_element->add_linkset($linkset);
                // add HAW_linkset to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "TABLE":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_TABLE, $parser);
                $table = new HAW_table();
                $tag_stack->push($table, HAX_TAG_TABLE);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_table object
                $table = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck, HAW_form, ...)
                $base_element = $element["element"];
                $base_element->add_table($table);
                // add HAW_table to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "TR":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_ROW, $parser);
                $row = new HAW_row();
                $tag_stack->push($row, HAX_TAG_ROW);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_row object
                $row = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_table)
                $base_element = $element["element"];
                $base_element->add_row($row);
                // add HAW_row to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "TD":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_TD, $parser);
                $td = new HAX_td();
                $tag_stack->push($td, HAX_TAG_TD);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAX_td object
                $td = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_row)
                $base_element = $element["element"];
                $base_element->add_column($td->element);
                // add included element of HAX_td to row
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "HR":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_RULE, $parser);
                if (isset($attrs["WIDTH"]) && isset($attrs["SIZE"])) {
                    $rule = new HAW_rule($attrs["WIDTH"], $attrs["SIZE"]);
                } elseif (isset($attrs["WIDTH"])) {
                    $rule = new HAW_rule($attrs["WIDTH"]);
                } elseif (isset($attrs["SIZE"])) {
                    $rule = new HAW_rule("100%", $attrs["SIZE"]);
                } else {
                    $rule = new HAW_rule();
                }
                $tag_stack->push($rule, HAX_TAG_RULE);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_rule object
                $rule = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck or HAW_form)
                $base_element = $element["element"];
                $base_element->add_rule($rule);
                // add HAW_rule to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "PHONE":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_PHONE, $parser);
                if (isset($attrs["TITLE"])) {
                    $phone = new HAW_phone("", $attrs["TITLE"]);
                } else {
                    $phone = new HAW_phone("");
                }
                if (isset($attrs["CSS_CLASS"])) {
                    $phone->set_css_class($attrs["CSS_CLASS"]);
                }
                if (isset($attrs["VOICE_INPUT"])) {
                    $phone->set_voice_input($attrs["VOICE_INPUT"]);
                }
                if (isset($attrs["VOICE_DTMF"])) {
                    $phone->set_voice_dtmf($attrs["VOICE_DTMF"]);
                }
                if (isset($attrs["VOICE_TIMEOUT"])) {
                    $phone->set_voice_timeout($attrs["VOICE_TIMEOUT"] + 0);
                }
                // convert string to int!
                if (isset($attrs["BR"]) && $attrs["BR"] >= 0) {
                    $phone->set_br($attrs["BR"] + 0);
                }
                // convert string to int!
                $tag_stack->push($phone, HAX_TAG_PHONE);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_phone object
                $phone = $element["element"];
                if (!$phone->voice_text) {
                    $phone->voice_text = $phone->label;
                }
                // update voice_text if not already set
                $element = $tag_stack->pop();
                // pop base object (HAW_deck)
                $base_element = $element["element"];
                $base_element->add_phone($phone);
                // add HAW_phone to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "VOICE_TEXT":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_VOICE_TEXT, $parser);
                if (isset($attrs["AUDIO_SRC"])) {
                    $audio_src = $attrs["AUDIO_SRC"];
                } else {
                    $audio_src = "";
                }
                $event = new HAX_voice_event(HAX_TAG_VOICE_TEXT, "", $audio_src);
                $tag_stack->push($event, HAX_TAG_VOICE_TEXT);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAX_voice_event object
                $event = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck, HAW_input, ...)
                $base_element = $element["element"];
                // set voice text for base element
                $base_element->set_voice_text($event->text, $event->audio_src);
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "VOICE_HELP":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_VOICE_HELP, $parser);
                if (isset($attrs["AUDIO_SRC"])) {
                    $audio_src = $attrs["AUDIO_SRC"];
                } else {
                    $audio_src = "";
                }
                if (isset($attrs["URL"])) {
                    $url = $attrs["URL"];
                } else {
                    $url = "";
                }
                $event = new HAX_voice_event(HAX_TAG_VOICE_HELP, "", $audio_src, $url);
                $tag_stack->push($event, HAX_TAG_VOICE_HELP);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAX_voice_event object
                $event = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck, HAW_input, ...)
                $base_element = $element["element"];
                // activate voice help for base element
                $base_element->set_voice_help($event->text, $event->audio_src, $event->url);
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "VOICE_NOMATCH":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_VOICE_NOMATCH, $parser);
                if (isset($attrs["AUDIO_SRC"])) {
                    $audio_src = $attrs["AUDIO_SRC"];
                } else {
                    $audio_src = "";
                }
                if (isset($attrs["URL"])) {
                    $url = $attrs["URL"];
                } else {
                    $url = "";
                }
                $event = new HAX_voice_event(HAX_TAG_VOICE_NOMATCH, "", $audio_src, $url);
                $tag_stack->push($event, HAX_TAG_VOICE_NOMATCH);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAX_voice_event object
                $event = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck, HAW_input, ...)
                $base_element = $element["element"];
                // activate voice nomatch for base element
                $base_element->set_voice_nomatch($event->text, $event->audio_src, $event->url);
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "VOICE_NOINPUT":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_VOICE_NOINPUT, $parser);
                if (isset($attrs["AUDIO_SRC"])) {
                    $audio_src = $attrs["AUDIO_SRC"];
                } else {
                    $audio_src = "";
                }
                if (isset($attrs["URL"])) {
                    $url = $attrs["URL"];
                } else {
                    $url = "";
                }
                $event = new HAX_voice_event(HAX_TAG_VOICE_NOINPUT, "", $audio_src, $url);
                $tag_stack->push($event, HAX_TAG_VOICE_NOINPUT);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAX_voice_event object
                $event = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck, HAW_input, ...)
                $base_element = $element["element"];
                // activate voice noinput for base element
                $base_element->set_voice_noinput($event->text, $event->audio_src, $event->url);
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        case "RAW":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_RAW, $parser);
                if (!isset($attrs["MARKUP_LANGUAGE"])) {
                    error("<raw> " . $err[7] . " markup_language", $parser, $line);
                }
                // markup_language attribute is missing
                if (strtolower($attrs["MARKUP_LANGUAGE"]) == "html") {
                    if (HAX_RAW_HTML_ALLOWED == false) {
                        error($err[4], $parser, $line);
                    }
                    // raw html not allowed
                    $raw = new HAW_raw(HAW_HTML, "");
                } elseif (strtolower($attrs["MARKUP_LANGUAGE"]) == "wml") {
                    if (HAX_RAW_WML_ALLOWED == false) {
                        error($err[4], $parser, $line);
                    }
                    // raw wml not allowed
                    $raw = new HAW_raw(HAW_WML, "");
                } elseif (strtolower($attrs["MARKUP_LANGUAGE"]) == "hdml") {
                    if (HAX_RAW_HDML_ALLOWED == false) {
                        error($err[4], $parser, $line);
                    }
                    // raw hdml not allowed
                    $raw = new HAW_raw(HAW_HDML, "");
                } elseif (strtolower($attrs["MARKUP_LANGUAGE"]) == "voicexml") {
                    if (HAX_RAW_VXML_ALLOWED == false) {
                        error($err[4], $parser, $line);
                    }
                    // raw VoiceXML not allowed
                    $raw = new HAW_raw(HAW_VXML, "");
                } else {
                    error("<raw> " . $err[14] . " markup_language", $parser, $line);
                }
                // invalid markup_language attribute
                $tag_stack->push($raw, HAX_TAG_RAW);
                $raw_mode = true;
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_raw object
                $raw = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck or HAW_form)
                $base_element = $element["element"];
                $base_element->add_raw($raw);
                // add HAW_raw to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
                $raw_mode = false;
            }
            break;
        case "PLUGIN":
            if ($pos == HAX_PARSE_BEGIN) {
                check_state(HAX_TAG_RAW, $parser);
                if (!isset($attrs["NAME"])) {
                    error("<plugin> " . $err[7] . " name", $parser, $line);
                }
                // markup_language attribute is missing
                // determine filename of plugin php script
                // must be located in the same directory as hawxy.php
                $plugin_filename = dirname(__FILE__) . '/' . HAX_PLUGIN_PREFIX . $attrs["NAME"] . '.php';
                // security check 1: test if plugin file exists
                if (!file_exists($plugin_filename)) {
                    error($err[15] . $attrs["NAME"], $parser, $line);
                }
                // plugin not found
                // setup php instructions
                $php_cmd = "require_once(\"{$plugin_filename}\");" . '$udef = new ' . HAX_PLUGIN_PREFIX . $attrs["NAME"] . "();";
                while (list($key, $val) = each($attrs)) {
                    // security check 2: allow alphanumeric characters only!
                    $param = preg_replace('/[^\\w]/', "", $val);
                    if (strtolower($key) != "name") {
                        $php_cmd .= '$udef->set_' . strtolower($key) . '(\'' . $param . '\');';
                    }
                }
                // create user-defined object and call set methods
                if (eval($php_cmd) === false) {
                    // eval might exit silently in case of fatal errors within the plugin!
                    error($err[16] . " " . $attrs["NAME"], $parser, $line);
                }
                // error in plugin's php code
                $tag_stack->push($udef, HAX_TAG_PLUGIN);
            } else {
                // HAX_PARSE_END
                $element = $tag_stack->pop();
                // pop HAW_plugin object
                $udef = $element["element"];
                $element = $tag_stack->pop();
                // pop base object (HAW_deck or HAW_form)
                $base_element = $element["element"];
                $base_element->add_userdefined($udef);
                // add HAW_plugin to base object
                $tag_stack->push($base_element, $element["tag"]);
                // re-push base object
            }
            break;
        default:
            if ($raw_mode == true) {
                // only in raw mode unknown tags will be handled
                $element = $tag_stack->pop();
                if ($element["tag"] == HAX_TAG_RAW) {
                    if ($pos == HAX_PARSE_BEGIN) {
                        // copy opening (raw) tag with all its attributes
                        $element["element"]->code .= "<" . strtolower($name);
                        while (list($key, $value) = each($attrs)) {
                            $element["element"]->code .= " " . strtolower($key) . "=\"" . $value . "\"";
                        }
                        $element["element"]->code .= ">";
                    } else {
                        // HAX_PARSE_END
                        $element["element"]->code .= "</" . strtolower($name) . ">";
                    }
                }
                $tag_stack->push($element["element"], $element["tag"]);
            }
            break;
    }
}