C++11 requires a space between literal and string macro
[amule.git] / src / webserver / src / php_amule_lib.cpp
bloba4a14f39de89a2aa5e65bca7c9009824adeb1bb0
1 //
2 // This file is part of the aMule Project.
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.
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.
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.
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
27 #include <string> // Do_not_auto_remove (g++-4.0.1)
29 #include <sys/types.h>
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
35 #include "WebServer.h"
36 #include <ec/cpp/ECSpecialTags.h>
38 #include "php_syntree.h"
39 #include "php_core_lib.h"
41 #include <wx/datetime.h>
44 * Built-in php functions. Those are amule-specific funcions, accessing EC and internal
45 * datastructre
49 void php_native_shared_file_cmd(PHP_VALUE_NODE *)
51 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
52 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
53 php_report_error(PHP_ERROR, "Invalid or missing argument 1");
54 return;
56 char *str_hash = si->var->value.str_val;
58 si = get_scope_item(g_current_scope, "__param_1");
59 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
60 php_report_error(PHP_ERROR, "Invalid or missing argument 2");
61 return;
63 char *cmd_name = si->var->value.str_val;
64 si = get_scope_item(g_current_scope, "__param_2");
65 PHP_VAR_NODE *opt_param = si ? si->var : 0;
67 if ( !strcmp(cmd_name, "prio") && !opt_param ) {
68 php_report_error(PHP_ERROR, "Command 'prio' need 3-rd argument");
69 return;
73 CPhPLibContext::g_curr_context->WebServer()->Send_SharedFile_Cmd(wxString(char2unicode(str_hash)),
74 wxString(char2unicode(cmd_name)),
75 opt_param ? opt_param->value.int_val : 0);
78 void php_native_reload_shared_file_cmd(PHP_VALUE_NODE *)
80 CPhPLibContext::g_curr_context->WebServer()->Send_ReloadSharedFile_Cmd();
85 * Usage: php_native_download_file_cmd($file_hash, "command", $optional_arg)
88 void php_native_download_file_cmd(PHP_VALUE_NODE *)
90 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
91 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
92 php_report_error(PHP_ERROR, "Invalid or missing argument 1");
93 return;
95 char *str_hash = si->var->value.str_val;
97 si = get_scope_item(g_current_scope, "__param_1");
98 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
99 php_report_error(PHP_ERROR, "Invalid or missing argument 2");
100 return;
102 char *cmd_name = si->var->value.str_val;
103 si = get_scope_item(g_current_scope, "__param_2");
104 PHP_VAR_NODE *opt_param = si ? si->var : 0;
106 if ( (!strcmp(cmd_name, "prio") || !strcmp(cmd_name, "setcat")) && !opt_param ) {
107 php_report_error(PHP_ERROR, "Commands 'prio' and 'setcat' needs 3-rd argument");
108 return;
111 CPhPLibContext::g_curr_context->WebServer()->Send_DownloadFile_Cmd(wxString(char2unicode(str_hash)),
112 wxString(char2unicode(cmd_name)),
113 opt_param ? opt_param->value.int_val : 0);
117 * Usage amule_kad_connect($bootstrap_ip, $bootstrap_port)
119 void php_native_kad_connect(PHP_VALUE_NODE *)
121 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
122 if ( !si ) {
123 php_report_error(PHP_ERROR, "Missing or bad argument 1: $bootstrap_ip_addr");
124 return;
126 cast_value_dnum(&si->var->value);
127 unsigned int ipaddr = si->var->value.int_val;
129 si = get_scope_item(g_current_scope, "__param_1");
130 if ( !si ) {
131 php_report_error(PHP_ERROR, "Missing or bad argument 2: $bootstrap_ip_port");
132 return;
134 cast_value_dnum(&si->var->value);
135 unsigned int ipport = si->var->value.int_val;
137 CECPacket req(EC_OP_KAD_BOOTSTRAP_FROM_IP);
138 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_IP, ipaddr));
139 req.AddTag(CECTag(EC_TAG_BOOTSTRAP_PORT, ipport));
140 CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
143 void php_native_kad_disconnect(PHP_VALUE_NODE *)
145 CECPacket req(EC_OP_KAD_STOP);
146 CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
150 * Usage amule_add_server_cmd($server_addr, $server_port, $server_name);
152 void php_native_add_server_cmd(PHP_VALUE_NODE *)
154 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
155 if ( !si || (si->var->value.type != PHP_VAL_STRING) ) {
156 php_report_error(PHP_ERROR, "Missing or bad argument 1: $server_addr");
157 return;
159 char *addr = si->var->value.str_val;
161 si = get_scope_item(g_current_scope, "__param_1");
162 if ( !si ) {
163 php_report_error(PHP_ERROR, "Missing argument 2: $server_port");
164 return;
166 cast_value_dnum(&si->var->value);
167 int port = si->var->value.int_val;
169 si = get_scope_item(g_current_scope, "__param_2");
170 if ( !si || (si->var->value.type != PHP_VAL_STRING) ) {
171 php_report_error(PHP_ERROR, "Invalid or missing argument 3: $server_name");
172 return;
174 char *name = si->var->value.str_val;
176 CPhPLibContext::g_curr_context->WebServer()->Send_AddServer_Cmd(wxString(char2unicode(addr)),
177 wxString::Format(wxT("%d"), port), wxString(char2unicode(name)));
181 * Usage amule_server_cmd($server_ip, $server_port, "command");
183 void php_native_server_cmd(PHP_VALUE_NODE *)
185 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
186 if ( !si ) {
187 php_report_error(PHP_ERROR, "Missing argument 1: $server_ip");
188 return;
190 cast_value_dnum(&si->var->value);
191 uint32_t ip = si->var->value.int_val;
193 si = get_scope_item(g_current_scope, "__param_1");
194 if ( !si ) {
195 php_report_error(PHP_ERROR, "Missing argument 2: $server_port");
196 return;
198 cast_value_dnum(&si->var->value);
199 int port = si->var->value.int_val;
201 si = get_scope_item(g_current_scope, "__param_2");
202 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
203 php_report_error(PHP_ERROR, "Invalid or missing argument 3: $command");
204 return;
206 char *cmd = si->var->value.str_val;
208 CPhPLibContext::g_curr_context->WebServer()->Send_Server_Cmd(ip, port, wxString(char2unicode(cmd)));
212 * Query amule status. Return hash containing stats values
214 void php_get_amule_stats(PHP_VALUE_NODE *result)
216 CECPacket stat_req(EC_OP_STAT_REQ, EC_DETAIL_FULL);
217 const CECPacket *stats = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&stat_req);
218 if (!stats) {
219 return ;
221 const CEC_ConnState_Tag *tag = static_cast<const CEC_ConnState_Tag *>(stats->GetTagByName(EC_TAG_CONNSTATE));
222 if (!tag) {
223 return ;
226 cast_value_array(result);
227 PHP_VAR_NODE *id = array_get_by_str_key(result, "id");
228 cast_value_dnum(&id->value);
229 id->value.int_val = tag->GetEd2kId();
230 const CECTag *server = tag->GetTagByName(EC_TAG_SERVER);
231 if ( server ) {
232 PHP_VAR_NODE *srv_ip = array_get_by_str_key(result, "serv_addr");
233 value_value_free(&srv_ip->value);
234 srv_ip->value.type = PHP_VAL_STRING;
235 srv_ip->value.str_val =strdup(unicode2UTF8(server->GetIPv4Data().StringIP()));
237 const CECTag *sname = server->GetTagByName(EC_TAG_SERVER_NAME);
238 if ( sname ) {
239 PHP_VAR_NODE *srv_name = array_get_by_str_key(result, "serv_name");
240 value_value_free(&srv_name->value);
241 srv_name->value.type = PHP_VAL_STRING;
242 srv_name->value.str_val = strdup(unicode2UTF8(sname->GetStringData()));
245 const CECTag *susers = server->GetTagByName(EC_TAG_SERVER_USERS);
246 if ( susers ) {
247 PHP_VAR_NODE *srv_users = array_get_by_str_key(result, "serv_users");
248 value_value_free(&srv_users->value);
249 srv_users->value.type = PHP_VAL_INT;
250 srv_users->value.int_val = susers->GetInt();
254 // kademlia
255 PHP_VAR_NODE *kad = array_get_by_str_key(result, "kad_connected");
256 value_value_free(&kad->value);
257 kad->value.type = PHP_VAL_BOOL;
258 if ( tag->IsConnectedKademlia() ) {
259 kad->value.int_val = 1;
260 PHP_VAR_NODE *kad_fwl = array_get_by_str_key(result, "kad_firewalled");
261 kad_fwl->value.type = PHP_VAL_BOOL;
262 kad_fwl->value.int_val = tag->IsKadFirewalled();
263 } else {
264 kad->value.int_val = 0;
266 // traffic stats
267 PHP_VAR_NODE *speed;
268 speed = array_get_by_str_key(result, "speed_up");
269 value_value_free(&speed->value);
270 speed->value.type = PHP_VAL_INT;
271 speed->value.int_val = stats->GetTagByName(EC_TAG_STATS_UL_SPEED)->GetInt();
273 speed = array_get_by_str_key(result, "speed_down");
274 value_value_free(&speed->value);
275 speed->value.type = PHP_VAL_INT;
276 speed->value.int_val = stats->GetTagByName(EC_TAG_STATS_DL_SPEED)->GetInt();
278 speed = array_get_by_str_key(result, "speed_limit_up");
279 value_value_free(&speed->value);
280 speed->value.type = PHP_VAL_INT;
281 speed->value.int_val = stats->GetTagByName(EC_TAG_STATS_UL_SPEED_LIMIT)->GetInt();
283 speed = array_get_by_str_key(result, "speed_limit_down");
284 value_value_free(&speed->value);
285 speed->value.type = PHP_VAL_INT;
286 speed->value.int_val = stats->GetTagByName(EC_TAG_STATS_DL_SPEED_LIMIT)->GetInt();
288 delete stats;
291 void php_get_amule_categories(PHP_VALUE_NODE *result)
293 cast_value_array(result);
295 CECPacket req(EC_OP_GET_PREFERENCES);
296 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, (uint32)EC_PREFS_CATEGORIES));
297 const CECPacket *reply = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
298 if ( !reply ) {
299 return ;
301 const CECTag *cats_tag = reply->GetFirstTagSafe();
302 if (cats_tag->HasChildTags()) {
303 int i = 0;
304 for (CECTag::const_iterator it = cats_tag->begin(); it != cats_tag->end(); ++it) {
305 const CECTag *categoryTitle = it->GetTagByName(EC_TAG_CATEGORY_TITLE);
306 PHP_VAR_NODE *cat = array_get_by_int_key(result, i++);
307 value_value_free(&cat->value);
308 cat->value.type = PHP_VAL_STRING;
309 cat->value.str_val = strdup(unicode2UTF8(categoryTitle->GetStringData()));
311 } else {
312 PHP_VAR_NODE *cat = array_get_by_int_key(result, 0);
313 value_value_free(&cat->value);
314 cat->value.type = PHP_VAL_STRING;
315 cat->value.str_val = strdup("all");
317 delete reply;
320 typedef struct {
321 const char *php_name;
322 ECTagNames tagname;
323 int opsize;
324 } PHP_2_EC_OPT_DEF;
326 PHP_2_EC_OPT_DEF g_connection_opt_defs[] = {
327 { "max_line_up_cap", EC_TAG_CONN_UL_CAP, 4}, { "max_line_down_cap", EC_TAG_CONN_DL_CAP, 4},
328 { "max_up_limit", EC_TAG_CONN_MAX_UL, 2}, { "max_down_limit", EC_TAG_CONN_MAX_DL, 2},
329 { "slot_alloc", EC_TAG_CONN_SLOT_ALLOCATION, 2},
330 { "tcp_port", EC_TAG_CONN_TCP_PORT, 2}, { "udp_port", EC_TAG_CONN_UDP_PORT, 2},
331 { "udp_dis", EC_TAG_CONN_UDP_DISABLE, 0},
332 { "max_file_src", EC_TAG_CONN_MAX_FILE_SOURCES, 2},
333 { "max_conn_total", EC_TAG_CONN_MAX_CONN, 2},
334 { "autoconn_en", EC_TAG_CONN_AUTOCONNECT, 0}, { "reconn_en", EC_TAG_CONN_RECONNECT, 0},
335 {0, (ECTagNames)0, 0}
338 PHP_2_EC_OPT_DEF g_file_opt_defs[] = {
339 { "ich_en", EC_TAG_FILES_ICH_ENABLED, 0},
340 { "aich_trust", EC_TAG_FILES_AICH_TRUST, 0},
341 { "new_files_paused", EC_TAG_FILES_NEW_PAUSED, 0},
342 { "new_files_auto_dl_prio", EC_TAG_FILES_NEW_AUTO_DL_PRIO, 0},
343 { "preview_prio", EC_TAG_FILES_PREVIEW_PRIO, 0},
344 { "new_files_auto_ul_prio", EC_TAG_FILES_NEW_AUTO_UL_PRIO, 0},
345 { "upload_full_chunks", EC_TAG_FILES_UL_FULL_CHUNKS, 0},
346 { "first_last_chunks_prio", EC_TAG_FILES_PREVIEW_PRIO, 0},
347 { "start_next_paused", EC_TAG_FILES_START_NEXT_PAUSED, 0},
348 { "resume_same_cat", EC_TAG_FILES_RESUME_SAME_CAT, 0},
349 { "save_sources", EC_TAG_FILES_SAVE_SOURCES, 0},
350 { "extract_metadata", EC_TAG_FILES_EXTRACT_METADATA, 0},
351 { "alloc_full", EC_TAG_FILES_ALLOC_FULL_SIZE, 0},
352 { "check_free_space", EC_TAG_FILES_CHECK_FREE_SPACE, 0},
353 { "min_free_space", EC_TAG_FILES_MIN_FREE_SPACE, 4},
354 {0, (ECTagNames)0, 0}
357 PHP_2_EC_OPT_DEF g_webserver_opt_defs[] = {
358 { "use_gzip", EC_TAG_WEBSERVER_USEGZIP, 0},
359 { "autorefresh_time", EC_TAG_WEBSERVER_REFRESH, 4},
360 {0, (ECTagNames)0, 0}
363 PHP_2_EC_OPT_DEF g_coretweak_opt_defs[] = {
364 { "max_conn_5sec", EC_TAG_CORETW_MAX_CONN_PER_FIVE, 2},
365 {0, (ECTagNames)0, 0}
368 void set_array_int_val(PHP_VALUE_NODE *array, std::string arrkey, int value)
370 PHP_VAR_NODE *key = array_get_by_str_key(array, arrkey);
371 PHP_VALUE_NODE intval;
372 intval.type = PHP_VAL_INT;
373 intval.int_val = value;
374 value_value_assign(&key->value, &intval);
377 void ec_tag_2_php(const CECTag *cattag, PHP_2_EC_OPT_DEF *opts, PHP_VAR_NODE *catvar)
379 for(PHP_2_EC_OPT_DEF *def = opts; def->php_name; def++) {
380 int val;
381 switch(def->opsize) {
382 case 0: val = cattag->GetTagByName(def->tagname) ? 1 : 0; break;
383 case 1: val = cattag->GetTagByNameSafe(def->tagname)->GetInt(); break;
384 case 2: val = cattag->GetTagByNameSafe(def->tagname)->GetInt(); break;
385 case 4: val = cattag->GetTagByNameSafe(def->tagname)->GetInt(); break;
386 default: val = -1;
388 wxASSERT(val != -1);
389 //printf("OPT_DEBUG: %s of size %d -> %d\n", def->php_name, def->opsize, val);
390 set_array_int_val(&catvar->value, def->php_name, val);
395 * Return hash of amule options.
396 * Key: option name
397 * Value: option value (string)
399 void php_get_amule_options(PHP_VALUE_NODE *result)
401 cast_value_array(result);
403 CECPacket req(EC_OP_GET_PREFERENCES);
404 req.AddTag(CECTag(EC_TAG_SELECT_PREFS, (uint32)0xffffffff));
405 const CECPacket *reply = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
406 if ( !reply || !reply->HasChildTags()) {
407 return ;
409 const CECTag *cattag = 0;
410 if ((cattag = reply->GetTagByName(EC_TAG_PREFS_GENERAL)) != 0) {
411 PHP_VAR_NODE *key = array_get_by_str_key(result, "nick");
412 value_value_free(&key->value);
413 key->value.type = PHP_VAL_STRING;
414 key->value.str_val = strdup(unicode2UTF8(cattag->GetTagByNameSafe(EC_TAG_USER_NICK)->GetStringData()));
417 if ((cattag = reply->GetTagByName(EC_TAG_PREFS_CONNECTIONS)) != 0) {
418 PHP_VAR_NODE *cat = array_get_by_str_key(result, "connection");
419 cast_value_array(&cat->value);
421 ec_tag_2_php(cattag, g_connection_opt_defs, cat);
423 if ((cattag = reply->GetTagByName(EC_TAG_PREFS_FILES)) != 0) {
424 PHP_VAR_NODE *cat = array_get_by_str_key(result, "files");
425 cast_value_array(&cat->value);
427 ec_tag_2_php(cattag, g_file_opt_defs, cat);
430 if ((cattag = reply->GetTagByName(EC_TAG_PREFS_REMOTECTRL)) != 0) {
431 PHP_VAR_NODE *cat = array_get_by_str_key(result, "webserver");
432 cast_value_array(&cat->value);
434 ec_tag_2_php(cattag, g_webserver_opt_defs, cat);
437 if ((cattag = reply->GetTagByName(EC_TAG_PREFS_CORETWEAKS)) != 0) {
438 PHP_VAR_NODE *cat = array_get_by_str_key(result, "coretweaks");
439 cast_value_array(&cat->value);
441 ec_tag_2_php(cattag, g_coretweak_opt_defs, cat);
445 bool php_2_ec_tag(CECTag *cattag, PHP_2_EC_OPT_DEF *opts, PHP_VALUE_NODE *catvar)
447 for(PHP_2_EC_OPT_DEF *def = opts; def->php_name; def++) {
448 PHP_VAR_NODE *opt_var = array_get_by_str_key(catvar, def->php_name);
449 if ( opt_var->value.type == PHP_VAL_NONE ) {
450 continue;
452 cast_value_dnum(&opt_var->value);
453 switch(def->opsize) {
454 case 0: // always transmit !
455 case 1: cattag->AddTag(CECTag(def->tagname ,(uint8)opt_var->value.int_val)); break;
456 case 2: cattag->AddTag(CECTag(def->tagname ,(uint16)opt_var->value.int_val)); break;
457 case 4: cattag->AddTag(CECTag(def->tagname ,(uint32)opt_var->value.int_val)); break;
458 default: return false;
461 return true;
465 * Set amule options from given array. Argument looks like "amule_get_options" result
467 void php_set_amule_options(PHP_VALUE_NODE *)
469 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
470 if ( !si || (si->var->value.type != PHP_VAL_ARRAY)) {
471 php_report_error(PHP_ERROR, "Invalid or missing argument 1 (options array)");
472 return;
475 CECPacket req(EC_OP_SET_PREFERENCES);
476 PHP_VAR_NODE *opt_group_array = 0;
478 // files
479 opt_group_array = array_get_by_str_key(&si->var->value, "files");
480 if ( opt_group_array->value.type == PHP_VAL_ARRAY ) {
481 CECEmptyTag filePrefs(EC_TAG_PREFS_FILES);
482 php_2_ec_tag(&filePrefs, g_file_opt_defs, &opt_group_array->value);
483 req.AddTag(filePrefs);
485 // connection
486 opt_group_array = array_get_by_str_key(&si->var->value, "connection");
487 if ( opt_group_array->value.type == PHP_VAL_ARRAY ) {
488 CECEmptyTag connPrefs(EC_TAG_PREFS_CONNECTIONS);
489 php_2_ec_tag(&connPrefs, g_connection_opt_defs, &opt_group_array->value);
490 req.AddTag(connPrefs);
492 // webserver
493 opt_group_array = array_get_by_str_key(&si->var->value, "webserver");
494 if ( opt_group_array->value.type == PHP_VAL_ARRAY ) {
495 CECEmptyTag webPrefs(EC_TAG_PREFS_REMOTECTRL);
496 php_2_ec_tag(&webPrefs, g_webserver_opt_defs, &opt_group_array->value);
497 req.AddTag(webPrefs);
498 // also apply settings localy
499 PHP_VAR_NODE *pref = array_get_by_str_key(&opt_group_array->value, "use_gzip");
500 cast_value_dnum(&pref->value);
501 CPhPLibContext::g_curr_context->WebServer()->webInterface->m_UseGzip = pref->value.int_val != 0;
502 pref = array_get_by_str_key(&opt_group_array->value, "autorefresh_time");
503 cast_value_dnum(&pref->value);
504 CPhPLibContext::g_curr_context->WebServer()->webInterface->m_PageRefresh = pref->value.int_val;
506 CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
510 * Download 1 of search results. Params: hash, category (default=0)
512 void php_native_search_download_cmd(PHP_VALUE_NODE *)
514 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
515 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
516 php_report_error(PHP_ERROR, "Invalid or missing argument 1 (file hash)");
517 return;
519 char *str_hash = si->var->value.str_val;
521 si = get_scope_item(g_current_scope, "__param_1");
522 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
523 php_report_error(PHP_ERROR, "Invalid or missing argument 2 (category)");
524 return;
527 cast_value_dnum(&si->var->value);
528 int cat = si->var->value.int_val;
530 CPhPLibContext::g_curr_context->WebServer()->Send_DownloadSearchFile_Cmd(
531 wxString(char2unicode(str_hash)), cat);
534 void php_native_search_start_cmd(PHP_VALUE_NODE *)
536 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
537 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
538 php_report_error(PHP_ERROR, "Invalid or missing argument 1 (search term)");
539 return;
541 char *search = si->var->value.str_val;
543 if ( !(si = get_scope_item(g_current_scope, "__param_1")) || (si->var->value.type != PHP_VAL_STRING)) {
544 php_report_error(PHP_ERROR, "Invalid or missing argument 2 (file extension)");
545 return;
547 char *ext = si->var->value.str_val;
549 if ( !(si = get_scope_item(g_current_scope, "__param_2")) || (si->var->value.type != PHP_VAL_STRING)) {
550 php_report_error(PHP_ERROR, "Invalid or missing argument 3 (file type)");
551 return;
553 char *type = si->var->value.str_val;
555 if ( !(si = get_scope_item(g_current_scope, "__param_3")) ) {
556 php_report_error(PHP_ERROR, "Invalid or missing argument 4 (search type)");
557 return;
559 cast_value_dnum(&si->var->value);
561 EC_SEARCH_TYPE search_type;
562 switch(si->var->value.int_val) {
563 case 0: search_type = EC_SEARCH_LOCAL; break;
564 case 1: search_type = EC_SEARCH_GLOBAL; break;
565 case 2: search_type = EC_SEARCH_KAD; break;
566 default:
567 php_report_error(PHP_ERROR, "Invalid search type %" PRIu64, si->var->value.int_val);
568 return;
571 if ( !(si = get_scope_item(g_current_scope, "__param_4")) ) {
572 php_report_error(PHP_ERROR, "Invalid or missing argument 5 (availability)");
573 return;
575 cast_value_dnum(&si->var->value);
576 int avail = si->var->value.int_val;
578 if ( !(si = get_scope_item(g_current_scope, "__param_5")) ) {
579 php_report_error(PHP_ERROR, "Invalid or missing argument 6 (min size)");
580 return;
582 cast_value_dnum(&si->var->value);
583 int min_size = si->var->value.int_val;
585 if ( !(si = get_scope_item(g_current_scope, "__param_6")) ) {
586 php_report_error(PHP_ERROR, "Invalid or missing argument 7 (max size)");
587 return;
589 cast_value_dnum(&si->var->value);
590 int max_size = si->var->value.int_val;
593 CPhPLibContext::g_curr_context->WebServer()->Send_Search_Cmd(
594 wxString(char2unicode(search)), wxString(char2unicode(ext)), wxString(char2unicode(type)),
595 search_type, avail, min_size, max_size);
599 * Request contents of log
601 void php_get_log(PHP_VALUE_NODE *result)
603 value_value_free(result);
605 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
606 bool rst;
607 if ( !si ) {
608 rst = false;
609 } else {
610 cast_value_dnum(&si->var->value);
611 rst = si->var->value.int_val != 0;
613 if ( rst ) {
614 CECPacket req(EC_OP_RESET_LOG);
615 CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
617 CECPacket req(EC_OP_GET_LOG);
618 const CECPacket *response = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
619 if (response) {
620 wxString serverInfoString(_SpecialChars(response->GetFirstTagSafe()->GetStringData()));
621 delete response;
622 result->type = PHP_VAL_STRING;
623 result->str_val = strdup((const char *)unicode2UTF8(serverInfoString));
628 * Request contents of server info
630 void php_get_serverinfo(PHP_VALUE_NODE *result)
632 value_value_free(result);
634 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
635 bool rst;
636 if ( !si ) {
637 rst = false;
638 } else {
639 cast_value_dnum(&si->var->value);
640 rst = si->var->value.int_val != 0;
643 if ( rst ) {
644 CECPacket req(EC_OP_CLEAR_SERVERINFO);
645 CPhPLibContext::g_curr_context->WebServer()->Send_Discard_V2_Request(&req);
647 CECPacket req(EC_OP_GET_SERVERINFO);
648 const CECPacket *response = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
649 if (response) {
650 wxString serverInfoString(_SpecialChars(response->GetFirstTagSafe()->GetStringData()));
651 delete response;
652 result->type = PHP_VAL_STRING;
653 result->str_val = strdup((const char *)unicode2UTF8(serverInfoString));
659 * Download ed2k link. Params: link, category (default=0)
661 void php_native_ed2k_download_cmd(PHP_VALUE_NODE *result)
663 PHP_SCOPE_ITEM *si = get_scope_item(g_current_scope, "__param_0");
664 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
665 php_report_error(PHP_ERROR, "Invalid or missing argument 1 (file link)");
666 return;
668 char *str_link = si->var->value.str_val;
670 si = get_scope_item(g_current_scope, "__param_1");
671 if ( !si || (si->var->value.type != PHP_VAL_STRING)) {
672 php_report_error(PHP_ERROR, "Invalid or missing argument 2 (category)");
673 return;
676 cast_value_dnum(&si->var->value);
677 int cat = si->var->value.int_val;
679 bool cmd_result = CPhPLibContext::g_curr_context->WebServer()->Send_DownloadEd2k_Cmd(
680 wxString(char2unicode(str_link)), cat);
681 if ( result ) {
682 cast_value_bool(result);
683 result->int_val = cmd_result;
689 * Load amule variables into interpreter scope.
690 * "varname" will tell us, what kind of variables need to load:
691 * "downloads", "uploads", "searchresult", "servers", "options" etc
693 template <class C, class T>
694 void amule_obj_array_create(const char *class_name, PHP_VALUE_NODE *result)
696 if ( !result ) {
697 return;
699 C *container = T::GetContainerInstance();
701 container->ReQuery();
703 typename std::list<T>::const_iterator it = container->GetBeginIterator();
704 while ( it != container->GetEndIterator()) {
705 PHP_VAR_NODE *var = array_push_back(result);
706 var->value.type = PHP_VAL_OBJECT;
707 var->value.obj_val.class_name = class_name;
708 const T *cur_item = &(*it);
709 var->value.obj_val.inst_ptr = (void *)cur_item;
710 ++it;
714 void amule_load_downloads(PHP_VALUE_NODE *result)
716 amule_obj_array_create<DownloadFileInfo, DownloadFile>("AmuleDownloadFile", result);
719 void amule_load_servers(PHP_VALUE_NODE *result)
721 amule_obj_array_create<ServersInfo, ServerEntry>("AmuleServer", result);
724 void amule_load_shared(PHP_VALUE_NODE *result)
726 amule_obj_array_create<SharedFileInfo, SharedFile>("AmuleSharedFile", result);
729 void amule_load_search(PHP_VALUE_NODE *result)
731 amule_obj_array_create<SearchInfo, SearchFile>("AmuleSearchFile", result);
734 void amule_load_uploads(PHP_VALUE_NODE *result)
736 amule_obj_array_create<UploadsInfo, UploadFile>("AmuleUploadFile", result);
739 void amule_load_stats()
741 CPhPLibContext::g_curr_context->WebServer()->Reload_Stats();
745 * Convert CEC_StatTree_Node_Tag into php associative array
747 * Since data structure is recoursive - we need helper function
748 * to perform conversion
750 void ecstats2php(CEC_StatTree_Node_Tag *root, PHP_VALUE_NODE *result)
752 cast_value_array(result);
753 std::string key(unicode2UTF8(root->GetDisplayString()));
754 PHP_VAR_NODE *v_key = array_get_by_str_key(result, key);
755 for (CECTag::const_iterator it = root->begin(); it != root->end(); ++it) {
756 CEC_StatTree_Node_Tag *tag = (CEC_StatTree_Node_Tag*) & *it;
757 if (tag->GetTagName() == EC_TAG_STATTREE_NODE) {
758 ecstats2php(tag, &v_key->value);
764 void amule_load_stats_tree(PHP_VALUE_NODE *result)
766 if ( !result ) {
767 return;
769 value_value_free(result);
771 CECPacket req(EC_OP_GET_STATSTREE, EC_DETAIL_WEB);
772 const CECPacket *response = CPhPLibContext::g_curr_context->WebServer()->webInterface->SendRecvMsg_v2(&req);
773 if ( !response ) {
774 return;
776 const CECTag *server_ver = response->GetTagByName(EC_TAG_SERVER_VERSION);
777 const CECTag *user_nick = response->GetTagByName(EC_TAG_USER_NICK);
778 if ( !server_ver || !user_nick ) {
779 delete response;
780 return;
782 const CEC_StatTree_Node_Tag *stats_root = static_cast<const CEC_StatTree_Node_Tag *>(response->GetTagByName(EC_TAG_STATTREE_NODE));
783 //ecstats2php(stats_root, result);
784 for (CECTag::const_iterator it = stats_root->begin(); it != stats_root->end(); ++it) {
785 CEC_StatTree_Node_Tag *tag = (CEC_StatTree_Node_Tag*) & *it;
786 if (tag->GetTagName() == EC_TAG_STATTREE_NODE) {
787 ecstats2php(tag, result);
792 void php_native_load_amule_vars(PHP_VALUE_NODE *result)
794 PHP_SCOPE_ITEM *si_str = get_scope_item(g_current_scope, "__param_0");
795 if ( !si_str ) {
796 php_report_error(PHP_ERROR, "Missing argument 'varname' for 'load_amule_vars'");
797 return;
799 PHP_VALUE_NODE *str = &si_str->var->value;
800 if ( str->type != PHP_VAL_STRING ) {
801 php_report_error(PHP_ERROR, "Argument 'varname' for 'load_amule_vars' must be string");
802 return;
804 char *varname = str->str_val;
805 if ( result ) {
806 cast_value_array(result);
808 if ( strcmp(varname, "downloads") == 0 ) {
809 amule_load_downloads(result);
810 } else if ( strcmp(varname, "uploads") == 0 ) {
811 amule_load_uploads(result);
812 } else if ( strcmp(varname, "shared") == 0 ) {
813 amule_load_shared(result);
814 } else if ( strcmp(varname, "searchresult") == 0 ) {
815 amule_load_search(result);
816 } else if ( strcmp(varname, "servers") == 0 ) {
817 amule_load_servers(result);
818 } else if ( strcmp(varname, "stats_graph") == 0 ) {
819 amule_load_stats();
820 } else if ( strcmp(varname, "stats_tree") == 0 ) {
821 amule_load_stats_tree(result);
822 } else {
823 value_value_free(result);
824 php_report_error(PHP_ERROR, "This type of amule variable is unknown");
829 * Amule objects implementations
831 void amule_download_file_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
833 if ( !ptr ) {
834 value_value_free(result);
835 return;
837 DownloadFile *obj = static_cast<DownloadFile *>(ptr);
838 result->type = PHP_VAL_INT;
839 if ( strcmp(prop_name, "name") == 0 ) {
840 result->type = PHP_VAL_STRING;
841 result->str_val = strdup((const char *)unicode2UTF8(obj->sFileName));
842 } else if ( strcmp(prop_name, "short_name") == 0 ) {
843 result->type = PHP_VAL_STRING;
844 wxString short_name(obj->sFileName.Length() > 60 ? (obj->sFileName.Left(60) + (wxT(" ..."))) : obj->sFileName);
845 result->str_val = strdup((const char *)unicode2UTF8(short_name));
846 } else if ( strcmp(prop_name, "hash") == 0 ) {
847 result->type = PHP_VAL_STRING;
848 result->str_val = strdup((const char *)unicode2UTF8(obj->sFileHash));
849 } else if ( strcmp(prop_name, "progress") == 0 ) {
850 result->type = PHP_VAL_STRING;
851 result->str_val = strdup((const char *)unicode2UTF8(obj->m_Image->GetHTML()));
852 } else if ( strcmp(prop_name, "link") == 0 ) {
853 result->type = PHP_VAL_STRING;
854 result->str_val = strdup((const char *)unicode2UTF8(obj->sED2kLink));
855 } else if ( strcmp(prop_name, "category") == 0 ) {
856 result->int_val = obj->nCat;
857 } else if ( strcmp(prop_name, "status") == 0 ) {
858 result->int_val = obj->nFileStatus;
859 } else if ( strcmp(prop_name, "size") == 0 ) {
860 result->int_val = obj->lFileSize;
861 } else if ( strcmp(prop_name, "size_done") == 0 ) {
862 result->int_val = obj->lFileCompleted;
863 } else if ( strcmp(prop_name, "size_xfer") == 0 ) {
864 result->int_val = obj->lFileTransferred;
865 } else if ( strcmp(prop_name, "speed") == 0 ) {
866 result->int_val = obj->lFileSpeed;
867 } else if ( strcmp(prop_name, "src_count") == 0 ) {
868 result->int_val = obj->lSourceCount;
869 } else if ( strcmp(prop_name, "src_count_not_curr") == 0 ) {
870 result->int_val = obj->lNotCurrentSourceCount;
871 } else if ( strcmp(prop_name, "src_count_a4af") == 0 ) {
872 result->int_val = obj->lSourceCountA4AF;
873 } else if ( strcmp(prop_name, "src_count_xfer") == 0 ) {
874 result->int_val = obj->lTransferringSourceCount;
875 } else if ( strcmp(prop_name, "prio") == 0 ) {
876 result->int_val = obj->lFilePrio;
877 } else if ( strcmp(prop_name, "prio_auto") == 0 ) {
878 result->int_val = obj->bFileAutoPriority;
879 } else if ( strcmp(prop_name, "last_seen_complete") == 0 ) {
880 result->int_val = obj->wxtLastSeenComplete.GetTicks();
881 } else {
882 php_report_error(PHP_ERROR, "'DownloadFile' property [%s] is unknown", prop_name);
886 void amule_upload_file_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
888 if ( !ptr ) {
889 value_value_free(result);
890 return;
892 UploadFile *obj = static_cast<UploadFile *>(ptr);
893 result->type = PHP_VAL_INT;
894 if ( strcmp(prop_name, "name") == 0 ) {
895 result->type = PHP_VAL_STRING;
896 SharedFile *sharedfile = SharedFile::GetContainerInstance()->GetByID(obj->nUploadFile);
897 // uploading file we don't share ?! We are either out of sync with core or a shared file has been removed while uploading it
898 if ( !sharedfile ) {
899 SharedFile::GetContainerInstance()->ReQuery();
900 sharedfile = SharedFile::GetContainerInstance()->GetByID(obj->nUploadFile);
902 result->str_val = strdup(sharedfile ? (const char *)unicode2UTF8(sharedfile->sFileName) : "???");
903 } else if ( strcmp(prop_name, "short_name") == 0 ) {
904 result->type = PHP_VAL_STRING;
905 SharedFile *sharedfile = SharedFile::GetContainerInstance()->GetByID(obj->nUploadFile);
906 if ( !sharedfile ) {
907 SharedFile::GetContainerInstance()->ReQuery();
908 sharedfile = SharedFile::GetContainerInstance()->GetByID(obj->nUploadFile);
910 wxString short_name;
911 if (sharedfile) {
912 short_name = sharedfile->sFileName.Length() > 60 ? (sharedfile->sFileName.Left(60) + (wxT(" ..."))) : sharedfile->sFileName;
913 } else {
914 short_name = wxT("???");
916 result->str_val = strdup((const char *)unicode2UTF8(short_name));
917 } else if ( strcmp(prop_name, "user_name") == 0 ) {
918 result->type = PHP_VAL_STRING;
919 result->str_val = strdup((const char *)unicode2UTF8(obj->sUserName));
920 } else if ( strcmp(prop_name, "xfer_up") == 0 ) {
921 result->int_val = obj->nTransferredUp;
922 } else if ( strcmp(prop_name, "xfer_down") == 0 ) {
923 result->int_val = obj->nTransferredDown;
924 } else if ( strcmp(prop_name, "xfer_speed") == 0 ) {
925 result->int_val = obj->nSpeed;
926 } else {
927 php_report_error(PHP_ERROR, "'UploadFile' property [%s] is unknown", prop_name);
931 void amule_server_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
933 if ( !ptr ) {
934 value_value_free(result);
935 return;
937 ServerEntry *obj = static_cast<ServerEntry *>(ptr);
938 if ( strcmp(prop_name, "name") == 0 ) {
939 result->type = PHP_VAL_STRING;
940 result->str_val = strdup((const char *)unicode2UTF8(obj->sServerName));
941 } else if ( strcmp(prop_name, "desc") == 0 ) {
942 result->type = PHP_VAL_STRING;
943 result->str_val = strdup((const char *)unicode2UTF8(obj->sServerDescription));
944 } else if ( strcmp(prop_name, "addr") == 0 ) {
945 result->type = PHP_VAL_STRING;
946 result->str_val = strdup((const char *)unicode2UTF8(obj->sServerIP));
947 } else if ( strcmp(prop_name, "users") == 0 ) {
948 result->type = PHP_VAL_INT;
949 result->int_val = obj->nServerUsers;
950 } else if ( strcmp(prop_name, "ip") == 0 ) {
951 result->type = PHP_VAL_INT;
952 result->int_val = obj->nServerIP;
953 } else if ( strcmp(prop_name, "port") == 0 ) {
954 result->type = PHP_VAL_INT;
955 result->int_val = obj->nServerPort;
956 } else if ( strcmp(prop_name, "maxusers") == 0 ) {
957 result->type = PHP_VAL_INT;
958 result->int_val = obj->nServerMaxUsers;
959 } else if ( strcmp(prop_name, "files") == 0 ) {
960 result->type = PHP_VAL_INT;
961 result->int_val = obj->nServerFiles;
962 } else {
963 php_report_error(PHP_ERROR, "'ServerEntry' property [%s] is unknown", prop_name);
967 void amule_shared_file_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
969 if ( !ptr ) {
970 value_value_free(result);
971 return;
973 SharedFile *obj = static_cast<SharedFile *>(ptr);
974 if ( strcmp(prop_name, "name") == 0 ) {
975 result->type = PHP_VAL_STRING;
976 result->str_val = strdup((const char *)unicode2UTF8(obj->sFileName));
977 } else if ( strcmp(prop_name, "short_name") == 0 ) {
978 result->type = PHP_VAL_STRING;
979 wxString short_name(obj->sFileName.Length() > 60 ? (obj->sFileName.Left(60) + (wxT(" ..."))) : obj->sFileName);
980 result->str_val = strdup((const char *)unicode2UTF8(short_name));
981 } else if ( strcmp(prop_name, "hash") == 0 ) {
982 result->type = PHP_VAL_STRING;
983 result->str_val = strdup((const char *)unicode2UTF8(obj->sFileHash));
984 } else if ( strcmp(prop_name, "size") == 0 ) {
985 result->type = PHP_VAL_INT;
986 result->int_val = obj->lFileSize;
987 } else if ( strcmp(prop_name, "link") == 0 ) {
988 result->type = PHP_VAL_STRING;
989 result->str_val = strdup(unicode2UTF8(obj->sED2kLink));
990 } else if ( strcmp(prop_name, "xfer") == 0 ) {
991 result->type = PHP_VAL_INT;
992 result->int_val = obj->nFileTransferred;
993 } else if ( strcmp(prop_name, "xfer_all") == 0 ) {
994 result->type = PHP_VAL_INT;
995 result->int_val = obj->nFileAllTimeTransferred;
996 } else if ( strcmp(prop_name, "req") == 0 ) {
997 result->type = PHP_VAL_INT;
998 result->int_val = obj->nFileRequests;
999 } else if ( strcmp(prop_name, "req_all") == 0 ) {
1000 result->type = PHP_VAL_INT;
1001 result->int_val = obj->nFileAllTimeRequests;
1002 } else if ( strcmp(prop_name, "accept") == 0 ) {
1003 result->type = PHP_VAL_INT;
1004 result->int_val = obj->nFileAccepts;
1005 } else if ( strcmp(prop_name, "accept_all") == 0 ) {
1006 result->type = PHP_VAL_INT;
1007 result->int_val = obj->nFileAllTimeAccepts;
1008 } else if ( strcmp(prop_name, "prio") == 0 ) {
1009 result->type = PHP_VAL_INT;
1010 result->int_val = obj->nFilePriority;
1011 } else if ( strcmp(prop_name, "prio_auto") == 0 ) {
1012 result->type = PHP_VAL_BOOL;
1013 result->int_val = obj->bFileAutoPriority;
1014 } else {
1015 php_report_error(PHP_ERROR, "'SharedFile' property [%s] is unknown", prop_name);
1019 void amule_search_file_prop_get(void *ptr, char *prop_name, PHP_VALUE_NODE *result)
1021 if ( !ptr ) {
1022 value_value_free(result);
1023 return;
1025 SearchFile *obj = static_cast<SearchFile *>(ptr);
1026 if ( strcmp(prop_name, "name") == 0 ) {
1027 result->type = PHP_VAL_STRING;
1028 result->str_val = strdup((const char *)unicode2UTF8(obj->sFileName));
1029 } else if ( strcmp(prop_name, "short_name") == 0 ) {
1030 result->type = PHP_VAL_STRING;
1031 wxString short_name(obj->sFileName.Length() > 60 ? (obj->sFileName.Left(60) + (wxT(" ..."))) : obj->sFileName);
1032 result->str_val = strdup((const char *)unicode2UTF8(short_name));
1033 } else if ( strcmp(prop_name, "hash") == 0 ) {
1034 result->type = PHP_VAL_STRING;
1035 result->str_val = strdup((const char *)unicode2UTF8(obj->sHash));
1036 } else if ( strcmp(prop_name, "size") == 0 ) {
1037 result->type = PHP_VAL_INT;
1038 result->int_val = obj->lFileSize;
1039 } else if ( strcmp(prop_name, "sources") == 0 ) {
1040 result->type = PHP_VAL_INT;
1041 result->int_val = obj->lSourceCount;
1042 } else if ( strcmp(prop_name, "present") == 0 ) {
1043 result->type = PHP_VAL_BOOL;
1044 result->int_val = obj->bPresent;
1045 } else {
1046 php_report_error(PHP_ERROR, "'SearchFile' property [%s] is unknown", prop_name);
1050 #ifndef PACKAGE_VERSION
1051 #include <common/ClientVersion.h>
1052 #define PACKAGE_VERSION (PACKAGE " " VERSION)
1053 #endif
1055 void amule_version(PHP_VALUE_NODE *val)
1057 if ( !val ) {
1058 return;
1060 value_value_free(val);
1062 val->type = PHP_VAL_STRING;
1063 val->str_val = strdup(PACKAGE_VERSION);
1067 PHP_BLTIN_FUNC_DEF amule_lib_funcs[] = {
1069 "amule_load_vars",
1070 1, php_native_load_amule_vars,
1073 "amule_get_stats",
1074 0, php_get_amule_stats,
1077 "amule_get_categories",
1078 0, php_get_amule_categories,
1081 "amule_get_options",
1082 0, php_get_amule_options,
1085 "amule_set_options",
1086 1, php_set_amule_options,
1089 "amule_do_server_cmd",
1091 php_native_server_cmd,
1094 "amule_do_add_server_cmd",
1096 php_native_add_server_cmd,
1099 "amule_do_download_cmd",
1101 php_native_download_file_cmd,
1104 "amule_do_shared_cmd",
1106 php_native_shared_file_cmd,
1109 "amule_do_reload_shared_cmd",
1110 0, php_native_reload_shared_file_cmd,
1113 "amule_do_search_download_cmd",
1115 php_native_search_download_cmd,
1118 "amule_do_search_start_cmd",
1120 php_native_search_start_cmd,
1123 "amule_do_ed2k_download_cmd",
1125 php_native_ed2k_download_cmd,
1128 "amule_get_log",
1129 1, php_get_log,
1132 "amule_get_serverinfo",
1133 1, php_get_serverinfo,
1136 "amule_get_version",
1137 0, amule_version,
1139 { 0, 0, 0, },
1142 void php_init_amule_lib()
1144 // load function definitions
1145 PHP_BLTIN_FUNC_DEF *curr_def = amule_lib_funcs;
1146 while ( curr_def->name ) {
1147 php_add_native_func(curr_def);
1148 curr_def++;
1150 // load object definitions
1151 php_add_native_class("AmuleDownloadFile", amule_download_file_prop_get);
1152 php_add_native_class("AmuleUploadFile", amule_upload_file_prop_get);
1153 php_add_native_class("AmuleServer", amule_server_prop_get);
1154 php_add_native_class("AmuleSharedFile", amule_shared_file_prop_get);
1155 php_add_native_class("AmuleSearchFile", amule_search_file_prop_get);
1158 // File_checked_for_headers