/* S M S D A Linux/Unix GUI for Nokia mobile phones. Copyright (C) 1999 Pavel Janík ml., Hugh Blemings & Ján Derfiòák . Released under the terms of the GNU GPL, see file COPYING for more details. Last modification: Sun Dec 17 2000 Modified by Jan Derfinak */ #define ATS_PRAHA 1 #include #include #include #include #include #include #include #include #include "db.h" #include "smsd.h" #include "gsm-common.h" #include "gsm-ringtones.h" #include "gsm-filetypes.h" static PGconn *connIn = NULL; static PGconn *connOut = NULL; void DB_Bye (void) { if (connIn) PQfinish (connIn); if (connOut) PQfinish (connOut); } gint DB_ConnectInbox (const gchar * const conninfo) { connIn = PQconnectdb (conninfo); if (PQstatus (connIn) == CONNECTION_BAD) { g_print ("Connection to database '%s' failed.\n", conninfo); g_print ("%s", PQerrorMessage(connIn)); return (1); } return (0); } gint DB_ConnectOutbox (const gchar * const conninfo) { connOut = PQconnectdb (conninfo); if (PQstatus (connOut) == CONNECTION_BAD) { g_print ("Connection to database '%s' failed.\n", conninfo); g_print ("%s", PQerrorMessage(connOut)); return (1); } return (0); } gint DB_InsertSMS (const GSM_SMSMessage * const data) { GString *buf; PGresult *res; buf = g_string_sized_new (128); g_string_sprintf (buf, "INSERT INTO inbox VALUES ('%s', '%02d-%02d-%02d %02d:%02d:%02d+01', 'now', '%s', 'f')", data->Sender, data->Time.Year + 2000, data->Time.Month, data->Time.Day, data->Time.Hour, data->Time.Minute, data->Time.Second, data->MessageText); res = PQexec(connIn, buf->str); g_string_free(buf, TRUE); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { PQclear (res); return (1); } PQclear (res); return (0); } #define DBL_FieldString "id, number, text, hexencode, type, fromfile, netcode, udhpresent, longuseudh, eightbit, smsc" enum DBL_Field { DBLF_id, DBLF_number, DBLF_text, DBLF_hexencode, DBLF_type, DBLF_fromfile, DBLF_netcode, DBLF_udhpresent, DBLF_longuseudh, DBLF_eightbit, DBLF_smsc, }; #define DBL_true "t" #define DBL_false "f" static int DBL_safestrcasecmp(const char *s1,const char *s2) { if (!s1 || !s2) return((!!s1)-(!!s2)); return(strcasecmp(s1,s2)); } void DB_Look (void) { GString *buf; PGresult *res1, *res2; register int i; buf = g_string_sized_new (128); #ifndef ATS_PRAHA g_string_sprintf (buf, "BEGIN"); res1 = PQexec(connOut, buf->str); PQclear (res1); #endif g_string_sprintf (buf, "SELECT " DBL_FieldString " FROM outbox \ WHERE processed='f' FOR UPDATE"); res1 = PQexec(connOut, buf->str); if (!res1 || PQresultStatus (res1) != PGRES_TUPLES_OK) { g_print ("%s\n", PQcmdStatus (res1)); PQclear (res1); g_print ("%d: SELECT FROM command failed\n", __LINE__); res1 = PQexec (connOut, "ROLLBACK TRANSACTION"); PQclear (res1); g_string_free (buf, TRUE); return; } for (i = 0; i < PQntuples (res1); i++) { GSM_SMSMessage sms; char *type = PQgetvalue (res1, i, DBLF_type); bool fromfile = !DBL_safestrcasecmp(DBL_true, PQgetvalue (res1, i, DBLF_fromfile)); char *smsc = PQgetvalue (res1, i, DBLF_smsc); char *smsbuf = PQgetvalue (res1, i, DBLF_text); size_t smsbuflen = strlen(smsbuf); bool sendlogo; if (!smsc) sms.MessageCenter.No = 1; else { sms.MessageCenter.No = 0; if (strlen(smsc)+1 > sizeof(sms.MessageCenter.Number)) continue; /* error */ strcpy(sms.MessageCenter.Number, smsc); } sms.Type = GST_MO; sms.Class = -1; sms.Compression = false; sms.EightBit = !DBL_safestrcasecmp(DBL_true, PQgetvalue (res1, i, DBLF_eightbit)); sms.Validity = 4320; sms.UDHPresent = !DBL_safestrcasecmp(DBL_true, PQgetvalue (res1, i, DBLF_udhpresent)); if (!DBL_safestrcasecmp(DBL_true, PQgetvalue (res1, i, DBLF_hexencode))) { char *d_end = (char *)SMS_BlockFromHex(smsbuf/*d*/, smsbuf/*s*/, smsbuflen); if (!d_end) continue; smsbuflen = d_end - smsbuf; } sendlogo=false; if (!DBL_safestrcasecmp("ringtone" ,type)) { SMS_SetupUDH(&sms, GSM_RingtoneUDH); if (fromfile) { GSM_Ringtone ringtone; static char ringbuf[GSM_MAX_RINGTONE_PACKAGE_LENGTH]; int ringbuflen=GSM_MAX_RINGTONE_PACKAGE_LENGTH; if (GSM_ReadRingtoneFile(smsbuf, &ringtone)) continue; /* error */ GSM_PackRingtone(&ringtone, ringbuf, &ringbuflen); smsbuf=ringbuf; smsbuflen=ringbuflen; } } else if (!DBL_safestrcasecmp("oplogo" ,type)) { SMS_SetupUDH(&sms, GSM_OpLogo); sendlogo=true; } else if (!DBL_safestrcasecmp("calleridlogo",type)) { SMS_SetupUDH(&sms, GSM_CallerIDLogo); sendlogo=true; } else { /* "text" */ if (fromfile) { static char textbuf[GSM_MAX_CONCATENATED_SMS_LENGTH]; int textbuflen; int fd; if (-1==(fd=open(smsbuf,O_RDONLY))) continue; /* error */ if (-1==(textbuflen=read(fd,textbuf,sizeof(textbuf)))) continue; /* error */ close(fd); smsbuf=textbuf; smsbuflen=textbuflen; } if (sms.UDHPresent) { u8 len=1+(*(u8 *)smsbuf); if (len>smsbuflen || len>sizeof(sms.UDH)) g_print ("%d: UDH too long: UDHlen=%d, smsbuflen=%d, sizeof(sms.UDH)=%d !!!\n", __LINE__, len, smsbuflen,sizeof(sms.UDH)); else { memcpy(sms.UDH,smsbuf,len); memmove(smsbuf,smsbuf+len,smsbuflen-len); smsbuflen-=len; } } } if (sendlogo) { GSM_Bitmap bitmap; static u8 bin[sizeof(bitmap.bitmap) +64/*headers safety*/]; u8 *d; char *usernetcode=PQgetvalue (res1, i, DBLF_netcode); if (GE_NONE!=GSM_ReadBitmapFile(smsbuf, &bitmap)) continue; /* error */ d=bin; if (!DBL_safestrcasecmp("oplogo" ,type)) { if (usernetcode) { if (strlen(usernetcode)+1 > sizeof(bitmap.netcode)) continue; /* error */ strcpy(bitmap.netcode, usernetcode); } *d++ = ((bitmap.netcode[1] & 0x0f) << 4) | (bitmap.netcode[0] & 0xf); *d++ = 0xf0 | (bitmap.netcode[2] & 0x0f); *d++ = ((bitmap.netcode[5] & 0x0f) << 4) | (bitmap.netcode[4] & 0xf); } /* Set the logo size */ *d++ = 0x00; /* RFU by Nokia */ *d++ = bitmap.width; *d++ = bitmap.height; *d++ = 0x01; /* depth=number of grayscales */ memcpy(d,bitmap.bitmap,bitmap.size); d+=bitmap.size; smsbuf=bin; smsbuflen=d-bin; } strncpy (sms.Destination, PQgetvalue (res1, i, DBLF_number), GSM_MAX_DESTINATION_LENGTH + 1); sms.Destination[GSM_MAX_DESTINATION_LENGTH] = '\0'; #ifdef XDEBUG g_print ("To: %s\n", sms.Destination); #endif if (GE_SMSSENDOK == WriteSMS_deconcatenated (&sms, smsbuf, smsbuflen, !DBL_safestrcasecmp(DBL_true, PQgetvalue (res1, i, DBLF_longuseudh)))) { g_string_sprintf (buf, "UPDATE outbox SET processed='t' WHERE id='%s'", PQgetvalue (res1, i, DBLF_id)); res2 = PQexec(connOut, buf->str); if (!res2 || PQresultStatus (res2) != PGRES_COMMAND_OK) { g_print ("%s\n", PQcmdStatus (res2)); g_print ("%d: UPDATE command failed\n", __LINE__); } PQclear (res2); } } PQclear (res1); #ifndef ATS_PRAHA g_string_sprintf (buf, "COMMIT"); res1 = PQexec(connOut, buf->str); PQclear (res1); #endif g_string_free(buf, TRUE); #ifdef ATS_PRAHA if (!access("/tmp/smsd-exit",F_OK)) { g_print("/tmp/smsd-exit exists, terminating\n"); if (unlink("/tmp/smsd-exit")) g_print("/tmp/smsd-exit unlink failed: %s\n",strerror(errno)); exit(0); } #endif }