--- /home/wolpert/src/jabberd-2.0cvs/c2s/c2s.c 2005-01-07 07:39:20.000000000 -0700 +++ c2s/c2s.c 2005-02-10 10:48:51.835153956 -0700 @@ -20,6 +20,65 @@ #include "c2s.h" +/* + * M.Bootsma, LogicaCMG Hoofddorp, Netherlands + * October 2004 + * + * Added a patch for flash:stream support + * + * Flash is not 100% compatible with the XML stream standard: + * 1. it terminates every XML message with a '\0' + * 2. it terminates the stream header with a / + * (this would close the stream) + * 3. it starts the stream with a flash:stream header instead of + * a stream:stream header. + * + * The patch checks the first message of a starting session stream + * for any '\0'. If found it flags the session as a Flash session + * and replases the complete header with a Jabber compatible + * header. + * After that every incoming message is filtered and '\0' is + * replaced with ' '. + * For every outgoing message, a '\0' is appended and the response + * of the header is replaced for a flash friendly version + * + * The whole flash patch can be switched off by undefining CP2005_FLASH_PATCH + * in config.h(.in) + */ + +#ifdef CP2005_FLASH_PATCH + +#define FLASH_BUFFER_SIZE 256 + +static const char caStreamHeader [] = "<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='%s' >"; +static const char caFlashHeader [] = "<?xml version='1.0'?><flash:stream xmlns:flash='http://www.jabber.com/streams/flash' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' from='%s' id='%s' />"; + +static void ExtractValue(char *pMessage, char *pVariable, char *pValue) { + int iLen; + char *p; + char *pEnd; + + /* + * extract the value of an attribute from a XML message + * eg: <.... id='1234567890' ....> returns 1234567890 + */ + + p = strstr(pMessage, pVariable); + if (p != NULL) { + p += (strlen(pVariable) + 1); + /* find end of value, search for closing ' or " */ + pEnd = strchr(p, p [-1]); + iLen = pEnd - p; + if (iLen < FLASH_BUFFER_SIZE) { + memcpy(pValue, p, iLen); + pValue[iLen] = '\0'; + log_debug(ZONE, "++++ Extracted Var %s: [%s]\n", pVariable, pValue); + } + } +} +#endif + + static int _c2s_client_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) { sess_t sess = (sess_t) arg; sx_buf_t buf = (sx_buf_t) data; @@ -28,6 +87,12 @@ nad_t nad; char root[9]; +#ifdef CP2005_FLASH_PATCH + char *p, *pEnd; + char caHost[FLASH_BUFFER_SIZE]; + char caID[FLASH_BUFFER_SIZE]; +#endif + switch(e) { case event_WANT_READ: log_debug(ZONE, "want read"); @@ -94,15 +159,74 @@ return -1; } - log_debug(ZONE, "read %d bytes", len); - buf->len = len; +#ifdef CP2005_FLASH_PATCH + /* check for 0 bytes in the first packet + * if found it must be a flash client + * remove any 0 in the data and + * the / that ends the <?xml... header + */ + + pEnd = &buf->data[len]; + + if (sess->s->state == state_NONE) { + /* stream is new, look for flash signature */ + if (strstr(buf->data,"flash:stream")){ + log_debug(ZONE, "++++ Flash Stream detected\n%.*s", buf->len, buf->data); + sess->flash_client = 1; + + /* extract destination host */ + ExtractValue(buf->data, "to=", caHost); + + /* create normal stream:stream header, resize data buffer first */ + _sx_buffer_alloc_margin(buf, 0, sizeof(caStreamHeader) + strlen(caHost) + 8); + sprintf(buf->data, caStreamHeader, caHost); + buf->len = strlen(buf->data); + + log_debug(ZONE, "++++ Converted to\n%.*s", buf->len, buf->data); + } + } + + /* Check all other messages in the stream to remove \0's etc */ + if (sess->flash_client) + /* remove 0's from flash packets */ + for (p = buf->data; p < pEnd; p++) + if (*p == '\0') + *p = ' '; +#endif + log_debug(ZONE, "read %d bytes", len); + return len; case event_WRITE: log_debug(ZONE, "writing to %d", sess->fd); +#ifdef CP2005_FLASH_PATCH + if (sess->flash_client) { + /* look for the header <? xml ...*/ + if (strncmp(buf->data, "<?xml ", 6) == 0) { + /* replace normal stream header with flash friendly header */ + log_debug(ZONE, "++++ Found <?xml..., \n%.*s", buf->len, buf->data); + + /* extract id from id="123456567778765" or id='45454545454' */ + ExtractValue(buf->data, "from=", caHost); + ExtractValue(buf->data, "id=", caID); + + /* create flash:stream header, realloc buffer first */ + _sx_buffer_alloc_margin(buf, 0, sizeof(caFlashHeader) + strlen(caHost) + strlen(caID) + 8); + sprintf(buf->data, caFlashHeader, caHost, caID); + buf->len = strlen(buf->data); + + log_debug(ZONE, "++++ Converted to %s", buf->data); + } + + /* add a 0 to flash packets */ + buf->data[buf->len] = '\0'; + buf->len++; + } +#endif + len = send(sess->fd, buf->data, buf->len, 0); if(len >= 0) { log_debug(ZONE, "%d bytes written", len); --- /home/wolpert/src/jabberd-2.0cvs/c2s/c2s.h 2004-12-07 08:38:02.000000000 -0700 +++ c2s/c2s.h 2005-01-11 14:57:42.000000000 -0700 @@ -62,6 +62,10 @@ int bound; int active; +#ifdef CP2005_FLASH_PATCH + int flash_client; +#endif + nad_t result; int sasl_authd; /* 1 = they did a sasl auth */