1 //
2 // This file is part of the aMule Project.
3 
4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2005-2011 Froenchenko Leonid ( lfroen@gmail.com / http://www.amule.org )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
10 //
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
24 //
25 
26 
27 #include <string> // Do_not_auto_remove (g++-4.0.1)
28 
29 #include <sys/types.h>
30 
31 #include "config.h"
32 
33 #include "WebServer.h"
34 #include <ec/cpp/ECSpecialTags.h>
35 
36 #include "php_syntree.h"
37 #include "php_core_lib.h"
38 
39 #include <wx/datetime.h>
40 
41 /*
42  * Built-in php functions. Those are amule-specific funcions, accessing EC and internal
43  * datastructre
44  *
45  */
46 
php_native_shared_file_cmd(PHP_VALUE_NODE *)47 void php_native_shared_file_cmd(PHP_VALUE_NODE *)
48 {
49 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
50 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
51 		php_report_error(PHP_ERROR, "Invalid or missing argument 1");
52 		return;
53 	}
54 	char *str_hash = si->var->value.str_val;
55 
56 	si = get_scope_item(g_current_scope, "__param_1");
57 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
58 		php_report_error(PHP_ERROR, "Invalid or missing argument 2");
59 		return;
60 	}
61 	char *cmd_name = si->var->value.str_val;
62 	si = get_scope_item(g_current_scope, "__param_2");
63 	PHP_VAR_NODE *opt_param = si ? si->var : 0;
64 
65 	if ( !strcmp(cmd_name, "prio") && !opt_param ) {
66 		php_report_error(PHP_ERROR, "Command 'prio' need 3-rd argument");
67 		return;
68 	}
69 
70 
71 	CPhPLibContext::g_curr_context->WebServer()->Send_SharedFile_Cmd(wxString(char2unicode(str_hash)),
72 		wxString(char2unicode(cmd_name)),
73 		opt_param ? opt_param->value.int_val : 0);
74 }
75 
php_native_reload_shared_file_cmd(PHP_VALUE_NODE *)76 void php_native_reload_shared_file_cmd(PHP_VALUE_NODE *)
77 {
78 	CPhPLibContext::g_curr_context->WebServer()->Send_ReloadSharedFile_Cmd();
79 }
80 
81 /*
82  *
83  * Usage: php_native_download_file_cmd($file_hash, "command", $optional_arg)
84  *
85  */
php_native_download_file_cmd(PHP_VALUE_NODE *)86 void php_native_download_file_cmd(PHP_VALUE_NODE *)
87 {
88 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
89 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
90 		php_report_error(PHP_ERROR, "Invalid or missing argument 1");
91 		return;
92 	}
93 	char *str_hash = si->var->value.str_val;
94 
95 	si = get_scope_item(g_current_scope, "__param_1");
96 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
97 		php_report_error(PHP_ERROR, "Invalid or missing argument 2");
98 		return;
99 	}
100 	char *cmd_name = si->var->value.str_val;
101 	si = get_scope_item(g_current_scope, "__param_2");
102 	PHP_VAR_NODE *opt_param = si ? si->var : 0;
103 
104 	if ( (!strcmp(cmd_name, "prio") || !strcmp(cmd_name, "setcat")) && !opt_param ) {
105 		php_report_error(PHP_ERROR, "Commands 'prio' and 'setcat' needs 3-rd argument");
106 		return;
107 	}
108 
109 	CPhPLibContext::g_curr_context->WebServer()->Send_DownloadFile_Cmd(wxString(char2unicode(str_hash)),
110 		wxString(char2unicode(cmd_name)),
111 		opt_param ? opt_param->value.int_val : 0);
112 }
113 
114 /*
115  * Usage amule_kad_connect($bootstrap_ip, $bootstrap_port)
116  */
php_native_kad_connect(PHP_VALUE_NODE *)117 void php_native_kad_connect(PHP_VALUE_NODE *)
118 {
119 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
120 	if ( !si ) {
121 		php_report_error(PHP_ERROR, "Missing or bad argument 1: $bootstrap_ip_addr");
122 		return;
123 	}
124 	cast_value_dnum(&si->var->value);
125 	unsigned int ipaddr = si->var->value.int_val;
126 
127 	si = get_scope_item(g_current_scope, "__param_1");
128 	if ( !si ) {
129 		php_report_error(PHP_ERROR, "Missing or bad argument 2: $bootstrap_ip_port");
130 		return;
131 	}
132 	cast_value_dnum(&si->var->value);
133 	unsigned int ipport = si->var->value.int_val;
134 
135 	CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
136 	req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ipaddr));
137 	req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, ipport));
138 	CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
139 }
140 
php_native_kad_disconnect(PHP_VALUE_NODE *)141 void php_native_kad_disconnect(PHP_VALUE_NODE *)
142 {
143 	CECPacket req(EC_OP_KAD_STOP);
144 	CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
145 }
146 
147 /*
148  * Usage amule_add_server_cmd($server_addr, $server_port, $server_name);
149  */
php_native_add_server_cmd(PHP_VALUE_NODE *)150 void php_native_add_server_cmd(PHP_VALUE_NODE *)
151 {
152 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
153 	if ( !si || (si->var->value.type != PHP_VAL_STRING) ) {
154 		php_report_error(PHP_ERROR, "Missing or bad argument 1: $server_addr");
155 		return;
156 	}
157 	char *addr = si->var->value.str_val;
158 
159 	si = get_scope_item(g_current_scope, "__param_1");
160 	if ( !si ) {
161 		php_report_error(PHP_ERROR, "Missing argument 2: $server_port");
162 		return;
163 	}
164 	cast_value_dnum(&si->var->value);
165 	int port = si->var->value.int_val;
166 
167 	si = get_scope_item(g_current_scope, "__param_2");
168 	if ( !si || (si->var->value.type != PHP_VAL_STRING) ) {
169 		php_report_error(PHP_ERROR, "Invalid or missing argument 3: $server_name");
170 		return;
171 	}
172 	char *name = si->var->value.str_val;
173 
174 	CPhPLibContext::g_curr_context->WebServer()->Send_AddServer_Cmd(wxString(char2unicode(addr)),
175 		wxString::Format(wxT("%d"), port), wxString(char2unicode(name)));
176 }
177 
178 /*
179  * Usage amule_server_cmd($server_ip, $server_port, "command");
180  */
php_native_server_cmd(PHP_VALUE_NODE *)181 void php_native_server_cmd(PHP_VALUE_NODE *)
182 {
183 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
184 	if ( !si ) {
185 		php_report_error(PHP_ERROR, "Missing argument 1: $server_ip");
186 		return;
187 	}
188 	cast_value_dnum(&si->var->value);
189 	uint32_t ip = si->var->value.int_val;
190 
191 	si = get_scope_item(g_current_scope, "__param_1");
192 	if ( !si ) {
193 		php_report_error(PHP_ERROR, "Missing argument 2: $server_port");
194 		return;
195 	}
196 	cast_value_dnum(&si->var->value);
197 	int port = si->var->value.int_val;
198 
199 	si = get_scope_item(g_current_scope, "__param_2");
200 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
201 		php_report_error(PHP_ERROR, "Invalid or missing argument 3: $command");
202 		return;
203 	}
204 	char *cmd = si->var->value.str_val;
205 
206 	CPhPLibContext::g_curr_context->WebServer()->Send_Server_Cmd(ip, port, wxString(char2unicode(cmd)));
207 }
208 
209 /*
210  * Query amule status. Return hash containing stats values
211  */
php_get_amule_stats(PHP_VALUE_NODE * result)212 void php_get_amule_stats(PHP_VALUE_NODE *result)
213 {
214 	CECPacket stat_req(EC_OP_STAT_REQ, EC_DETAIL_FULL);
215 	const CECPacket *stats = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&stat_req);
216 	if (!stats) {
217 		return ;
218 	}
219 	const CEC_ConnState_Tag *tag = static_cast<const CEC_ConnState_Tag *>(stats->GetTagByName(EC_TAG_CONNSTATE));
220 	if (!tag) {
221 		return ;
222 	}
223 
224 	cast_value_array(result);
225 	PHP_VAR_NODE *id = array_get_by_str_key(result, "id");
226 	cast_value_dnum(&id->value);
227 	id->value.int_val = tag->GetEd2kId();
228 	const CECTag *server = tag->GetTagByName(EC_TAG_SERVER);
229 	if ( server ) {
230 		PHP_VAR_NODE *srv_ip = array_get_by_str_key(result, "serv_addr");
231 		value_value_free(&srv_ip->value);
232 		srv_ip->value.type = PHP_VAL_STRING;
233 		srv_ip->value.str_val =strdup(unicode2UTF8(server->GetIPv4Data().StringIP()));
234 
235 		const CECTag *sname = server->GetTagByName(EC_TAG_SERVER_NAME);
236 		if ( sname ) {
237 			PHP_VAR_NODE *srv_name = array_get_by_str_key(result, "serv_name");
238 			value_value_free(&srv_name->value);
239 			srv_name->value.type = PHP_VAL_STRING;
240 			srv_name->value.str_val = strdup(unicode2UTF8(sname->GetStringData()));
241 		}
242 
243 		const CECTag *susers = server->GetTagByName(EC_TAG_SERVER_USERS);
244 		if ( susers ) {
245 			PHP_VAR_NODE *srv_users = array_get_by_str_key(result, "serv_users");
246 			value_value_free(&srv_users->value);
247 			srv_users->value.type = PHP_VAL_INT;
248 			srv_users->value.int_val = susers->GetInt();
249 		}
250 
251 	}
252 	// kademlia
253 	PHP_VAR_NODE *kad = array_get_by_str_key(result, "kad_connected");
254 	value_value_free(&kad->value);
255 	kad->value.type = PHP_VAL_BOOL;
256 	if ( tag->IsConnectedKademlia() ) {
257 		kad->value.int_val = 1;
258 		PHP_VAR_NODE *kad_fwl = array_get_by_str_key(result, "kad_firewalled");
259 		kad_fwl->value.type = PHP_VAL_BOOL;
260 		kad_fwl->value.int_val = tag->IsKadFirewalled();
261 	} else {
262 		kad->value.int_val = 0;
263 	}
264 	// traffic stats
265 	PHP_VAR_NODE *speed;
266 	speed = array_get_by_str_key(result, "speed_up");
267 	value_value_free(&speed->value);
268 	speed->value.type = PHP_VAL_INT;
269 	speed->value.int_val = stats->GetTagByName(EC_TAG_STATS_UL_SPEED)->GetInt();
270 
271 	speed = array_get_by_str_key(result, "speed_down");
272 	value_value_free(&speed->value);
273 	speed->value.type = PHP_VAL_INT;
274 	speed->value.int_val = stats->GetTagByName(EC_TAG_STATS_DL_SPEED)->GetInt();
275 
276 	speed = array_get_by_str_key(result, "speed_limit_up");
277 	value_value_free(&speed->value);
278 	speed->value.type = PHP_VAL_INT;
279 	speed->value.int_val = stats->GetTagByName(EC_TAG_STATS_UL_SPEED_LIMIT)->GetInt();
280 
281 	speed = array_get_by_str_key(result, "speed_limit_down");
282 	value_value_free(&speed->value);
283 	speed->value.type = PHP_VAL_INT;
284 	speed->value.int_val = stats->GetTagByName(EC_TAG_STATS_DL_SPEED_LIMIT)->GetInt();
285 
286 	delete stats;
287 }
288 
php_get_amule_categories(PHP_VALUE_NODE * result)289 void php_get_amule_categories(PHP_VALUE_NODE *result)
290 {
291 	cast_value_array(result);
292 
293 	CECPacket req(EC_OP_GET_PREFERENCES);
294 	req.AddTag(CECTag(EC_TAG_SELECT_PREFS, (uint32)EC_PREFS_CATEGORIES));
295 	const CECPacket *reply = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
296 	if ( !reply ) {
297 		return ;
298 	}
299 	const CECTag *cats_tag = reply->GetFirstTagSafe();
300 	if (cats_tag->HasChildTags()) {
301 		int i = 0;
302 		for (CECTag::const_iterator it = cats_tag->begin(); it != cats_tag->end(); ++it) {
303 			const CECTag *categoryTitle = it->GetTagByName(EC_TAG_CATEGORY_TITLE);
304 			PHP_VAR_NODE *cat = array_get_by_int_key(result, i++);
305 			value_value_free(&cat->value);
306 			cat->value.type = PHP_VAL_STRING;
307 			cat->value.str_val = strdup(unicode2UTF8(categoryTitle->GetStringData()));
308 		}
309 	} else {
310 		PHP_VAR_NODE *cat = array_get_by_int_key(result, 0);
311 		value_value_free(&cat->value);
312 		cat->value.type = PHP_VAL_STRING;
313 		cat->value.str_val = strdup("all");
314 	}
315 	delete reply;
316 }
317 
318 typedef struct {
319 	const char *php_name;
320 	ECTagNames tagname;
321 	int opsize;
322 } PHP_2_EC_OPT_DEF;
323 
324 PHP_2_EC_OPT_DEF g_connection_opt_defs[] = {
325 	{ "max_line_up_cap", EC_TAG_CONN_UL_CAP, 4}, { "max_line_down_cap", EC_TAG_CONN_DL_CAP, 4},
326 	{ "max_up_limit", EC_TAG_CONN_MAX_UL, 2}, { "max_down_limit", EC_TAG_CONN_MAX_DL, 2},
327 	{ "slot_alloc", EC_TAG_CONN_SLOT_ALLOCATION, 2},
328 	{ "tcp_port", EC_TAG_CONN_TCP_PORT, 2}, { "udp_port", EC_TAG_CONN_UDP_PORT, 2},
329 	{ "udp_dis", EC_TAG_CONN_UDP_DISABLE, 0},
330 	{ "max_file_src", EC_TAG_CONN_MAX_FILE_SOURCES, 2},
331 	{ "max_conn_total", EC_TAG_CONN_MAX_CONN, 2},
332 	{ "autoconn_en", EC_TAG_CONN_AUTOCONNECT, 0}, { "reconn_en", EC_TAG_CONN_RECONNECT, 0},
333 	{0, (ECTagNames)0, 0}
334 };
335 
336 PHP_2_EC_OPT_DEF g_file_opt_defs[] = {
337 	{ "ich_en", EC_TAG_FILES_ICH_ENABLED, 0},
338 	{ "aich_trust", EC_TAG_FILES_AICH_TRUST, 0},
339 	{ "new_files_paused", EC_TAG_FILES_NEW_PAUSED, 0},
340 	{ "new_files_auto_dl_prio", EC_TAG_FILES_NEW_AUTO_DL_PRIO, 0},
341 	{ "preview_prio", EC_TAG_FILES_PREVIEW_PRIO, 0},
342 	{ "new_files_auto_ul_prio", EC_TAG_FILES_NEW_AUTO_UL_PRIO, 0},
343 	{ "upload_full_chunks", EC_TAG_FILES_UL_FULL_CHUNKS, 0},
344 	{ "first_last_chunks_prio", EC_TAG_FILES_PREVIEW_PRIO, 0},
345 	{ "start_next_paused", EC_TAG_FILES_START_NEXT_PAUSED, 0},
346 	{ "resume_same_cat", EC_TAG_FILES_RESUME_SAME_CAT, 0},
347 	{ "save_sources", EC_TAG_FILES_SAVE_SOURCES, 0},
348 	{ "extract_metadata", EC_TAG_FILES_EXTRACT_METADATA, 0},
349 	{ "alloc_full", EC_TAG_FILES_ALLOC_FULL_SIZE, 0},
350 	{ "check_free_space", EC_TAG_FILES_CHECK_FREE_SPACE, 0},
351 	{ "min_free_space", EC_TAG_FILES_MIN_FREE_SPACE, 4},
352 	{0, (ECTagNames)0, 0}
353 };
354 
355 PHP_2_EC_OPT_DEF g_webserver_opt_defs[] = {
356 	{ "use_gzip", EC_TAG_WEBSERVER_USEGZIP, 0},
357 	{ "autorefresh_time", EC_TAG_WEBSERVER_REFRESH, 4},
358 	{0, (ECTagNames)0, 0}
359 };
360 
361 PHP_2_EC_OPT_DEF g_coretweak_opt_defs[] = {
362 	{ "max_conn_5sec", EC_TAG_CORETW_MAX_CONN_PER_FIVE, 2},
363 	{0, (ECTagNames)0, 0}
364 };
365 
set_array_int_val(PHP_VALUE_NODE * array,const std::string & arrkey,int value)366 void set_array_int_val(PHP_VALUE_NODE *array, const std::string &arrkey, int value)
367 {
368 	PHP_VAR_NODE *key = array_get_by_str_key(array, arrkey);
369 	PHP_VALUE_NODE intval;
370 	intval.type = PHP_VAL_INT;
371 	intval.int_val = value;
372 	value_value_assign(&key->value, &intval);
373 }
374 
ec_tag_2_php(const CECTag * cattag,PHP_2_EC_OPT_DEF * opts,PHP_VAR_NODE * catvar)375 void ec_tag_2_php(const CECTag *cattag, PHP_2_EC_OPT_DEF *opts, PHP_VAR_NODE *catvar)
376 {
377 	for(PHP_2_EC_OPT_DEF *def = opts; def->php_name; def++) {
378 		int val;
379 		switch(def->opsize) {
380 			case 0: val = cattag->GetTagByName(def->tagname) ? 1 : 0; break;
381 			case 1: val = cattag->GetTagByNameSafe(def->tagname)->GetInt(); break;
382 			case 2: val = cattag->GetTagByNameSafe(def->tagname)->GetInt(); break;
383 			case 4: val = cattag->GetTagByNameSafe(def->tagname)->GetInt(); break;
384 			default: val = -1;
385 		}
386 		wxASSERT(val != -1);
387 		//printf("OPT_DEBUG: %s of size %d -> %d\n", def->php_name, def->opsize, val);
388 		set_array_int_val(&catvar->value, def->php_name, val);
389 	}
390 }
391 
392 /*
393  * Return hash of amule options.
394  *  Key: option name
395  *  Value: option value (string)
396  */
php_get_amule_options(PHP_VALUE_NODE * result)397 void php_get_amule_options(PHP_VALUE_NODE *result)
398 {
399 	cast_value_array(result);
400 
401 	CECPacket req(EC_OP_GET_PREFERENCES);
402 	req.AddTag(CECTag(EC_TAG_SELECT_PREFS, (uint32)0xffffffff));
403 	const CECPacket *reply = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
404 	if ( !reply || !reply->HasChildTags()) {
405 		return ;
406 	}
407 	const CECTag *cattag = 0;
408     if ((cattag = reply->GetTagByName(EC_TAG_PREFS_GENERAL)) != 0) {
409 		PHP_VAR_NODE *key = array_get_by_str_key(result, "nick");
410 		value_value_free(&key->value);
411 		key->value.type = PHP_VAL_STRING;
412 		key->value.str_val = strdup(unicode2UTF8(cattag->GetTagByNameSafe(EC_TAG_USER_NICK)->GetStringData()));
413 	}
414 
415 	if ((cattag = reply->GetTagByName(EC_TAG_PREFS_CONNECTIONS)) != 0) {
416 		PHP_VAR_NODE *cat = array_get_by_str_key(result, "connection");
417 		cast_value_array(&cat->value);
418 
419 		ec_tag_2_php(cattag, g_connection_opt_defs, cat);
420 	}
421 	if ((cattag = reply->GetTagByName(EC_TAG_PREFS_FILES)) != 0) {
422 		PHP_VAR_NODE *cat = array_get_by_str_key(result, "files");
423 		cast_value_array(&cat->value);
424 
425 		ec_tag_2_php(cattag, g_file_opt_defs, cat);
426 	}
427 
428 	if ((cattag = reply->GetTagByName(EC_TAG_PREFS_REMOTECTRL)) != 0) {
429 		PHP_VAR_NODE *cat = array_get_by_str_key(result, "webserver");
430 		cast_value_array(&cat->value);
431 
432 		ec_tag_2_php(cattag, g_webserver_opt_defs, cat);
433 	}
434 
435 	if ((cattag = reply->GetTagByName(EC_TAG_PREFS_CORETWEAKS)) != 0) {
436 		PHP_VAR_NODE *cat = array_get_by_str_key(result, "coretweaks");
437 		cast_value_array(&cat->value);
438 
439 		ec_tag_2_php(cattag, g_coretweak_opt_defs, cat);
440 	}
441 }
442 
php_2_ec_tag(CECTag * cattag,PHP_2_EC_OPT_DEF * opts,PHP_VALUE_NODE * catvar)443 bool php_2_ec_tag(CECTag *cattag, PHP_2_EC_OPT_DEF *opts, PHP_VALUE_NODE *catvar)
444 {
445 	for(PHP_2_EC_OPT_DEF *def = opts; def->php_name; def++) {
446 		PHP_VAR_NODE *opt_var = array_get_by_str_key(catvar, def->php_name);
447 		if ( opt_var->value.type == PHP_VAL_NONE ) {
448 			continue;
449 		}
450 		cast_value_dnum(&opt_var->value);
451 		switch(def->opsize) {
452 			case 0: // always transmit !
453 			case 1: cattag->AddTag(CECTag(def->tagname ,(uint8)opt_var->value.int_val)); break;
454 			case 2: cattag->AddTag(CECTag(def->tagname ,(uint16)opt_var->value.int_val)); break;
455 			case 4: cattag->AddTag(CECTag(def->tagname ,(uint32)opt_var->value.int_val)); break;
456 			default: return false;
457 		}
458 	}
459 	return true;
460 }
461 
462 /*
463  * Set amule options from given array. Argument looks like "amule_get_options" result
464  */
php_set_amule_options(PHP_VALUE_NODE *)465 void php_set_amule_options(PHP_VALUE_NODE *)
466 {
467 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
468 	if ( !si || (si->var->value.type != PHP_VAL_ARRAY)) {
469 		php_report_error(PHP_ERROR, "Invalid or missing argument 1 (options array)");
470 		return;
471 	}
472 
473 	CECPacket req(EC_OP_SET_PREFERENCES);
474 	PHP_VAR_NODE *opt_group_array = 0;
475 
476 	// files
477 	opt_group_array = array_get_by_str_key(&si->var->value, "files");
478 	if ( opt_group_array->value.type == PHP_VAL_ARRAY ) {
479 		CECEmptyTag filePrefs(EC_TAG_PREFS_FILES);
480 		php_2_ec_tag(&filePrefs, g_file_opt_defs, &opt_group_array->value);
481 		req.AddTag(filePrefs);
482 	}
483 	// connection
484 	opt_group_array = array_get_by_str_key(&si->var->value, "connection");
485 	if ( opt_group_array->value.type == PHP_VAL_ARRAY ) {
486 		CECEmptyTag connPrefs(EC_TAG_PREFS_CONNECTIONS);
487 		php_2_ec_tag(&connPrefs, g_connection_opt_defs, &opt_group_array->value);
488 		req.AddTag(connPrefs);
489 	}
490 	// webserver
491 	opt_group_array = array_get_by_str_key(&si->var->value, "webserver");
492 	if ( opt_group_array->value.type == PHP_VAL_ARRAY ) {
493 		CECEmptyTag webPrefs(EC_TAG_PREFS_REMOTECTRL);
494 		php_2_ec_tag(&webPrefs, g_webserver_opt_defs, &opt_group_array->value);
495 		req.AddTag(webPrefs);
496 		// also apply settings localy
497 		PHP_VAR_NODE *pref = array_get_by_str_key(&opt_group_array->value, "use_gzip");
498 		cast_value_dnum(&pref->value);
499 		CPhPLibContext::g_curr_context->WebServer()->webInterface->m_UseGzip = pref->value.int_val != 0;
500 		pref = array_get_by_str_key(&opt_group_array->value, "autorefresh_time");
501 		cast_value_dnum(&pref->value);
502 		CPhPLibContext::g_curr_context->WebServer()->webInterface->m_PageRefresh = pref->value.int_val;
503 	}
504 	CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
505 }
506 
507 /*
508  * Download 1 of search results. Params: hash, category (default=0)
509  */
php_native_search_download_cmd(PHP_VALUE_NODE *)510 void php_native_search_download_cmd(PHP_VALUE_NODE *)
511 {
512 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
513 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
514 		php_report_error(PHP_ERROR, "Invalid or missing argument 1 (file hash)");
515 		return;
516 	}
517 	char *str_hash = si->var->value.str_val;
518 
519 	si = get_scope_item(g_current_scope, "__param_1");
520 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
521 		php_report_error(PHP_ERROR, "Invalid or missing argument 2 (category)");
522 		return;
523 	}
524 
525 	cast_value_dnum(&si->var->value);
526 	int cat = si->var->value.int_val;
527 
528 	CPhPLibContext::g_curr_context->WebServer()->Send_DownloadSearchFile_Cmd(
529 		wxString(char2unicode(str_hash)), cat);
530 }
531 
php_native_search_start_cmd(PHP_VALUE_NODE *)532 void php_native_search_start_cmd(PHP_VALUE_NODE *)
533 {
534 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
535 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
536 		php_report_error(PHP_ERROR, "Invalid or missing argument 1 (search term)");
537 		return;
538 	}
539 	char *search = si->var->value.str_val;
540 
541 	if ( !(si = get_scope_item(g_current_scope, "__param_1")) || (si->var->value.type != PHP_VAL_STRING)) {
542 		php_report_error(PHP_ERROR, "Invalid or missing argument 2 (file extension)");
543 		return;
544 	}
545 	char *ext = si->var->value.str_val;
546 
547 	if ( !(si = get_scope_item(g_current_scope, "__param_2")) || (si->var->value.type != PHP_VAL_STRING)) {
548 		php_report_error(PHP_ERROR, "Invalid or missing argument 3 (file type)");
549 		return;
550 	}
551 	char *type = si->var->value.str_val;
552 
553 	if ( !(si = get_scope_item(g_current_scope, "__param_3")) ) {
554 		php_report_error(PHP_ERROR, "Invalid or missing argument 4 (search type)");
555 		return;
556 	}
557 	cast_value_dnum(&si->var->value);
558 
559 	EC_SEARCH_TYPE search_type;
560 	switch(si->var->value.int_val) {
561 		case 0: search_type = EC_SEARCH_LOCAL; break;
562 		case 1: search_type = EC_SEARCH_GLOBAL; break;
563 		case 2: search_type = EC_SEARCH_KAD; break;
564 		default:
565 			php_report_error(PHP_ERROR, "Invalid search type %" PRIu64, si->var->value.int_val);
566 			return;
567 	}
568 
569 	if ( !(si = get_scope_item(g_current_scope, "__param_4")) ) {
570 		php_report_error(PHP_ERROR, "Invalid or missing argument 5 (availability)");
571 		return;
572 	}
573 	cast_value_dnum(&si->var->value);
574 	int avail = si->var->value.int_val;
575 
576 	if ( !(si = get_scope_item(g_current_scope, "__param_5")) ) {
577 		php_report_error(PHP_ERROR, "Invalid or missing argument 6 (min size)");
578 		return;
579 	}
580 	cast_value_dnum(&si->var->value);
581 	int min_size = si->var->value.int_val;
582 
583 	if ( !(si = get_scope_item(g_current_scope, "__param_6")) ) {
584 		php_report_error(PHP_ERROR, "Invalid or missing argument 7 (max size)");
585 		return;
586 	}
587 	cast_value_dnum(&si->var->value);
588 	int max_size = si->var->value.int_val;
589 
590 
591 	CPhPLibContext::g_curr_context->WebServer()->Send_Search_Cmd(
592 		wxString(char2unicode(search)), wxString(char2unicode(ext)), wxString(char2unicode(type)),
593 		search_type, avail, min_size, max_size);
594 }
595 
596 /*
597  * Request contents of log
598  */
php_get_log(PHP_VALUE_NODE * result)599 void php_get_log(PHP_VALUE_NODE *result)
600 {
601 	value_value_free(result);
602 
603 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
604 	bool rst;
605 	if ( !si ) {
606 		rst = false;
607 	} else {
608 		cast_value_dnum(&si->var->value);
609 		rst = si->var->value.int_val != 0;
610 	}
611 	if ( rst ) {
612 		CECPacket req(EC_OP_RESET_LOG);
613 		CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
614 	}
615 	CECPacket req(EC_OP_GET_LOG);
616 	const CECPacket *response = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
617 	if (response) {
618 		wxString serverInfoString(_SpecialChars(response->GetFirstTagSafe()->GetStringData()));
619 		delete response;
620 		result->type = PHP_VAL_STRING;
621 		result->str_val = strdup((const char *)unicode2UTF8(serverInfoString));
622 	}
623 }
624 
625 /*
626  * Request contents of server info
627  */
php_get_serverinfo(PHP_VALUE_NODE * result)628 void php_get_serverinfo(PHP_VALUE_NODE *result)
629 {
630 	value_value_free(result);
631 
632 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
633 	bool rst;
634 	if ( !si ) {
635 		rst = false;
636 	} else {
637 		cast_value_dnum(&si->var->value);
638 		rst = si->var->value.int_val != 0;
639 	}
640 
641 	if ( rst ) {
642 		CECPacket req(EC_OP_CLEAR_SERVERINFO);
643 		CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
644 	}
645 	CECPacket req(EC_OP_GET_SERVERINFO);
646 	const CECPacket *response = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
647 	if (response) {
648 		wxString serverInfoString(_SpecialChars(response->GetFirstTagSafe()->GetStringData()));
649 		delete response;
650 		result->type = PHP_VAL_STRING;
651 		result->str_val = strdup((const char *)unicode2UTF8(serverInfoString));
652 	}
653 }
654 
655 
656 /*
657  * Download ed2k link. Params: link, category (default=0)
658  */
php_native_ed2k_download_cmd(PHP_VALUE_NODE * result)659 void php_native_ed2k_download_cmd(PHP_VALUE_NODE *result)
660 {
661 	PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
662 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
663 		php_report_error(PHP_ERROR, "Invalid or missing argument 1 (file link)");
664 		return;
665 	}
666 	char *str_link = si->var->value.str_val;
667 
668 	si = get_scope_item(g_current_scope, "__param_1");
669 	if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
670 		php_report_error(PHP_ERROR, "Invalid or missing argument 2 (category)");
671 		return;
672 	}
673 
674 	cast_value_dnum(&si->var->value);
675 	int cat = si->var->value.int_val;
676 
677 	bool cmd_result = CPhPLibContext::g_curr_context->WebServer()->Send_DownloadEd2k_Cmd(
678 		wxString(char2unicode(str_link)), cat);
679 	if ( result ) {
680 		cast_value_bool(result);
681 		result->int_val = cmd_result;
682 	}
683 }
684 
685 
686 /*
687  * Load amule variables into interpreter scope.
688  *  "varname" will tell us, what kind of variables need to load:
689  *    "downloads", "uploads", "searchresult", "servers", "options" etc
690  */
691 template <class C, class T>
amule_obj_array_create(const char * class_name,PHP_VALUE_NODE * result)692 void amule_obj_array_create(const char *class_name, PHP_VALUE_NODE *result)
693 {
694 	if ( !result ) {
695 		return;
696 	}
697 	C *container = T::GetContainerInstance();
698 
699 	container->ReQuery();
700 
701 	typename std::list<T>::const_iterator it = container->GetBeginIterator();
702 	while ( it != container->GetEndIterator()) {
703 		PHP_VAR_NODE *var = array_push_back(result);
704 		var->value.type = PHP_VAL_OBJECT;
705 		var->value.obj_val.class_name = class_name;
706 		const T *cur_item = &(*it);
707 		var->value.obj_val.inst_ptr = (void *)cur_item;
708 		++it;
709 	}
710 }
711 
amule_load_downloads(PHP_VALUE_NODE * result)712 void amule_load_downloads(PHP_VALUE_NODE *result)
713 {
714 	amule_obj_array_create<DownloadFileInfo, DownloadFile>("AmuleDownloadFile", result);
715 }
716 
amule_load_servers(PHP_VALUE_NODE * result)717 void amule_load_servers(PHP_VALUE_NODE *result)
718 {
719 	amule_obj_array_create<ServersInfo, ServerEntry>("AmuleServer", result);
720 }
721 
amule_load_shared(PHP_VALUE_NODE * result)722 void amule_load_shared(PHP_VALUE_NODE *result)
723 {
724 	amule_obj_array_create<SharedFileInfo, SharedFile>("AmuleSharedFile", result);
725 }
726 
amule_load_search(PHP_VALUE_NODE * result)727 void amule_load_search(PHP_VALUE_NODE *result)
728 {
729 	amule_obj_array_create<SearchInfo, SearchFile>("AmuleSearchFile", result);
730 }
731 
amule_load_uploads(PHP_VALUE_NODE * result)732 void amule_load_uploads(PHP_VALUE_NODE *result)
733 {
734 	amule_obj_array_create<UploadsInfo, UploadFile>("AmuleUploadFile", result);
735 }
736 
amule_load_stats()737 void amule_load_stats()
738 {
739 	CPhPLibContext::g_curr_context->WebServer()->Reload_Stats();
740 }
741 
742 /*
743  * Convert CEC_StatTree_Node_Tag into php associative array
744  *
745  * Since data structure is recoursive - we need helper function
746  * to perform conversion
747  */
ecstats2php(CEC_StatTree_Node_Tag * root,PHP_VALUE_NODE * result)748 void ecstats2php(CEC_StatTree_Node_Tag *root, PHP_VALUE_NODE *result)
749 {
750 	cast_value_array(result);
751 	std::string key(unicode2UTF8(root->GetDisplayString()));
752 	PHP_VAR_NODE *v_key = array_get_by_str_key(result, key);
753 	for (CECTag::const_iterator it = root->begin(); it != root->end(); ++it) {
754 		CEC_StatTree_Node_Tag *tag = (CEC_StatTree_Node_Tag*) & *it;
755 		if (tag->GetTagName() == EC_TAG_STATTREE_NODE) {
756 			ecstats2php(tag, &v_key->value);
757 		}
758 	}
759 
760 }
761 
amule_load_stats_tree(PHP_VALUE_NODE * result)762 void amule_load_stats_tree(PHP_VALUE_NODE *result)
763 {
764 	if ( !result ) {
765 		return;
766 	}
767 	value_value_free(result);
768 
769 	CECPacket req(EC_OP_GET_STATSTREE, EC_DETAIL_WEB);
770 	const CECPacket *response = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
771 	if ( !response ) {
772 		return;
773 	}
774 	const CECTag *server_ver = response->GetTagByName(EC_TAG_SERVER_VERSION);
775 	const CECTag *user_nick = response->GetTagByName(EC_TAG_USER_NICK);
776 	if ( !server_ver || !user_nick ) {
777 		delete response;
778 		return;
779 	}
780 	const CEC_StatTree_Node_Tag *stats_root = static_cast<const CEC_StatTree_Node_Tag *>(response->GetTagByName(EC_TAG_STATTREE_NODE));
781 	//ecstats2php(stats_root, result);
782 	for (CECTag::const_iterator it = stats_root->begin(); it != stats_root->end(); ++it) {
783 		CEC_StatTree_Node_Tag *tag = (CEC_StatTree_Node_Tag*) & *it;
784 		if (tag->GetTagName() == EC_TAG_STATTREE_NODE) {
785 			ecstats2php(tag, result);
786 		}
787 	}
788 }
789 
php_native_load_amule_vars(PHP_VALUE_NODE * result)790 void php_native_load_amule_vars(PHP_VALUE_NODE *result)
791 {
792 	PHP_SCOPE_ITEM *si_str = get_scope_item(g_current_scope, "__param_0");
793 	if ( !si_str  ) {
794 		php_report_error(PHP_ERROR, "Missing argument 'varname' for 'load_amule_vars'");
795 		return;
796 	}
797 	PHP_VALUE_NODE *str = &si_str->var->value;
798 	if ( str->type != PHP_VAL_STRING ) {
799 		php_report_error(PHP_ERROR, "Argument 'varname' for 'load_amule_vars' must be string");
800 		return;
801 	}
802 	char *varname = str->str_val;
803 	if ( result ) {
804 		cast_value_array(result);
805 	}
806 	if ( strcmp(varname, "downloads") == 0 ) {
807 		amule_load_downloads(result);
808 	} else if ( strcmp(varname, "uploads") == 0 ) {
809 		amule_load_uploads(result);
810 	} else if ( strcmp(varname, "shared") == 0 ) {
811 		amule_load_shared(result);
812 	} else if ( strcmp(varname, "searchresult") == 0 ) {
813 		amule_load_search(result);
814 	} else if ( strcmp(varname, "servers") == 0 ) {
815 		amule_load_servers(result);
816 	} else if ( strcmp(varname, "stats_graph") == 0 ) {
817 		amule_load_stats();
818 	} else if ( strcmp(varname, "stats_tree") == 0 ) {
819 		amule_load_stats_tree(result);
820 	} else {
821 		value_value_free(result);
822 		php_report_error(PHP_ERROR, "This type of amule variable is unknown");
823 	}
824 }
825 
826 /*
827  * Amule objects implementations
828  */
amule_download_file_prop_get(void * ptr,char * prop_name,PHP_VALUE_NODE * result)829 void amule_download_file_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
830 {
831 	if ( !ptr ) {
832 		value_value_free(result);
833 		return;
834 	}
835 	DownloadFile *obj = static_cast<DownloadFile *>(ptr);
836 	result->type = PHP_VAL_INT;
837 	if ( strcmp(prop_name, "name") == 0 ) {
838 		result->type = PHP_VAL_STRING;
839 		result->str_val = strdup((const char *)unicode2UTF8(obj->sFileName));
840 	} else if ( strcmp(prop_name, "short_name") == 0 ) {
841 		result->type = PHP_VAL_STRING;
842 		wxString short_name(obj->sFileName.Length() > 60 ? (obj->sFileName.Left(60) + (wxT(" ..."))) : obj->sFileName);
843 		result->str_val = strdup((const char *)unicode2UTF8(short_name));
844 	} else if ( strcmp(prop_name, "hash") == 0 ) {
845 		result->type = PHP_VAL_STRING;
846 		result->str_val = strdup((const char *)unicode2UTF8(obj->sFileHash));
847 	} else if ( strcmp(prop_name, "progress") == 0 ) {
848 		result->type = PHP_VAL_STRING;
849 		result->str_val = strdup((const char *)unicode2UTF8(obj->m_Image->GetHTML()));
850 	} else if ( strcmp(prop_name, "link") == 0 ) {
851 		result->type = PHP_VAL_STRING;
852 		result->str_val = strdup((const char *)unicode2UTF8(obj->sED2kLink));
853 	} else if ( strcmp(prop_name, "category") == 0 ) {
854 		result->int_val = obj->nCat;
855 	} else if ( strcmp(prop_name, "status") == 0 ) {
856 		result->int_val = obj->nFileStatus;
857 	} else if ( strcmp(prop_name, "size") == 0 ) {
858 		result->int_val = obj->lFileSize;
859 	} else if ( strcmp(prop_name, "size_done") == 0 ) {
860 		result->int_val = obj->lFileCompleted;
861 	} else if ( strcmp(prop_name, "size_xfer") == 0 ) {
862 		result->int_val = obj->lFileTransferred;
863 	} else if ( strcmp(prop_name, "speed") == 0 ) {
864 		result->int_val = obj->lFileSpeed;
865 	} else if ( strcmp(prop_name, "src_count") == 0 ) {
866 		result->int_val = obj->lSourceCount;
867 	} else if ( strcmp(prop_name, "src_count_not_curr") == 0 ) {
868 		result->int_val = obj->lNotCurrentSourceCount;
869 	} else if ( strcmp(prop_name, "src_count_a4af") == 0 ) {
870 		result->int_val = obj->lSourceCountA4AF;
871 	} else if ( strcmp(prop_name, "src_count_xfer") == 0 ) {
872 		result->int_val = obj->lTransferringSourceCount;
873 	} else if ( strcmp(prop_name, "prio") == 0 ) {
874 		result->int_val = obj->lFilePrio;
875 	} else if ( strcmp(prop_name, "prio_auto") == 0 ) {
876 		result->int_val = obj->bFileAutoPriority;
877 	} else if ( strcmp(prop_name, "last_seen_complete") == 0 ) {
878 		result->int_val = obj->wxtLastSeenComplete.GetTicks();
879 	} else {
880 		php_report_error(PHP_ERROR, "'DownloadFile' property [%s] is unknown", prop_name);
881 	}
882 }
883 
amule_upload_file_prop_get(void * ptr,char * prop_name,PHP_VALUE_NODE * result)884 void amule_upload_file_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
885 {
886 	if ( !ptr ) {
887 		value_value_free(result);
888 		return;
889 	}
890 	UploadFile *obj = static_cast<UploadFile *>(ptr);
891 	result->type = PHP_VAL_INT;
892 	if ( strcmp(prop_name, "name") == 0 ) {
893 		result->type = PHP_VAL_STRING;
894 		SharedFile *sharedfile = SharedFile::GetContainerInstance()->GetByID(obj->nUploadFile);
895 		// uploading file we don't share ?! We are either out of sync with core or a shared file has been removed while uploading it
896 		if ( !sharedfile ) {
897 			SharedFile::GetContainerInstance()->ReQuery();
898 			sharedfile = SharedFile::GetContainerInstance()->GetByID(obj->nUploadFile);
899 		}
900 		result->str_val = strdup(sharedfile ? (const char *)unicode2UTF8(sharedfile->sFileName) : "???");
901 	} else if ( strcmp(prop_name, "short_name") == 0 ) {
902 		result->type = PHP_VAL_STRING;
903 		SharedFile *sharedfile = SharedFile::GetContainerInstance()->GetByID(obj->nUploadFile);
904 		if ( !sharedfile ) {
905 			SharedFile::GetContainerInstance()->ReQuery();
906 			sharedfile = SharedFile::GetContainerInstance()->GetByID(obj->nUploadFile);
907 		}
908 		wxString short_name;
909 		if (sharedfile) {
910 			short_name = sharedfile->sFileName.Length() > 60 ? (sharedfile->sFileName.Left(60) + (wxT(" ..."))) : sharedfile->sFileName;
911 		} else {
912 			short_name = wxT("???");
913 		}
914 		result->str_val = strdup((const char *)unicode2UTF8(short_name));
915 	} else if ( strcmp(prop_name, "user_name") == 0 ) {
916 		result->type = PHP_VAL_STRING;
917 		result->str_val = strdup((const char *)unicode2UTF8(obj->sUserName));
918 	} else if ( strcmp(prop_name, "xfer_up") == 0 ) {
919 		result->int_val = obj->nTransferredUp;
920 	} else if ( strcmp(prop_name, "xfer_down") == 0 ) {
921 		result->int_val = obj->nTransferredDown;
922 	} else if ( strcmp(prop_name, "xfer_speed") == 0 ) {
923 		result->int_val = obj->nSpeed;
924 	} else {
925 		php_report_error(PHP_ERROR, "'UploadFile' property [%s] is unknown", prop_name);
926 	}
927 }
928 
amule_server_prop_get(void * ptr,char * prop_name,PHP_VALUE_NODE * result)929 void amule_server_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
930 {
931 	if ( !ptr ) {
932 		value_value_free(result);
933 		return;
934 	}
935 	ServerEntry *obj = static_cast<ServerEntry *>(ptr);
936 	if ( strcmp(prop_name, "name") == 0 ) {
937 		result->type = PHP_VAL_STRING;
938 		result->str_val = strdup((const char *)unicode2UTF8(obj->sServerName));
939 	} else if ( strcmp(prop_name, "desc") == 0 ) {
940 		result->type = PHP_VAL_STRING;
941 		result->str_val = strdup((const char *)unicode2UTF8(obj->sServerDescription));
942 	} else if ( strcmp(prop_name, "addr") == 0 ) {
943 		result->type = PHP_VAL_STRING;
944 		result->str_val = strdup((const char *)unicode2UTF8(obj->sServerIP));
945 	} else if ( strcmp(prop_name, "users") == 0 ) {
946 		result->type = PHP_VAL_INT;
947 		result->int_val = obj->nServerUsers;
948 	} else if ( strcmp(prop_name, "ip") == 0 ) {
949 		result->type = PHP_VAL_INT;
950 		result->int_val = obj->nServerIP;
951 	} else if ( strcmp(prop_name, "port") == 0 ) {
952 		result->type = PHP_VAL_INT;
953 		result->int_val = obj->nServerPort;
954 	} else if ( strcmp(prop_name, "maxusers") == 0 ) {
955 		result->type = PHP_VAL_INT;
956 		result->int_val = obj->nServerMaxUsers;
957 	} else if ( strcmp(prop_name, "files") == 0 ) {
958 		result->type = PHP_VAL_INT;
959 		result->int_val = obj->nServerFiles;
960 	} else {
961 		php_report_error(PHP_ERROR, "'ServerEntry' property [%s] is unknown", prop_name);
962 	}
963 }
964 
amule_shared_file_prop_get(void * ptr,char * prop_name,PHP_VALUE_NODE * result)965 void amule_shared_file_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
966 {
967 	if ( !ptr ) {
968 		value_value_free(result);
969 		return;
970 	}
971 	SharedFile *obj = static_cast<SharedFile *>(ptr);
972 	if ( strcmp(prop_name, "name") == 0 ) {
973 		result->type = PHP_VAL_STRING;
974 		result->str_val = strdup((const char *)unicode2UTF8(obj->sFileName));
975 	} else if ( strcmp(prop_name, "short_name") == 0 ) {
976 		result->type = PHP_VAL_STRING;
977 		wxString short_name(obj->sFileName.Length() > 60 ? (obj->sFileName.Left(60) + (wxT(" ..."))) : obj->sFileName);
978 		result->str_val = strdup((const char *)unicode2UTF8(short_name));
979 	} else if ( strcmp(prop_name, "hash") == 0 ) {
980 		result->type = PHP_VAL_STRING;
981 		result->str_val = strdup((const char *)unicode2UTF8(obj->sFileHash));
982 	} else if ( strcmp(prop_name, "size") == 0 ) {
983 		result->type = PHP_VAL_INT;
984 		result->int_val = obj->lFileSize;
985 	} else if ( strcmp(prop_name, "link") == 0 ) {
986 		result->type = PHP_VAL_STRING;
987 		result->str_val = strdup(unicode2UTF8(obj->sED2kLink));
988 	} else if ( strcmp(prop_name, "xfer") == 0 ) {
989 		result->type = PHP_VAL_INT;
990 		result->int_val = obj->nFileTransferred;
991 	} else if ( strcmp(prop_name, "xfer_all") == 0 ) {
992 		result->type = PHP_VAL_INT;
993 		result->int_val = obj->nFileAllTimeTransferred;
994 	} else if ( strcmp(prop_name, "req") == 0 ) {
995 		result->type = PHP_VAL_INT;
996 		result->int_val = obj->nFileRequests;
997 	} else if ( strcmp(prop_name, "req_all") == 0 ) {
998 		result->type = PHP_VAL_INT;
999 		result->int_val = obj->nFileAllTimeRequests;
1000 	} else if ( strcmp(prop_name, "accept") == 0 ) {
1001 		result->type = PHP_VAL_INT;
1002 		result->int_val = obj->nFileAccepts;
1003 	} else if ( strcmp(prop_name, "accept_all") == 0 ) {
1004 		result->type = PHP_VAL_INT;
1005 		result->int_val = obj->nFileAllTimeAccepts;
1006 	} else if ( strcmp(prop_name, "prio") == 0 ) {
1007 		result->type = PHP_VAL_INT;
1008 		result->int_val = obj->nFilePriority;
1009 	} else if ( strcmp(prop_name, "prio_auto") == 0 ) {
1010 		result->type = PHP_VAL_BOOL;
1011 		result->int_val = obj->bFileAutoPriority;
1012 	} else {
1013 		php_report_error(PHP_ERROR, "'SharedFile' property [%s] is unknown", prop_name);
1014 	}
1015 }
1016 
amule_search_file_prop_get(void * ptr,char * prop_name,PHP_VALUE_NODE * result)1017 void amule_search_file_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
1018 {
1019 	if ( !ptr ) {
1020 		value_value_free(result);
1021 		return;
1022 	}
1023 	SearchFile *obj = static_cast<SearchFile *>(ptr);
1024 	if ( strcmp(prop_name, "name") == 0 ) {
1025 		result->type = PHP_VAL_STRING;
1026 		result->str_val = strdup((const char *)unicode2UTF8(obj->sFileName));
1027 	} else if ( strcmp(prop_name, "short_name") == 0 ) {
1028 		result->type = PHP_VAL_STRING;
1029 		wxString short_name(obj->sFileName.Length() > 60 ? (obj->sFileName.Left(60) + (wxT(" ..."))) : obj->sFileName);
1030 		result->str_val = strdup((const char *)unicode2UTF8(short_name));
1031 	} else if ( strcmp(prop_name, "hash") == 0 ) {
1032 		result->type = PHP_VAL_STRING;
1033 		result->str_val = strdup((const char *)unicode2UTF8(obj->sHash));
1034 	} else if ( strcmp(prop_name, "size") == 0 ) {
1035 		result->type = PHP_VAL_INT;
1036 		result->int_val = obj->lFileSize;
1037 	} else if ( strcmp(prop_name, "sources") == 0 ) {
1038 		result->type = PHP_VAL_INT;
1039 		result->int_val = obj->lSourceCount;
1040 	} else if ( strcmp(prop_name, "present") == 0 ) {
1041 		result->type = PHP_VAL_BOOL;
1042 		result->int_val = obj->bPresent;
1043 	} else {
1044 		php_report_error(PHP_ERROR, "'SearchFile' property [%s] is unknown", prop_name);
1045 	}
1046 }
1047 
1048 #ifndef PACKAGE_VERSION
1049 #include <common/ClientVersion.h>
1050 #define PACKAGE_VERSION (PACKAGE " " VERSION)
1051 #endif
1052 
amule_version(PHP_VALUE_NODE * val)1053 void amule_version(PHP_VALUE_NODE *val)
1054 {
1055 	if ( !val ) {
1056 		return;
1057 	}
1058 	value_value_free(val);
1059 
1060 	val->type = PHP_VAL_STRING;
1061 	val->str_val = strdup(PACKAGE_VERSION);
1062 }
1063 
1064 
1065 PHP_BLTIN_FUNC_DEF amule_lib_funcs[] = {
1066 	{
1067 		"amule_load_vars",
1068 		1, php_native_load_amule_vars,
1069 	},
1070 	{
1071 		"amule_get_stats",
1072 		0, php_get_amule_stats,
1073 	},
1074 	{
1075 		"amule_get_categories",
1076 		0, php_get_amule_categories,
1077 	},
1078 	{
1079 		"amule_get_options",
1080 		0, php_get_amule_options,
1081 	},
1082 	{
1083 		"amule_set_options",
1084 		1, php_set_amule_options,
1085 	},
1086 	{
1087 		"amule_do_server_cmd",
1088 		3,
1089 		php_native_server_cmd,
1090 	},
1091 	{
1092 		"amule_do_add_server_cmd",
1093 		3,
1094 		php_native_add_server_cmd,
1095 	},
1096 	{
1097 		"amule_do_download_cmd",
1098 		3,
1099 		php_native_download_file_cmd,
1100 	},
1101 	{
1102 		"amule_do_shared_cmd",
1103 		3,
1104 		php_native_shared_file_cmd,
1105 	},
1106 	{
1107 		"amule_do_reload_shared_cmd",
1108 		0, php_native_reload_shared_file_cmd,
1109 	},
1110 	{
1111 		"amule_do_search_download_cmd",
1112 		2,
1113 		php_native_search_download_cmd,
1114 	},
1115 	{
1116 		"amule_do_search_start_cmd",
1117 		7,
1118 		php_native_search_start_cmd,
1119 	},
1120 	{
1121 		"amule_do_ed2k_download_cmd",
1122 		2,
1123 		php_native_ed2k_download_cmd,
1124 	},
1125 	{
1126 		"amule_get_log",
1127 		1, php_get_log,
1128 	},
1129 	{
1130 		"amule_get_serverinfo",
1131 		1, php_get_serverinfo,
1132 	},
1133 	{
1134 		"amule_get_version",
1135 		0, amule_version,
1136 	},
1137 	{ 0, 0, 0, },
1138 };
1139 
php_init_amule_lib()1140 void php_init_amule_lib()
1141 {
1142 	// load function definitions
1143 	PHP_BLTIN_FUNC_DEF *curr_def = amule_lib_funcs;
1144 	while ( curr_def->name ) {
1145 		php_add_native_func(curr_def);
1146 		curr_def++;
1147 	}
1148 	// load object definitions
1149 	php_add_native_class("AmuleDownloadFile", amule_download_file_prop_get);
1150 	php_add_native_class("AmuleUploadFile", amule_upload_file_prop_get);
1151 	php_add_native_class("AmuleServer", amule_server_prop_get);
1152 	php_add_native_class("AmuleSharedFile", amule_shared_file_prop_get);
1153 	php_add_native_class("AmuleSearchFile", amule_search_file_prop_get);
1154 }
1155 
1156 // File_checked_for_headers
1157