+ SilcServerCommandContext cmd = query->cmd;
+ SilcUInt16 ident = silc_command_get_ident(cmd->payload);
+ SilcStatus status;
+ unsigned char *tmp;
+ SilcUInt32 len;
+ SilcBuffer idp;
+ int i, k, valid_count;
+ char nh[256], uh[256];
+
+ SILC_LOG_DEBUG(("Sending reply to query"));
+
+ status = SILC_STATUS_OK;
+
+ /* Send clients */
+ if (clients_count) {
+ SilcClientEntry entry;
+ SilcSocketConnection hsock;
+
+ /* Mark all invalid entries */
+ for (i = 0, valid_count = 0; i < clients_count; i++) {
+ entry = clients[i];
+ switch (query->querycmd) {
+ case SILC_COMMAND_WHOIS:
+ if (!entry->nickname || !entry->username || !entry->userinfo ||
+ !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
+ /* When querying by ID, every "unfound" entry must cause error */
+ if (query->ids)
+ silc_server_query_add_error_id(server, query,
+ SILC_STATUS_ERR_TIMEDOUT,
+ entry->id, SILC_ID_CLIENT);
+ clients[i] = NULL;
+ continue;
+ }
+ break;
+
+ case SILC_COMMAND_IDENTIFY:
+ if (!entry->nickname ||
+ !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
+ /* When querying by ID, every "unfound" entry must cause error */
+ if (query->ids)
+ silc_server_query_add_error_id(server, query,
+ SILC_STATUS_ERR_TIMEDOUT,
+ entry->id, SILC_ID_CLIENT);
+ clients[i] = NULL;
+ continue;
+ }
+ break;
+
+ case SILC_COMMAND_WHOWAS:
+ if (!entry->nickname || !entry->username ||
+ entry->data.status & SILC_IDLIST_STATUS_REGISTERED) {
+ clients[i] = NULL;
+ continue;
+ }
+ break;
+ }
+ valid_count++;
+ }
+
+ /* Start processing found clients */
+ status = SILC_STATUS_OK;
+ if (valid_count > 1)
+ status = SILC_STATUS_LIST_START;
+
+ /* Now do the sending of valid entries */
+ k = 0;
+ for (i = 0; i < clients_count && valid_count; i++) {
+ entry = clients[i];
+ if (!entry)
+ continue;
+
+ if (k >= 1)
+ status = SILC_STATUS_LIST_ITEM;
+ if (valid_count > 1 && k == valid_count - 1
+ && !servers_count && !channels_count && !query->errors_count)
+ status = SILC_STATUS_LIST_END;
+ if (query->reply_count && k - 1 == query->reply_count)
+ status = SILC_STATUS_LIST_END;
+
+ SILC_LOG_DEBUG(("%s: client %s",
+ (status == SILC_STATUS_OK ? " OK" :
+ status == SILC_STATUS_LIST_START ? "START" :
+ status == SILC_STATUS_LIST_ITEM ? " ITEM" :
+ status == SILC_STATUS_LIST_END ? " END" :
+ " : "), entry->nickname));
+
+ idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
+ memset(uh, 0, sizeof(uh));
+ memset(nh, 0, sizeof(nh));
+
+ silc_strncat(nh, sizeof(nh), entry->nickname, strlen(entry->nickname));
+ if (!strchr(entry->nickname, '@')) {
+ silc_strncat(nh, sizeof(nh), "@", 1);
+ if (entry->servername) {
+ silc_strncat(nh, sizeof(nh), entry->servername,
+ strlen(entry->servername));
+ } else {
+ len = entry->router ? strlen(entry->router->server_name) :
+ strlen(server->server_name);
+ silc_strncat(nh, sizeof(nh), entry->router ?
+ entry->router->server_name :
+ server->server_name, len);
+ }
+ }
+
+ switch (query->querycmd) {
+
+ case SILC_COMMAND_WHOIS:
+ {
+ unsigned char idle[4], mode[4];
+ unsigned char *fingerprint, fempty[20];
+ SilcBuffer channels, umode_list = NULL;
+
+ memset(fempty, 0, sizeof(fempty));
+ silc_strncat(uh, sizeof(uh), entry->username,
+ strlen(entry->username));
+ if (!strchr(entry->username, '@') && entry->connection) {
+ hsock = entry->connection;
+ silc_strncat(uh, sizeof(uh), "@", 1);
+ len = strlen(hsock->hostname);
+ silc_strncat(uh, sizeof(uh), hsock->hostname, len);
+ }
+
+ if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
+ channels =
+ silc_server_get_client_channel_list(server, entry, FALSE,
+ FALSE, &umode_list);
+ else
+ channels =
+ silc_server_get_client_channel_list(server, entry, TRUE,
+ TRUE, &umode_list);
+
+ if (memcmp(entry->data.fingerprint, fempty, sizeof(fempty)))
+ fingerprint = entry->data.fingerprint;
+ else
+ fingerprint = NULL;
+
+ SILC_PUT32_MSB(entry->mode, mode);
+ if (entry->connection)
+ SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
+
+ /* Send command reply */
+ silc_server_send_command_reply(server, cmd->sock, query->querycmd,
+ status, 0, ident, 9,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh),
+ 4, uh, strlen(uh),
+ 5, entry->userinfo,
+ strlen(entry->userinfo),
+ 6, channels ? channels->data : NULL,
+ channels ? channels->len : 0,
+ 7, mode, 4,
+ 8, idle, 4,
+ 9, fingerprint,
+ fingerprint ? 20 : 0,
+ 10, umode_list ? umode_list->data :
+ NULL, umode_list ? umode_list->len :
+ 0);
+
+ if (channels)
+ silc_buffer_free(channels);
+ if (umode_list) {
+ silc_buffer_free(umode_list);
+ umode_list = NULL;
+ }
+ }
+ break;
+
+ case SILC_COMMAND_IDENTIFY:
+ if (!entry->username) {
+ silc_server_send_command_reply(server, cmd->sock, query->querycmd,
+ status, 0, ident, 2,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh));
+ } else {
+ silc_strncat(uh, sizeof(uh), entry->username,
+ strlen(entry->username));
+ if (!strchr(entry->username, '@') && entry->connection) {
+ hsock = entry->connection;
+ silc_strncat(uh, sizeof(uh), "@", 1);
+ len = strlen(hsock->hostname);
+ silc_strncat(uh, sizeof(uh), hsock->hostname, len);
+ }
+
+ silc_server_send_command_reply(server, cmd->sock, query->querycmd,
+ status, 0, ident, 3,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh),
+ 4, uh, strlen(uh));
+ }
+ break;
+
+ case SILC_COMMAND_WHOWAS:
+ silc_strncat(uh, sizeof(uh), entry->username, strlen(entry->username));
+ if (!strchr(entry->username, '@'))
+ silc_strncat(uh, sizeof(uh), "@*private*", 10);
+
+ /* Send command reply */
+ silc_server_send_command_reply(server, cmd->sock, query->querycmd,
+ status, 0, ident, 4,
+ 2, idp->data, idp->len,
+ 3, nh, strlen(nh),
+ 4, uh, strlen(uh),
+ 5, entry->userinfo,
+ entry->userinfo ?
+ strlen(entry->userinfo) : 0);
+ break;
+ }
+
+ silc_buffer_free(idp);