00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "syncml.h"
00023
00024 #include "syncml_internals.h"
00025 #include "sml_notification_internals.h"
00026 #include "sml_transport_internals.h"
00027 #include "sml_command_internals.h"
00028 #include "sml_manager_internals.h"
00029 #include "sml_error_internals.h"
00030 #include "objects/sml_auth_internals.h"
00031 #include "sml_elements_internals.h"
00032
00033 SmlNotification *smlNotificationNew(SmlNotificationVersion version, SmlNotificationUIMode mode, SmlNotificationInitiator init, unsigned int sessionID, const char *identifier, const char *target, SmlMimeType type, SmlError **error)
00034 {
00035 smlTrace(TRACE_ENTRY, "%s(%i, %i, %i, %i, %s, %s, %i, %p)", __func__, version, mode, init, sessionID, VA_STRING(identifier), VA_STRING(target), type, error);
00036 CHECK_ERROR_REF
00037
00038 SmlNotification *san = smlTryMalloc0(sizeof(SmlNotification), error);
00039 if (!san)
00040 goto error;
00041
00042 san->version = version;
00043 san->mode = mode;
00044 san->init = init;
00045 san->sessionID = sessionID;
00046 san->identifier = g_strdup(identifier);
00047 san->type = type;
00048 san->cred = NULL;
00049 san->sessionType = SML_SESSION_TYPE_SERVER;
00050 san->manager = NULL;
00051
00052 san->target = smlLocationNew(target, NULL, error);
00053 if (!san->target)
00054 goto error_free_san;
00055
00056 smlTrace(TRACE_EXIT, "%s: %p", __func__, san);
00057 return san;
00058
00059 error_free_san:
00060
00061 error:
00062 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00063 return NULL;
00064 }
00065
00066 void smlNotificationSetCred(SmlNotification *san, SmlCred *cred)
00067 {
00068 smlTrace(TRACE_ENTRY, "%s", __func__);
00069 smlAssert(san);
00070 smlAssert(cred);
00071 if (san->cred)
00072 smlCredUnref(san->cred);
00073 san->cred = cred;
00074
00075
00076
00077
00078
00079 san->sessionType = SML_SESSION_TYPE_CLIENT;
00080 smlCredRef(cred);
00081 smlTrace(TRACE_EXIT, "%s", __func__);
00082 }
00083
00084 void smlNotificationSetManager(SmlNotification *san, SmlManager *manager)
00085 {
00086 smlTrace(TRACE_ENTRY, "%s", __func__);
00087 smlAssert(san);
00088 smlAssert(manager);
00089 san->manager = manager;
00090 smlTrace(TRACE_EXIT, "%s", __func__);
00091 }
00092
00093 void smlNotificationFree(SmlNotification *san)
00094 {
00095 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, san);
00096 smlAssert(san);
00097
00098 while (san->alerts) {
00099 SmlSanAlert *alert = san->alerts->data;
00100 san->alerts = g_list_remove(san->alerts, alert);
00101 smlNotificationFreeAlert(alert);
00102 }
00103
00104 if (san->target) {
00105 smlLocationUnref(san->target);
00106 san->target = NULL;
00107 }
00108
00109 if (san->cred) {
00110 smlCredUnref(san->cred);
00111 san->cred = NULL;
00112 }
00113
00114 if (san->identifier)
00115 smlSafeCFree(&(san->identifier));
00116 smlSafeFree((gpointer *)&san);
00117
00118 smlTrace(TRACE_EXIT, "%s", __func__);
00119 }
00120
00121 SmlBool smlNotificationNewAlert(SmlNotification *san, SmlAlertType type, const char *contenttype, const char *serverURI, SmlError **error)
00122 {
00123 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, error);
00124 CHECK_ERROR_REF
00125 smlAssert(type >= 206 && type <= 210);
00126
00127 SmlSanAlert *alert = smlTryMalloc0(sizeof(SmlSanAlert), error);
00128 if (!alert)
00129 goto error;
00130
00131 alert->type = type;
00132 alert->contenttype = g_strdup(contenttype);
00133 alert->serverURI = g_strdup(serverURI);
00134
00135 san->alerts = g_list_append(san->alerts, alert);
00136
00137 smlTrace(TRACE_EXIT, "%s: %p", __func__, alert);
00138 return TRUE;
00139
00140 error:
00141 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00142 return FALSE;
00143 }
00144
00145 void smlNotificationFreeAlert(SmlSanAlert *alert)
00146 {
00147 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, alert);
00148 smlAssert(alert);
00149
00150 smlSafeCFree(&(alert->contenttype));
00151 smlSafeCFree(&(alert->serverURI));
00152 smlSafeFree((gpointer *)&alert);
00153
00154 smlTrace(TRACE_EXIT, "%s", __func__);
00155 }
00156
00157 SmlNotification *smlNotificationParse(const char *data, unsigned int size, SmlError **error)
00158 {
00159 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, data, size, error);
00160 CHECK_ERROR_REF
00161 smlAssert(data);
00162 smlAssert(size);
00163
00164 if (size < 25) {
00165 smlErrorSet(error, SML_ERROR_GENERIC, "Size too small");
00166 goto error;
00167 }
00168
00169 unsigned int idLength = (uint8_t)data[23];
00170 if (size < (25 + idLength)) {
00171 smlErrorSet(error, SML_ERROR_GENERIC, "Size too small2");
00172 goto error;
00173 }
00174
00175 SmlNotification *san = smlTryMalloc0(sizeof(SmlNotification), error);
00176 if (!san)
00177 goto error;
00178 san->type = SML_MIMETYPE_SAN;
00179
00180
00181 unsigned int version = ((uint8_t)data[16]) << 2;
00182 version = version | ((uint8_t)data[17]) >> 6;
00183 switch (version) {
00184 case 12:
00185 san->version = SML_SAN_VERSION_12;
00186 break;
00187 default:
00188 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown version");
00189 goto error_free_san;
00190 }
00191
00192
00193 san->mode = (((uint8_t)data[17]) & 0x30) >> 4;
00194
00195
00196 san->init = (((uint8_t)data[17]) & 0x08) >> 3;
00197
00198
00199 san->sessionID = ((uint8_t)data[21]) << 8;
00200 san->sessionID = san->sessionID | (uint8_t)data[22];
00201
00202
00203 if (idLength) {
00204
00205 san->identifier = smlTryMalloc0(idLength + 1, error);
00206 if (!san->identifier)
00207 goto error_free_san;
00208
00209 memcpy(san->identifier, data + 24, idLength);
00210 }
00211
00212 unsigned int numSync = ((uint8_t)data[24 + idLength]) >> 4;
00213 data += 25 + idLength;
00214 unsigned int alertLength = 25 + idLength;
00215
00216 unsigned int i = 0;
00217 for (i = 0; i < numSync; i++) {
00218 if (size < alertLength + 5) {
00219 smlErrorSet(error, SML_ERROR_GENERIC, "Size too small3");
00220 goto error_free_san;
00221 }
00222
00223 idLength = (uint8_t)data[4];
00224 if (size < (alertLength + 5 + idLength)) {
00225 smlErrorSet(error, SML_ERROR_GENERIC, "Size too small4");
00226 goto error_free_san;
00227 }
00228 alertLength = alertLength + 5 + idLength;
00229
00230
00231 SmlAlertType alert_type = (((uint8_t)data[0]) >> 4) + 200;
00232 if (alert_type < 206 || alert_type > 210) {
00233 smlErrorSet(error, SML_ERROR_GENERIC, "Wrong alert type");
00234 goto error_free_san;
00235 }
00236
00237 unsigned int contenttype = ((uint8_t)data[1]) << 16;
00238 contenttype = contenttype | ((uint8_t)data[2]) << 8;
00239 contenttype = contenttype | ((uint8_t)data[3]);
00240
00241
00242 const char *alert_ct;
00243 switch (contenttype) {
00244 case 0x00:
00245
00246
00247
00248
00249 alert_ct = NULL;
00250 break;
00251 case 0x07:
00252 alert_ct = SML_ELEMENT_TEXT_VCARD;
00253 break;
00254 case 0x06:
00255 alert_ct = SML_ELEMENT_TEXT_VCAL;
00256 break;
00257 case 0x03:
00258 alert_ct = SML_ELEMENT_TEXT_PLAIN;
00259 break;
00260 case 0x0305:
00261 alert_ct = SML_ELEMENT_TEXT_ICAL;
00262 break;
00263 case 0x0306:
00264 alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_EMAIL;
00265 break;
00266 case 0x0307:
00267 alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_FILE;
00268 break;
00269 case 0x0308:
00270 alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_FOLDER;
00271 break;
00272 case 0x0309:
00273 alert_ct = SML_ELEMENT_TEXT_VCARD_30;
00274 break;
00275 default:
00276
00277 smlErrorSet(error, SML_ERROR_GENERIC, "The OMNA WSP Content Type Number 0x%xd is not supported.", contenttype);
00278 goto error_free_san;
00279 }
00280
00281
00282 char *alert_uri;
00283 if (idLength) {
00284
00285 alert_uri = smlTryMalloc0(idLength + 1, error);
00286 if (!alert_uri)
00287 goto error_free_san;
00288
00289 memcpy(alert_uri, data + 5, idLength);
00290 }
00291 data += 5 + idLength;
00292
00293
00294 if (!smlNotificationNewAlert(san, alert_type, alert_ct, alert_uri, error))
00295 goto error_free_san;
00296
00297
00298 if (idLength)
00299 smlSafeCFree(&alert_uri);
00300 }
00301
00302 if (size > alertLength) {
00303 smlErrorSet(error, SML_ERROR_GENERIC, "Extra chunk at the end of the buffer");
00304 goto error_free_san;
00305 }
00306
00307 smlTrace(TRACE_EXIT, "%s: %p", __func__, san);
00308 return san;
00309
00310 error_free_san:
00311 while (san->alerts) {
00312 smlNotificationFreeAlert(san->alerts->data);
00313 san->alerts = g_list_delete_link(san->alerts, san->alerts);
00314 }
00315 if (san->identifier)
00316 smlSafeCFree(&(san->identifier));
00317 smlSafeFree((gpointer *)&san);
00318 error:
00319 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00320 return NULL;
00321 }
00322
00323 SmlBool smlNotificationAssemble11(SmlNotification *san, char **data, unsigned int *size, SmlProtocolVersion version, SmlError **error)
00324 {
00325 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %p)", __func__, san, data, size, version, error);
00326 CHECK_ERROR_REF
00327 smlAssert(san);
00328 smlAssert(data);
00329 smlAssert(size);
00330
00331
00332
00333
00334
00335 smlAssert(san->manager);
00336
00337 SmlAssembler *assm = NULL;
00338 SmlLocation *source = NULL;
00339 SmlSession *session = NULL;
00340 SmlSanAlert *alert = NULL;
00341 SmlCommand *cmd = NULL;
00342
00343 source = smlLocationNew(san->identifier, NULL, error);
00344 if (!source)
00345 goto error;
00346
00347 char *sessionString = smlManagerGetNewSessionID(san->manager);
00348 session = smlSessionNew(san->sessionType, san->type, version, SML_PROTOCOL_SYNCML, san->target, source, sessionString, 0, error);
00349 if (!session) {
00350 smlSafeCFree(&sessionString);
00351 smlLocationUnref(source);
00352 goto error;
00353 }
00354 smlSafeCFree(&sessionString);
00355 smlManagerSessionAdd(san->manager, session, NULL, error);
00356
00357 assm = smlAssemblerNew(san->type, 0, error);
00358 if (!assm)
00359 goto error;
00360
00361 if (!smlAssemblerStart(assm, session, error))
00362 goto error;
00363
00364 if (!smlAssemblerAddHeader(assm, session, error))
00365 goto error;
00366
00367 GList *a = NULL;
00368 int i = 1;
00369 for (a = san->alerts; a; a = a->next) {
00370 alert = a->data;
00371
00372
00373 SmlLocation *loc = smlLocationNew(alert->serverURI, NULL, error);
00374 if (!loc)
00375 goto error;
00376
00377 cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY_BY_SERVER, NULL, loc, NULL, NULL, alert->contenttype, error);
00378 if (!cmd) {
00379 smlLocationUnref(loc);
00380 goto error;
00381 }
00382
00383 cmd->cmdID = i;
00384 i++;
00385
00386 if (!smlAssemblerStartCommand(assm, NULL, cmd, error) == SML_ASSEMBLER_RESULT_OK)
00387 goto error;
00388
00389 if (!smlAssemblerEndCommand(assm, NULL, error))
00390 goto error;
00391
00392 smlLocationUnref(loc);
00393
00394 smlCommandUnref(cmd);
00395 }
00396
00397 if (!smlAssemblerRun(assm, data, size, NULL, TRUE, error))
00398 goto error;
00399
00400 smlAssemblerFlush(assm);
00401
00402 smlSessionUnref(session);
00403
00404 smlLocationUnref(source);
00405
00406 smlAssemblerFree(assm);
00407
00408 char *hex = smlPrintHex(*data, *size);
00409 smlTrace(TRACE_INTERNAL, "San packet assembled: %s", hex);
00410 smlSafeCFree(&hex);
00411
00412 smlTrace(TRACE_EXIT, "%s", __func__);
00413 return TRUE;
00414
00415 error:
00416 if (cmd)
00417 smlCommandUnref(cmd);
00418 if (session)
00419 smlSessionUnref(session);
00420 if (assm)
00421 smlAssemblerFree(assm);
00422 *data = NULL;
00423 *size = 0;
00424 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00425 return FALSE;
00426 }
00427
00428 static SmlBool _smlNotificationAssemble12(SmlNotification *san, char **data, unsigned int *size, SmlError **error)
00429 {
00430 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, san, data, size, error);
00431 CHECK_ERROR_REF
00432 smlAssert(san);
00433 smlAssert(data);
00434 smlAssert(*data == NULL);
00435 smlAssert(size);
00436 unsigned int numsync = 0;
00437 SmlSanAlert *alert = NULL;
00438
00439
00440 unsigned int length = 16 + 8 + strlen(san->identifier) + 1 ;
00441 GList *a = NULL;
00442 for (a = san->alerts; a; a = a->next) {
00443 alert = a->data;
00444 length += 5 + strlen(alert->serverURI);
00445 numsync++;
00446 }
00447
00448
00449 char *buffer = smlTryMalloc0(length, error);
00450 if (!buffer)
00451 goto error;
00452 *data = buffer;
00453 *size = length;
00454
00455
00456
00457
00458
00459 buffer[16] = 0x03;
00460
00461
00462 buffer[17] = buffer[17] | (san->mode << 4);
00463
00464
00465 buffer[17] = buffer[17] | (san->init << 3);
00466
00467
00468
00469
00470 buffer[21] = san->sessionID >> 8;
00471 buffer[22] = san->sessionID;
00472
00473
00474 buffer[23] = strlen(san->identifier);
00475 strncpy(buffer + 24, san->identifier, strlen(san->identifier));
00476
00477 buffer += 24 + strlen(san->identifier);
00478
00479
00480 buffer[0] = numsync << 4;
00481 buffer++;
00482
00483 for (a = san->alerts; a; a = a->next) {
00484 alert = a->data;
00485
00486 buffer[0] = (alert->type - 200) << 4;
00487
00488
00489 if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCARD)) {
00490 buffer[3] = 0x07;
00491 } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCAL)) {
00492 buffer[3] = 0x06;
00493 } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_PLAIN)) {
00494 buffer[3] = 0x03;
00495 } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_ICAL)) {
00496 buffer[2] = 0x03;
00497 buffer[3] = 0x05;
00498 } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_EMAIL)) {
00499 buffer[2] = 0x03;
00500 buffer[3] = 0x06;
00501 } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_FILE)) {
00502 buffer[2] = 0x03;
00503 buffer[3] = 0x07;
00504 } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_FOLDER)) {
00505 buffer[2] = 0x03;
00506 buffer[3] = 0x08;
00507 } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCARD_30)) {
00508 buffer[2] = 0x03;
00509 buffer[3] = 0x09;
00510 } else {
00511
00512 smlTrace(TRACE_INTERNAL,
00513 "%s: The OMNA WSP Content Type Number is unknown for %s.",
00514 __func__, alert->contenttype);
00515
00516 }
00517
00518
00519 buffer[4] = strlen(alert->serverURI);
00520 strncpy(buffer + 5, alert->serverURI, strlen(alert->serverURI));
00521 buffer += 5 + strlen(alert->serverURI);
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531 unsigned char digest[16];
00532 smlMD5GetDigest (*data+16, length - 16 , digest);
00533 char *b64_san = g_base64_encode(digest, 16);
00534 smlTrace(TRACE_INTERNAL, "%s: b64(md5(san)) ::= %s", __func__, b64_san);
00535
00536
00537 const char *username = "";
00538 const char *password = "";
00539 if (san->cred) {
00540 username = san->cred->username;
00541 password = san->cred->password;
00542 }
00543 char *auth = g_strdup_printf("%s:%s", username, password);
00544 smlMD5GetDigest (auth, strlen(auth), digest);
00545 smlSafeCFree(&auth);
00546 char *b64_auth = g_base64_encode(digest, 16);
00547 smlTrace(TRACE_INTERNAL, "%s: b64(md5(username:password)) ::= %s", __func__, b64_auth);
00548
00549
00550 char *complete = g_strdup_printf("%s::%s", b64_auth, b64_san);
00551 smlSafeCFree(&b64_auth);
00552 smlSafeCFree(&b64_san);
00553 smlMD5GetDigest (complete, strlen(complete), digest);
00554 smlSafeCFree(&complete);
00555 smlTrace(TRACE_INTERNAL, "%s: md5(auth::san) complete", __func__);
00556
00557
00558 memcpy(*data, digest, 16);
00559 smlTrace(TRACE_INTERNAL, "%s: md5(auth::san) copied to san", __func__);
00560
00561
00562
00563 char *hex = smlPrintHex(*data, *size);
00564 smlTrace(TRACE_INTERNAL, "San packet assembled: %s", hex);
00565 smlSafeCFree(&hex);
00566
00567 smlTrace(TRACE_EXIT, "%s", __func__);
00568 return TRUE;
00569
00570 error:
00571 if (*data)
00572 smlSafeCFree(data);
00573 *size = 0;
00574 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00575 return FALSE;
00576 }
00577
00578 SmlBool smlNotificationAssemble(SmlNotification *san, char **data, unsigned int *size, SmlError **error)
00579 {
00580 CHECK_ERROR_REF
00581 switch (san->version) {
00582 case SML_SAN_VERSION_12:
00583 return _smlNotificationAssemble12(san, data, size, error);
00584 case SML_SAN_VERSION_10:
00585 return smlNotificationAssemble11(san, data, size, SML_VERSION_10, error);
00586 case SML_SAN_VERSION_11:
00587 return smlNotificationAssemble11(san, data, size, SML_VERSION_11, error);
00588 case SML_SAN_VERSION_UNKNOWN:
00589 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown SAN version.");
00590 break;
00591 }
00592
00593 return FALSE;
00594 }
00595
00596 SmlBool smlNotificationSend(SmlNotification *san, SmlTransport *tsp, SmlError **error)
00597 {
00598 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, san, tsp, error);
00599 CHECK_ERROR_REF
00600 smlAssert(san);
00601 smlAssert(tsp);
00602
00603 char *data = NULL;
00604 unsigned int size = 0;
00605 if (!smlNotificationAssemble(san, &data, &size, error))
00606 goto error;
00607
00608 SmlTransportData *tspdata = NULL;
00609 if (san->version == SML_SAN_VERSION_12)
00610 tspdata = smlTransportDataNew(data, size, SML_MIMETYPE_SAN, TRUE, error);
00611 else
00612 tspdata = smlTransportDataNew(data, size, san->type, TRUE, error);
00613
00614 if (!tspdata)
00615 goto error_free_data;
00616
00617 data = NULL;
00618
00619
00620
00621
00622 if (san->version == SML_SAN_VERSION_12)
00623 tspdata->type_get = san->type;
00624
00625 if (!smlTransportSend(tsp, NULL, tspdata, error))
00626 goto error_free_tspdata;
00627
00628 smlTransportDataDeref(tspdata);
00629
00630 smlTrace(TRACE_EXIT, "%s", __func__);
00631 return TRUE;
00632
00633 error_free_tspdata:
00634 smlTransportDataDeref(tspdata);
00635 error_free_data:
00636 smlSafeCFree(&data);
00637 error:
00638 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00639 return FALSE;
00640 }
00641
00642 SmlNotificationVersion smlNotificationGetVersion(SmlNotification *san)
00643 {
00644 smlAssert(san);
00645 return san->version;
00646 }
00647
00648 SmlNotificationUIMode smlNotificationGetMode(SmlNotification *san)
00649 {
00650 smlAssert(san);
00651 return san->mode;
00652 }
00653
00654 SmlNotificationInitiator smlNotificationGetInitiator(SmlNotification *san)
00655 {
00656 smlAssert(san);
00657 return san->init;
00658 }
00659
00660 unsigned int smlNotificationGetSessionID(SmlNotification *san)
00661 {
00662 smlAssert(san);
00663 return san->sessionID;
00664 }
00665
00666 const char *smlNotificationGetIdentifier(SmlNotification *san)
00667 {
00668 smlAssert(san);
00669 return san->identifier;
00670 }
00671
00672 unsigned int smlNotificationNumAlerts(SmlNotification *san)
00673 {
00674 smlAssert(san);
00675 return g_list_length(san->alerts);
00676 }
00677
00678 SmlSanAlert *smlNotificationNthAlert(SmlNotification *san, unsigned int nth)
00679 {
00680 smlAssert(san);
00681 return g_list_nth_data(san->alerts, nth);
00682 }
00683
00684 SmlAlertType smlSanAlertGetType(SmlSanAlert *alert)
00685 {
00686 smlAssert(alert);
00687 return alert->type;
00688 }
00689
00690 const char *smlSanAlertGetContentType(SmlSanAlert *alert)
00691 {
00692 smlAssert(alert);
00693 return alert->contenttype;
00694 }
00695 const char *smlSanAlertGetServerURI(SmlSanAlert *alert)
00696 {
00697 smlAssert(alert);
00698 return alert->serverURI;
00699 }