Работа с сокетами и контекстом на примере получения кук для авторизации по сессии

1
2
3
4
5
6
7
8
9
10
<?
// Авторизуемся и получаем идентификатор сессии
$cookies = getUriCookies('http://mysite.com/login.php', array('login' => 'My login', 'password' => 'my password'), 'POST');

// Создаём контекст с переданными куками, включая идентификатор сессии
$context = createCookiesContext($cookies);

// Получаем приватный файл, используя сессию
echo file_get_contents('http://mysite.com/private.php?id=someId', false, $context);
?>
Функция - getUriCookies
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<?
/**
 * Функция возвращает массив кук по заданному запросу
 *
 * @author zg
 * @param string $uri Адрес запроса
 * @param array $params Параметры запроса
 * @param string $method Метод запроса
 * @return array
 */
function getUriCookies( $uri, $params = null, $method = null )
{
    if ( !isset($method) )$method = 'GET';
    if ( $method !== 'GET' && $method !== 'POST' ) 
        throw new Exception('Function '. __FUNCTION__ .'(): Invalid method '. $method .'. Must be GET or POST.');
    
    // Парсим запрос
    $url = parse_url( $uri );
    
    // Получаем данные из адреса запроса
    $host  = isset($url['host']) ? $url['host'] : null;
    $path  = isset($url['path']) ? $url['path'] : null;
    $query = isset($url['query']) ? $url['query'] : null;
    
    // Защита от нулевого хоста
    if ( !$host ) throw new Exception('Function '. __FUNCTION__ .'(): Invalid hostname in URI "'. $uri .'".');
    
    // Строим массив параметров
    $outParams = array();
    
    // Заполняем массив параметров из строки запроса
    if ( isset($query) ) parse_str($query, $outParams);
    
    // Добавляем параметры из аргументов функции, если метод GET
    if ( $method === 'GET' && is_array($params) ) $outParams = array_merge( $outParams, $params );
    
    // Получаем результирующий запрос
    $query = http_build_query( $outParams );
    
    // Формируем заголовки
    $headers = array();
    
    // Общие заголовки
    $headers[] = $method .' '. $path .'?'. $query .' HTTP/1.0';
    $headers[] = 'Host: '. $host;
    
    // Тело запроса
    $content = null;
    
    // Если метод запроса POST
    if ( $method === 'POST' && is_array( $params ) )
    {
        // Добавляем параметры запроса
        $headers[] = 'Content-type: application/x-www-form-urlencoded';
        $content   = http_build_query($params);
    }
    
    // Дбоавляем к заголовкам тело запроса
    $headers[] = 'Content-length: '. strlen($content);
    $headers[] = 'Connection: close';
    $headers[] = '';
    $headers[] = $content;
    
    // Формируем запрос
    $request = join("\r\n", $headers);
    
    // Открываем сокет для записи
    $fp = @fsockopen($host, 80, $errno, $error);
    
    // Проверка правильности открытия сокета
    if ( !$fp ) throw new Exception('Function '. __FUNCTION__ .'(): Filed open URL '. $uri .'');
    
    // Посылаем запрос
    fputs($fp, $request);
    
    // Массив результата
    $result = array();
    
    // Считываем ответ построчно
    while ( !feof($fp) )
    {
        $line = trim(fgets( $fp ));
        
        // Меня интерисует только заголовок
        if ( !$line ) break;
        
        // В заголовке меня интерисуют только куки
        @list($field, $value) = preg_split('/\s*:\s*/', $line, 2);
        
        // Запоминаем найденную куку
        if ( strtolower($field) === 'set-cookie' )
        {
            // Точнее, запоминаем только само значение куки (недекодированное)
            $result[] = array_shift(preg_split('/\s*;\s*/', $value, 2));
        }
    }
    
    // Тут можно сделать обработку тела ответа, например, проверку результата логирования
    // но это специфичный код, поэтому я его опущу
    
    // Вывод тела ответа
    //fpassthru($fp);
    
    // Закрываем сокет
    fclose($fp);
    
    // Возвращаем массив результата
    return $result;
}
?>
Функция - createCookiesContext
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?
/**
 * Создание контекста со значениями кук
 * 
 * @author zg
 * @param array $cookies
 * @return resource
 */
function createCookiesContext( $cookies )
{
    return stream_context_create(array(
        'http' => array(
            'header' => 'Cookie: '. join('; ', $cookies),
        ),
    ));
}
?>

Ссылки по теме

http://ru2.php.net/manual/ru/context.http.php - описание опций контекста