В планах сегодня было уехать в Ростов-на-Дону по семейным обстоятельствам.
Все шло хорошо, вещи были собраны, у друга взял ноутбук ( т.к. мой еще пол года назад сгорел не выдержав той нагрузки которая мне нужна была ).
Приехал на Ж/Д вокзал, купил в 13 с копейками билет на 26.05.2010 в 15:00 на Ростов-на-Дону и сел в зал ожидания.
Дождавшись посадки спросил где останавливается автобус на Ростов, мне любезно показали на автобус стоящий перед выходом, но частично он меня смутил т.к. была табличка “Москва”, я спросил у водилы “Вы на Ростов”, он кивнул и любезно показал на дверь, мол садитесь.
В 15:00 как по часам мы тронулись, второе что смутило не та дорога, но после того как я увидел заброшенную заправку которая на выезде из Саратова в сторону Волгограда да и сам знак Волгограда мои сомнения рассеялись и я уснул.
В Калининске меня любезно растолкал контролер и спросил мол кто я и куда я, я ответил кто я и что я в Ростов.
Мне же любезно сказали что я идиот и сел не на тот автобус, матерясь вышел из автобуса взял вещи и купил билет до Саратова.
В итоге, я уезжаю завтра и то после разговора с администратором фирмы “Властелин”.
Tags:
Сегодня в ТП HF обратился клиент с вопросом в каком виде у нас стоит PHP, в виде модуля Apache или FastCGI.
Ответил естественно что FastCGI, но т.к. было не рабочее время поинтересовался зачем ему эти данные. Оказалось DLE требует для расширенной авторизации PHP в виде модуля.
И под конец из-за того что делать было нечего я решил скачать DLE и посмотреть зачем же ему PHP нужен в виде модуля.
Оказалось, расширенная авторизация в DLE подразумевает HTTP авторизацию и да ключей PHP_AUTH_USER и PHP_AUTH_PW в массиве $_SERVER нет когда PHP в виде FastCGI.
Но, их можно спокойно вернуть, если даже и PHP в виде FastCGI.
А точнее, в файле ./engine/inc/include/init.php найти:
1
| if( $config['extra_login'] ) { |
Добавить после:
1
2
3
4
5
6
7
8
9
10
11
| if (php_sapi_name() != 'apache') {
if(isset($_SERVER['Authorization'])) {
list($hf_auth_type, $hf_auth_data) = preg_split("/[\s,]+/", $_SERVER['Authorization']);
list($_hf_login, $_hf_pass) = preg_split("/:/", base64_decode($hf_auth_data));
$_SERVER['PHP_AUTH_USER'] = $_hf_login;
$_SERVER['PHP_AUTH_PW'] = $_hf_pass;
unset($hf_auth_type, $hf_auth_data, $_hf_login, $_hf_pass);
}
} |
И вуаля, расширенная авторитизация работает даже когда PHP в виде FastCGI.
Встает вопрос, за что же я плачу при покупке DLE?
За недоработанную CMS?
Сегодня решил решил запустить 2й анонсер который бы находился в Интернет и собирал статистику по интернет пользователям.
Но столкнулся с проблемой что где то 20 – 30% моих торрентов обновились с ошибками в виде не правильного peer_id или info_hash.
Обрыл весь скрипт от начала до места где возникает ошибка, не нашел.
Плюнув на все написал функцию ( на основе старой из Multi Scrape ) которая убила 2х зайцев.
1. Исправила мою проблему.
2. Если скрипту кто-то подумает передать массив он не обработается ( будет очень полезно начинающим программистам, когда их скрипт должен принимать только строковые параметры из $_GET ).
Сама функция
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| function clean_string_get ()
{
unset($_GET);
$query = explode("&", $_SERVER['QUERY_STRING']);
foreach($query as $k)
{
list($key, $value) = explode('=', $k);
$key = str_replace('?', '', $key);
$value = urldecode($value);
if ($key != '' and $value !='')
{
$_GET[$key] = (string) $value;
}
}
} |
Замечу, что данная функция уначтожит стандартный массив $_GET и создаст свой, в котором все ключи строки (string).
Сегодня появилась идея ( честно лучше бы ее не было ) для облегчения себе жизни.
Идея заключалась в следующем, имея ICQ робота мы отсылаем ему команду которую он обрабатывает, заходит на удаленный SSH сервер, выполняет там команду и наконец результат команды возвращает на обратно. Все естественно на PHP5.
Первым делом попался PECL модуль ssh2.
Пляски с бубном вокруг него породили статический SSH класс:
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
| <?php
/***
* R114 PHP-SSH class ver. 0.0.2b
* (c) 2010 R114, All rights reserved.
* URL: http://www.rostov114
* E-mail: info@rostov114.net
*/
class SSH
{
/*
* Идантификатор содинения с SSH сервером
*
* @access private
*/
private static $connection;
/*
* Идантификатор shell режима
*
* @access private
*/
private static $shell = FALSE;
/*
* Метод использованный при логине
*
* @access public
*/
public static $auth_method = FALSE;
/*
* shell тип
*
* @access public
*/
public static $shell_type = '';
/*
* Будет ли функция exec выводить результат массивом или нет
*
* @access public
*/
public static $return_exec_array = TRUE;
/**
* Произвести подключение к SSH серверу
*
* @access public
* @param string
* @param int
* @param array
* @param array
* @return bool
*/
public static function connect($host, $port = 22, $methods = array(), $callbacks = array())
{
if (!extension_loaded('ssh2'))
{
die('Please install package PECL: ssh2');
}
self::$connection = @ssh2_connect($host, $port, $methods, $callbacks);
return is_resource(self::$connection);
}
/**
* Попытаться произвести логин на сервере
*
* @access public
* @param string
* @param string
* @return bool
*/
public static function login($username, $password)
{
if (self::$connection === FALSE)
{
return FALSE;
}
$auth_methods = @ssh2_auth_none(self::$connection, $username);
foreach ($auth_methods as $method)
{
switch ($method)
{
case 'password':
$is_auth = @ssh2_auth_password(self::$connection, $username, $password);
break;
case 'publickey':
#$is_auth = @ssh2_auth_pubkey_file(self::$connection, $username, 'test_key.rsa.pub', 'test_key.rsa', $password);
$is_auth = FALSE;
break;
case 'keyboard-interactive':
$is_auth = FALSE;
break;
default:
$is_auth = FALSE;
break;
}
if ($is_auth === TRUE)
{
self::$auth_method = $method;
return TRUE;
}
}
return FALSE;
}
/**
* Выполнить комманду (комманды) на удаленном сервере
*
* @access public
* @return mixed
*/
public static function exec()
{
if (is_resource(self::$shell) or self::$auth_method === FALSE or self::$connection === FALSE)
{
return FALSE;
}
$argv = func_get_args();
if (self::$return_exec_array === TRUE)
{
$return = array();
foreach ($argv as $com)
{
$stream = @ssh2_exec(self::$connection, $com);
@stream_set_blocking($stream, true);
$return[] = @stream_get_contents($stream);
}
return $return;
}
$stream = @ssh2_exec(self::$connection, implode(' && ', $argv));
@stream_set_blocking($stream, true);
return @stream_get_contents($stream);
}
/**
* Перейти в shell режим
*
* @access public
* @return bool
*/
public static function shell()
{
if (self::$auth_method === FALSE or self::$connection === FALSE)
{
return FALSE;
}
if (!is_resource(self::$shell))
{
self::$shell = @ssh2_shell(self::$connection, self::$shell_type);
}
$argv = func_get_args();
foreach ($argv as $com)
{
@fwrite(self::$shell, $com.PHP_EOL);
}
return TRUE;
}
} |
Отличия от большинства других классов написанных с использованием функций ssh2:
1. Продуманные условия “против дурака”,
2. Компактный,
3. Может выполнить несколько exec команд за раз и вернуть результат 1 для всех команд или для каждого свой (массивом),
4. Понятный и читабельный код без идиотизма.
Tags:
На этот раз мне захотелось еще раз вые выпиндриться, и сделать в своем scrape поддержку Multi Scrape запросов.
Долгие пляски вокруг $_GET, фактически ничего не дали но зато дал плоды $_SERVER['QUERY_STRING'].
Зацепившись за него минут за 15 накатал простенькую функцию которая выдает массив хеш-сумм переданные в URI. В случае если хотя бы одна хеш-сумма не будет равна 20 символам то функция завершиться с ошибкой Invalid info_hash.
Сама функция:
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
| function scrape_parse_query()
{
$info_hash = array();
$query = $_SERVER['QUERY_STRING'];
$query = explode("&", $query);
foreach($query as $k)
{
list($key, $value) = explode('=', $k);
$key = str_replace('?', '', $key);
$value = urldecode($value);
if($key == 'info_hash' && strlen($value) == 20)
{
$info_hash[] = bin2hex($value);
}
else
{
if(strlen($value) != 20 and $key == 'info_hash')
{
msg_die('Invalid info_hash');
}
}
}
return $info_hash;
} |
На выходе у функции будет массив хеш-сумм (в BTIH).
Что с данными хеш суммами делать, решайте сами.
Кстати, чуть не забыл сказать, данная функция писалась под scrape на основе TorrentPier.
Недавно понадобилось протестировать собственный же анонсер, по всем критериям и один из них нормальная работа в compact режиме (т.е. пиров нам анонсер отдает в закодированном виде, что уменьшает в свою очередь трафик между сервером и клиентами).
Для того чтобы прекратить из compact в обычный вид написал функцию, которая до ужаса банальна, но работает:
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
| function peers_to_array($data)
{
if (!is_array($data['peers']))
{
$new_peers = array();
while (strlen($data['peers']) > 0)
{
list(, $ip) = @unpack('N', substr($data['peers'], 0, 4));
list(, $port) = @unpack('n', substr($data['peers'], 4, 6));
$new_peers[] = array
(
'ip' => long2ip($ip),
'port' => $port
);
$data['peers'] = substr($data['peers'], 6);
}
$data['peers'] = $new_peers;
unset($new_peers);
}
return $data;
} |
Как ее использовать я думаю объяснять не нужно.