Example #1
0
function handshake($socket)
{
    $bytes = socket_recv($socket, $buffer, 2048, 0);
    $header_list = parse_header($buffer);
    $accept = $header_list['Sec-WebSocket-Key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
    $accept = base64_encode(sha1($accept, true));
    $upgrade = array('HTTP/1.1 101 Switching Protocols', 'Upgrade: websocket', 'Connection: Upgrade', "Sec-WebSocket-Accept: {$accept}", "WebSocket-Origin: {$header_list['Origin']}", "WebSocket-Location: ws://{$header_list['Host']}/ws/server.php", "\r\n");
    $upgrade = implode("\r\n", $upgrade);
    socket_write($socket, $upgrade);
}
Example #2
0
 /**
  *	用户 header
  *
  *	1 参数 用户标识符
  *
  *	返回值 false 或 连接类型
  **/
 function header($data, $accept)
 {
     $header = parse_header($data, true);
     $msg = '';
     // 最多 4096 信息
     if (strlen($data) >= 4096) {
         return false;
     }
     // 系统本身的 api 条用
     if (!empty($header['api'])) {
         // key = 验证的 time = 验证的
         $arr = explode('|', trim($header['api']), 2);
         if (count($arr) != 2) {
             return false;
         }
         list($time, $key) = $arr;
         if ($time > time() || $time < time() - 10) {
             return false;
         }
         if (empty($this->key) || strlen($key) != 64) {
             return false;
         }
         if (md5($this->key . $time) . md5($time . $this->key) !== $key) {
             return false;
         }
         $msg .= '200';
         if (!socket_write($accept, $msg, strlen($msg))) {
             return false;
         }
         return WEBSOCKET_TYPE_API;
     }
     // flash 验证信息
     if (trim(implode('', $header)) == '<policy-file-request/>') {
         $msg .= '<?xml version="1.0"?>';
         $msg .= '<cross-domain-policy>';
         $msg .= '<allow-access-from domain="' . ($this->domain ? '*.' . $this->domain : '*') . '" to-ports="*"/>';
         $msg .= '</cross-domain-policy>';
         $msg .= "";
         socket_write($accept, $msg, strlen($msg));
         return false;
     }
     // 超过最大在线
     if (WEBSOCKET_ONLINE <= count($this->accept)) {
         return false;
     }
     // 来路
     $origin = empty($header['origin']) ? empty($header['websocket-origin']) ? '' : $header['websocket-origin'] : $header['origin'];
     $parse = parse_url($origin);
     $scheme = empty($parse['scheme']) || $parse['scheme'] != 'https' ? '' : 's';
     $origin = $origin && !empty($parse['host']) ? 'http' . $scheme . '://' . $parse['host'] : '';
     // 无效来路
     if ($this->domain && !empty($parse['host']) && !preg_match('/(^|\\.)' . preg_quote($this->domain, '/') . '$/i', $parse['host'])) {
         return false;
     }
     //  10+ 版本的
     if (!empty($header['sec-websocket-key'])) {
         $type = WEBSOCKET_TYPE_2;
         $a = base64_encode(sha1(trim($header['sec-websocket-key']) . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
         $msg .= "HTTP/1.1 101 Switching Protocols\r\n";
         $msg .= "Upgrade: websocket\r\n";
         $msg .= "Connection: Upgrade\r\n";
         if ($origin) {
             $msg .= "Sec-WebSocket-Origin: {$origin}\r\n";
         }
         $msg .= "Sec-WebSocket-Accept: {$a}\r\n";
         $msg .= "\r\n";
         if (!socket_write($accept, $msg, strlen($msg))) {
             return false;
         }
         return WEBSOCKET_TYPE_2;
     }
     // 10- 版本的
     if (!empty($header['sec-websocket-key1']) && !empty($header['sec-websocket-key2']) && !empty($header['html'])) {
         $key1 = $header['sec-websocket-key1'];
         $key2 = $header['sec-websocket-key2'];
         $key3 = $header['html'];
         if (!preg_match_all('/([\\d]+)/', $key1, $key1_num) || !preg_match_all('/([\\d]+)/', $key2, $key2_num)) {
             return false;
         }
         $key1_num = implode($key1_num[0]);
         $key2_num = implode($key2_num[0]);
         if (!preg_match_all('/([ ]+)/', $key1, $key1_spc) || !preg_match_all('/([ ]+)/', $key2, $key2_spc)) {
             return false;
         }
         $key1_spc = strlen(implode($key1_spc[0]));
         $key2_spc = strlen(implode($key2_spc[0]));
         $key1_sec = pack("N", $key1_num / $key1_spc);
         $key2_sec = pack("N", $key2_num / $key2_spc);
         $msg .= "HTTP/1.1 101 Web Socket Protocol Handshake\r\n";
         $msg .= "Upgrade: WebSocket\r\n";
         $msg .= "Connection: Upgrade\r\n";
         if ($origin) {
             $msg .= "Sec-WebSocket-Origin: {$origin}\r\n";
         }
         $msg .= "Sec-WebSocket-Location: ws{$scheme}://{$this->host}:{$this->port}{$this->path}\r\n";
         $msg .= "\r\n";
         $msg .= md5($key1_sec . $key2_sec . $key3, true);
         if (!socket_write($accept, $msg, strlen($msg))) {
             return false;
         }
         return WEBSOCKET_TYPE_1;
     }
     return false;
 }
Example #3
0
function parse_message($rawmessage)
{
    global $attachment_delete_alternative, $attachment_uudecode;
    // Read the header of the message:
    $count_rawmessage = count($rawmessage);
    $message = new messageType();
    $rawheader = array();
    $i = 0;
    while ($rawmessage[$i] != "") {
        $rawheader[] = $rawmessage[$i];
        $i++;
    }
    // Parse the Header:
    $message->header = parse_header($rawheader);
    // Now we know if the message is a mime-multipart message:
    $content_type = split("/", $message->header->content_type[0]);
    if ($content_type[0] == "multipart") {
        $message->header->content_type = array();
        // We have multible bodies, so we split the message into its parts
        $boundary = "--" . $message->header->content_type_boundary;
        // lets find the first part
        while ($rawmessage[$i] != $boundary) {
            $i++;
        }
        $i++;
        $part = array();
        while ($i <= $count_rawmessage) {
            if ($rawmessage[$i] == $boundary || $i == $count_rawmessage - 1 || $rawmessage[$i] == $boundary . '--') {
                $partmessage = parse_message($part);
                // merge the content-types of the message with those of the part
                for ($o = 0; $o < count($partmessage->header->content_type); $o++) {
                    $message->header->content_type[] = $partmessage->header->content_type[$o];
                    $message->header->content_type_charset[] = $partmessage->header->content_type_charset[$o];
                    $message->header->content_type_name[] = $partmessage->header->content_type_name[$o];
                    $message->body[] = $partmessage->body[$o];
                }
                $part = array();
            } else {
                if ($i < $count_rawmessage) {
                    $part[] = $rawmessage[$i];
                }
            }
            if ($rawmessage[$i] == $boundary . '--') {
                break;
            }
            $i++;
        }
        // Is this a multipart/alternative multipart-message? Do we have to
        // delete all non plain/text parts?
        if ($attachment_delete_alternative && $content_type[1] == "alternative") {
            $plaintext = false;
            for ($o = 0; $o < count($message->header->content_type); $o++) {
                if ($message->header->content_type[$o] == "text/plain") {
                    $plaintext = true;
                }
                // we found at least one text/plain
            }
            if ($plaintext) {
                // now we can delete the other parts
                for ($o = 0; $o < count($message->header->content_type); $o++) {
                    if ($message->header->content_type[$o] != "text/plain") {
                        unset($message->header->content_type[$o]);
                        unset($message->header->content_type_name[$o]);
                        unset($message->header->content_type_charset[$o]);
                        unset($message->body[$o]);
                    }
                }
            }
        }
    } else {
        // No mime-attachments in the message:
        $body = "";
        $uueatt = 0;
        // as default we have no uuencoded attachments
        for ($i++; $i < $count_rawmessage; $i++) {
            // do we have an inlay uuencoded file?
            if (strtolower(substr($rawmessage[$i], 0, 5)) != "begin" || $attachment_uudecode == false) {
                $body .= $rawmessage[$i] . "\n";
                // yes, it seems, we have!
            } else {
                $old_i = $i;
                $uue_infoline_raw = $rawmessage[$i];
                $uue_infoline = explode(" ", $uue_infoline_raw);
                $uue_data = "";
                $i++;
                while ($rawmessage[$i] != "end") {
                    if (strlen(trim($rawmessage[$i])) > 2) {
                        $uue_data .= $rawmessage[$i] . "\n";
                    }
                    $i++;
                }
                // now write the data in an attachment
                $uueatt++;
                $message->body[$uueatt] = uudecode($uue_data);
                $message->header->content_type_name[$uueatt] = "";
                for ($o = 2; $o < count($uue_infoline); $o++) {
                    $message->header->content_type_name[$uueatt] .= $uue_infoline[$o];
                }
                $message->header->content_type[$uueatt] = get_mimetype_by_filename($message->header->content_type_name[$uueatt]);
            }
        }
        if ($message->header->content_type[0] == "text/plain") {
            $body = trim($body);
            if ($body == "") {
                $body = " ";
            }
        }
        $body = decode_body($body, $message->header->content_transfer_encoding);
        $message->body[0] = $body;
    }
    if (!isset($message->header->content_type_charset)) {
        $message->header->content_type_charset = array("ISO-8859-1");
    }
    if (!isset($message->header->content_type_name)) {
        $message->header->content_type_name = array("unnamed");
    }
    for ($o = 0; $o < count($message->body); $o++) {
        if (!isset($message->header->content_type_charset[$o])) {
            $message->header->content_type_charset[$o] = "ISO-8859-1";
        }
        if (!isset($message->header->content_type_name[$o])) {
            $message->header->content_type_name[$o] = "unnamed";
        }
    }
    return $message;
}
function fetch_and_store_images(array $img_urls)
{
    $return_arr = array('valid_images' => array(), 'invalid_image_urls' => array());
    $valid_status = array(200, 301, 304);
    $kvdb = new SaeKV();
    $kvdb->init();
    foreach ($img_urls as $hash_size_name => $img_url) {
        list($hash, $size, $filename) = explode('#', $hash_size_name);
        if ($filename !== 'none' && file_exists("saestor://tumblrlikes/{$filename}")) {
            $img = file_get_contents("saestor://tumblrlikes/{$filename}");
        } else {
            $filename = basename($img_url);
            $img = @file_get_contents($img_url);
            $fetch_succeed = in_array(parse_header($http_response_header, 'status'), $valid_status);
            $img_info = array('date' => date('Y-m-d'), 'size' => $size, 'read_counter' => 1, 'remark' => $fetch_succeed ? '' : 'inaccessible');
            $kvdb->set($filename, $img_info);
            if ($img === false || !$fetch_succeed) {
                $return_arr['invalid_image_urls'][] = $img_url;
                continue;
            } else {
                file_put_contents("saestor://tumblrlikes/{$filename}", $img);
            }
        }
        $return_arr['valid_images'][$img_url] = $img;
    }
    return $return_arr;
}
 function header($data, $accept, $index = 0)
 {
     $header = parse_header($data, true);
     if (strlen($data) >= 4096) {
         return false;
     }
     if (count($this->accept) > WEBSOCKET_ONLINE) {
         return false;
     }
     $msg = '';
     if (trim(implode('', $header)) == '<policy-file-request/>') {
         $msg .= '<?xml version="1.0"?>';
         $msg .= '<cross-domain-policy>';
         $msg .= '<allow-access-from domain="' . ($this->domain ? '*.' . $this->domain : '*') . '" to-ports="*"/>';
         $msg .= '</cross-domain-policy>';
         $msg .= "";
         socket_write($accept, $msg, strlen($msg));
         return false;
     }
     $origin = empty($header['origin']) ? empty($header['websocket-origin']) ? '' : $header['websocket-origin'] : $header['origin'];
     $parse = parse_url($origin);
     $scheme = empty($parse['scheme']) || $parse['scheme'] != 'https' ? '' : 's';
     $origin = $origin && !empty($parse['host']) ? 'http' . $scheme . '://' . $parse['host'] : '';
     if ($this->domain && !empty($parse['host']) && !preg_match('/(^|\\.)' . preg_quote($this->domain, '/') . '$/i', $parse['host'])) {
         return false;
     }
     if (!empty($header['sec-websocket-key'])) {
         $a = base64_encode(sha1(trim($header['sec-websocket-key']) . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
         $msg .= "HTTP/1.1 101 Switching Protocols\r\n";
         $msg .= "Upgrade: websocket\r\n";
         $msg .= "Connection: Upgrade\r\n";
         if ($origin) {
             $msg .= "Sec-WebSocket-Origin: {$origin}\r\n";
         }
         $msg .= "Sec-WebSocket-Accept: {$a}\r\n";
         $msg .= "\r\n";
         if (!socket_write($accept, $msg, strlen($msg))) {
             return false;
         }
         return 2;
     }
     if (!empty($header['sec-websocket-key1']) && !empty($header['sec-websocket-key2']) && !empty($header['html'])) {
         $key1 = $header['sec-websocket-key1'];
         $key2 = $header['sec-websocket-key2'];
         $key3 = $header['html'];
         if (!preg_match_all('/([\\d]+)/', $key1, $key1_num) || !preg_match_all('/([\\d]+)/', $key2, $key2_num)) {
             return false;
         }
         $key1_num = implode($key1_num[0]);
         $key2_num = implode($key2_num[0]);
         if (!preg_match_all('/([ ]+)/', $key1, $key1_spc) || !preg_match_all('/([ ]+)/', $key2, $key2_spc)) {
             return false;
         }
         $key1_spc = strlen(implode($key1_spc[0]));
         $key2_spc = strlen(implode($key2_spc[0]));
         $key1_sec = pack("N", $key1_num / $key1_spc);
         $key2_sec = pack("N", $key2_num / $key2_spc);
         $msg .= "HTTP/1.1 101 Web Socket Protocol Handshake\r\n";
         $msg .= "Upgrade: WebSocket\r\n";
         $msg .= "Connection: Upgrade\r\n";
         if ($origin) {
             $msg .= "Sec-WebSocket-Origin: {$origin}\r\n";
         }
         $msg .= "Sec-WebSocket-Location: ws{$scheme}://{$this->host}:{$this->port}{$this->path}\r\n";
         $msg .= "\r\n";
         $msg .= md5($key1_sec . $key2_sec . $key3, true);
         if (!socket_write($accept, $msg, strlen($msg))) {
             return false;
         }
         return 1;
     }
     return false;
 }
Example #6
0
function parse_link($link, $level=0) {
    global $name, $the_file_name, $the_link, $locationheader, $parsed_link, $link_update;
    if ($level > 3)
        return FALSE;
    if ($link == "***" && $link_update)
        $link = getLinkPath($link_update);

    $url_parts = @parse_url( $link );
    //filter out localhost and reserved or private IPs
    if (stripos($url_parts["host"], 'localhost') !== false
        || stripos($url_parts["host"], 'loopback') !== false
        || (filter_var($url_parts["host"], FILTER_VALIDATE_IP) !== false
            && (strpos($url_parts["host"],'127') === 0
                || filter_var($url_parts["host"], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false)
            )
        ) {
        return array('response' => 'HTTP/1.0 400 Bad Request', 'response_code' => 400);
    }
    if (substr($link,0,6) == "ftp://") {
        // Parsing an FTF-Adress
        $documentpath = $url_parts["path"];

        if (strpos($url_parts["host"],"@")) {
            $url_parts["pass"] .= "@".substr($url_parts["host"],0,strpos($url_parts["host"],"@"));
            $url_parts["host"] = substr(strrchr($url_parts["host"],"@"),1);
        }

        if (preg_match('/[^a-z0-9_.-]/i',$url_parts['host'])){ // exists umlauts ?
            $IDN = new idna_convert();
            $out = $IDN->encode(utf8_encode($url_parts['host'])); // false by error
            $url_parts['host'] = ($out)? $out : $url_parts['host'];
        }

        $ftp = ftp_connect($url_parts["host"]);

        if (!$url_parts["user"]) $url_parts["user"] = "******";
        if (!$url_parts["pass"]) {
            $mailclass = new StudipMail();
            $url_parts["pass"] = $mailclass->getSenderEmail();
        }
        if (!@ftp_login($ftp,$url_parts["user"],$url_parts["pass"])) {
            ftp_quit($ftp);
            return FALSE;
        }
        $parsed_link["Content-Length"] = ftp_size($ftp, $documentpath);
        ftp_quit($ftp);
        if ($parsed_link["Content-Length"] != "-1") {
            $parsed_link["HTTP/1.0 200 OK"] = "HTTP/1.0 200 OK";
            $parsed_link["response_code"] = 200;
        } else {
            $parsed_link = FALSE;
        }
        $url_parts["pass"] = preg_replace("!@!","%40",$url_parts["pass"]);
        $the_link = "ftp://".$url_parts["user"].":".$url_parts["pass"]."@".$url_parts["host"].$documentpath;
        return $parsed_link;

    } else {
        if (!empty( $url_parts["path"])){
            $documentpath = $url_parts["path"];
        } else {
            $documentpath = "/";
        }
        if ( !empty( $url_parts["query"] ) ) {
            $documentpath .= "?" . $url_parts["query"];
        }
        $host = $url_parts["host"];
        $port = $url_parts["port"];
        $scheme = strtolower($url_parts['scheme']);
        if (!in_array($scheme , words('http https'))) {
            return array('response' => 'HTTP/1.0 400 Bad Request', 'response_code' => 400);
        }
        if ($scheme == "https") {
            $ssl = TRUE;
            if (empty($port)) $port = 443;
        } else {
            $ssl = FALSE;
        }
        if (empty( $port ) ) $port = "80";

        if (preg_match('/[^a-z0-9_.-]/i',$host)){ // exists umlauts ?
            $IDN = new idna_convert();
            $out = $IDN->encode(utf8_encode($host)); // false by error
            $host = ($out)? $out : $host;
            $pwtxt = ($url_parts['user'] && $url_parts['pass'])? $url_parts['user'].':'. $url_parts['pass'].'@':'';
            $the_link = $url_parts['scheme'].'://'.$pwtxt.$host.':'.$port.$documentpath;
        }
        $socket = @fsockopen( ($ssl? 'ssl://':'').$host, $port, $errno, $errstr, 10 );
        if (!$socket) {
            return array('response' => 'HTTP/1.0 400 Bad Request', 'response_code' => 400);
        } else {
            $urlString = "GET ".$documentpath." HTTP/1.0\r\nHost: $host\r\n";
            if ($url_parts["user"] && $url_parts["pass"]) {
                $pass = $url_parts["pass"];
                $user = $url_parts["user"];
                $urlString .= "Authorization: Basic ".base64_encode("$user:$pass")."\r\n";
            }
            $urlString .= sprintf("User-Agent: Stud.IP v%s File Crawler\r\n", $GLOBALS['SOFTWARE_VERSION']);
            $urlString .= "Connection: close\r\n\r\n";
            fputs($socket, $urlString);
            stream_set_timeout($socket, 5);
            $response = '';
            do {
                $response .= fgets($socket, 128);
                $info = stream_get_meta_data($socket);
            } while (!feof($socket) && !$info['timed_out'] && strlen($response) < 1024);
            fclose($socket);
        }
        $parsed_link = parse_header($response);

        // Anderer Dateiname?
        $disposition_header = $parsed_link['Content-Disposition']
                           ?: $parsed_link['content-disposition'];
        if ($disposition_header) {
            $header_parts = explode(';', $disposition_header);
            foreach ($header_parts as $part) {
                $part = trim($part);
                list($key, $value) = explode('=', $part, 2);
                if (strtolower($key) === 'filename') {
                    $the_file_name = trim($value, '"');
                }
            }
        } else {
            $the_file_name = basename($url_parts['path']) ?: $the_file_name;
        }
        // Weg über einen Locationheader:
        $location_header = $parsed_link["Location"]
                        ?: $parsed_link["location"];
        if (in_array($parsed_link["response_code"], array(300,301,302,303,305,307)) && $location_header) {
            if (strpos($location_header, 'http') !== 0) {
                $location_header = $url_parts['scheme'] . '://' . $url_parts['host'] . '/' . $location_header;
            }
            $parsed_link = parse_link($location_header, $level + 1);
        }
        return $parsed_link;
    }
}