diff options
Diffstat (limited to 'smsd')
-rw-r--r-- | smsd/core.c | 106 | ||||
-rw-r--r-- | smsd/core.h | 6 | ||||
-rw-r--r-- | smsd/main.c | 4 | ||||
-rw-r--r-- | smsd/services/odbc.c | 7 | ||||
-rw-r--r-- | smsd/services/sql-core.h | 4 | ||||
-rw-r--r-- | smsd/services/sql.c | 149 | ||||
-rwxr-xr-x | smsd/test-smsd.sh.in | 14 | ||||
-rw-r--r-- | smsd/uid.c | 4 |
8 files changed, 249 insertions, 45 deletions
diff --git a/smsd/core.c b/smsd/core.c index 80bbe3c..ff99f1b 100644 --- a/smsd/core.c +++ b/smsd/core.c @@ -139,6 +139,7 @@ void SMSD_SendSMSStatusCallback (GSM_StateMachine *sm, int status, int mr, void } else { Config->SendingSMSStatus = ERR_UNKNOWN; } + Config->StatusCode = status; } /** @@ -385,6 +386,7 @@ void SMSD_Log_Function(const char *text, void *data) GSM_SMSDConfig *SMSD_NewConfig(const char *name) { GSM_SMSDConfig *Config; + int i; Config = (GSM_SMSDConfig *)malloc(sizeof(GSM_SMSDConfig)); if (Config == NULL) return Config; @@ -418,6 +420,10 @@ GSM_SMSDConfig *SMSD_NewConfig(const char *name) Config->conn.pg = NULL; #endif + for (i = 0; i < GSM_MAX_MULTI_SMS; i++) { + Config->SkipMessage[i] = FALSE; + } + /* Prepare lists */ GSM_StringArray_New(&(Config->IncludeNumbersList)); GSM_StringArray_New(&(Config->ExcludeNumbersList)); @@ -862,6 +868,7 @@ GSM_Error SMSD_ReadConfig(const char *filename, GSM_SMSDConfig *Config, gboolean Config->RunOnReceive = INI_GetValue(Config->smsdcfgfile, "smsd", "runonreceive", FALSE); Config->RunOnFailure = INI_GetValue(Config->smsdcfgfile, "smsd", "runonfailure", FALSE); Config->RunOnSent = INI_GetValue(Config->smsdcfgfile, "smsd", "runonsent", FALSE); + Config->RunOnIncomingCall = INI_GetValue(Config->smsdcfgfile, "smsd", "runonincomingcall", FALSE); str = INI_GetValue(Config->smsdcfgfile, "smsd", "smsc", FALSE); if (str) { @@ -1061,6 +1068,9 @@ void SMSD_RunOnReceiveEnvironment(GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Conf sprintf(buffer, "%d", sms->SMS[i].Class); sprintf(name, "SMS_%d_CLASS", i + 1); setenv(name, buffer, 1); + sprintf(buffer, "%d", sms->SMS[i].MessageReference); + sprintf(name, "SMS_%d_REFERENCE", i + 1); + setenv(name, buffer, 1); sprintf(name, "SMS_%d_NUMBER", i + 1); setenv(name, DecodeUnicodeConsole(sms->SMS[i].Number), 1); if (sms->SMS[i].Coding != SMS_Coding_8bit && sms->SMS[i].UDH.Type != UDH_UserUDH) { @@ -1113,7 +1123,7 @@ void SMSD_RunOnReceiveEnvironment(GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Conf * * This is Windows variant. */ -gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, const char *locations) +gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, const char *locations, const char *event) { BOOL ret; STARTUPINFO si; @@ -1131,7 +1141,7 @@ gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfi si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); - SMSD_Log(DEBUG_INFO, Config, "Starting run on command: %s", cmdline); + SMSD_Log(DEBUG_INFO, Config, "Starting run on %s: %s", event, cmdline); ret = CreateProcess(NULL, /* No module name (use command line) */ cmdline, /* Command line */ @@ -1160,7 +1170,7 @@ gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfi * * This is POSIX variant. */ -gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, const char *locations) +gboolean SMSD_RunOn(const char *command, GSM_MultiSMSMessage *sms, GSM_SMSDConfig *Config, const char *locations, const char *event) { int pid; int pipefd[2]; @@ -1253,7 +1263,7 @@ out: /* Calculate command line */ cmdline = SMSD_RunOnCommand(locations, command); - SMSD_Log(DEBUG_INFO, Config, "Starting run on receive: %s", cmdline); + SMSD_Log(DEBUG_INFO, Config, "Starting run on %s: %s", event, cmdline); /* Close all file descriptors */ for (i = 0; i < 255; i++) { @@ -1363,7 +1373,7 @@ GSM_Error SMSD_ProcessSMS(GSM_SMSDConfig *Config, GSM_MultiSMSMessage *sms) error = Config->Service->SaveInboxSMS(sms, Config, &locations); /* RunOnReceive handling */ if (Config->RunOnReceive != NULL && error == ERR_NONE) { - SMSD_RunOn(Config->RunOnReceive, sms, Config, locations); + SMSD_RunOn(Config->RunOnReceive, sms, Config, locations, "receive"); } /* Free memory allocated by SaveInboxSMS */ free(locations); @@ -1653,6 +1663,7 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config) GSM_Error error; unsigned int j; int i, z; + char destinationnumber[3 * GSM_MAX_NUMBER_LENGTH + 1]; /* Clean structure before use */ for (i = 0; i < GSM_MAX_MULTI_SMS; i++) { @@ -1683,6 +1694,10 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config) if (Config->SMSID[0] != 0 && (Config->retries > Config->maxretries)) { SMSD_Log(DEBUG_NOTICE, Config, "Moved to errorbox, reached MaxRetries: %s", Config->SMSID); for (i=0;i<sms.Number;i++) { + if (Config->SkipMessage[i] == TRUE) { + SMSD_Log(DEBUG_NOTICE, Config, "Skipping %s:%d message for errorbox", Config->SMSID, i+1); + continue; + } Config->Status->Failed++; Config->Service->AddSentSMSInfo(&sms, Config, Config->SMSID, i + 1, SMSD_SEND_SENDING_ERROR, Config->TPMR); } @@ -1694,6 +1709,11 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config) } for (i = 0; i < sms.Number; i++) { + if (Config->SkipMessage[i] == TRUE) { + SMSD_Log(DEBUG_NOTICE, Config, "Skipping %s:%d message for delivery", Config->SMSID, i+1); + continue; + } + /* No SMSC set in message */ if (sms.SMS[i].SMSC.Location == 0 && UnicodeLength(sms.SMS[i].SMSC.Number) == 0 && Config->SMSC.Location == 0) { SMSD_Log(DEBUG_INFO, Config, "Message without SMSC, using configured one"); @@ -1739,7 +1759,22 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config) SMSD_PhoneStatus(Config); Config->TPMR = -1; Config->SendingSMSStatus = ERR_TIMEOUT; - error = GSM_SendSMS(Config->gsm, &sms.SMS[i]); + Config->StatusCode = -1; + Config->Part = i + 1; + if (sms.SMS[i].Class == GSM_SMS_USSD) { + EncodeUTF8(destinationnumber, sms.SMS[i].Number); + SMSD_Log(DEBUG_NOTICE, Config, "Sending USSD request to %s", destinationnumber); + error = GSM_DialService(Config->gsm, destinationnumber); + /* Fallback to voice call, it can work with some phones */ + if (error == ERR_NOTIMPLEMENTED || error == ERR_NOTSUPPORTED) { + error = GSM_DialVoice(Config->gsm, destinationnumber, GSM_CALL_DefaultNumberPresence); + } + if (error == ERR_NONE) { + Config->SendingSMSStatus = ERR_NONE; + } + } else { + error = GSM_SendSMS(Config->gsm, &sms.SMS[i]); + } if (error != ERR_NONE) { SMSD_LogError(DEBUG_INFO, Config, "Error sending SMS", error); Config->TPMR = -1; @@ -1787,13 +1822,13 @@ GSM_Error SMSD_SendSMS(GSM_SMSDConfig *Config) } if (Config->RunOnSent != NULL && error == ERR_NONE) { - SMSD_RunOn(Config->RunOnSent, &sms, Config, Config->SMSID); + SMSD_RunOn(Config->RunOnSent, &sms, Config, Config->SMSID, "sent"); } return ERR_NONE; failure_unsent: if (Config->RunOnFailure != NULL) { - SMSD_RunOn(Config->RunOnFailure, NULL, Config, Config->SMSID); + SMSD_RunOn(Config->RunOnFailure, NULL, Config, Config->SMSID, "failure"); } Config->Status->Failed++; @@ -1924,6 +1959,7 @@ GSM_Error SMSD_FreeSharedMemory(GSM_SMSDConfig *Config, gboolean writable) */ void SMSD_IncomingCallCallback(GSM_StateMachine *s, GSM_Call *call, void *user_data) { GSM_SMSDConfig *Config = user_data; + GSM_Error error; switch (call->Status) { case GSM_CALL_IncomingCall: { time_t now = time(NULL); @@ -1933,9 +1969,26 @@ void SMSD_IncomingCallCallback(GSM_StateMachine *s, GSM_Call *call, void *user_d SMSD_Log(DEBUG_INFO, Config, "Incoming call! # hanging up @%ld %ld.\n", now, lastRing); lastRing = now; if (call->CallIDAvailable) { - GSM_CancelCall(s, call->CallID, TRUE); - } else { - GSM_CancelCall(s, 0, TRUE); + error = GSM_CancelCall(s, call->CallID, TRUE); + } + if (!call->CallIDAvailable || error == ERR_NOTSUPPORTED) { + error = GSM_CancelCall(s, 0, TRUE); + } + if (error != ERR_NONE) { + SMSD_LogError(DEBUG_ERROR, Config, "Failed call hangup!", error); + } + + if (Config->RunOnIncomingCall != NULL) { +#define BUFS 1024 + char buf[BUFS]; + int ret=0; + snprintf(buf, BUFS,"%s '%s'", + Config->RunOnIncomingCall, + DecodeUnicodeString(call->PhoneNumber)); + ret = system(buf); + if (ret<0) { + SMSD_Log(DEBUG_ERROR, Config, "Incoming call - could not run script: %s\n", strerror(errno) ); + } } } break; @@ -1950,6 +2003,29 @@ void SMSD_IncomingCallCallback(GSM_StateMachine *s, GSM_Call *call, void *user_d } } +void SMSD_IncomingUSSDCallback(GSM_StateMachine *sm UNUSED, GSM_USSDMessage *ussd, void *user_data) +{ + GSM_MultiSMSMessage sms; + GSM_Error error; + GSM_SMSDConfig *Config = user_data; + + SMSD_Log(DEBUG_NOTICE, Config, "%s", __FUNCTION__); + + memset(&sms, 0, sizeof(GSM_MultiSMSMessage)); + sms.Number = 1; + sms.SMS[0].Class = GSM_SMS_USSD; + memcpy(&sms.SMS[0].Text, ussd->Text, UnicodeLength(ussd->Text)*2); + sms.SMS[0].PDU = SMS_Deliver; + sms.SMS[0].Coding = SMS_Coding_Unicode_No_Compression; + GSM_GetCurrentDateTime(&sms.SMS[0].DateTime); + sms.SMS[0].DeliveryStatus = ussd->Status; + + error = SMSD_ProcessSMS(Config, &sms); + if (error != ERR_NONE) { + SMSD_LogError(DEBUG_INFO, Config, "Error processing USSD", error); + } +} + /** * Main loop which takes care of connection to phone and processing of * messages. @@ -2010,7 +2086,7 @@ GSM_Error SMSD_MainLoop(GSM_SMSDConfig *Config, gboolean exit_on_failure, int ma error = GSM_InitConnection_Log(Config->gsm, 2, SMSD_Log_Function, Config); /* run on error */ if (error != ERR_NONE && Config->RunOnFailure != NULL) { - SMSD_RunOn(Config->RunOnFailure, NULL, Config, "INIT"); + SMSD_RunOn(Config->RunOnFailure, NULL, Config, "INIT", "failure"); } switch (error) { case ERR_NONE: @@ -2029,6 +2105,9 @@ GSM_Error SMSD_MainLoop(GSM_SMSDConfig *Config, gboolean exit_on_failure, int ma /* We use polling so store messages to SIM */ GSM_SetIncomingSMS(Config->gsm, TRUE); + GSM_SetIncomingUSSDCallback(Config->gsm, SMSD_IncomingUSSDCallback, Config); + GSM_SetIncomingUSSD(Config->gsm, TRUE); + GSM_SetSendSMSStatusCallback(Config->gsm, SMSD_SendSMSStatusCallback, Config); /* On first start we need to initialize some variables */ if (first_start) { @@ -2039,7 +2118,7 @@ GSM_Error SMSD_MainLoop(GSM_SMSDConfig *Config, gboolean exit_on_failure, int ma error = Config->Service->InitAfterConnect(Config); if (error!=ERR_NONE) { if (Config->RunOnFailure != NULL) { - SMSD_RunOn(Config->RunOnFailure, NULL, Config, "INIT"); + SMSD_RunOn(Config->RunOnFailure, NULL, Config, "INIT", "failure"); } SMSD_Terminate(Config, "Post initialisation failed, stopping Gammu smsd", error, TRUE, -1); goto done_connected; @@ -2150,6 +2229,7 @@ GSM_Error SMSD_MainLoop(GSM_SMSDConfig *Config, gboolean exit_on_failure, int ma SMSD_InterruptibleSleep(Config, Config->loopsleep - lastsleep); } } + GSM_SetIncomingUSSD(Config->gsm, FALSE); Config->Service->Free(Config); done_connected: diff --git a/smsd/core.h b/smsd/core.h index 9e7928e..de3476e 100644 --- a/smsd/core.h +++ b/smsd/core.h @@ -17,7 +17,7 @@ #define SMSD_SHM_VERSION (2) #define SMSD_SHM_KEY (0xfa << 16 || SMSD_SHM_VERSION) -#define SMSD_DB_VERSION (16) +#define SMSD_DB_VERSION (17) #include "log.h" @@ -87,6 +87,7 @@ struct _GSM_SMSDConfig { const char *RunOnReceive; const char *RunOnFailure; /* run this command on phone communication failure */ const char *RunOnSent; /* run this command when an SMS has been sent successfully */ + const char *RunOnIncomingCall; /* run this command when a phone call has been canceled */ gboolean checksecurity; gboolean hangupcalls; gboolean checkbattery; @@ -109,6 +110,7 @@ struct _GSM_SMSDConfig { GSM_SMSC SMSC, SMSCCache; const char *skipsmscnumber; int IgnoredMessages; + gboolean SkipMessage[GSM_MAX_MULTI_SMS]; #if defined(HAVE_MYSQL_MYSQL_H) || defined(HAVE_POSTGRESQL_LIBPQ_FE_H) || defined(LIBDBI_FOUND) || defined(ODBC_FOUND) /* options for SQL database */ @@ -195,6 +197,8 @@ struct _GSM_SMSDConfig { * Message reference set by callback from libGammu. */ volatile int TPMR; + volatile int StatusCode; + volatile int Part; /** * Multipart messages processing. diff --git a/smsd/main.c b/smsd/main.c index c3e4c3e..afde2aa 100644 --- a/smsd/main.c +++ b/smsd/main.c @@ -247,13 +247,13 @@ void process_commandline(int argc, char **argv, SMSD_Parameters * params) #ifdef HAVE_UID case 'U': if (!fill_uid(params, optarg)) { - fprintf(stderr, "Wrong user name/ID!\n"); + fprintf(stderr, "Wrong user name or ID: %s\n", optarg); exit(1); } break; case 'G': if (!fill_gid(params, optarg)) { - fprintf(stderr, "Wrong group name/ID!\n"); + fprintf(stderr, "Wrong group name or ID: %s\n", optarg); exit(1); } break; diff --git a/smsd/services/odbc.c b/smsd/services/odbc.c index a57a1a0..e3c385e 100644 --- a/smsd/services/odbc.c +++ b/smsd/services/odbc.c @@ -125,9 +125,14 @@ const char *SMSDODBC_GetString(GSM_SMSDConfig * Config, SQL_result *res, unsigne gboolean SMSDODBC_GetBool(GSM_SMSDConfig * Config, SQL_result *res, unsigned int field) { - long long intval; + long long intval = 0; const char * charval; + /* Try bit field */ + if (SQL_SUCCEEDED(SQLGetData(res->odbc, field + 1, SQL_C_BIT, &intval, 0, NULL))) { + return intval ? TRUE : FALSE; + } + /* Try to get numeric value first */ intval = SMSDODBC_GetNumber(Config, res, field); if (intval == -1) { diff --git a/smsd/services/sql-core.h b/smsd/services/sql-core.h index 0383b9a..16e395e 100644 --- a/smsd/services/sql-core.h +++ b/smsd/services/sql-core.h @@ -119,6 +119,10 @@ enum { SQL_QUERY_DELETE_OUTBOX_MULTIPART, SQL_QUERY_CREATE_OUTBOX, SQL_QUERY_CREATE_OUTBOX_MULTIPART, + SQL_QUERY_UPDATE_OUTBOX, + SQL_QUERY_UPDATE_OUTBOX_MULTIPART, + SQL_QUERY_UPDATE_OUTBOX_STATUSCODE, + SQL_QUERY_UPDATE_OUTBOX_MULTIPART_STATUSCODE, SQL_QUERY_ADD_SENT_INFO, SQL_QUERY_UPDATE_SENT, SQL_QUERY_REFRESH_PHONE_STATUS, diff --git a/smsd/services/sql.c b/smsd/services/sql.c index 9e3ef33..1a2da63 100644 --- a/smsd/services/sql.c +++ b/smsd/services/sql.c @@ -49,7 +49,7 @@ const char now_plus_pgsql[] = "now() + interval '%d seconds'"; const char now_plus_sqlite[] = "datetime('now', '+%d seconds', 'localtime')"; const char now_plus_freetds[] = "DATEADD('second', %d, CURRENT_TIMESTAMP)"; const char now_plus_access[] = "now()+#00:00:%d#"; -const char now_plus_oracle[] = "CURRENT_TIMESTAMP + INTERVAL '%d' SECOND'"; +const char now_plus_oracle[] = "CURRENT_TIMESTAMP + INTERVAL '%d' SECOND"; const char now_plus_fallback[] = "NOW() + INTERVAL %d SECOND"; @@ -99,7 +99,9 @@ static const char *SMSDSQL_EscapeChar(GSM_SMSDConfig * Config) return escape_char_pgsql; } else if (strncasecmp(driver_name, "sqlite", 6) == 0) { return escape_char_sqlite; - } else if (strcasecmp(driver_name, "oracle") == 0 || strcasecmp(driver_name, "freetds") == 0 || strcasecmp(driver_name, "mssql") == 0 || strcasecmp(driver_name, "sybase") == 0) { + } else if (strcasecmp(driver_name, "oracle") == 0) { + return escape_char_fallback; + } else if (strcasecmp(driver_name, "freetds") == 0 || strcasecmp(driver_name, "mssql") == 0 || strcasecmp(driver_name, "sybase") == 0) { return escape_char_freetds; } else if (strcasecmp(Config->driver, "odbc") == 0 || strcasecmp(Config->driver, "mssql") == 0) { return escape_char_odbc; @@ -222,9 +224,9 @@ static const char *SMSDSQL_Now(GSM_SMSDConfig * Config) return now_pgsql; } else if (strncasecmp(driver_name, "sqlite", 6) == 0) { return now_sqlite; - } else if (strcasecmp(Config->driver, "oracle") == 0 || strcasecmp(driver_name, "freetds") == 0 || strcasecmp(driver_name, "mssql") == 0 || strcasecmp(driver_name, "sybase") == 0) { + } else if (strcasecmp(driver_name, "oracle") == 0 || strcasecmp(driver_name, "freetds") == 0 || strcasecmp(driver_name, "mssql") == 0 || strcasecmp(driver_name, "sybase") == 0) { return now_freetds; - } else if (strcasecmp(Config->driver, "access") == 0) { + } else if (strcasecmp(driver_name, "access") == 0) { return now_access; } else if (strcasecmp(Config->driver, "odbc") == 0) { return now_odbc; @@ -384,7 +386,16 @@ static GSM_Error SMSDSQL_NamedQuery(GSM_SMSDConfig * Config, const char *sql_que if (sms != NULL) { switch (c) { case 'R': - EncodeUTF8(static_buff, sms->Number); + /* + * Always store international numnbers with + prefix + * to allow easy matching later. + */ + if (sms->Number[0] == '0' && sms->Number[1] == '0') { + static_buff[0] = '+'; + EncodeUTF8(static_buff + 1, sms->Number + 2); + } else { + EncodeUTF8(static_buff, sms->Number); + } to_print = static_buff; break; case 'F': @@ -674,8 +685,8 @@ static GSM_Error SMSDSQL_SaveInboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig found = FALSE; while (db->NextRow(Config, &res)) { - smsc = db->GetString(Config, &res, 4); state = db->GetString(Config, &res, 1); + smsc = db->GetString(Config, &res, 4); SMSD_Log(DEBUG_NOTICE, Config, "Checking for delivery report, SMSC=%s, state=%s", smsc, state); if (strcmp(smsc, smsc_message) != 0) { @@ -814,12 +825,18 @@ static GSM_Error SMSDSQL_UpdateRetries(GSM_SMSDConfig * Config, char *ID) { SQL_result res; GSM_Error error; + size_t query_type; struct GSM_SMSDdbobj *db = Config->db; - SQL_Var vars[3] = { + /* 1 = ID, 2 = Retries, 3 = StatusCode, 4 = SequencePosition */ + SQL_Var vars[5] = { {SQL_TYPE_STRING, {ID}}, {SQL_TYPE_INT, {NULL}}, + {SQL_TYPE_INT, {NULL}}, + {SQL_TYPE_INT, {NULL}}, {SQL_TYPE_NONE, {NULL}}}; vars[1].v.i = Config->retries; + vars[2].v.i = Config->StatusCode; + vars[3].v.i = Config->Part; error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[SQL_QUERY_UPDATE_RETRIES], NULL, vars, &res); if (error != ERR_NONE) { @@ -833,6 +850,17 @@ static GSM_Error SMSDSQL_UpdateRetries(GSM_SMSDConfig * Config, char *ID) } db->FreeResult(Config, &res); + + if (Config->StatusCode != -1) { + query_type = (Config->Part == 1) ? SQL_QUERY_UPDATE_OUTBOX_STATUSCODE : SQL_QUERY_UPDATE_OUTBOX_MULTIPART_STATUSCODE; + error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[query_type], NULL, vars, &res); + if (error != ERR_NONE) { + SMSD_Log(DEBUG_INFO, Config, "Error updating StatusCode (%s)", __FUNCTION__); + return error; + } + db->FreeResult(Config, &res); + } + return ERR_NONE; } @@ -844,6 +872,7 @@ static GSM_Error SMSDSQL_FindOutboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig SQL_result res; struct GSM_SMSDdbobj *db = Config->db; int i; + gboolean last; time_t timestamp; const char *coding; const char *text; @@ -852,6 +881,7 @@ static GSM_Error SMSDSQL_FindOutboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig const char *destination; const char *udh; const char *q; + const char *status; size_t udh_len; SQL_Var vars[3]; GSM_Error error; @@ -917,21 +947,33 @@ static GSM_Error SMSDSQL_FindOutboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig return ERR_NONE; } - coding = db->GetString(Config, &res, 1); + status = db->GetString(Config, &res, i == 1 ? 12 : 7); + if (status != NULL && strncmp(status, "SendingOK", 9) == 0) { + SMSD_Log(DEBUG_NOTICE, Config, "Marking %s:%d message for skip", ID, i); + Config->SkipMessage[sms->Number] = TRUE; + } else { + Config->SkipMessage[sms->Number] = FALSE; + } + text = db->GetString(Config, &res, 0); + coding = db->GetString(Config, &res, 1); if (text == NULL) { text_len = 0; } else { text_len = strlen(text); } - text_decoded = db->GetString(Config, &res, 4); udh = db->GetString(Config, &res, 2); + sms->SMS[sms->Number].Class = (int)db->GetNumber(Config, &res, 3); + text_decoded = db->GetString(Config, &res, 4); if (udh == NULL) { udh_len = 0; } else { udh_len = strlen(udh); } + /* ID, we don't need it, but some ODBC backend need to fetch all values */ + db->GetNumber(Config, &res, 5); + sms->SMS[sms->Number].Coding = GSM_StringToSMSCoding(coding); if (sms->SMS[sms->Number].Coding == 0) { if (text == NULL || text_len == 0) { @@ -996,26 +1038,24 @@ static GSM_Error SMSDSQL_FindOutboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig } } - sms->SMS[sms->Number].Class = (int)db->GetNumber(Config, &res, 3); sms->SMS[sms->Number].PDU = SMS_Submit; sms->Number++; if (i == 1) { - strncpy(Config->CreatorID, db->GetString(Config, &res, 10), sizeof(Config->CreatorID)); - Config->CreatorID[sizeof(Config->CreatorID) - 1] = 0; + /* Is this a multipart message? */ + last = !db->GetBool(Config, &res, 7); Config->relativevalidity = (int)db->GetNumber(Config, &res, 8); Config->currdeliveryreport = db->GetBool(Config, &res, 9); + strncpy(Config->CreatorID, db->GetString(Config, &res, 10), sizeof(Config->CreatorID)); + Config->CreatorID[sizeof(Config->CreatorID) - 1] = 0; Config->retries = (int)db->GetNumber(Config, &res, 11); - - /* Is this a multipart message? */ - if (!db->GetBool(Config, &res, 7)) { - db->FreeResult(Config, &res); - break; - } - } db->FreeResult(Config, &res); + if (last) { + last = FALSE; + break; + } } return ERR_NONE; @@ -1110,9 +1150,10 @@ static GSM_Error SMSDSQL_AddSentSMSInfo(GSM_MultiSMSMessage * sms, GSM_SMSDConfi SQL_result res; struct GSM_SMSDdbobj *db = Config->db; GSM_Error error; + size_t query_type; const char *message_state; - SQL_Var vars[6]; + SQL_Var vars[7]; char smsc[GSM_MAX_NUMBER_LENGTH + 1]; char destination[GSM_MAX_NUMBER_LENGTH + 1]; @@ -1150,6 +1191,22 @@ static GSM_Error SMSDSQL_AddSentSMSInfo(GSM_MultiSMSMessage * sms, GSM_SMSDConfi vars[4].v.s = Config->DT; vars[5].type = SQL_TYPE_NONE; + query_type = (Part == 1) ? SQL_QUERY_FIND_OUTBOX_BODY : SQL_QUERY_FIND_OUTBOX_MULTIPART; + error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[query_type], NULL, vars, &res); + if (error != ERR_NONE) { + SMSD_Log(DEBUG_ERROR, Config, "Error reading from database (%s)", __FUNCTION__); + return error; + } + if (db->NextRow(Config, &res) != 1) { + db->FreeResult(Config, &res); + return ERR_NONE; + } + /* 6 = StatusCode */ + vars[5].type = SQL_TYPE_INT; + vars[5].v.i = (int)db->GetNumber(Config, &res, Part == 1 ? 13 : 8); + vars[6].type = SQL_TYPE_NONE; + db->FreeResult(Config, &res); + error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[SQL_QUERY_ADD_SENT_INFO], &sms->SMS[Part - 1], vars, &res); if (error != ERR_NONE) { SMSD_Log(DEBUG_INFO, Config, "Error writing to database (%s)", __FUNCTION__); @@ -1164,6 +1221,16 @@ static GSM_Error SMSDSQL_AddSentSMSInfo(GSM_MultiSMSMessage * sms, GSM_SMSDConfi } db->FreeResult(Config, &res); + if (sms->Number != 1) { + query_type = (Part == 1) ? SQL_QUERY_UPDATE_OUTBOX : SQL_QUERY_UPDATE_OUTBOX_MULTIPART; + error = SMSDSQL_NamedQuery(Config, Config->SMSDSQL_queries[query_type], &sms->SMS[Part - 1], vars, &res); + if (error != ERR_NONE) { + SMSD_Log(DEBUG_INFO, Config, "Error updating status of multipart messages (%s)", __FUNCTION__); + return error; + } + db->FreeResult(Config, &res); + } + return ERR_NONE; } @@ -1426,8 +1493,9 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config) ", ", ESCAPE_FIELD("UDH"), ", ", ESCAPE_FIELD("Class"), ", ", ESCAPE_FIELD("TextDecoded"), - ", ", ESCAPE_FIELD("RecipientID"), ")" - " VALUES (%d, %E, %R, %c, %F, %u, %x, %T, %P)", NULL) != ERR_NONE) { + ", ", ESCAPE_FIELD("RecipientID"), + ", ", ESCAPE_FIELD("Status"), ")", + " VALUES (%d, %E, %R, %c, %F, %u, %x, %T, %P, %e)", NULL) != ERR_NONE) { return ERR_UNKNOWN; } @@ -1486,6 +1554,8 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config) ", ", ESCAPE_FIELD("DeliveryReport"), ", ", ESCAPE_FIELD("CreatorID"), ", ", ESCAPE_FIELD("Retries"), + ", ", ESCAPE_FIELD("Status"), + ", ", ESCAPE_FIELD("StatusCode"), " FROM ", Config->table_outbox, " WHERE ", ESCAPE_FIELD("ID"), "=%1", NULL) != ERR_NONE) { return ERR_UNKNOWN; @@ -1500,6 +1570,8 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config) ", ", ESCAPE_FIELD("TextDecoded"), ", ", ESCAPE_FIELD("ID"), ", ", ESCAPE_FIELD("SequencePosition"), + ", ", ESCAPE_FIELD("Status"), + ", ", ESCAPE_FIELD("StatusCode"), " FROM ", Config->table_outbox_multipart, " WHERE ", ESCAPE_FIELD("ID"), "=%1 AND ", ESCAPE_FIELD("SequencePosition"), "=%2", NULL) != ERR_NONE) { @@ -1547,6 +1619,36 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config) return ERR_UNKNOWN; } + if (SMSDSQL_option(Config, SQL_QUERY_UPDATE_OUTBOX, "update_outbox", + "UPDATE ", Config->table_outbox, " SET ", + ESCAPE_FIELD("Status"), "=%3 WHERE ", + ESCAPE_FIELD("ID"), "=%1", NULL) != ERR_NONE) { + return ERR_UNKNOWN; + } + + if (SMSDSQL_option(Config, SQL_QUERY_UPDATE_OUTBOX_MULTIPART, "update_outbox_multipart", + "UPDATE ", Config->table_outbox_multipart, " SET ", + ESCAPE_FIELD("Status"), "=%3 WHERE ", + ESCAPE_FIELD("ID"), "=%1 AND ", + ESCAPE_FIELD("SequencePosition"), "=%2", NULL) != ERR_NONE) { + return ERR_UNKNOWN; + } + + if (SMSDSQL_option(Config, SQL_QUERY_UPDATE_OUTBOX_STATUSCODE, "update_outbox_statuscode", + "UPDATE ", Config->table_outbox, " SET ", + ESCAPE_FIELD("StatusCode"), "=%3 WHERE ", + ESCAPE_FIELD("ID"), "=%1", NULL) != ERR_NONE) { + return ERR_UNKNOWN; + } + + if (SMSDSQL_option(Config, SQL_QUERY_UPDATE_OUTBOX_MULTIPART_STATUSCODE, "update_outbox_multipart_statuscode", + "UPDATE ", Config->table_outbox_multipart, " SET ", + ESCAPE_FIELD("StatusCode"), "=%3 WHERE ", + ESCAPE_FIELD("ID"), "=%1 AND ", + ESCAPE_FIELD("SequencePosition"), "=%4", NULL) != ERR_NONE) { + return ERR_UNKNOWN; + } + if (SMSDSQL_option(Config, SQL_QUERY_ADD_SENT_INFO, "add_sent_info", "INSERT INTO ", Config->table_sentitems, " " "(", ESCAPE_FIELD("CreatorID"), @@ -1565,10 +1667,11 @@ GSM_Error SMSDSQL_ReadConfiguration(GSM_SMSDConfig *Config) ", ", ESCAPE_FIELD("TextDecoded"), ", ", ESCAPE_FIELD("InsertIntoDB"), ", ", ESCAPE_FIELD("RelativeValidity"), + ", ", ESCAPE_FIELD("StatusCode"), ") " " VALUES (%A, %1, %2, %3, ", SMSDSQL_Now(Config), - ", %F, %4, %P, %E, %R, %c, %u, %x, %T, %5, %V)", NULL) != ERR_NONE) { + ", %F, %4, %P, %E, %R, %c, %u, %x, %T, %5, %V, %6)", NULL) != ERR_NONE) { return ERR_UNKNOWN; } diff --git a/smsd/test-smsd.sh.in b/smsd/test-smsd.sh.in index 0350565..f319382 100755 --- a/smsd/test-smsd.sh.in +++ b/smsd/test-smsd.sh.in @@ -9,7 +9,8 @@ SMSD_CMD="$2" SMSD_INJECT_CMD="$3" SMSD_MONITOR_CMD="$4" -TEST_MATCH=";999999999999999;994299429942994;3;9;0;100;42" +TEST_MATCH=";999999999999999;994299429942994;4;10;0;100;42" +INCOMING_USSD=1 if [ "x@HAVE_KILL@" = x1 ] ; then SMSD_EXTRA_PARAMS="-p @CMAKE_CURRENT_BINARY_DIR@/smsd-test-$SERVICE/smsd.pid" @@ -115,6 +116,7 @@ EOT ;; null) TEST_MATCH=";999999999999999;994299429942994;0;9;0;100;42" + INCOMING_USSD=0 cat >> .smsdrc <<EOT service = null EOT @@ -194,7 +196,8 @@ case $SERVICE in esac $SMSD_INJECT_CMD -c "$CONFIG_PATH" TEXT 123465 -text "Lorem ipsum." & -$SMSD_INJECT_CMD -c "$CONFIG_PATH" TEXT 123465 -text "Lorem ipsum." +$SMSD_INJECT_CMD -c "$CONFIG_PATH" TEXT 123465 -text "Lorem ipsum." & +$SMSD_INJECT_CMD -c "$CONFIG_PATH" USSD 123465 $SMSD_CMD -c "$CONFIG_PATH" $SMSD_EXTRA_PARAMS & SMSD_PID=$! @@ -222,7 +225,7 @@ sleep 5 $SMSD_MONITOR_CMD -C -c "$CONFIG_PATH" -n 1 -d 0 -if [ `wc -l < @CMAKE_CURRENT_BINARY_DIR@/smsd-test-$SERVICE/received.log` -ne 8 ] ; then +if [ `wc -l < @CMAKE_CURRENT_BINARY_DIR@/smsd-test-$SERVICE/received.log` -ne $((8 + $INCOMING_USSD)) ] ; then echo "ERROR: Wrong number of messages received!" exit 1 fi @@ -231,3 +234,8 @@ if ! grep -q -F 'MMS_ADDRESS=http://mmscz/?m=m5da5a9jn210ma56q20' @CMAKE_CURRENT echo "ERROR: Wrong MMS message received!" exit 1 fi + +if [ $INCOMING_USSD -gt 0 ] && ! grep -q -F 'Reply for 123465' @CMAKE_CURRENT_BINARY_DIR@/smsd-test-$SERVICE/env.log ; then + echo "ERROR: Got no correct USSD reply!" + exit 1 +fi @@ -54,7 +54,7 @@ gboolean fill_uid(SMSD_Parameters *params, const char *name) if (pwd == NULL) { /* Try to handle it as a number */ uid = strtol(name, &endptr, 10); - if (*endptr == 0 && uid > 0) { + if (*endptr == 0 && uid >= 0) { pwd = getpwuid(uid); } } @@ -85,7 +85,7 @@ gboolean fill_gid(SMSD_Parameters *params, const char *name) /* Try to handle it as a number */ if (grp == NULL) { gid = strtol(name, &endptr, 10); - if (*endptr == 0 && gid > 0) { + if (*endptr == 0 && gid >= 0) { grp = getgrgid(gid); } } |