6 #define __STDC_LIMIT_MACROS
10 #include <sys/socket.h>
13 #include <sys/select.h>
14 #include <netinet/ip.h>
40 static std::string
realpath(std::string path) {
41 char newpath[PATH_MAX];
43 return std::string(newpath);
46 #define NOTBLOCKING(x) fcntl(x, F_SETFL, fcntl(x, F_GETFL) | O_NONBLOCK)
61 std::map<int,SocketInfo>::iterator it;
62 for(it = sockets_.begin(); it != sockets_.end(); ++it) {
65 std::vector<int>::iterator it2;
66 for(it2 = tcpServers_.begin(); it2 != tcpServers_.end(); ++it2) {
69 for(it2 = localServers_.begin(); it2 != localServers_.end(); ++it2) {
75 fd_set sockets, out_sockets;
77 struct timeval timeout;
79 FD_ZERO(&out_sockets);
80 std::vector<int>::iterator it;
81 for(it = tcpServers_.begin(); it != tcpServers_.end(); ++it) {
84 FD_SET(*it, &sockets);
86 for(it = localServers_.begin(); it != localServers_.end(); ++it) {
89 FD_SET(*it, &sockets);
91 std::map<int,SocketInfo>::iterator it2;
92 for(it2 = sockets_.begin(); it2 != sockets_.end(); ++it2) {
93 if(it2->first > highest)
95 FD_SET(it2->first, &sockets);
98 std::vector<Network*>::const_iterator nit;
99 for(nit = dazeus_->networks().begin(); nit != dazeus_->networks().end(); ++nit) {
100 if((*nit)->activeServer()) {
102 (*nit)->addDescriptors(&sockets, &out_sockets, &ircmaxfd);
103 if(ircmaxfd > highest)
107 timeout.tv_sec = timeout_sec;
109 int socks = select(highest + 1, &sockets, &out_sockets, NULL, &timeout);
112 fprintf(stderr,
"select() failed: %s\n", strerror(errno));
122 else if(socks == 0) {
124 for(nit = dazeus_->networks().begin(); nit != dazeus_->networks().end(); ++nit) {
125 if((*nit)->activeServer()) {
126 (*nit)->checkTimeouts();
131 for(it = tcpServers_.begin(); it != tcpServers_.end(); ++it) {
132 if(FD_ISSET(*it, &sockets)) {
137 for(it = localServers_.begin(); it != localServers_.end(); ++it) {
138 if(FD_ISSET(*it, &sockets)) {
139 newLocalConnection();
143 for(it2 = sockets_.begin(); it2 != sockets_.end(); ++it2) {
144 if(FD_ISSET(it2->first, &sockets)) {
149 for(nit = dazeus_->networks().begin(); nit != dazeus_->networks().end(); ++nit) {
150 if((*nit)->activeServer()) {
151 (*nit)->processDescriptors(&sockets, &out_sockets);
152 (*nit)->checkTimeouts();
158 std::vector<SocketConfig*>::const_iterator it;
160 for(it = config_->getSockets().begin(); it != config_->getSockets().end(); ++it) {
162 if(sc->
type ==
"unix") {
163 unlink(sc->
path.c_str());
164 int server = ::socket(AF_UNIX, SOCK_STREAM, 0);
166 fprintf(stderr,
"(PluginComm) Failed to create socket at %s: %s\n", sc->
path.c_str(), strerror(errno));
170 struct sockaddr_un addr;
171 addr.sun_family = AF_UNIX;
172 strcpy(addr.sun_path, sc->
path.c_str());
173 if(bind(server, (
struct sockaddr*) &addr,
sizeof(
struct sockaddr_un)) < 0) {
175 fprintf(stderr,
"(PluginComm) Failed to start listening for local connections on %s: %s\n", sc->
path.c_str(), strerror(errno));
178 if(listen(server, 5) < 0) {
180 unlink(sc->
path.c_str());
185 localServers_.push_back(server);
186 }
else if(sc->
type ==
"tcp") {
189 std::stringstream portStrSs;
190 portStrSs << sc->
port;
191 portStr = portStrSs.str();
194 struct addrinfo *hints, *result;
195 hints = (
struct addrinfo*)calloc(1,
sizeof(
struct addrinfo));
197 hints->ai_family = AF_INET;
198 hints->ai_socktype = SOCK_STREAM;
199 hints->ai_protocol = 0;
201 int s = getaddrinfo(sc->
host.c_str(), portStr.c_str(), hints, &result);
206 fprintf(stderr,
"(PluginComm) Failed to resolve TCP address: %s\n", (
char*)gai_strerror(s));
210 int server = ::socket(AF_INET, SOCK_STREAM, 0);
212 fprintf(stderr,
"(PluginComm) Failed to create socket: %s\n", strerror(errno));
216 if(bind(server, result->ai_addr, result->ai_addrlen) < 0) {
218 fprintf(stderr,
"(PluginComm) Failed to start listening for TCP connections on %s:%d: %s\n",
219 sc->
host.c_str(), sc->
port, strerror(errno));
221 if(listen(server, 5) < 0) {
226 if(result->ai_family == AF_INET) {
227 sockaddr_in *addr = (sockaddr_in*)result->ai_addr;
228 if(addr->sin_addr.s_addr == INADDR_ANY) {
229 sc->
host =
"127.0.0.1";
233 tcpServers_.push_back(server);
235 fprintf(stderr,
"(PluginComm) Skipping socket: unknown type >%s<\n", sc->
type.c_str());
240 void dazeus::PluginComm::newTcpConnection() {
241 std::vector<int>::iterator it;
242 for(it = tcpServers_.begin(); it != tcpServers_.end(); ++it) {
244 int sock = accept(*it, NULL, NULL);
246 if(errno != EWOULDBLOCK)
247 fprintf(stderr,
"Error on listening socket: %s\n", strerror(errno));
251 sockets_[sock] = SocketInfo(
"tcp");
252 assert(!sockets_[sock].didHandshake());
257 void dazeus::PluginComm::newLocalConnection() {
258 std::vector<int>::iterator it;
259 for(it = localServers_.begin(); it != localServers_.end(); ++it) {
261 int sock = accept(*it, NULL, NULL);
263 if(errno != EWOULDBLOCK)
264 fprintf(stderr,
"Error on listening socket: %s\n", strerror(errno));
268 sockets_[sock] = SocketInfo(
"unix");
269 assert(!sockets_[sock].didHandshake());
274 void dazeus::PluginComm::poll() {
275 std::vector<int> toRemove;
276 std::map<int,SocketInfo>::iterator it;
277 for(it = sockets_.begin(); it != sockets_.end(); ++it) {
279 SocketInfo info = it->second;
282 struct pollfd fds[1];
284 fds[0].events = fds[0].revents = 0;
285 if(::poll(fds, 1, 0) == -1) {
286 perror(
"Failed to check socket error state");
288 toRemove.push_back(dev);
290 }
else if(fds[0].revents & POLLERR || fds[0].revents & POLLHUP) {
292 toRemove.push_back(dev);
296 bool appended =
false;
298 char *readahead = (
char*)malloc(512);
299 ssize_t r = read(dev, readahead, 512);
303 toRemove.push_back(dev);
306 if(errno != EWOULDBLOCK) {
307 fprintf(stderr,
"Socket error: %s\n", strerror(errno));
309 toRemove.push_back(dev);
315 info.readahead.append(readahead, r);
322 parsedPacket =
false;
323 if(info.waitingSize == 0) {
325 std::string waitingSize;
327 for(j = 0; j < info.readahead.size(); ++j) {
328 if(isdigit(info.readahead[j])) {
329 s << info.readahead[j];
330 }
else if(info.readahead[j] ==
'{') {
334 info.waitingSize = waitingSize;
339 if(info.waitingSize != 0)
340 info.readahead = info.readahead.substr(j);
342 if(info.waitingSize != 0) {
343 if((
signed)info.readahead.length() >= info.waitingSize) {
344 std::string packet = info.readahead.substr(0, info.waitingSize);
345 info.readahead = info.readahead.substr(info.waitingSize);
346 handle(dev, packet, info);
347 info.waitingSize = 0;
351 }
while(parsedPacket);
355 std::vector<int>::iterator toRemoveIt;
356 for(toRemoveIt = toRemove.begin(); toRemoveIt != toRemove.end(); ++toRemoveIt) {
357 sockets_.erase(*toRemoveIt);
362 std::map<int,SocketInfo>::iterator it;
363 for(it = sockets_.begin(); it != sockets_.end(); ++it) {
364 SocketInfo &info = it->second;
365 if(info.isSubscribed(event)) {
366 info.dispatch(it->first, event, parameters);
371 void dazeus::PluginComm::flushCommandQueue(
const std::string &nick,
bool identified) {
372 std::vector<Command*>::iterator cit;
373 for(cit = commandQueue_.begin(); cit != commandQueue_.end(); ++cit) {
382 bool whoisRequired =
false;
383 std::map<int,SocketInfo>::iterator it;
384 for(it = sockets_.begin(); it != sockets_.end(); ++it) {
385 SocketInfo &info = it->second;
386 if(info.commandMightNeedWhois(cmd->command)
387 && !cmd->network.isIdentified(cmd->origin)) {
388 whoisRequired =
true;
394 if(whoisRequired && nick != cmd->origin) {
395 if(!cmd->whoisSent) {
396 cmd->network.sendWhois(cmd->origin);
397 cmd->whoisSent =
true;
405 assert(!whoisRequired || cmd->network.isIdentified(cmd->origin)
406 || nick == cmd->origin);
408 std::vector<std::string> parameters;
409 parameters.push_back(cmd->network.networkName());
410 parameters.push_back(cmd->origin);
411 parameters.push_back(cmd->channel);
412 parameters.push_back(cmd->command);
413 parameters.push_back(cmd->fullArgs);
414 for(std::vector<std::string>::const_iterator itt = cmd->args.begin(); itt != cmd->args.end(); ++itt) {
415 parameters.push_back(*itt);
418 for(it = sockets_.begin(); it != sockets_.end(); ++it) {
419 SocketInfo &info = it->second;
420 if(!info.isSubscribedToCommand(cmd->command, cmd->channel, cmd->origin,
421 cmd->network.isIdentified(cmd->origin) || identified, cmd->network)) {
426 info.dispatch(it->first,
"COMMAND", parameters);
429 cit = commandQueue_.erase(cit);
435 void dazeus::PluginComm::messageReceived(
const std::string &origin,
const std::string &message,
436 const std::string &receiver, Network *n ) {
439 GlobalConfig *c = config_->getGlobalConfig();
442 if(
startsWith(message, n->nick() +
":",
true)
443 ||
startsWith(message, n->nick() +
",",
true)) {
444 payload =
trim(message.substr(n->nick().length() + 1));
445 }
else if(
startsWith(message, c->highlight,
true)) {
446 payload =
trim(message.substr(c->highlight.length()));
449 if(payload.length() != 0) {
451 bool inQuoteArg =
false;
452 bool inEscape =
false;
453 bool hasCommand =
false;
454 std::vector<std::string> args;
455 std::string stringBuilder;
456 std::string fullArgs;
458 for(
unsigned i = 0; i < payload.length(); ++i) {
460 fullArgs += payload.at(i);
463 stringBuilder += payload.at(i);
464 }
else if(payload.at(i) ==
'\\') {
466 }
else if(!inQuoteArg && payload.at(i) ==
' ') {
468 args.push_back(stringBuilder);
469 stringBuilder.clear();
471 }
else if(payload.at(i) ==
'"') {
472 inQuoteArg = !inQuoteArg;
474 stringBuilder += payload.at(i);
477 if(stringBuilder.length() != 0)
478 args.push_back(stringBuilder);
480 if(args.size() > 0) {
481 const std::string command = args.front();
482 args.erase(args.begin());
484 Command *cmd =
new Command(*n);
485 cmd->origin = origin;
486 cmd->channel = receiver;
487 cmd->command = command;
488 cmd->fullArgs =
trim(fullArgs);
490 commandQueue_.push_back(cmd);
494 std::vector<std::string> args;
495 args << n->networkName() << origin << receiver << message << (n->isIdentified(origin) ?
"true" :
"false");
496 dispatch(
"PRIVMSG", args);
501 std::vector<std::string> args;
503 #define MIN(a) if(params.size() < a) { fprintf(stderr, "Too few parameters for event %s (%lu)\n", event.c_str(), params.size()); return; }
504 if(event ==
"PRIVMSG") {
506 messageReceived(origin, params[1], params[0], n);
507 }
else if(event ==
"NOTICE") {
509 args << origin << params[0] << params[1] << (n->
isIdentified(origin) ?
"true" :
"false");
510 dispatch(
"NOTICE", args);
511 }
else if(event ==
"MODE" || event ==
"UMODE") {
513 args << origin << params;
514 dispatch(
"MODE", args);
515 }
else if(event ==
"NICK") {
517 args << origin << params[0];
518 dispatch(
"NICK", args);
519 }
else if(event ==
"JOIN") {
521 args << origin << params[0];
522 dispatch(
"JOIN", args);
523 }
else if(event ==
"PART") {
526 if(params.size() == 2)
528 args << origin << params[0] << message;
529 dispatch(
"PART", args);
530 }
else if(event ==
"KICK") {
532 std::string nick = params[1];
534 if(params.size() == 3)
536 args << origin << params[0] << nick << message;
537 dispatch(
"KICK", args);
538 }
else if(event ==
"INVITE") {
540 std::string channel = params[1];
541 args << origin << channel;
542 dispatch(
"INVITE", args);
543 }
else if(event ==
"QUIT") {
545 if(params.size() == 1)
547 args << origin << message;
548 dispatch(
"QUIT", args);
549 }
else if(event ==
"TOPIC") {
552 if(params.size() > 1)
554 args << origin << params[0] << topic;
555 dispatch(
"TOPIC", args);
556 }
else if(event ==
"CONNECT") {
557 dispatch(
"CONNECT", args);
558 }
else if(event ==
"DISCONNECT") {
559 dispatch(
"DISCONNECT", args);
560 }
else if(event ==
"CTCP_REQ" || event ==
"CTCP") {
565 std::string to = n->
nick();
566 args << origin << to << params[0];
567 dispatch(
"CTCP", args);
568 }
else if(event ==
"CTCP_REP") {
571 std::string to = n->
nick();
572 args << origin << to << params[0];
573 dispatch(
"CTCP_REP", args);
574 }
else if(event ==
"CTCP_ACTION" || event ==
"ACTION") {
577 if(params.size() >= 2)
579 args << origin << params[0] << message;
580 dispatch(
"ACTION", args);
581 }
else if(event ==
"WHOIS") {
583 args << origin << params[0] << params[1];
584 dispatch(
"WHOIS", args);
585 flushCommandQueue(params[0], params[1] ==
"true");
586 }
else if(event ==
"NAMES") {
588 args << origin << params;
589 dispatch(
"NAMES", args);
590 }
else if(event ==
"NUMERIC") {
592 args << origin << params[0] << params;
593 dispatch(
"NUMERIC", args);
594 }
else if(event ==
"ACTION_ME" || event ==
"CTCP_ME" || event ==
"PRIVMSG_ME") {
596 args << origin << params;
597 dispatch(event, args);
598 }
else if(event ==
"PONG") {
599 args << origin << params;
600 dispatch(event, args);
602 fprintf(stderr,
"Unknown event: \"%s\" \"%s\" \"%s\"\n",
Network::toString(n).c_str(), event.c_str(), origin.c_str());
603 args << origin << params[0] <<
event << params;
604 dispatch(
"UNKNOWN", args);
609 void dazeus::PluginComm::handle(
int dev,
const std::string &line, SocketInfo &info) {
610 const std::vector<Network*> &networks = dazeus_->networks();
611 std::vector<Network*>::const_iterator nit;
614 json_t *n = json_loads(line.c_str(), 0, &error);
616 fprintf(stderr,
"Got incorrect JSON, ignoring: %s\n", error.text);
620 std::vector<std::string> params;
621 std::vector<std::string> scope;
624 json_t *jParams = json_object_get(n,
"params");
626 if(!json_is_array(jParams)) {
627 fprintf(stderr,
"Got params, but of the wrong type, ignoring\n");
629 for(
unsigned i = 0; i < json_array_size(jParams); ++i) {
630 json_t *v = json_array_get(jParams, i);
631 std::stringstream value;
632 switch(json_typeof(v)) {
633 case JSON_STRING: value << json_string_value(v);
break;
634 case JSON_INTEGER: value << json_integer_value(v);
break;
635 case JSON_REAL: value << json_real_value(v);
break;
636 case JSON_TRUE: value <<
"true";
break;
637 case JSON_FALSE: value <<
"false";
break;
638 default: std::cerr <<
"Param " << i <<
" is of wrong type, ignoring\n";
640 params.push_back(value.str());
645 json_t *jScope = json_object_get(n,
"scope");
647 if(!json_is_array(jScope)) {
648 fprintf(stderr,
"Got scope, but of the wrong type, ignoring\n");
650 for(
unsigned int i = 0; i < json_array_size(jScope); ++i) {
651 json_t *v = json_array_get(jScope, i);
652 scope.push_back(json_is_string(v) ? json_string_value(v) :
"");
657 json_t *jAction = json_object_get(n,
"get");
659 jAction = json_object_get(n,
"do");
661 if(!json_is_string(jAction)) {
662 fprintf(stderr,
"Got action, but of the wrong type, ignoring\n");
664 action = json_string_value(jAction);
668 json_t *response = json_object();
670 if(action ==
"networks") {
671 json_object_set_new(response,
"got", json_string(
"networks"));
672 json_object_set_new(response,
"success", json_true());
673 json_t *nets = json_array();
674 for(nit = networks.begin(); nit != networks.end(); ++nit) {
675 json_array_append_new(nets, json_string((*nit)->networkName().c_str()));
677 json_object_set_new(response,
"networks", nets);
678 }
else if(action ==
"handshake") {
679 json_object_set_new(response,
"did", json_string(
"handshake"));
680 if(info.didHandshake()) {
681 json_object_set_new(response,
"success", json_false());
682 json_object_set_new(response,
"error", json_string(
"Already did handshake"));
683 }
else if(params.size() < 4) {
684 json_object_set_new(response,
"success", json_false());
685 json_object_set_new(response,
"error", json_string(
"Missing parameters"));
686 }
else if(params[2] !=
"1") {
687 json_object_set_new(response,
"succes", json_false());
688 json_object_set_new(response,
"error", json_string(
"Protocol version must be '1'"));
690 json_object_set_new(response,
"success", json_true());
691 info.plugin_name = params[0];
692 info.plugin_version = params[1];
693 std::stringstream version(params[2]);
694 version >> info.protocol_version;
695 info.config_group = params[3];
696 std::cout <<
"Plugin handshake: " << info.plugin_name <<
" v"
697 << info.plugin_version <<
" (protocol version "
698 << info.protocol_version <<
", config group "
699 << info.config_group <<
")" << std::endl;
702 }
else if(action ==
"channels" || action ==
"whois" || action ==
"join" || action ==
"part"
703 || action ==
"nick") {
704 if(action ==
"channels" || action ==
"nick") {
705 json_object_set_new(response,
"got", json_string(action.c_str()));
707 json_object_set_new(response,
"did", json_string(action.c_str()));
709 std::string network =
"";
710 if(params.size() > 0) {
713 json_object_set_new(response,
"network", json_string(network.c_str()));
715 for(nit = networks.begin(); nit != networks.end(); ++nit) {
716 if((*nit)->networkName() == network) {
721 json_object_set_new(response,
"success", json_false());
722 json_object_set_new(response,
"error", json_string(
"Not on that network"));
724 if(action ==
"channels") {
725 json_object_set_new(response,
"success", json_true());
726 json_t *chans = json_array();
727 const std::vector<std::string> &channels = net->joinedChannels();
728 for(
unsigned i = 0; i < channels.size(); ++i) {
729 json_array_append_new(chans, json_string(channels[i].c_str()));
731 json_object_set_new(response,
"channels", chans);
732 }
else if(action ==
"whois" || action ==
"join" || action ==
"part") {
733 if(params.size() < 2) {
734 json_object_set_new(response,
"success", json_false());
735 json_object_set_new(response,
"error", json_string(
"Missing parameters"));
737 json_object_set_new(response,
"success", json_true());
738 if(action ==
"whois") {
739 net->sendWhois(params[1]);
740 }
else if(action ==
"join") {
741 net->joinChannel(params[1]);
742 }
else if(action ==
"part") {
743 net->leaveChannel(params[1]);
749 }
else if(action ==
"nick") {
750 json_object_set_new(response,
"success", json_true());
751 json_object_set_new(response,
"nick", json_string(net->nick().c_str()));
758 }
else if(action ==
"message" || action ==
"action" || action ==
"names") {
759 json_object_set_new(response,
"did", json_string(action.c_str()));
760 if(params.size() < 2 || (action !=
"names" && params.size() < 3)) {
761 fprintf(stderr,
"Wrong parameter size for message, skipping.\n");
764 std::string network = params[0];
765 std::string receiver = params[1];
767 if(action !=
"names") {
770 json_object_set_new(response,
"network", json_string(network.c_str()));
771 if(action ==
"names") {
772 json_object_set_new(response,
"channel", json_string(receiver.c_str()));
774 json_object_set_new(response,
"receiver", json_string(receiver.c_str()));
775 json_object_set_new(response,
"message", json_string(message.c_str()));
778 bool netfound =
false;
779 for(nit = networks.begin(); nit != networks.end(); ++nit) {
781 if(n->networkName() == network) {
784 json_object_set_new(response,
"success", json_true());
785 if(action ==
"names") {
787 }
else if(action ==
"message") {
788 n->say(receiver, message);
790 n->action(receiver, message);
793 fprintf(stderr,
"Request for communication to network %s receiver %s, but not in that channel, dropping\n",
794 network.c_str(), receiver.c_str());
795 json_object_set_new(response,
"success", json_false());
796 json_object_set_new(response,
"error", json_string(
"Not in that channel"));
802 fprintf(stderr,
"Request for communication to network %s, but that network isn't joined, dropping\n", network.c_str());
803 json_object_set_new(response,
"success", json_false());
804 json_object_set_new(response,
"error", json_string(
"Not on that network"));
807 }
else if(action ==
"subscribe") {
808 json_object_set_new(response,
"did", json_string(
"subscribe"));
809 json_object_set_new(response,
"success", json_true());
811 std::vector<std::string>::const_iterator pit;
812 for(pit = params.begin(); pit != params.end(); ++pit) {
813 if(info.subscribe(*pit))
816 json_object_set_new(response,
"added", json_integer(added));
817 }
else if(action ==
"unsubscribe") {
818 json_object_set_new(response,
"did", json_string(
"unsubscribe"));
819 json_object_set_new(response,
"success", json_true());
821 std::vector<std::string>::const_iterator pit;
822 for(pit = params.begin(); pit != params.end(); ++pit) {
823 if(info.unsubscribe(*pit))
826 json_object_set_new(response,
"removed", json_integer(removed));
827 }
else if(action ==
"command") {
828 json_object_set_new(response,
"did", json_string(
"command"));
833 if(params.size() == 0) {
834 json_object_set_new(response,
"success", json_false());
835 json_object_set_new(response,
"error", json_string(
"Missing parameters"));
837 std::string commandName = params.front();
838 params.erase(params.begin());
839 RequirementInfo *req = 0;
841 if(params.size() > 0) {
842 for(nit = networks.begin(); nit != networks.end(); ++nit) {
843 if((*nit)->networkName() == params.at(0)) {
848 if(params.size() == 0) {
850 req =
new RequirementInfo();
851 }
else if(params.size() == 1) {
853 req =
new RequirementInfo(net);
854 }
else if(params.size() == 3) {
856 bool isSender = params.at(1) ==
"true";
857 req =
new RequirementInfo(net, params.at(2), isSender);
859 json_object_set_new(response,
"success", json_false());
860 json_object_set_new(response,
"error", json_string(
"Wrong number of parameters"));
863 info.subscribeToCommand(commandName, req);
864 json_object_set_new(response,
"success", json_true());
867 }
else if(action ==
"property") {
868 json_object_set_new(response,
"did", json_string(
"property"));
870 std::string network, receiver, sender;
871 switch(scope.size()) {
873 case 3: sender = scope[2];
874 case 2: receiver = scope[1];
875 case 1: network = scope[0];
879 if(params.size() < 2) {
880 json_object_set_new(response,
"success", json_false());
881 json_object_set_new(response,
"error", json_string(
"Missing parameters"));
882 }
else if(params[0] ==
"get") {
883 std::string value = database_->property(params[1], network, receiver, sender);
884 json_object_set_new(response,
"success", json_true());
885 json_object_set_new(response,
"variable", json_string(params[1].c_str()));
886 if(value.length() > 0) {
887 json_object_set_new(response,
"value", json_string(value.c_str()));
889 }
else if(params[0] ==
"set") {
890 if(params.size() < 3) {
891 json_object_set_new(response,
"success", json_false());
892 json_object_set_new(response,
"error", json_string(
"Missing parameters"));
894 database_->setProperty(params[1], params[2], network, receiver, sender);
895 json_object_set_new(response,
"success", json_true());
897 }
else if(params[0] ==
"unset") {
898 if(params.size() < 2) {
899 json_object_set_new(response,
"success", json_false());
900 json_object_set_new(response,
"error", json_string(
"Missing parameters"));
902 database_->setProperty(params[1], std::string(), network, receiver, sender);
903 json_object_set_new(response,
"success", json_true());
905 }
else if(params[0] ==
"keys") {
906 std::vector<std::string> pKeys = database_->propertyKeys(params[1], network, receiver, sender);
907 json_t *keys = json_array();
908 std::vector<std::string>::iterator kit;
909 for(kit = pKeys.begin(); kit != pKeys.end(); ++kit) {
910 json_array_append_new(keys, json_string(kit->c_str()));
912 json_object_set_new(response,
"keys", keys);
913 json_object_set_new(response,
"success", json_true());
915 json_object_set_new(response,
"success", json_false());
916 json_object_set_new(response,
"error", json_string(
"Did not understand request"));
918 }
else if(action ==
"config") {
919 json_object_set_new(response,
"got", json_string(
"config"));
920 if(params.size() != 2) {
921 json_object_set_new(response,
"success", json_false());
922 json_object_set_new(response,
"error", json_string(
"Missing parameters"));
924 std::string configtype = params[0];
925 std::string configvar = params[1];
927 if(configtype ==
"plugin" && !info.didHandshake()) {
928 json_object_set_new(response,
"success", json_false());
929 json_object_set_new(response,
"error", json_string(
"Need to do handshake for retrieving plugin configuration"));
930 }
else if(configtype ==
"plugin") {
931 json_object_set_new(response,
"success", json_true());
932 json_object_set_new(response,
"group", json_string(configtype.c_str()));
933 json_object_set_new(response,
"variable", json_string(configvar.c_str()));
936 const std::vector<PluginConfig*> &plugins = config_->getPlugins();
937 for(std::vector<PluginConfig*>::const_iterator cit = plugins.begin(); cit != plugins.end(); ++cit) {
938 PluginConfig *pc = *cit;
939 if(pc->name == info.config_group) {
940 std::map<std::string,std::string>::iterator configIt = pc->config.find(configvar);
941 if(configIt != pc->config.end()) {
942 json_object_set_new(response,
"value", json_string(configIt->second.c_str()));
947 }
else if(configtype ==
"core") {
948 GlobalConfig *global = config_->getGlobalConfig();
949 json_object_set_new(response,
"success", json_true());
950 json_object_set_new(response,
"group", json_string(configtype.c_str()));
951 json_object_set_new(response,
"variable", json_string(configvar.c_str()));
952 if(configvar ==
"nickname") {
953 json_object_set_new(response,
"value", json_string(global->default_nickname.c_str()));
954 }
else if(configvar ==
"username") {
955 json_object_set_new(response,
"value", json_string(global->default_username.c_str()));
956 }
else if(configvar ==
"fullname") {
957 json_object_set_new(response,
"value", json_string(global->default_fullname.c_str()));
958 }
else if(configvar ==
"highlight") {
959 json_object_set_new(response,
"value", json_string(global->highlight.c_str()));
962 json_object_set_new(response,
"success", json_false());
963 json_object_set_new(response,
"error", json_string(
"Unrecognised config group"));
967 json_object_set_new(response,
"success", json_false());
968 json_object_set_new(response,
"error", json_string(
"Did not understand request"));
971 char *raw_json = json_dumps(response, 0);
972 std::string jsonMsg = raw_json;
974 std::stringstream mstr;
975 mstr << jsonMsg.length();
978 std::string finalResponse = mstr.str();
979 if(write(dev, finalResponse.c_str(), finalResponse.length()) != (
unsigned)finalResponse.length()) {
980 fprintf(stderr,
"Failed to write correct number of JSON bytes to client socket.\n");
985 json_decref(response);