diff options
author | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-10-12 14:18:20 +0000 |
---|---|---|
committer | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-10-12 14:18:20 +0000 |
commit | 0ecadfc45326fce5fc4ba28b27a0a7ad484e5b84 (patch) | |
tree | fef68e6433f39bd8d51e0718f0de8ea425e52be3 /protocols/Gadu-Gadu/core.cpp | |
parent | ef1f6f8fac28594a151c4cd811d1590cfc7ff81d (diff) |
Gadu-Gadu: folders restructurization
git-svn-id: http://svn.miranda-ng.org/main/trunk@1888 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/Gadu-Gadu/core.cpp')
-rw-r--r-- | protocols/Gadu-Gadu/core.cpp | 1756 |
1 files changed, 0 insertions, 1756 deletions
diff --git a/protocols/Gadu-Gadu/core.cpp b/protocols/Gadu-Gadu/core.cpp deleted file mode 100644 index 63d5d37b24..0000000000 --- a/protocols/Gadu-Gadu/core.cpp +++ /dev/null @@ -1,1756 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////
-// Gadu-Gadu Plugin for Miranda IM
-//
-// Copyright (c) 2003-2009 Adam Strzelecki <ono+miranda@java.pl>
-// Copyright (c) 2009-2012 Bartosz Białek
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-////////////////////////////////////////////////////////////////////////////////
-
-#include "gg.h"
-#include <errno.h>
-#include <io.h>
-
-////////////////////////////////////////////////////////////
-// Swap bits in DWORD
-uint32_t swap32(uint32_t x)
-{
- return (uint32_t)
- (((x & (uint32_t) 0x000000ffU) << 24) |
- ((x & (uint32_t) 0x0000ff00U) << 8) |
- ((x & (uint32_t) 0x00ff0000U) >> 8) |
- ((x & (uint32_t) 0xff000000U) >> 24));
-}
-
-////////////////////////////////////////////////////////////
-// Is online function
-
-int GGPROTO::isonline()
-{
- mir_cslock lck(sess_mutex);
- return (sess != NULL);
-}
-
-////////////////////////////////////////////////////////////
-// Send disconnect request and wait for server thread to die
-void GGPROTO::disconnect()
-{
- // If main loop then send disconnect request
- if (isonline())
- {
- // Fetch proper status msg
- char *szMsg = NULL;
-
- // Loadup status
- if (db_get_b(NULL, m_szModuleName, GG_KEY_LEAVESTATUSMSG, GG_KEYDEF_LEAVESTATUSMSG))
- {
- DBVARIANT dbv;
- switch (db_get_w(NULL, m_szModuleName, GG_KEY_LEAVESTATUS, GG_KEYDEF_LEAVESTATUS)) {
- case ID_STATUS_ONLINE:
- EnterCriticalSection(&modemsg_mutex);
- szMsg = mir_strdup(modemsg.online);
- LeaveCriticalSection(&modemsg_mutex);
- if (!szMsg && !db_get_s(NULL, "SRAway", gg_status2db(ID_STATUS_ONLINE, "Default"), &dbv, DBVT_ASCIIZ)) {
- if (dbv.pszVal && *(dbv.pszVal))
- szMsg = mir_strdup(dbv.pszVal);
- DBFreeVariant(&dbv);
- }
- break;
- case ID_STATUS_AWAY:
- EnterCriticalSection(&modemsg_mutex);
- szMsg = mir_strdup(modemsg.away);
- LeaveCriticalSection(&modemsg_mutex);
- if (!szMsg && !db_get_s(NULL, "SRAway", gg_status2db(ID_STATUS_AWAY, "Default"), &dbv, DBVT_ASCIIZ)) {
- if (dbv.pszVal && *(dbv.pszVal))
- szMsg = mir_strdup(dbv.pszVal);
- DBFreeVariant(&dbv);
- }
- break;
- case ID_STATUS_DND:
- EnterCriticalSection(&modemsg_mutex);
- szMsg = mir_strdup(modemsg.dnd);
- LeaveCriticalSection(&modemsg_mutex);
- if (!szMsg && !db_get_s(NULL, "SRAway", gg_status2db(ID_STATUS_DND, "Default"), &dbv, DBVT_ASCIIZ)) {
- if (dbv.pszVal && *(dbv.pszVal))
- szMsg = mir_strdup(dbv.pszVal);
- DBFreeVariant(&dbv);
- }
- break;
- case ID_STATUS_FREECHAT:
- EnterCriticalSection(&modemsg_mutex);
- szMsg = mir_strdup(modemsg.freechat);
- LeaveCriticalSection(&modemsg_mutex);
- if (!szMsg && !db_get_s(NULL, "SRAway", gg_status2db(ID_STATUS_FREECHAT, "Default"), &dbv, DBVT_ASCIIZ)) {
- if (dbv.pszVal && *(dbv.pszVal))
- szMsg = mir_strdup(dbv.pszVal);
- DBFreeVariant(&dbv);
- }
- break;
- case ID_STATUS_INVISIBLE:
- EnterCriticalSection(&modemsg_mutex);
- szMsg = mir_strdup(modemsg.invisible);
- LeaveCriticalSection(&modemsg_mutex);
- if (!szMsg && !db_get_s(NULL, "SRAway", gg_status2db(ID_STATUS_INVISIBLE, "Default"), &dbv, DBVT_ASCIIZ)) {
- if (dbv.pszVal && *(dbv.pszVal))
- szMsg = mir_strdup(dbv.pszVal);
- DBFreeVariant(&dbv);
- }
- break;
- default:
- // Set last status
- EnterCriticalSection(&modemsg_mutex);
- szMsg = mir_strdup(getstatusmsg(m_iStatus));
- LeaveCriticalSection(&modemsg_mutex);
- }
- }
-
- EnterCriticalSection(&sess_mutex);
- // Check if it has message
- if (szMsg)
- {
- gg_change_status_descr(sess, GG_STATUS_NOT_AVAIL_DESCR, szMsg);
- mir_free(szMsg);
- // Wait for disconnection acknowledge
- }
- else
- {
- gg_change_status(sess, GG_STATUS_NOT_AVAIL);
- // Send logoff immediately
- gg_logoff(sess);
- }
- LeaveCriticalSection(&sess_mutex);
- }
- // Else cancel connection attempt
- else if (sock)
- closesocket(sock);
-}
-
-////////////////////////////////////////////////////////////
-// DNS lookup function
-uint32_t gg_dnslookup(GGPROTO *gg, char *host)
-{
- uint32_t ip;
- struct hostent *he;
-
- ip = inet_addr(host);
- if (ip != INADDR_NONE)
- {
-#ifdef DEBUGMODE
- gg->netlog("gg_dnslookup(): Parameter \"%s\" is already IP number.", host);
-#endif
- return ip;
- }
- he = gethostbyname(host);
- if (he)
- {
- ip = *(uint32_t *) he->h_addr_list[0];
-#ifdef DEBUGMODE
- gg->netlog("gg_dnslookup(): Parameter \"%s\" was resolved to %d.%d.%d.%d.", host,
- LOBYTE(LOWORD(ip)), HIBYTE(LOWORD(ip)), LOBYTE(HIWORD(ip)), HIBYTE(HIWORD(ip)));
-#endif
- return ip;
- }
- gg->netlog("gg_dnslookup(): Cannot resolve hostname \"%s\".", host);
- return 0;
-}
-
-////////////////////////////////////////////////////////////
-// Host list decoder
-typedef struct
-{
- char hostname[128];
- int port;
-} GGHOST;
-#define ISHOSTALPHA(a) (((a) >= '0' && (a) <= '9') || ((a) >= 'a' && (a) <= 'z') || (a) == '.' || (a) == '-')
-int gg_decodehosts(char *var, GGHOST *hosts, int max)
-{
- int hp = 0;
- char *hostname = NULL;
- char *portname = NULL;
-
- while(var && *var && hp < max)
- {
- if (ISHOSTALPHA(*var))
- {
- hostname = var;
-
- while(var && *var && ISHOSTALPHA(*var)) var ++;
-
- if (var && *var == ':' && var++ && *var && isdigit(*var))
- {
- *(var - 1) = 0;
- portname = var;
- while(var && *var && isdigit(*var)) var++;
- if (*var) { *var = 0; var ++; }
- }
- else
- if (*var) { *var = 0; var ++; }
-
- // Insert new item
- hosts[hp].hostname[127] = 0;
- strncpy(hosts[hp].hostname, hostname, 127);
- hosts[hp].port = portname ? atoi(portname) : 443;
- hp ++;
-
- // Zero the names
- hostname = NULL;
- portname = NULL;
- }
- else
- var ++;
- }
- return hp;
-}
-
-////////////////////////////////////////////////////////////
-// Main connection session thread
-void __cdecl GGPROTO::mainthread(void *)
-{
- // Miranda variables
- NETLIBUSERSETTINGS nlus = {0};
- DBVARIANT dbv;
- // Gadu-Gadu variables
- gg_login_params p = {0};
- gg_event *e;
- // Host cycling variables
- int hostnum = 0, hostcount = 0;
- GGHOST hosts[64];
- // Gadu-gadu login errors
- static const struct tagReason { int type; TCHAR *str; } reason[] = {
- { GG_FAILURE_RESOLVING, LPGENT("Miranda was unable to resolve the name of the Gadu-Gadu server to its numeric address.") },
- { GG_FAILURE_CONNECTING, LPGENT("Miranda was unable to make a connection with a server. It is likely that the server is down, in which case you should wait for a while and try again later.") },
- { GG_FAILURE_INVALID, LPGENT("Received invalid server response.") },
- { GG_FAILURE_READING, LPGENT("The connection with the server was abortively closed during the connection attempt. You may have lost your local network connection.") },
- { GG_FAILURE_WRITING, LPGENT("The connection with the server was abortively closed during the connection attempt. You may have lost your local network connection.") },
- { GG_FAILURE_PASSWORD, LPGENT("Your Gadu-Gadu number and password combination was rejected by the Gadu-Gadu server. Please check login details at M->Options->Network->Gadu-Gadu and try again.") },
- { GG_FAILURE_404, LPGENT("Connecting to Gadu-Gadu hub failed.") },
- { GG_FAILURE_TLS, LPGENT("Cannot establish secure connection.") },
- { GG_FAILURE_NEED_EMAIL, LPGENT("Server disconnected asking you for changing your e-mail.") },
- { GG_FAILURE_INTRUDER, LPGENT("Too many login attempts with invalid password.") },
- { GG_FAILURE_UNAVAILABLE, LPGENT("Gadu-Gadu servers are now down. Try again later.") },
- { 0, LPGENT("Unknown") }
- };
- time_t logonTime = 0;
- time_t timeDeviation = db_get_w(NULL, m_szModuleName, GG_KEY_TIMEDEVIATION, GG_KEYDEF_TIMEDEVIATION);
- int gg_failno = 0;
-
- netlog("gg_mainthread(%x): Server Thread Starting", this);
-#ifdef DEBUGMODE
- gg_debug_level = GG_DEBUG_NET | GG_DEBUG_TRAFFIC | GG_DEBUG_FUNCTION | GG_DEBUG_MISC;
-#else
- gg_debug_level = 0;
-#endif
-
- // Broadcast that service is connecting
- broadcastnewstatus(ID_STATUS_CONNECTING);
-
- // Client version and misc settings
- p.client_version = GG_DEFAULT_CLIENT_VERSION;
- p.protocol_version = GG_DEFAULT_PROTOCOL_VERSION;
- p.protocol_features = GG_FEATURE_DND_FFC | GG_FEATURE_UNKNOWN_100 | GG_FEATURE_USER_DATA | GG_FEATURE_MSG_ACK | GG_FEATURE_TYPING_NOTIFICATION | GG_FEATURE_MULTILOGON;
- p.encoding = GG_ENCODING_CP1250;
- p.status_flags = GG_STATUS_FLAG_UNKNOWN;
- if (db_get_b(NULL, m_szModuleName, GG_KEY_SHOWLINKS, GG_KEYDEF_SHOWLINKS))
- p.status_flags |= GG_STATUS_FLAG_SPAM;
-
- // Use audio
- /* p.has_audio = 1; */
-
- // Use async connections
- /* p.async = 1; */
-
- // Send Era Omnix info if set
- p.era_omnix = db_get_b(NULL, m_szModuleName, "EraOmnix", 0);
-
- // Setup proxy
- nlus.cbSize = sizeof(nlus);
- if (CallService(MS_NETLIB_GETUSERSETTINGS, (WPARAM)netlib, (LPARAM)&nlus))
- {
- if (nlus.useProxy)
- netlog("gg_mainthread(%x): Using proxy %s:%d.", this, nlus.szProxyServer, nlus.wProxyPort);
- gg_proxy_enabled = nlus.useProxy;
- gg_proxy_host = nlus.szProxyServer;
- gg_proxy_port = nlus.wProxyPort;
- if (nlus.useProxyAuth)
- {
- gg_proxy_username = nlus.szProxyAuthUser;
- gg_proxy_password = nlus.szProxyAuthPassword;
- }
- else
- gg_proxy_username = gg_proxy_password = NULL;
- }
- else
- {
- netlog("gg_mainthread(%x): Failed loading proxy settings.", this);
- gg_proxy_enabled = 0;
- }
-
- // Check out manual host setting
- if (db_get_b(NULL, m_szModuleName, GG_KEY_MANUALHOST, GG_KEYDEF_MANUALHOST))
- {
- if (!db_get_s(NULL, m_szModuleName, GG_KEY_SERVERHOSTS, &dbv, DBVT_ASCIIZ))
- {
- hostcount = gg_decodehosts(dbv.pszVal, hosts, 64);
- DBFreeVariant(&dbv);
- }
- }
-
- // Readup password
- if (!db_get_s(NULL, m_szModuleName, GG_KEY_PASSWORD, &dbv, DBVT_ASCIIZ))
- {
- CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal) + 1, (LPARAM) dbv.pszVal);
- p.password = mir_strdup(dbv.pszVal);
- DBFreeVariant(&dbv);
- }
- else
- {
- netlog("gg_mainthread(%x): No password specified. Exiting.", this);
- broadcastnewstatus(ID_STATUS_OFFLINE);
- return;
- }
-
- // Readup number
- if (!(p.uin = db_get_dw(NULL, m_szModuleName, GG_KEY_UIN, 0)))
- {
- netlog("gg_mainthread(%x): No Gadu-Gadu number specified. Exiting.", this);
- broadcastnewstatus(ID_STATUS_OFFLINE);
- mir_free(p.password);
- return;
- }
-
- // Readup SSL/TLS setting
- if (p.tls = db_get_b(NULL, m_szModuleName, GG_KEY_SSLCONN, GG_KEYDEF_SSLCONN))
- netlog("gg_mainthread(%x): Using TLS/SSL for connections.", this);
-
- // Gadu-Gadu accepts image sizes upto 255
- p.image_size = 255;
-
- ////////////////////////////// DCC STARTUP /////////////////////////////
- // Uin is ok so startup dcc if not started already
- if (!dcc)
- {
- hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- dccstart();
-
- // Wait for DCC
-#ifdef DEBUGMODE
- netlog("gg_mainthread(%x): Waiting DCC service to start...", this);
-#endif
- while (WaitForSingleObjectEx(hEvent, INFINITE, TRUE) != WAIT_OBJECT_0);
- CloseHandle(hEvent); hEvent = NULL;
- }
- // Check if dcc is running and setup forwarding port
- if (dcc && db_get_b(NULL, m_szModuleName, GG_KEY_FORWARDING, GG_KEYDEF_FORWARDING))
- {
- if (!db_get_s(NULL, m_szModuleName, GG_KEY_FORWARDHOST, &dbv, DBVT_ASCIIZ))
- {
- if (!(p.external_addr = gg_dnslookup(this, dbv.pszVal)))
- {
- TCHAR error[128];
- mir_sntprintf(error, SIZEOF(error), TranslateT("External direct connections hostname %S is invalid. Disabling external host forwarding."), dbv.pszVal);
- showpopup(m_tszUserName, error, GG_POPUP_WARNING | GG_POPUP_ALLOW_MSGBOX);
- }
- else
- netlog("gg_mainthread(%x): Loading forwarding host %s and port %d.", dbv.pszVal, p.external_port, this);
- if (p.external_addr) p.external_port = db_get_w(NULL, m_szModuleName, GG_KEY_FORWARDPORT, GG_KEYDEF_FORWARDPORT);
- DBFreeVariant(&dbv);
- }
- }
- // Setup client port
- if (dcc) p.client_port = dcc->port;
-
-retry:
- // Loadup startup status & description
- EnterCriticalSection(&modemsg_mutex);
- p.status_descr = mir_strdup(getstatusmsg(m_iDesiredStatus));
- p.status = status_m2gg(m_iDesiredStatus, p.status_descr != NULL);
-
- netlog("gg_mainthread(%x): Connecting with number %d, status %d and description \"%s\".", this, p.uin, m_iDesiredStatus,
- p.status_descr ? p.status_descr : "<none>");
- LeaveCriticalSection(&modemsg_mutex);
-
- // Check manual hosts
- if (hostnum < hostcount)
- {
- if (!(p.server_addr = gg_dnslookup(this, hosts[hostnum].hostname)))
- {
- TCHAR error[128];
- mir_sntprintf(error, SIZEOF(error), TranslateT("Server hostname %S is invalid. Using default hostname provided by the network."), hosts[hostnum].hostname);
- showpopup(m_tszUserName, error, GG_POPUP_WARNING | GG_POPUP_ALLOW_MSGBOX);
- }
- else
- {
- p.server_port = hosts[hostnum].port;
- netlog("gg_mainthread(%x): Connecting to manually specified host %s (%d.%d.%d.%d) and port %d.", this,
- hosts[hostnum].hostname, LOBYTE(LOWORD(p.server_addr)), HIBYTE(LOWORD(p.server_addr)),
- LOBYTE(HIWORD(p.server_addr)), HIBYTE(HIWORD(p.server_addr)), p.server_port);
- }
- }
- else
- p.server_port = p.server_addr = 0;
-
- // Send login request
- if (!(sess = gg_login(&p, &sock, &gg_failno)))
- {
- broadcastnewstatus(ID_STATUS_OFFLINE);
- // Check if connection attempt wasn't cancelled by the user
- if (m_iDesiredStatus != ID_STATUS_OFFLINE)
- {
- TCHAR error[128], *perror = NULL;
- // Lookup for error desciption
- if (errno == EACCES) {
- for (int i = 0; reason[i].type; i++) if (reason[i].type == gg_failno) {
- perror = TranslateTS(reason[i].str);
- break;
- }
- }
- if (!perror) {
- mir_sntprintf(error, SIZEOF(error), TranslateT("Connection cannot be established because of error:\n\t%s"), _tcserror(errno));
- perror = error;
- }
- netlog("gg_mainthread(%x): %s", this, perror);
- if (db_get_b(NULL, m_szModuleName, GG_KEY_SHOWCERRORS, GG_KEYDEF_SHOWCERRORS))
- showpopup(m_tszUserName, perror, GG_POPUP_ERROR | GG_POPUP_ALLOW_MSGBOX | GG_POPUP_ONCE);
-
- // Check if we should reconnect
- if ((gg_failno >= GG_FAILURE_RESOLVING && gg_failno != GG_FAILURE_PASSWORD && gg_failno != GG_FAILURE_INTRUDER && gg_failno != GG_FAILURE_UNAVAILABLE)
- && errno == EACCES
- && (db_get_b(NULL, m_szModuleName, GG_KEY_ARECONNECT, GG_KEYDEF_ARECONNECT) || (hostnum < hostcount - 1)))
- {
- DWORD dwInterval = db_get_dw(NULL, m_szModuleName, GG_KEY_RECONNINTERVAL, GG_KEYDEF_RECONNINTERVAL), dwResult;
- BOOL bRetry = TRUE;
-
- hConnStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- dwResult = WaitForSingleObjectEx(hConnStopEvent, dwInterval, TRUE);
- if ((dwResult == WAIT_OBJECT_0 && m_iDesiredStatus == ID_STATUS_OFFLINE)
- || (dwResult == WAIT_IO_COMPLETION && Miranda_Terminated()))
- bRetry = FALSE;
- CloseHandle(hConnStopEvent);
- hConnStopEvent = NULL;
-
- // Reconnect to the next server on the list
- if (bRetry)
- {
- if (hostnum < hostcount - 1) hostnum++;
- mir_free(p.status_descr);
- broadcastnewstatus(ID_STATUS_CONNECTING);
- goto retry;
- }
- }
- // We cannot do more about this
- EnterCriticalSection(&modemsg_mutex);
- m_iDesiredStatus = ID_STATUS_OFFLINE;
- LeaveCriticalSection(&modemsg_mutex);
- }
- else
- netlog("gg_mainthread(%x)): Connection attempt cancelled by the user.", this);
- }
- else
- {
- // Successfully connected
- logonTime = time(NULL);
- db_set_dw(NULL, m_szModuleName, GG_KEY_LOGONTIME, logonTime);
- EnterCriticalSection(&sess_mutex);
- sess = sess;
- LeaveCriticalSection(&sess_mutex);
- // Subscribe users status notifications
- notifyall();
- // Set startup status
- if (m_iDesiredStatus != status_gg2m(p.status))
- refreshstatus(m_iDesiredStatus);
- else
- {
- broadcastnewstatus(m_iDesiredStatus);
- // Change status of the contact with our own UIN (if got yourself added to the contact list)
- changecontactstatus(p.uin, p.status, p.status_descr, 0, 0, 0, 0);
- }
- if (check_first_conn) // First connection to the account
- {
- // Start search for user data
- GetInfo(NULL, 0);
- // Fetch user avatar
- getUserAvatar();
- check_first_conn = 0;
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- // Main loop
- while(isonline())
- {
- // Connection broken/closed
- if (!(e = gg_watch_fd(sess)))
- {
- netlog("gg_mainthread(%x): Connection closed.", this);
- EnterCriticalSection(&sess_mutex);
- gg_free_session(sess);
- sess = NULL;
- LeaveCriticalSection(&sess_mutex);
- break;
- }
- else
- netlog("gg_mainthread(%x): Event: %s", this, ggdebug_eventtype(e));
-
- switch(e->type)
- {
- // Client connected
- case GG_EVENT_CONN_SUCCESS:
- // Nada
- break;
-
- // Client disconnected or connection failure
- case GG_EVENT_CONN_FAILED:
- case GG_EVENT_DISCONNECT:
- EnterCriticalSection(&sess_mutex);
- gg_free_session(sess);
- sess = NULL;
- LeaveCriticalSection(&sess_mutex);
- break;
-
- // Client allowed to disconnect
- case GG_EVENT_DISCONNECT_ACK:
- // Send logoff
- gg_logoff(sess);
- break;
-
- // Received ackowledge
- case GG_EVENT_ACK:
- if (e->event.ack.seq && e->event.ack.recipient)
- {
- ProtoBroadcastAck(m_szModuleName, getcontact((DWORD)e->event.ack.recipient, 0, 0, NULL),
- ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE) e->event.ack.seq, 0);
- }
- break;
-
- // Statuslist notify (deprecated)
- case GG_EVENT_NOTIFY:
- case GG_EVENT_NOTIFY_DESCR:
- {
- struct gg_notify_reply *n;
-
- n = (e->type == GG_EVENT_NOTIFY) ? e->event.notify : e->event.notify_descr.notify;
-
- for (; n->uin; n++)
- {
- char *descr = (e->type == GG_EVENT_NOTIFY_DESCR) ? e->event.notify_descr.descr : NULL;
- changecontactstatus(n->uin, n->status, descr, 0, n->remote_ip, n->remote_port, n->version);
- }
- break;
- }
- // Statuslist notify (version >= 6.0)
- case GG_EVENT_NOTIFY60:
- {
- uin_t uin = (uin_t)db_get_dw(NULL, m_szModuleName, GG_KEY_UIN, 0);
- int i;
- for(i = 0; e->event.notify60[i].uin; i++) {
- if (e->event.notify60[i].uin == uin) continue;
- changecontactstatus(e->event.notify60[i].uin, e->event.notify60[i].status, e->event.notify60[i].descr,
- e->event.notify60[i].time, e->event.notify60[i].remote_ip, e->event.notify60[i].remote_port,
- e->event.notify60[i].version);
- requestAvatar(getcontact(e->event.notify60[i].uin, 0, 0, NULL), 0);
- }
- break;
- }
-
- // Pubdir search reply && read own data reply
- case GG_EVENT_PUBDIR50_SEARCH_REPLY:
- case GG_EVENT_PUBDIR50_READ:
- case GG_EVENT_PUBDIR50_WRITE:
- {
- gg_pubdir50_t res = e->event.pubdir50;
- int i, count;
-
- if (e->type == GG_EVENT_PUBDIR50_SEARCH_REPLY)
- {
- netlog("gg_mainthread(%x): Got user info.", this);
- // Store next search UIN
- if (res->seq == GG_SEQ_SEARCH)
- next_uin = gg_pubdir50_next(res);
- }
- else if (e->type == GG_EVENT_PUBDIR50_READ)
- {
- netlog("gg_mainthread(%x): Got owner info.", this);
- }
- else if (e->type == GG_EVENT_PUBDIR50_WRITE)
- {
- netlog("gg_mainthread(%x): Public directory save succesful.", this);
- // Update user details
- GetInfo(NULL, 0);
- }
-
- if ((count = gg_pubdir50_count(res)) > 0)
- {
- for (i = 0; i < count; i++)
- {
- // Loadup fields
- const char *__fmnumber = gg_pubdir50_get(res, i, GG_PUBDIR50_UIN);
- const char *__nick = gg_pubdir50_get(res, i, GG_PUBDIR50_NICKNAME);
- const char *__firstname = gg_pubdir50_get(res, i, GG_PUBDIR50_FIRSTNAME);
- const char *__lastname = gg_pubdir50_get(res, i, GG_PUBDIR50_LASTNAME);
- const char *__familyname = gg_pubdir50_get(res, i, GG_PUBDIR50_FAMILYNAME);
- const char *__birthyear = gg_pubdir50_get(res, i, GG_PUBDIR50_BIRTHYEAR);
- const char *__city = gg_pubdir50_get(res, i, GG_PUBDIR50_CITY);
- const char *__origincity = gg_pubdir50_get(res, i, GG_PUBDIR50_FAMILYCITY);
- const char *__gender = gg_pubdir50_get(res, i, GG_PUBDIR50_GENDER);
- const char *__status = gg_pubdir50_get(res, i, GG_PUBDIR50_STATUS);
- uin_t uin = __fmnumber ? atoi(__fmnumber) : 0;
-
- HANDLE hContact = (res->seq == GG_SEQ_CHINFO) ? NULL : getcontact(uin, 0, 0, NULL);
- netlog("gg_mainthread(%x): Search result for uin %d, seq %d.", this, uin, res->seq);
- if (res->seq == GG_SEQ_SEARCH)
- {
- char strFmt1[64];
- char strFmt2[64];
-
- mir_snprintf(strFmt2, sizeof(strFmt2), "%s", (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, status_gg2m(atoi(__status)), 0));
- if (__city)
- {
- mir_snprintf(strFmt1, sizeof(strFmt1), ", %s %s", Translate("City:"), __city);
- strncat(strFmt2, strFmt1, sizeof(strFmt2) - strlen(strFmt2));
- }
- if (__birthyear)
- {
- time_t t = time(NULL);
- struct tm *lt = localtime(&t);
- int br = atoi(__birthyear);
-
- if (br < (lt->tm_year + 1900) && br > 1900)
- {
- mir_snprintf(strFmt1, sizeof(strFmt1), ", %s %d", Translate("Age:"), (lt->tm_year + 1900) - br);
- strncat(strFmt2, strFmt1, sizeof(strFmt2) - strlen(strFmt2));
- }
- }
-
- GGSEARCHRESULT sr;
- memset(&sr, 0, sizeof(sr));
- sr.cbSize = sizeof(sr);
- sr.nick = mir_a2t(__nick);
- sr.firstName = mir_a2t(__firstname);
- sr.lastName = mir_a2t(__lastname);
- sr.email = mir_a2t(strFmt2);
- sr.id = mir_a2t(_ultoa(uin, strFmt1, 10));
- sr.uin = uin;
- ProtoBroadcastAck(m_szModuleName, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE) 1, (LPARAM)&sr);
- mir_free(sr.nick);
- mir_free(sr.firstName);
- mir_free(sr.lastName);
- mir_free(sr.email);
- mir_free(sr.id);
- }
-
- if (((res->seq == GG_SEQ_INFO || res->seq == GG_SEQ_GETNICK) && hContact != NULL)
- || res->seq == GG_SEQ_CHINFO)
- {
- // Change nickname if it's not present
- if (__nick && (res->seq == GG_SEQ_GETNICK || res->seq == GG_SEQ_CHINFO))
- db_set_s(hContact, m_szModuleName, GG_KEY_NICK, __nick);
-
- if (__nick)
- db_set_s(hContact, m_szModuleName, "NickName", __nick);
- else if (res->seq == GG_SEQ_CHINFO)
- db_unset(NULL, m_szModuleName, "NickName");
-
- // Change other info
- if (__city)
- db_set_s(hContact, m_szModuleName, "City", __city);
- else if (res->seq == GG_SEQ_CHINFO)
- db_unset(NULL, m_szModuleName, "City");
-
- if (__firstname)
- db_set_s(hContact, m_szModuleName, "FirstName", __firstname);
- else if (res->seq == GG_SEQ_CHINFO)
- db_unset(NULL, m_szModuleName, "FirstName");
-
- if (__lastname)
- db_set_s(hContact, m_szModuleName, "LastName", __lastname);
- else if (res->seq == GG_SEQ_CHINFO)
- db_unset(NULL, m_szModuleName, "LastName");
-
- if (__familyname)
- db_set_s(hContact, m_szModuleName, "FamilyName", __familyname);
- else if (res->seq == GG_SEQ_CHINFO)
- db_unset(NULL, m_szModuleName, "FamilyName");
-
- if (__origincity)
- db_set_s(hContact, m_szModuleName, "CityOrigin", __origincity);
- else if (res->seq == GG_SEQ_CHINFO)
- db_unset(NULL, m_szModuleName, "CityOrigin");
-
- if (__birthyear)
- {
- time_t t = time(NULL);
- struct tm *lt = localtime(&t);
- int br = atoi(__birthyear);
- if (br > 0)
- {
- db_set_w(hContact, m_szModuleName, "Age", (WORD)(lt->tm_year + 1900 - br));
- db_set_w(hContact, m_szModuleName, "BirthYear", (WORD)br);
- }
- }
- else if (res->seq == GG_SEQ_CHINFO)
- {
- db_unset(NULL, m_szModuleName, "Age");
- db_unset(NULL, m_szModuleName, "BirthYear");
- }
-
- // Gadu-Gadu Male <-> Female
- if (__gender)
- {
- if (res->seq == GG_SEQ_CHINFO)
- db_set_b(hContact, m_szModuleName, "Gender",
- (BYTE)(!strcmp(__gender, GG_PUBDIR50_GENDER_SET_MALE) ? 'M' :
- (!strcmp(__gender, GG_PUBDIR50_GENDER_SET_FEMALE) ? 'F' : '?')));
- else
- db_set_b(hContact, m_szModuleName, "Gender",
- (BYTE)(!strcmp(__gender, GG_PUBDIR50_GENDER_MALE) ? 'M' :
- (!strcmp(__gender, GG_PUBDIR50_GENDER_FEMALE) ? 'F' : '?')));
- }
- else if (res->seq == GG_SEQ_CHINFO)
- {
- db_unset(NULL, m_szModuleName, "Gender");
- }
-
- netlog("gg_mainthread(%x): Setting user info for uin %d.", this, uin);
- ProtoBroadcastAck(m_szModuleName, hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
- }
- }
- }
- if (res->seq == GG_SEQ_SEARCH)
- ProtoBroadcastAck(m_szModuleName, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
- break;
- }
-
- // Status (deprecated)
- case GG_EVENT_STATUS:
- changecontactstatus(e->event.status.uin, e->event.status.status, e->event.status.descr, 0, 0, 0, 0);
- break;
-
- // Status (version >= 6.0)
- case GG_EVENT_STATUS60:
- {
- HANDLE hContact = getcontact(e->event.status60.uin, 0, 0, NULL);
- int oldstatus = db_get_w(hContact, m_szModuleName, GG_KEY_STATUS, (WORD)ID_STATUS_OFFLINE);
- uin_t uin = (uin_t)db_get_dw(NULL, m_szModuleName, GG_KEY_UIN, 0);
-
- if (e->event.status60.uin == uin)
- {
- // Status was changed by the user simultaneously logged on using different Miranda account or IM client
- int iStatus = status_gg2m(e->event.status60.status);
- CallProtoService(m_szModuleName, PS_SETAWAYMSG, iStatus, (LPARAM)e->event.status60.descr);
- CallProtoService(m_szModuleName, PS_SETSTATUS, iStatus, 0);
- }
-
- changecontactstatus(e->event.status60.uin, e->event.status60.status, e->event.status60.descr,
- e->event.status60.time, e->event.status60.remote_ip, e->event.status60.remote_port, e->event.status60.version);
-
- if (oldstatus == ID_STATUS_OFFLINE && db_get_w(hContact, m_szModuleName, GG_KEY_STATUS, (WORD)ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE)
- requestAvatar(hContact, 0);
- }
- break;
-
- // Received userlist / or put info
- case GG_EVENT_USERLIST:
- switch (e->event.userlist.type) {
- case GG_USERLIST_GET_REPLY:
- if (e->event.userlist.reply) {
- parsecontacts(e->event.userlist.reply);
- MessageBox(NULL, TranslateT("List import successful."), m_tszUserName, MB_OK | MB_ICONINFORMATION);
- }
- break;
-
- case GG_USERLIST_PUT_REPLY:
- if (is_list_remove)
- MessageBox(NULL, TranslateT("List remove successful."), m_tszUserName, MB_OK | MB_ICONINFORMATION);
- else
- MessageBox(NULL, TranslateT("List export successful."), m_tszUserName, MB_OK | MB_ICONINFORMATION);
- break;
- }
- break;
-
- // Received message
- case GG_EVENT_MSG:
- // This is CTCP request
- if ((e->event.msg.msgclass & GG_CLASS_CTCP))
- {
- dccconnect(e->event.msg.sender);
- }
- // Check if not conference and block
- else if (!e->event.msg.recipients_count || gc_enabled)
- {
- // Check if groupchat
- if (e->event.msg.recipients_count && gc_enabled && !db_get_b(NULL, m_szModuleName, GG_KEY_IGNORECONF, GG_KEYDEF_IGNORECONF))
- {
- char *chat = gc_getchat(e->event.msg.sender, e->event.msg.recipients, e->event.msg.recipients_count);
- if (chat)
- {
- char id[32];
- GCDEST gcdest = {m_szModuleName, chat, GC_EVENT_MESSAGE};
- GCEVENT gcevent = {sizeof(GCEVENT), &gcdest};
- time_t t = time(NULL);
-
- UIN2ID(e->event.msg.sender, id);
-
- gcevent.pszUID = id;
- gcevent.pszText = e->event.msg.message;
- gcevent.pszNick = (char *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) getcontact(e->event.msg.sender, 1, 0, NULL), 0);
- gcevent.time = (!(e->event.msg.msgclass & GG_CLASS_OFFLINE) || e->event.msg.time > (t - timeDeviation)) ? t : e->event.msg.time;
- gcevent.dwFlags = GCEF_ADDTOLOG;
- netlog("gg_mainthread(%x): Conference message to room %s & id %s.", this, chat, id);
- CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gcevent);
- }
- }
- // Check if not empty message ( who needs it? )
- else if (!e->event.msg.recipients_count && e->event.msg.message && *e->event.msg.message && strcmp(e->event.msg.message, "\xA0\0"))
- {
- CCSDATA ccs = {0};
- PROTORECVEVENT pre = {0};
- time_t t = time(NULL);
- ccs.szProtoService = PSR_MESSAGE;
- ccs.hContact = getcontact(e->event.msg.sender, 1, 0, NULL);
- ccs.lParam = (LPARAM)⪯
- pre.timestamp = (!(e->event.msg.msgclass & GG_CLASS_OFFLINE) || e->event.msg.time > (t - timeDeviation)) ? t : e->event.msg.time;
- pre.szMessage = e->event.msg.message;
- CallService(MS_PROTO_CHAINRECV, 0, (LPARAM) &ccs);
- }
-
- // RichEdit format included (image)
- if (e->event.msg.formats_length &&
- db_get_b(NULL, m_szModuleName, GG_KEY_IMGRECEIVE, GG_KEYDEF_IMGRECEIVE) &&
- !(db_get_dw(getcontact(e->event.msg.sender, 1, 0, NULL), "Ignore", "Mask1", 0) & IGNOREEVENT_MESSAGE))
- {
- char *formats = (char*)e->event.msg.formats;
- int len = 0, formats_len = e->event.msg.formats_length, add_ptr;
-
- while (len < formats_len)
- {
- add_ptr = sizeof(struct gg_msg_richtext_format);
- if (((struct gg_msg_richtext_format*)formats)->font & GG_FONT_IMAGE)
- {
- struct gg_msg_richtext_image *image = (struct gg_msg_richtext_image *)(formats + add_ptr);
- EnterCriticalSection(&sess_mutex);
- gg_image_request(sess, e->event.msg.sender, image->size, image->crc32);
- LeaveCriticalSection(&sess_mutex);
-
- netlog("gg_mainthread: image request sent!");
- add_ptr += sizeof(struct gg_msg_richtext_image);
- }
- if (((struct gg_msg_richtext_format*)formats)->font & GG_FONT_COLOR)
- add_ptr += sizeof(struct gg_msg_richtext_color);
- len += add_ptr;
- formats += add_ptr;
- }
- }
- }
- break;
-
- // Message sent from concurrent user session
- case GG_EVENT_MULTILOGON_MSG:
- if (e->event.multilogon_msg.recipients_count && gc_enabled && !db_get_b(NULL, m_szModuleName, GG_KEY_IGNORECONF, GG_KEYDEF_IGNORECONF))
- {
- char *chat = gc_getchat(e->event.multilogon_msg.sender, e->event.multilogon_msg.recipients, e->event.multilogon_msg.recipients_count);
- if (chat)
- {
- char id[32];
- DBVARIANT dbv;
- GCDEST gcdest = {m_szModuleName, chat, GC_EVENT_MESSAGE};
- GCEVENT gcevent = {sizeof(GCEVENT), &gcdest};
-
- UIN2ID( db_get_dw(NULL, m_szModuleName, GG_KEY_UIN, 0), id);
-
- gcevent.pszUID = id;
- gcevent.pszText = e->event.multilogon_msg.message;
- if (!db_get_s(NULL, m_szModuleName, GG_KEY_NICK, &dbv, DBVT_ASCIIZ))
- gcevent.pszNick = dbv.pszVal;
- else
- gcevent.pszNick = Translate("Me");
- gcevent.time = e->event.multilogon_msg.time;
- gcevent.bIsMe = 1;
- gcevent.dwFlags = GCEF_ADDTOLOG;
- netlog("gg_mainthread(%x): Sent conference message to room %s.", this, chat);
- CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gcevent);
- if (gcevent.pszNick == dbv.pszVal) DBFreeVariant(&dbv);
- }
- }
- else if (!e->event.multilogon_msg.recipients_count && e->event.multilogon_msg.message && *e->event.multilogon_msg.message
- && strcmp(e->event.multilogon_msg.message, "\xA0\0"))
- {
- DBEVENTINFO dbei = {0};
- dbei.cbSize = sizeof(dbei);
- dbei.szModule = m_szModuleName;
- dbei.timestamp = (DWORD)e->event.multilogon_msg.time;
- dbei.flags = DBEF_SENT;
- dbei.eventType = EVENTTYPE_MESSAGE;
- dbei.cbBlob = (DWORD)strlen(e->event.multilogon_msg.message) + 1;
- dbei.pBlob = (PBYTE)e->event.multilogon_msg.message;
- CallService(MS_DB_EVENT_ADD, (WPARAM)getcontact(e->event.multilogon_msg.sender, 1, 0, NULL), (LPARAM)&dbei);
- }
- break;
-
- // Information on active concurrent sessions
- case GG_EVENT_MULTILOGON_INFO:
- {
- list_t l;
- int* iIndexes = NULL, i;
- netlog("gg_mainthread(): Concurrent sessions count: %d.", e->event.multilogon_info.count);
- if (e->event.multilogon_info.count > 0)
- iIndexes = (int*)mir_calloc(e->event.multilogon_info.count * sizeof(int));
- EnterCriticalSection(&sessions_mutex);
- for (l = sessions; l; l = l->next)
- {
- struct gg_multilogon_session* sess = (struct gg_multilogon_session*)l->data;
- for (i = 0; i < e->event.multilogon_info.count; i++)
- {
- if (!memcmp(&sess->id, &e->event.multilogon_info.sessions[i].id, sizeof(gg_multilogon_id_t)) && iIndexes)
- {
- iIndexes[i]++;
- break;
- }
- }
- mir_free(sess->name);
- mir_free(sess);
- }
- list_destroy(sessions, 0);
- sessions = NULL;
- for (i = 0; i < e->event.multilogon_info.count; i++)
- {
- gg_multilogon_session* sess = (gg_multilogon_session*)mir_alloc(sizeof(struct gg_multilogon_session));
- memcpy(sess, &e->event.multilogon_info.sessions[i], sizeof(struct gg_multilogon_session));
- sess->name = mir_strdup(*e->event.multilogon_info.sessions[i].name != '\0'
- ? e->event.multilogon_info.sessions[i].name
- : Translate("Unknown client"));
- list_add(&sessions, sess, 0);
- }
- LeaveCriticalSection(&sessions_mutex);
- sessions_updatedlg();
- if (ServiceExists(MS_POPUP_ADDPOPUPCLASS))
- {
- const TCHAR* szText = time(NULL) - logonTime > 3
- ? TranslateT("You have logged in at another location")
- : TranslateT("You are logged in at another location");
- for (i = 0; i < e->event.multilogon_info.count; i++)
- {
- TCHAR szMsg[MAX_SECONDLINE];
- if (iIndexes && iIndexes[i])
- continue;
-
- mir_sntprintf(szMsg, SIZEOF(szMsg), _T("%s (%s)"), szText,
- *e->event.multilogon_info.sessions[i].name != '\0' ?
- _A2T(e->event.multilogon_info.sessions[i].name) : TranslateT("Unknown client"));
- showpopup(m_tszUserName, szMsg, GG_POPUP_MULTILOGON);
- }
- }
- mir_free(iIndexes);
- }
- break;
-
- // Image reply sent
- case GG_EVENT_IMAGE_REPLY:
- // Get rid of empty image
- if (e->event.image_reply.size && e->event.image_reply.image)
- {
- HANDLE hContact = getcontact(e->event.image_reply.sender, 1, 0, NULL);
- void *img = (void *)img_loadpicture(e, 0);
-
- if (!img)
- break;
-
- if (db_get_b(NULL, m_szModuleName, GG_KEY_IMGMETHOD, GG_KEYDEF_IMGMETHOD) == 1 || img_opened(e->event.image_reply.sender))
- {
- img_display(hContact, img);
- }
- else if (db_get_b(NULL, m_szModuleName, GG_KEY_IMGMETHOD, GG_KEYDEF_IMGMETHOD) == 2)
- {
- img_displayasmsg(hContact, img);
- }
- else
- {
- CLISTEVENT cle = {0};
- char service[128];
- mir_snprintf(service, sizeof(service), GGS_RECVIMAGE, m_szModuleName);
-
- cle.cbSize = sizeof(cle);
- cle.hContact = hContact;
- cle.hIcon = LoadIconEx("image", FALSE);
- cle.flags = CLEF_URGENT;
- cle.hDbEvent = (HANDLE)"img";
- cle.lParam = (LPARAM)img;
- cle.pszService = service;
- cle.pszTooltip = Translate("Incoming image");
- CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle);
- ReleaseIconEx("image", FALSE);
- }
- }
- break;
-
- // Image send request
- case GG_EVENT_IMAGE_REQUEST:
- img_sendonrequest(e);
- break;
-
- // Incoming direct connection
- case GG_EVENT_DCC7_NEW:
- {
- struct gg_dcc7 *dcc7 = e->event.dcc7_new;
- netlog("gg_mainthread(%x): Incoming direct connection.", this);
- dcc7->contact = getcontact(dcc7->peer_uin, 0, 0, NULL);
-
- // Check if user is on the list and if it is my uin
- if (!dcc7->contact || db_get_dw(NULL, m_szModuleName, GG_KEY_UIN, -1) != dcc7->uin) {
- gg_dcc7_free(dcc7);
- e->event.dcc7_new = NULL;
- break;
- }
-
- // Add to waiting transfers
- EnterCriticalSection(&ft_mutex);
- list_add(&transfers, dcc7, 0);
- LeaveCriticalSection(&ft_mutex);
-
- //////////////////////////////////////////////////
- // Add file recv request
-
- netlog("gg_mainthread(%x): Client: %d, File ack filename \"%s\" size %d.", this, dcc7->peer_uin,
- dcc7->filename, dcc7->size);
-
- TCHAR* filenameT = mir_utf8decodeT((char*)dcc7->filename);
-
- PROTORECVFILET pre = {0};
- pre.flags = PREF_TCHAR;
- pre.fileCount = 1;
- pre.timestamp = time(NULL);
- pre.tszDescription = filenameT;
- pre.ptszFiles = &filenameT;
- pre.lParam = (LPARAM)dcc7;
-
- CCSDATA ccs = { dcc7->contact, PSR_FILE, 0, (LPARAM)&pre };
- CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
-
- mir_free(filenameT);
- e->event.dcc7_new = NULL;
- }
- break;
-
- // Direct connection rejected
- case GG_EVENT_DCC7_REJECT:
- {
- struct gg_dcc7 *dcc7 = e->event.dcc7_reject.dcc7;
- if (dcc7->type == GG_SESSION_DCC7_SEND)
- {
- netlog("gg_mainthread(%x): File transfer denied by client %d (reason = %d).", this, dcc7->peer_uin, e->event.dcc7_reject.reason);
- ProtoBroadcastAck(m_szModuleName, dcc7->contact, ACKTYPE_FILE, ACKRESULT_DENIED, dcc7, 0);
-
- // Remove from watches and free
- EnterCriticalSection(&ft_mutex);
- list_remove(&watches, dcc7, 0);
- LeaveCriticalSection(&ft_mutex);
- gg_dcc7_free(dcc7);
- }
- else
- {
- netlog("gg_mainthread(%x): File transfer aborted by client %d.", this, dcc7->peer_uin);
-
- // Remove transfer from waiting list
- EnterCriticalSection(&ft_mutex);
- list_remove(&transfers, dcc7, 0);
- LeaveCriticalSection(&ft_mutex);
- }
- }
- break;
-
- // Direct connection error
- case GG_EVENT_DCC7_ERROR:
- {
- struct gg_dcc7 *dcc7 = e->event.dcc7_error_ex.dcc7;
- switch (e->event.dcc7_error)
- {
- case GG_ERROR_DCC7_HANDSHAKE:
- netlog("gg_mainthread(%x): Client: %d, Handshake error.", this, dcc7 ? dcc7->peer_uin : 0);
- break;
- case GG_ERROR_DCC7_NET:
- netlog("gg_mainthread(%x): Client: %d, Network error.", this, dcc7 ? dcc7->peer_uin : 0);
- break;
- case GG_ERROR_DCC7_FILE:
- netlog("gg_mainthread(%x): Client: %d, File read/write error.", this, dcc7 ? dcc7->peer_uin : 0);
- break;
- case GG_ERROR_DCC7_EOF:
- netlog("gg_mainthread(%x): Client: %d, End of file/connection error.", this, dcc7 ? dcc7->peer_uin : 0);
- break;
- case GG_ERROR_DCC7_REFUSED:
- netlog("gg_mainthread(%x): Client: %d, Connection refused error.", this, dcc7 ? dcc7->peer_uin : 0);
- break;
- case GG_ERROR_DCC7_RELAY:
- netlog("gg_mainthread(%x): Client: %d, Relay connection error.", this, dcc7 ? dcc7->peer_uin : 0);
- break;
- default:
- netlog("gg_mainthread(%x): Client: %d, Unknown error.", this, dcc7 ? dcc7->peer_uin : 0);
- }
- if (!dcc7) break;
-
- // Remove from watches
- list_remove(&watches, dcc7, 0);
-
- // Close file & fail
- if (dcc7->file_fd != -1)
- {
- _close(dcc7->file_fd);
- dcc7->file_fd = -1;
- }
-
- if (dcc7->contact)
- ProtoBroadcastAck(m_szModuleName, dcc7->contact, ACKTYPE_FILE, ACKRESULT_FAILED, dcc7, 0);
-
- // Free dcc
- gg_dcc7_free(dcc7);
- }
- break;
-
- case GG_EVENT_XML_ACTION:
- if (db_get_b(NULL, m_szModuleName, GG_KEY_ENABLEAVATARS, GG_KEYDEF_ENABLEAVATARS)) {
- HXML hXml;
- TCHAR *xmlAction;
- TCHAR *tag;
-
- xmlAction = mir_a2t(e->event.xml_action.data);
- tag = mir_a2t("events");
- hXml = xi.parseString(xmlAction, 0, tag);
-
- if (hXml != NULL) {
- HXML node;
- char *type, *sender;
-
- mir_free(tag);
- tag = mir_a2t("event/type");
- node = xi.getChildByPath(hXml, tag, 0);
- type = node != NULL ? mir_t2a(xi.getText(node)) : NULL;
-
- mir_free(tag);
- tag = mir_a2t("event/sender");
- node = xi.getChildByPath(hXml, tag, 0);
- sender = node != NULL ? mir_t2a(xi.getText(node)) : NULL;
- netlog("gg_mainthread(%x): XML Action type: %s.", this, type != NULL ? type : "unknown");
- // Avatar change notify
- if (type != NULL && !strcmp(type, "28")) {
- netlog("gg_mainthread(%x): Client %s changed his avatar.", this, sender);
- requestAvatar(getcontact(atoi(sender), 0, 0, NULL), 0);
- }
- mir_free(type);
- mir_free(sender);
- xi.destroyNode(hXml);
- }
- mir_free(tag);
- mir_free(xmlAction);
- }
- break;
-
- case GG_EVENT_TYPING_NOTIFICATION:
- {
- HANDLE hContact = getcontact(e->event.typing_notification.uin, 0, 0, NULL);
-#ifdef DEBUGMODE
- netlog("gg_mainthread(%x): Typing notification from %d (%d).", this,
- e->event.typing_notification.uin, e->event.typing_notification.length);
-#endif
- CallService(MS_PROTO_CONTACTISTYPING, (WPARAM)hContact,
- e->event.typing_notification.length > 0 ? 7 : PROTOTYPE_CONTACTTYPING_OFF);
- }
- break;
- }
- // Free event struct
- gg_free_event(e);
- }
-
- broadcastnewstatus(ID_STATUS_OFFLINE);
- setalloffline();
- db_set_dw(NULL, m_szModuleName, GG_KEY_LOGONTIME, 0);
-
- // If it was unwanted disconnection reconnect
- if (m_iDesiredStatus != ID_STATUS_OFFLINE
- && db_get_b(NULL, m_szModuleName, GG_KEY_ARECONNECT, GG_KEYDEF_ARECONNECT))
- {
- netlog("gg_mainthread(%x): Unintentional disconnection detected. Going to reconnect...", this);
- hostnum = 0;
- broadcastnewstatus(ID_STATUS_CONNECTING);
- mir_free(p.status_descr);
- goto retry;
- }
-
- mir_free(p.password);
- mir_free(p.status_descr);
-
- // Destroy concurrent sessions list
- {
- list_t l;
- EnterCriticalSection(&sessions_mutex);
- for (l = sessions; l; l = l->next)
- {
- struct gg_multilogon_session* sess = (struct gg_multilogon_session*)l->data;
- mir_free(sess->name);
- mir_free(sess);
- }
- list_destroy(sessions, 0);
- sessions = NULL;
- LeaveCriticalSection(&sessions_mutex);
- }
-
- // Stop dcc server
- pth_dcc.dwThreadId = 0;
-#ifdef DEBUGMODE
- netlog("gg_mainthread(%x): Waiting until DCC Server Thread finished, if needed.", this);
-#endif
- threadwait(&pth_dcc);
-
- netlog("gg_mainthread(%x): Server Thread Ending", this);
- return;
-}
-
-////////////////////////////////////////////////////////////
-// Change status function
-void GGPROTO::broadcastnewstatus(int newStatus)
-{
- int oldStatus;
-
- EnterCriticalSection(&modemsg_mutex);
- oldStatus = m_iStatus;
- if (oldStatus == newStatus)
- {
- LeaveCriticalSection(&modemsg_mutex);
- return;
- }
- m_iStatus = newStatus;
- LeaveCriticalSection(&modemsg_mutex);
-
- ProtoBroadcastAck(m_szModuleName, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE) oldStatus, newStatus);
-
- netlog("gg_broadcastnewstatus(): Broadcast new status: %d.", newStatus);
-}
-
-////////////////////////////////////////////////////////////
-// When contact is deleted
-int GGPROTO::contactdeleted(WPARAM wParam, LPARAM lParam)
-{
- HANDLE hContact = (HANDLE) wParam;
- uin_t uin; int type;
- DBVARIANT dbv;
-
- uin = (uin_t)db_get_dw(hContact, m_szModuleName, GG_KEY_UIN, 0);
- type = db_get_b(hContact, m_szModuleName, "ChatRoom", 0);
-
- // Terminate conference if contact is deleted
- if (type && !db_get_s(hContact, m_szModuleName, "ChatRoomID", &dbv, DBVT_ASCIIZ) && gc_enabled)
- {
- GCDEST gcdest = {m_szModuleName, dbv.pszVal, GC_EVENT_CONTROL};
- GCEVENT gcevent = {sizeof(GCEVENT), &gcdest};
- GGGC *chat = gc_lookup(dbv.pszVal);
-
- netlog("gg_gc_event(): Terminating chat %x, id %s from contact list...", chat, dbv.pszVal);
- if (chat)
- {
- // Destroy chat entry
- free(chat->recipients);
- list_remove(&chats, chat, 1);
- // Terminate chat window / shouldn't cascade entry is deleted
- CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gcevent);
- CallServiceSync(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gcevent);
- }
-
- DBFreeVariant(&dbv);
- return 0;
- }
-
- if (uin && isonline())
- {
- EnterCriticalSection(&sess_mutex);
- gg_remove_notify_ex(sess, uin, GG_USER_NORMAL);
- LeaveCriticalSection(&sess_mutex);
- }
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////
-// When db settings changed
-
-int GGPROTO::dbsettingchanged(WPARAM wParam, LPARAM lParam)
-{
- DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam;
- HANDLE hContact = (HANDLE) wParam;
- char *szProto = NULL;
-
- // Check if the contact is NULL or we are not online
- if (!isonline())
- return 0;
-
- // If contact has been blocked
- if (!strcmp(cws->szModule, m_szModuleName) && !strcmp(cws->szSetting, GG_KEY_BLOCK))
- {
- notifyuser(hContact, 1);
- return 0;
- }
-
- // Contact is being renamed
- if (gc_enabled && !strcmp(cws->szModule, m_szModuleName) && !strcmp(cws->szSetting, GG_KEY_NICK)
- && cws->value.pszVal)
- {
- // Groupchat window contact is being renamed
- DBVARIANT dbv;
- int type = db_get_b(hContact, m_szModuleName, "ChatRoom", 0);
- if (type && !db_get_s(hContact, m_szModuleName, "ChatRoomID", &dbv, DBVT_ASCIIZ))
- {
- // Most important... check redundancy (fucking cascading)
- static int cascade = 0;
- if (!cascade && dbv.pszVal)
- {
- GCDEST gcdest = {m_szModuleName, dbv.pszVal, GC_EVENT_CHANGESESSIONAME};
- GCEVENT gcevent = {sizeof(GCEVENT), &gcdest};
- gcevent.pszText = cws->value.pszVal;
- netlog("gg_dbsettingchanged(): Conference %s was renamed to %s.", dbv.pszVal, cws->value.pszVal);
- // Mark cascading
- /* FIXME */ cascade = 1;
- CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gcevent);
- /* FIXME */ cascade = 0;
- }
- DBFreeVariant(&dbv);
- }
- else
- // Change contact name on all chats
- gc_changenick(hContact, cws->value.pszVal);
- }
-
- // Contact list changes
- if (!strcmp(cws->szModule, "CList"))
- {
- // If name changed... change nick
- if (!strcmp(cws->szSetting, "MyHandle") && cws->value.type == DBVT_ASCIIZ && cws->value.pszVal)
- db_set_s(hContact, m_szModuleName, GG_KEY_NICK, cws->value.pszVal);
-
- // If not on list changed
- if (!strcmp(cws->szSetting, "NotOnList"))
- {
- if (db_get_b(hContact, "CList", "Hidden", 0))
- return 0;
- // Notify user normally this time if added to the list permanently
- if (cws->value.type == DBVT_DELETED || (cws->value.type == DBVT_BYTE && cws->value.bVal == 0))
- notifyuser(hContact, 1);
- }
- }
- return 0;
-}
-
-////////////////////////////////////////////////////////////
-// All users set offline
-
-void GGPROTO::setalloffline()
-{
- netlog("gg_setalloffline(): Setting buddies offline");
- db_set_w(NULL, m_szModuleName, GG_KEY_STATUS, ID_STATUS_OFFLINE);
- HANDLE hContact = db_find_first();
- while (hContact)
- {
- char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
- if (szProto != NULL && !strcmp(szProto, m_szModuleName))
- {
- db_set_w(hContact, m_szModuleName, GG_KEY_STATUS, ID_STATUS_OFFLINE);
- // Clear IP and port settings
- db_unset(hContact, m_szModuleName, GG_KEY_CLIENTIP);
- db_unset(hContact, m_szModuleName, GG_KEY_CLIENTPORT);
- // Delete status descr
- db_unset(hContact, "CList", GG_KEY_STATUSDESCR);
- }
- hContact = db_find_next(hContact);
- }
-#ifdef DEBUGMODE
- netlog("gg_setalloffline(): End");
-#endif
-}
-
-////////////////////////////////////////////////////////////
-// All users set offline
-
-void GGPROTO::notifyuser(HANDLE hContact, int refresh)
-{
- uin_t uin;
- if (!hContact) return;
- if (isonline() && (uin = (uin_t)db_get_dw(hContact, m_szModuleName, GG_KEY_UIN, 0)))
- {
- // Check if user should be invisible
- // Or be blocked ?
- if ((db_get_w(hContact, m_szModuleName, GG_KEY_APPARENT, (WORD) ID_STATUS_ONLINE) == ID_STATUS_OFFLINE) ||
- db_get_b(hContact, "CList", "NotOnList", 0))
- {
- mir_cslock l(sess_mutex);
- if (refresh) {
- gg_remove_notify_ex(sess, uin, GG_USER_NORMAL);
- gg_remove_notify_ex(sess, uin, GG_USER_BLOCKED);
- }
-
- gg_add_notify_ex(sess, uin, GG_USER_OFFLINE);
- }
- else if (db_get_b(hContact, m_szModuleName, GG_KEY_BLOCK, 0))
- {
- mir_cslock l(sess_mutex);
- if (refresh)
- gg_remove_notify_ex(sess, uin, GG_USER_OFFLINE);
-
- gg_add_notify_ex(sess, uin, GG_USER_BLOCKED);
- }
- else {
- mir_cslock l(sess_mutex);
- if (refresh)
- gg_remove_notify_ex(sess, uin, GG_USER_BLOCKED);
-
- gg_add_notify_ex(sess, uin, GG_USER_NORMAL);
- }
- }
-}
-
-void GGPROTO::notifyall()
-{
- HANDLE hContact;
- char *szProto;
- int count = 0, cc = 0;
- uin_t *uins;
- char *types;
-
- netlog("gg_notifyall(): Subscribing notification to all users");
- // Readup count
- hContact = db_find_first();
- while (hContact)
- {
- szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
- if (szProto != NULL && !strcmp(szProto, m_szModuleName)) count ++;
- hContact = db_find_next(hContact);
- }
-
- // Readup list
- /* FIXME: If we have nothing on the list but we omit gg_notify_ex we have problem with receiving any contacts */
- if (count == 0)
- {
- if (isonline())
- {
- EnterCriticalSection(&sess_mutex);
- gg_notify_ex(sess, NULL, NULL, 0);
- LeaveCriticalSection(&sess_mutex);
- }
- return;
- }
- uins = (uin_t*)calloc(sizeof(uin_t), count);
- types = (char*)calloc(sizeof(char), count);
-
- hContact = db_find_first();
- while (hContact && cc < count)
- {
- szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
- if (szProto != NULL && !strcmp(szProto, m_szModuleName) && (uins[cc] = db_get_dw(hContact, m_szModuleName, GG_KEY_UIN, 0)))
- {
- if ((db_get_w(hContact, m_szModuleName, GG_KEY_APPARENT, (WORD) ID_STATUS_ONLINE) == ID_STATUS_OFFLINE) ||
- db_get_b(hContact, "CList", "NotOnList", 0))
- types[cc] = GG_USER_OFFLINE;
- else if (db_get_b(hContact, m_szModuleName, GG_KEY_BLOCK, 0))
- types[cc] = GG_USER_BLOCKED;
- else
- types[cc] = GG_USER_NORMAL;
- cc ++;
- }
- hContact = db_find_next(hContact);
- }
- if (cc < count) count = cc;
-
- // Send notification
- if (isonline())
- {
- EnterCriticalSection(&sess_mutex);
- gg_notify_ex(sess, uins, types, count);
- LeaveCriticalSection(&sess_mutex);
- }
-
- // Free variables
- free(uins); free(types);
-}
-
-////////////////////////////////////////////////////////////
-// Get contact by uin
-
-HANDLE GGPROTO::getcontact(uin_t uin, int create, int inlist, TCHAR *szNick)
-{
- // Look for contact in DB
- HANDLE hContact = db_find_first();
- while (hContact) {
- char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
- if (szProto != NULL && !strcmp(szProto, m_szModuleName)) {
- if ((uin_t)db_get_dw(hContact, m_szModuleName, GG_KEY_UIN, 0) == uin
- && db_get_b(hContact, m_szModuleName, "ChatRoom", 0) == 0)
- {
- if (inlist) {
- db_unset(hContact, "CList", "NotOnList");
- db_unset(hContact, "CList", "Hidden");
- }
- return hContact;
- }
- }
- hContact = db_find_next(hContact);
- }
- if (!create) return NULL;
-
- hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
- if (!hContact) {
- netlog("gg_getcontact(): Failed to create Gadu-Gadu contact %s", szNick);
- return NULL;
- }
-
- if (CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) m_szModuleName) != 0) {
- // For some reason we failed to register the protocol for this contact
- CallService(MS_DB_CONTACT_DELETE, (WPARAM) hContact, 0);
- netlog("Failed to register GG contact %d", uin);
- return NULL;
- }
-
- netlog("gg_getcontact(): Added buddy: %d", uin);
- if (!inlist)
- db_set_b(hContact, "CList", "NotOnList", 1);
-
- db_set_dw(hContact, m_szModuleName, GG_KEY_UIN, (DWORD) uin);
- db_set_w(hContact, m_szModuleName, GG_KEY_STATUS, ID_STATUS_OFFLINE);
-
- // If nick specified use it
- if (szNick)
- db_set_ts(hContact, m_szModuleName, GG_KEY_NICK, szNick);
- else if (isonline()) {
- gg_pubdir50_t req;
-
- // Search for that nick
- if (req = gg_pubdir50_new(GG_PUBDIR50_SEARCH)) {
- // Add uin and search it
- gg_pubdir50_add(req, GG_PUBDIR50_UIN, ditoa(uin));
- gg_pubdir50_seq_set(req, GG_SEQ_GETNICK);
- EnterCriticalSection(&sess_mutex);
- gg_pubdir50(sess, req);
- LeaveCriticalSection(&sess_mutex);
- gg_pubdir50_free(req);
- db_set_s(hContact, m_szModuleName, GG_KEY_NICK, ditoa(uin));
- netlog("gg_getcontact(): Search for nick on uin: %d", uin);
- }
- }
-
- // Add to notify list and pull avatar for the new contact
- if (isonline())
- {
- PROTO_AVATAR_INFORMATIONT pai = {0};
-
- EnterCriticalSection(&sess_mutex);
- gg_add_notify_ex(sess, uin, (char)(inlist ? GG_USER_NORMAL : GG_USER_OFFLINE));
- LeaveCriticalSection(&sess_mutex);
-
- pai.cbSize = sizeof(pai);
- pai.hContact = hContact;
- getavatarinfo((WPARAM)GAIF_FORCE, (LPARAM)&pai);
-
- // Change status of the contact with our own UIN (if got yourself added to the contact list)
- if (db_get_dw(NULL, m_szModuleName, GG_KEY_UIN, 0) == uin) {
- char *szMsg;
- EnterCriticalSection(&modemsg_mutex);
- szMsg = mir_strdup(getstatusmsg(m_iStatus));
- LeaveCriticalSection(&modemsg_mutex);
- changecontactstatus(uin, status_m2gg(m_iStatus, szMsg != NULL), szMsg, 0, 0, 0, 0);
- mir_free(szMsg);
- }
- }
-
- // TODO server side list & add buddy
- return hContact;
-}
-
-////////////////////////////////////////////////////////////
-// Status conversion
-
-int GGPROTO::status_m2gg(int status, int descr)
-{
- // check frends only
- int mask = db_get_b(NULL, m_szModuleName, GG_KEY_FRIENDSONLY, GG_KEYDEF_FRIENDSONLY) ? GG_STATUS_FRIENDS_MASK : 0;
-
- if (descr)
- {
- switch(status)
- {
- case ID_STATUS_OFFLINE: return GG_STATUS_NOT_AVAIL_DESCR | mask;
- case ID_STATUS_ONLINE: return GG_STATUS_AVAIL_DESCR | mask;
- case ID_STATUS_AWAY: return GG_STATUS_BUSY_DESCR | mask;
- case ID_STATUS_DND: return GG_STATUS_DND_DESCR | mask;
- case ID_STATUS_FREECHAT: return GG_STATUS_FFC_DESCR | mask;
- case ID_STATUS_INVISIBLE: return GG_STATUS_INVISIBLE_DESCR | mask;
- default: return GG_STATUS_BUSY_DESCR | mask;
- }
- }
- else
- {
- switch(status)
- {
- case ID_STATUS_OFFLINE: return GG_STATUS_NOT_AVAIL | mask;
- case ID_STATUS_ONLINE: return GG_STATUS_AVAIL | mask;
- case ID_STATUS_AWAY: return GG_STATUS_BUSY | mask;
- case ID_STATUS_DND: return GG_STATUS_DND | mask;
- case ID_STATUS_FREECHAT: return GG_STATUS_FFC | mask;
- case ID_STATUS_INVISIBLE: return GG_STATUS_INVISIBLE | mask;
- default: return GG_STATUS_BUSY | mask;
- }
- }
-}
-
-int GGPROTO::status_gg2m(int status)
-{
- // ignore additional flags
- status = GG_S(status);
-
- // when user has status description but is offline (show it invisible)
- if (status == GG_STATUS_NOT_AVAIL_DESCR && db_get_b(NULL, m_szModuleName, GG_KEY_SHOWINVISIBLE, GG_KEYDEF_SHOWINVISIBLE))
- return ID_STATUS_INVISIBLE;
-
- // rest of cases
- switch(status)
- {
- case GG_STATUS_NOT_AVAIL:
- case GG_STATUS_NOT_AVAIL_DESCR:
- return ID_STATUS_OFFLINE;
-
- case GG_STATUS_AVAIL:
- case GG_STATUS_AVAIL_DESCR:
- return ID_STATUS_ONLINE;
-
- case GG_STATUS_BUSY:
- case GG_STATUS_BUSY_DESCR:
- return ID_STATUS_AWAY;
-
- case GG_STATUS_DND:
- case GG_STATUS_DND_DESCR:
- return ID_STATUS_DND;
-
- case GG_STATUS_FFC:
- case GG_STATUS_FFC_DESCR:
- return ID_STATUS_FREECHAT;
-
- case GG_STATUS_INVISIBLE:
- case GG_STATUS_INVISIBLE_DESCR:
- return ID_STATUS_INVISIBLE;
-
- case GG_STATUS_BLOCKED:
- return ID_STATUS_NA;
-
- default:
- return ID_STATUS_OFFLINE;
- }
-}
-
-////////////////////////////////////////////////////////////
-// Called when contact status is changed
-
-void GGPROTO::changecontactstatus(uin_t uin, int status, const char *idescr, int time, uint32_t remote_ip, uint16_t remote_port, uint32_t version)
-{
- HANDLE hContact = getcontact(uin, 0, 0, NULL);
-
- // Check if contact is on list
- if (!hContact) return;
-
- // Write contact status
- db_set_w(hContact, m_szModuleName, GG_KEY_STATUS, (WORD)status_gg2m(status));
-
- // Check if there's description and if it's not empty
- if (idescr && *idescr)
- {
- netlog("gg_changecontactstatus(): Saving for %d status descr \"%s\".", uin, idescr);
- db_set_s(hContact, "CList", GG_KEY_STATUSDESCR, idescr);
- }
- else
- // Remove status if there's nothing
- db_unset(hContact, "CList", GG_KEY_STATUSDESCR);
-
- // Store contact ip and port
- if (remote_ip) db_set_dw(hContact, m_szModuleName, GG_KEY_CLIENTIP, (DWORD) swap32(remote_ip));
- if (remote_port) db_set_w(hContact, m_szModuleName, GG_KEY_CLIENTPORT, (WORD) remote_port);
- if (version)
- {
- char sversion[48];
- db_set_dw(hContact, m_szModuleName, GG_KEY_CLIENTVERSION, (DWORD) version);
- mir_snprintf(sversion, sizeof(sversion), "%sGadu-Gadu %s", (version & 0x00ffffff) > 0x2b ? "Nowe " : "", gg_version2string(version));
- db_set_s(hContact, m_szModuleName, "MirVer", sversion);
- }
-}
-
-////////////////////////////////////////////////////////////
-// Returns GG client version string from packet version
-const char *gg_version2string(int v)
-{
- const char *pstr = "???";
- v &= 0x00ffffff;
- switch(v)
- {
- case 0x2e:
- pstr = "8.0 build 8283"; break;
- case 0x2d:
- pstr = "8.0 build 4881"; break;
- case 0x2b:
- pstr = "< 8.0"; break;
- case 0x2a:
- pstr = "7.7 build 3315"; break;
- case 0x29:
- pstr = "7.6 build 1688"; break;
- case 0x28:
- pstr = "7.5 build 2201"; break;
- case 0x27:
- pstr = "7.0 build 22"; break;
- case 0x26:
- pstr = "7.0 build 20"; break;
- case 0x25:
- pstr = "7.0 build 1"; break;
- case 0x24:
- pstr = "6.1 (155) / 7.6 (1359)"; break;
- case 0x22:
- pstr = "6.0 build 140"; break;
- case 0x21:
- pstr = "6.0 build 133"; break;
- case 0x20:
- pstr = "6.0b"; break;
- case 0x1e:
- pstr = "5.7b build 121"; break;
- case 0x1c:
- pstr = "5.7b"; break;
- case 0x1b:
- pstr = "5.0.5"; break;
- case 0x19:
- pstr = "5.0.3"; break;
- case 0x18:
- pstr = "5.0.0-1"; break;
- case 0x17:
- pstr = "4.9.2"; break;
- case 0x16:
- pstr = "4.9.1"; break;
- case 0x15:
- pstr = "4.8.9"; break;
- case 0x14:
- pstr = "4.8.1-3"; break;
- case 0x11:
- pstr = "4.6.1-10"; break;
- case 0x10:
- pstr = "4.5.15-22"; break;
- case 0x0f:
- pstr = "4.5.12"; break;
- case 0x0b:
- pstr = "4.0.25-30"; break;
- default:
- if (v < 0x0b)
- pstr = "< 4.0.25";
- else if (v > 0x2e)
- pstr = ">= 8.0";
- break;
- }
- return pstr;
-}
|