Пример #1
0
abyss_bool
ConnWriteFromFile(TConn *  const connectionP,
                  TFile *  const fileP,
                  uint64_t const start,
                  uint64_t const last,
                  void *   const buffer,
                  uint32_t const buffersize,
                  uint32_t const rate) {
    /*----------------------------------------------------------------------------
       Write the contents of the file stream *fileP, from offset 'start'
       up through 'last', to the HTTP connection *connectionP.

       Meter the reading so as not to read more than 'rate' bytes per second.

       Use the 'bufferSize' bytes at 'buffer' as an internal buffer for this.
    -----------------------------------------------------------------------------*/
    abyss_bool retval;
    uint32_t waittime;
    abyss_bool success;
    uint32_t readChunkSize;

    if (rate > 0) {
        readChunkSize = MIN(buffersize, rate);  /* One second's worth */
        waittime = (1000 * buffersize) / rate;
    } else {
        readChunkSize = buffersize;
        waittime = 0;
    }

    success = FileSeek(fileP, start, SEEK_SET);
    if (!success)
        retval = FALSE;
    else {
        uint64_t const totalBytesToRead = last - start + 1;
        uint64_t bytesread;

        bytesread = 0;  /* initial value */

        while (bytesread < totalBytesToRead) {
            uint64_t const bytesLeft = totalBytesToRead - bytesread;
            uint64_t const bytesToRead = MIN(readChunkSize, bytesLeft);

            uint64_t bytesReadThisTime;

            bytesReadThisTime = FileRead(fileP, buffer, bytesToRead);
            bytesread += bytesReadThisTime;

            if (bytesReadThisTime > 0)
                ConnWrite(connectionP, buffer, bytesReadThisTime);
            else
                break;

            if (waittime > 0)
                xmlrpc_millisecond_sleep(waittime);
        }
        retval = (bytesread >= totalBytesToRead);
    }
    return retval;
}
Пример #2
0
bool
HTTPWriteContinue(TSession * const sessionP) {

    char const continueStatus[] = "HTTP/1.1 100 continue\r\n\r\n";
        /* This is a status line plus an end-of-header empty line */

    return ConnWrite(sessionP->connP, continueStatus, strlen(continueStatus));
}
Пример #3
0
static void
sendBody(TSession *   const sessionP,
         TFile *      const fileP,
         uint64_t     const filesize,
         const char * const mediatype,
         uint64_t     const start0,
         uint64_t     const end0,
         char *       const z) {

    if (sessionP->ranges.size == 0)
        ConnWriteFromFile(sessionP->conn, fileP, 0, filesize - 1, z, 4096, 0);
    else if (sessionP->ranges.size == 1)
        ConnWriteFromFile(sessionP->conn, fileP, start0, end0, z, 4096, 0);
    else {
        uint64_t i;
        for (i = 0; i <= sessionP->ranges.size; ++i) {
            ConnWrite(sessionP->conn,"--", 2);
            ConnWrite(sessionP->conn, BOUNDARY, strlen(BOUNDARY));
            ConnWrite(sessionP->conn, CRLF, 2);

            if (i < sessionP->ranges.size) {
                uint64_t start;
                uint64_t end;
                abyss_bool decoded;
                    
                decoded = RangeDecode((char *)(sessionP->ranges.item[i]),
                                      filesize,
                                      &start, &end);
                if (decoded) {
                    /* Entity header, not response header */
                    sprintf(z, "Content-type: %s" CRLF
                            "Content-range: bytes %llu-%llu/%llu" CRLF
                            "Content-length: %llu" CRLF
                            CRLF, mediatype, start, end,
                            filesize, end-start+1);

                    ConnWrite(sessionP->conn, z, strlen(z));

                    ConnWriteFromFile(sessionP->conn, fileP, start, end, z,
                                      4096, 0);
                }
            }
        }
    }
}
Пример #4
0
int
HandleCommand(QueueClient *client)
{
    int ccode = 0;
    
    while (Agent.agent.state < BONGO_AGENT_STATE_STOPPING
           && client && client->conn && !client->done) {
        client->buffer[0] = '\0';

        ccode = ConnReadAnswer(client->conn, client->buffer, CONN_BUFSIZE);

        if ((ccode != -1) && (ccode < CONN_BUFSIZE)) {            
            ProtocolCommand *command;

            if (client->authorized) {
                command = ProtocolCommandTreeSearch(&Agent.commands, client->buffer);
            } else {
                command = ProtocolCommandTreeSearch(&Agent.authCommands, client->buffer);                
            }
            
            if (command) {
                ccode = command->handler(client);
            } else {
                if (client->authorized) {
                    ccode = ConnWrite(client->conn, MSG3000UNKNOWN, sizeof(MSG3000UNKNOWN) - 1);
                } else {
                    ccode = ConnWrite(client->conn, MSG3240NOAUTH, sizeof(MSG3240NOAUTH) - 1);
                }
                
                Log(LOG_DEBUG, "Handled command from %s", LOGIP(client->conn->socketAddress));
            }
        } else if (ccode == -1) {
            break;
        }

        if ((ccode = ConnFlush(client->conn)) == -1) {
            break;
        }
    }

    return(ccode);  
}
Пример #5
0
bool
HTTPWriteEndChunk(TSession * const sessionP) {

    bool retval;

    if (sessionP->chunkedwrite && sessionP->chunkedwritemode) {
        /* May be one day trailer dumping will be added */
        sessionP->chunkedwritemode = false;
        retval = ConnWrite(sessionP->connP, "0\r\n\r\n", 5);
    } else
        retval = true;

    return retval;
}
Пример #6
0
static abyss_bool HTTPWriteEnd(TSession * s)
{
	if (!s->chunkedwritemode)
		return TRUE;

	if (s->chunkedwrite) {
		/* May be one day trailer dumping will be added */
		s->chunkedwritemode = FALSE;
		return ConnWrite(s->connP, "0" CRLF CRLF, 5);
	}

	s->requestInfo.keepalive = FALSE;
	return TRUE;
}
Пример #7
0
int ConnWriteFromFile(TConn *c,TFile *file,uint64 start,uint64 end,
			void *buffer,uint32 buffersize,uint32 rate)
{
	uint64 y = 0;
	uint64 bytesread=0;
	uint32 waittime = 0;

	/* sanity */
	if (!c || !buffer) {
		return FALSE;
	}


        if( c->out_bufferpos )
                ConnWriteFlush( c );

	if (rate>0)
	{
		if (buffersize>rate)
			buffersize=rate;

		waittime=(1000*buffersize)/rate;
	}
	else
		waittime=0;

	if (!FileSeek(file,start,SEEK_SET))
		return FALSE;

	while (bytesread<=end-start)
	{
		y=(end-start+1)-bytesread;

		if (y>buffersize)
			y=buffersize;

		y=FileRead(file,buffer,y);
		bytesread+=y;

		if (y>0)
			ConnWrite(c,buffer,y);
		else
			break;

		if (waittime)
			ThreadSleep(waittime);
	};

	return (bytesread>end-start);
}
Пример #8
0
bool
HTTPWriteBodyChunk(TSession *   const sessionP,
                   const char * const buffer,
                   uint32_t     const len) {

    bool succeeded;

    if (sessionP->chunkedwrite && sessionP->chunkedwritemode) {
        char chunkHeader[16];

        sprintf(chunkHeader, "%x\r\n", len);

        succeeded =
            ConnWrite(sessionP->connP, chunkHeader, strlen(chunkHeader));
        if (succeeded) {
            succeeded = ConnWrite(sessionP->connP, buffer, len);
            if (succeeded)
                succeeded = ConnWrite(sessionP->connP, "\r\n", 2);
        }
    } else
        succeeded = ConnWrite(sessionP->connP, buffer, len);

    return succeeded;
}
void
ResponseError2(TSession *   const sessionP,
               const char * const explanation) {

    const char * errorDocument;

    ResponseAddField(sessionP, "Content-type", "text/html");

    ResponseWriteStart(sessionP);
    
    xmlrpc_asprintf(&errorDocument,
                    "<HTML><HEAD><TITLE>Error %d</TITLE></HEAD>"
                    "<BODY>"
                    "<H1>Error %d</H1>"
                    "<P>%s</P>" SERVER_HTML_INFO 
                    "</BODY>"
                    "</HTML>",
                    sessionP->status, sessionP->status, explanation);
    
    ConnWrite(sessionP->connP, errorDocument, strlen(errorDocument)); 

    xmlrpc_strfree(errorDocument);
}
Пример #10
0
static BOOL 
SaveCalendarInvitation(ItipAgentClient *client,
                       Connection *nmap,
                       char *invitation)
{
    char buffer[CONN_BUFSIZE];
    int ccode;
    int size;
    
    size = strlen(invitation);

    ccode = NMAPCreateCollection(nmap, "/invitations/calendar", NULL);
    if (ccode != 4226 && ccode != 1000) {
        return ccode;
    }
    
    ccode = NMAPRunCommandF(nmap, 
                            buffer,
                            CONN_BUFSIZE, "WRITE /invitations/calendar %d %d\r\n", 
                            STORE_DOCTYPE_CALENDAR,
                            size);

    if (ccode != 2002) {
        return ccode;
    }

    ccode = ConnWrite(nmap, invitation, size);
    ConnFlush(nmap);

    if (ccode < 0) {
        return ccode;
    }

    ccode = NMAPReadAnswer(nmap, buffer, CONN_BUFSIZE, TRUE);

    return ccode;
}
Пример #11
0
static int 
CommandHelp(void *param)
{
    int ccode;
    unsigned char *ptr;
    QueueClient *client = (QueueClient *)param;

    ptr = client->buffer + 4;
    if (*ptr == '\0') {
        ccode = ConnWrite(client->conn, MSG2001HELP, sizeof(MSG2001HELP) - 1);
    } else if (*ptr++ == ' ') {
        ProtocolCommand *command;

        if (client->authorized) {
            command = ProtocolCommandTreeSearch(&Agent.commands, ptr);
        } else {
            command = ProtocolCommandTreeSearch(&Agent.authCommands, ptr);
        }
        
        if (command) {
            if (command->help) {
                ccode = ConnWrite(client->conn, command->help, strlen(command->help));
            } else {
                ccode = ConnWrite(client->conn, NMAP_HELP_NOT_DEFINED, sizeof(NMAP_HELP_NOT_DEFINED) - 1);
            }
        } else {
            return(ConnWrite(client->conn, MSG3000UNKNOWN, sizeof(MSG3000UNKNOWN) - 1));
        }
    } else {
        return(ConnWrite(client->conn, MSG3010BADARGC, sizeof(MSG3010BADARGC) - 1));
    }

    if (ccode != -1) {
        ccode = ConnWrite(client->conn, MSG1000OK, sizeof(MSG1000OK) - 1);
    }

    return(ccode);
}
Пример #12
0
ConnThread(void *arg)
{
    PRInt32 num;
    nsresult rv = NS_OK;

    ipcConnectionState *s = (ipcConnectionState *) arg;

    // we monitor two file descriptors in this thread.  the first (at index 0) is
    // the socket connection with the IPC daemon.  the second (at index 1) is the
    // pollable event we monitor in order to know when to send messages to the
    // IPC daemon.

    s->fds[SOCK].in_flags = PR_POLL_READ;
    s->fds[POLL].in_flags = PR_POLL_READ;

    while (NS_SUCCEEDED(rv))
    {
        s->fds[SOCK].out_flags = 0;
        s->fds[POLL].out_flags = 0;

        //
        // poll on the IPC socket and NSPR pollable event
        //
        num = PR_Poll(s->fds, 2, PR_INTERVAL_NO_TIMEOUT);
        if (num > 0)
        {
            ipcCallbackQ cbs_to_run;

            // check if something has been added to the send queue.  if so, then
            // acknowledge pollable event (wait should not block), and configure
            // poll flags to find out when we can write.

            if (s->fds[POLL].out_flags & PR_POLL_READ)
            {
                PR_WaitForPollableEvent(s->fds[POLL].fd);
                PR_Lock(s->lock);

                if (!s->send_queue.IsEmpty())
                    s->fds[SOCK].in_flags |= PR_POLL_WRITE;

                if (!s->callback_queue.IsEmpty())
                    s->callback_queue.MoveTo(cbs_to_run);

                PR_Unlock(s->lock);
            }

            // check if we can read...
            if (s->fds[SOCK].out_flags & PR_POLL_READ)
                rv = ConnRead(s);

            // check if we can write...
            if (s->fds[SOCK].out_flags & PR_POLL_WRITE)
                rv = ConnWrite(s);

            // check if we have callbacks to run
            while (!cbs_to_run.IsEmpty())
            {
                ipcCallback *cb = cbs_to_run.First();
                (cb->func)(cb->arg);
                cbs_to_run.DeleteFirst();
            }

            // check if we should exit this thread.  delay processing a shutdown
            // request until after all queued up messages have been sent and until
            // after all queued up callbacks have been run.
            PR_Lock(s->lock);
            if (s->shutdown && s->send_queue.IsEmpty() && s->callback_queue.IsEmpty())
                rv = NS_ERROR_ABORT;
            PR_Unlock(s->lock);
        }
        else
        {
            LOG(("PR_Poll returned error %d (%s), os error %d\n", PR_GetError(),
                 PR_ErrorToName(PR_GetError()), PR_GetOSError()));
            rv = NS_ERROR_UNEXPECTED;
        }
    }

    // notify termination of the IPC connection
    if (rv == NS_ERROR_ABORT)
        rv = NS_OK;
    IPC_OnConnectionEnd(rv);

    LOG(("IPC thread exiting\n"));
}
Пример #13
0
int 
CommandPass(void *param)
{
    unsigned char *ptr;
    unsigned char *pass;
    int result;
    struct sockaddr_in nmap;
    QueueClient *client = (QueueClient *)param;

    ptr = client->buffer + 4;

    if (*ptr++ == ' ') {
        if (       (toupper(ptr[0]) == 'U') 
                && (toupper(ptr[1]) == 'S') 
                && (toupper(ptr[2]) == 'E') 
                && (toupper(ptr[3]) == 'R') 
                && (ptr[4] == ' ') 
                && (ptr[5] != '\0') 
                && (!isspace(ptr[5])) 
                && ((pass = strchr(ptr + 5, ' ')) != NULL)) {
            ptr += 5;
            *pass++ = '\0';

            result = MsgAuthVerifyPassword(ptr, pass);

            if ((result==0) && (nmap.sin_addr.s_addr == MsgGetHostIPAddress())) {
                return(ConnWrite(client->conn, MSG1000OK, sizeof(MSG1000OK) - 1));
            } else {
                return(ConnWrite(client->conn, MSG4120USERLOCKED, sizeof(MSG4120USERLOCKED) - 1));
            }

            Log(LOG_NOTICE, "PASS USER failed for user from host %s", LOGIP(client->conn->socketAddress));
        } else if (    (toupper(ptr[0]) == 'S') 
                    && (toupper(ptr[1]) == 'Y') 
                    && (toupper(ptr[2]) == 'S') 
                    && (toupper(ptr[3]) == 'T') 
                    && (toupper(ptr[4]) == 'E') 
                    && (toupper(ptr[5]) == 'M') 
                    && (ptr[6] == ' ')) {
            ptr += 7;

#if defined(DEBUG)
            if (strcmp(Conf.serverHash, ptr) == 0) {
                client->authorized = TRUE;

                return(ConnWrite(client->conn, MSG1000OK, sizeof(MSG1000OK) - 1));
            }
#endif

            Log(LOG_NOTICE, "PASS SYSTEM failed from host %s", LOGIP(client->conn->socketAddress));
        }
    }

    XplDelay(2000);

    ConnWrite(client->conn, MSG3010BADARGC, sizeof(MSG3010BADARGC) - 1);

    client->done = TRUE;
    
    return(-1);
}
Пример #14
0
unsigned long 
ProxyPOP3Account(MailProxyClient *client, ProxyAccount *proxy)
{
    long i;
    long j;
    long len;
    long ccode;
    long id;
    long first;
    long total;
    long mCount;
    long mSize;
    unsigned char *ptr;
    unsigned char *uid;
    XplDnsRecord *dns = NULL;

    proxy->flags |= MAILPROXY_FLAG_STORE_UID;
    strcpy(client->lastUID, proxy->uid);

    len = strlen(proxy->host) - 1;
    if (proxy->host[len] == '.') {
        proxy->host[len] = '\0';
    }

    if ((client->conn = ConnAlloc(TRUE)) != NULL) {
        client->conn->socketAddress.sin_addr.s_addr = inet_addr(proxy->host);
        if (client->conn->socketAddress.sin_addr.s_addr == INADDR_NONE) {
            ptr = strchr(proxy->host, '@');
            if (ptr) {
                ptr++;
            } else {
                ptr = proxy->host;
            }

            ccode = XplDnsResolve(ptr, &dns, XPL_RR_A);
            switch (ccode) {
                case XPL_DNS_SUCCESS: {
                    client->conn->socketAddress.sin_addr = dns->A.addr;
                    MemFree(dns);
                    break;
                }

                case XPL_DNS_BADHOSTNAME:
                case XPL_DNS_NORECORDS: {
                    LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_BAD_HOSTNAME, LOG_DEBUG, 0, ptr, client->q->user, 0, 0, NULL, 0);
                    proxy->flags |= MAILPROXY_FLAG_BAD_HOST;

                    MemFree(dns);
                    return(-1);
                }

                default:
                case XPL_DNS_FAIL:
                case XPL_DNS_TIMEOUT: {
                    MemFree(dns);

                    LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, client->q->user, sizeof(Connection), __LINE__, NULL, 0);
                    return(-1);
                }
            }
        }

        client->conn->socketAddress.sin_family = AF_INET;
        client->conn->socketAddress.sin_port = htons(proxy->port);
    } else {
        LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, client->q->user, sizeof(Connection), __LINE__, NULL, 0);
        proxy->flags &= ~MAILPROXY_FLAG_STORE_UID;
        return(-1);
    }

    /* fixme - this check only works on single server solutions */
    if (MsgGetHostIPAddress() != client->conn->socketAddress.sin_addr.s_addr) {
        if (!(proxy->flags & MAILPROXY_FLAG_SSL)) {
            ccode = ConnConnect(client->conn, NULL, 0, NULL);
        } else if (MailProxy.client.ssl.enable) {
            if (proxy->port == PORT_POP3) {
                ccode = ConnConnect(client->conn, NULL, 0, NULL);
            } else {
                ccode = ConnConnect(client->conn, NULL, 0, MailProxy.client.ssl.context);
            }
        } else {
            ccode = -1;
        }
    } else {
        /* We don't want to proxy ourselves... */
        LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, client->q->user, NULL, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0);
        proxy->flags |= MAILPROXY_FLAG_BAD_HOST;
        return(-1);
    }

    /* POP3 greeting */
    if (ccode != -1) {
        if (proxy->flags & MAILPROXY_FLAG_SSL) {
            if (proxy->port == PORT_POP3) {
                if (((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) 
                        && (client->line[0] == '+') 
                        && ((ccode = ConnWrite(client->conn, "CAPA\r\n", 6)) != -1) 
                        && ((ccode = ConnFlush(client->conn)) != -1) 
                        && ((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) 
                        && (client->line[0] == '+')) {
                    proxy->flags &= ~MAILPROXY_FLAG_SSL;

                    while ((ccode != -1) && (client->line[0] != POP_OK)) {
                        ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE);
                        if (ccode != -1) {
                            CHOP_NEWLINE(client->line);

                            if (XplStrCaseCmp(client->line, "STLS") != 0) {
                                continue;
                            }

                            proxy->flags |= MAILPROXY_FLAG_SSL;
                        }
                    }

                    if ((ccode != -1) 
                            && (client->line[0] == '+') 
                            && (proxy->flags & MAILPROXY_FLAG_SSL) 
                            && ((ccode = ConnWrite(client->conn, "STLS\r\n", 6)) != -1) 
                            && ((ccode = ConnFlush(client->conn)) != -1) 
                            && ((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1)) {
                        client->conn->ssl.enable = TRUE;
                        ccode = ConnEncrypt(client->conn, MailProxy.client.ssl.context);
                    } else {
                        ccode = -1;
                    }
                } else {
                    ccode = -1;
                }
            } else {
                client->conn->ssl.enable = TRUE;
                if (((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) 
                        && (client->line[0] != POP_OK)) {
                    ccode = -1;
                }
            }
        } else if (((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) 
                && (client->line[0] != POP_OK)) {
            ccode = -1;
        }
    } else {
        proxy->flags |= MAILPROXY_FLAG_BAD_HANDSHAKE;
        LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_IP_CONNECT_FAILURE, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0);
        return(-1);
    }

    if ((ccode != -1) 
            && ((ccode = ConnWriteF(client->conn, "USER %s\r\n", proxy->user)) != -1) 
            && ((ccode = ConnFlush(client->conn)) != -1) 
            && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1) 
            && (client->line[0] == POP_OK) 
            && ((ccode = ConnWriteF(client->conn, "PASS %s\r\n", proxy->password)) != -1) 
            && ((ccode = ConnFlush(client->conn)) != -1) 
            && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1) 
            && (client->line[0] == POP_OK) 
            && ((ccode = ConnWrite(client->conn, "UIDL\r\n", 6)) != -1) 
            && ((ccode = ConnFlush(client->conn)) != -1) 
            && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1) 
            && (client->line[0] == POP_OK)) {
        first = 1;
        total = 0;
        while (((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1) 
                && (client->line[0] != POP_EOD)) {
            total++;

            id = atol(client->line);
            uid = strchr(client->line, ' ');
            if (uid) {
                while (*uid && isspace(*uid)) {
                    uid++;
                }

                if (strcmp(uid, proxy->uid) == 0) {
                    first = id + 1;
                }
            } else {
                LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NEGOTIATION_FAILED, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0);
                return(-1);
            }
        }
    } else {
        if (ccode != -1) {
            XplSafeIncrement(MailProxy.stats.wrongPassword);

            proxy->flags |= MAILPROXY_FLAG_BAD_PASSWORD;
            LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_WRONG_PASSWORD, LOG_ERROR, 0, client->q->user, proxy->password, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0);
        } else {
            proxy->flags |= MAILPROXY_FLAG_BAD_HANDSHAKE;
            LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NETWORK_IO_FAILURE, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), __LINE__, NULL, 0);
        }

        return(-1);
    }

    if (ccode != -1) {
        if (first <= total) {
            client->nmap = NMAPConnectEx(MailProxy.nmap.address, NULL, client->conn->trace.destination);
        } else {
            /* We've already got all the messages, or there are none */
            LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_PROXY_USER, LOG_WARNING, 0, client->q->user, proxy->host, 0, 0, NULL, 0);
            return(0);
        }
    } else {
        proxy->flags |= MAILPROXY_FLAG_BAD_PROXY;
        LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NEGOTIATION_FAILED, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0);
        return(-1);
    }

    if ((client->nmap) && (NMAPAuthenticate(client->nmap, client->line, CONN_BUFSIZE) == TRUE)) {
        mCount = 0;
        mSize = 0;
    } else {
        if (client->nmap) {
            NMAPSendCommand(client->nmap, "QUIT\r\n", 6);
            NMAPReadAnswer(client->nmap, client->line, CONN_BUFSIZE, FALSE);
            LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NMAP_UNAVAILABLE, LOG_ERROR, 0, NULL, NULL, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0);
        } else {
            LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, client->q->user, sizeof(Connection), __LINE__, NULL, 0);
        }

        proxy->flags |= MAILPROXY_FLAG_BAD_PROXY;
        return(-1);
    }

    if (client->nmap) {
        for (i = first; (ccode != -1) && (i <= total); i++) {
            ccode = NMAPSendCommandF(client->nmap, "QCREA\r\nQSTOR FLAGS 128\r\nQSTOR FROM %s %s -\r\nQSTOR LOCAL %s %s %d\r\nQSTOR MESSAGE\r\n", MailProxy.postmaster, MailProxy.postmaster, client->q->user, client->q->user, NO_FORWARD);
            for (j = 0; (ccode != -1) && (j < 4); j++) {
                /* QSTOR does not have an immediate result [it comes once the . makes it to the other side] */
                if ((ccode = NMAPReadAnswer(client->nmap, client->line, CONN_BUFSIZE, FALSE)) != -1) {
                    continue;
                }

                LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, client->q->user, "Create queue entry", ccode, 0, NULL, 0);
                XplConsolePrintf("bongomailprox: Could not create queue entry, NMAP error %lu, user %s", ccode, client->q->user);

                return(mCount);
            }

            if (((ccode = ConnWriteF(client->conn, "RETR %lu\r\n", i)) != -1) 
                    && ((ccode = ConnFlush(client->conn)) != -1) 
                    && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1) 
                    && (client->line[0] == POP_OK)) {
                ccode = ConnReadToConnUntilEOS(client->conn, client->nmap);
            } else {
                LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_NEGOTIATION_FAILED, LOG_ERROR, 0, proxy->host, client->q->user, XplHostToLittle(client->conn->socketAddress.sin_addr.s_addr), 0, NULL, 0);
                return(mCount);
            }

            if (ccode != -1) {
                if (((ccode = NMAPReadAnswer(client->nmap, client->line, CONN_BUFSIZE, TRUE)) == NMAP_OK) /* QSTOR MESSAGE */
                        && ((ccode = NMAPSendCommand(client->nmap, "QRUN\r\n", 6)) != -1) 
                        && ((ccode = NMAPReadAnswer(client->nmap, client->line, CONN_BUFSIZE, TRUE)) == NMAP_ENTRY_CREATED)) {
                    if (((ccode = ConnWriteF(client->conn, "UIDL %lu\r\n", i)) != -1) 
                            && ((ccode = ConnFlush(client->conn)) != -1) 
                            && ((ccode = ConnReadAnswer(client->conn, client->line, CONN_BUFSIZE)) != -1)
                            && (client->line[0] == POP_OK)) {
                        uid = strchr(client->line+4, ' ');
                        while (*uid && isspace(*uid)) {
                            uid++;
                        }
                        /* Save the UID because this message is now in Bongo */
                        strcpy(client->lastUID, uid);

                        mCount++;
                        mSize += ccode;

                        if (proxy->flags & MAILPROXY_FLAG_LEAVE_MAIL) {
                            continue;
                        }

                        if (((ccode = ConnWriteF(client->conn, "DELE %lu\r\n", i)) != -1) 
                                && ((ccode = ConnFlush(client->conn)) != -1) 
                                && ((ccode = ConnReadLine(client->conn, client->line, CONN_BUFSIZE)) != -1)
                                && (client->line[0] == POP_OK)) {
                            continue;
                        }
                    }
                }
            }

            return(mCount);
        }

        mSize = (mSize + 1023) / 1024;

        LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_PROXY_USER, LOG_WARNING, 0, client->q->user, proxy->host, mCount, mSize, NULL, 0);

        XplSafeAdd(MailProxy.stats.messages, mCount);
        XplSafeAdd(MailProxy.stats.kiloBytes, mSize);

        return(mCount);
    }

    LoggerEvent(MailProxy.handle.logging, LOGGER_SUBSYSTEM_GENERAL, LOGGER_EVENT_OUT_OF_MEMORY, LOG_ERROR, 0, __FILE__, client->q->user, sizeof(Connection), __LINE__, NULL, 0);
    return(-1);
}
Пример #15
0
abyss_bool handler_hook(TSession * r)
{
	//char *mime = "text/html";
	char buf[80] = "HTTP/1.1 200 OK\n";
	switch_stream_handle_t stream = { 0 };
	char *command;
	int i;
	TTableItem *ti;
	char *fs_user = NULL, *fs_domain = NULL;
	char *path_info = NULL;
	abyss_bool ret = TRUE;
	int html = 0, text = 0, xml = 0;
	const char *api_str;

	stream.data = r;
	stream.write_function = http_stream_write;
	stream.raw_write_function = http_stream_raw_write;

	if (!r || !r->requestInfo.uri) {
		return FALSE;
	}
	
	if ((command = strstr(r->requestInfo.uri, "/api/"))) {
		command += 5;
	} else if ((command = strstr(r->requestInfo.uri, "/webapi/"))) {
		command += 8;
		html++;
	} else if ((command = strstr(r->requestInfo.uri, "/txtapi/"))) {
		command += 8;
		text++;
	} else if ((command = strstr(r->requestInfo.uri, "/xmlapi/"))) {
		command += 8;
		xml++;
	} else {
		return FALSE;
	}

	if ((path_info = strchr(command, '/'))) {
		*path_info++ = '\0';
	}

	for (i = 0; i < r->response_headers.size; i++) {
		ti = &r->response_headers.item[i];
		if (!strcasecmp(ti->name, "freeswitch-user")) {
			fs_user = ti->value;
		} else if (!strcasecmp(ti->name, "freeswitch-domain")) {
			fs_domain = ti->value;
		}
	}

	if (is_authorized(r, command)) {
		goto auth;
	}

	ret = TRUE;
	goto end;

  auth:

	if (switch_event_create(&stream.param_event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
		const char *const content_length = RequestHeaderValue(r, "content-length");

		if (html)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/html");
		else if (text)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/plain");
		else if (xml)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "Content-type", "text/xml");
		if (fs_user)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user);
		if (fs_domain)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain);
		if (path_info)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info);
		switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-URI", r->requestInfo.uri);
		if (r->requestInfo.query)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", r->requestInfo.query);
		if (r->requestInfo.host)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-HOST", r->requestInfo.host);
		if (r->requestInfo.from)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-FROM", r->requestInfo.from);
		if (r->requestInfo.useragent)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", r->requestInfo.useragent);
		if (r->requestInfo.referer)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REFERER", r->requestInfo.referer);
		if (r->requestInfo.requestline)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", r->requestInfo.requestline);
		if (r->requestInfo.user)
			switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-USER", r->requestInfo.user);
		if (r->requestInfo.port)
			switch_event_add_header(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", r->requestInfo.port);
		if (r->requestInfo.query || content_length) {
			char *q, *qd;
			char *next;
			char *query = (char *) r->requestInfo.query;
			char *name, *val;
			char qbuf[8192] = "";

			if (r->requestInfo.method == m_post && content_length) {
				int len = atoi(content_length);
				int qlen = 0;

				if (len > 0) {
					int succeeded;
					char *qp = qbuf;
					do {
						int blen = r->conn->buffersize - r->conn->bufferpos;

						if ((qlen + blen) > len) {
							blen = len - qlen;
						}

						qlen += blen;

						if (qlen > sizeof(qbuf)) {
							break;
						}

						memcpy(qp, r->conn->buffer + r->conn->bufferpos, blen);
						qp += blen;

						if (qlen >= len) {
							break;
						}
					} while ((succeeded = ConnRead(r->conn, 2000)));

					query = qbuf;
				}
			}
			if (query) {
				switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query);

				qd = strdup(query);
				switch_assert(qd != NULL);

				q = qd;
				next = q;

				do {
					char *p;

					if ((next = strchr(next, '&'))) {
						*next++ = '\0';
					}

					for (p = q; p && *p; p++) {
						if (*p == '+') {
							*p = ' ';
						}
					}

					switch_url_decode(q);

					name = q;
					if ((val = strchr(name, '='))) {
						*val++ = '\0';
						switch_event_add_header_string(stream.param_event, SWITCH_STACK_BOTTOM, name, val);
					}
					q = next;
				} while (q != NULL);

				free(qd);
			}
		}
	}
	//ResponseChunked(r);

	//ResponseContentType(r, mime);
	//ResponseWrite(r);

	HTTPWrite(r, buf, (uint32_t) strlen(buf));

	//HTTPWrite(r, "<pre>\n\n", 7);

	/* generation of the date field */
	{
		const char *dateValue;

		DateToString(r->date, &dateValue);

		if (dateValue) {
			ResponseAddField(r, "Date", dateValue);
		}
	}


	/* Generation of the server field */
	ResponseAddField(r, "Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc");

	if (html) {
		ResponseAddField(r, "Content-Type", "text/html");
	} else if (text) {
		ResponseAddField(r, "Content-Type", "text/plain");
	} else if (xml) {
		ResponseAddField(r, "Content-Type", "text/xml");
	}

	for (i = 0; i < r->response_headers.size; i++) {
		ti = &r->response_headers.item[i];
		ConnWrite(r->conn, ti->name, (uint32_t) strlen(ti->name));
		ConnWrite(r->conn, ": ", 2);
		ConnWrite(r->conn, ti->value, (uint32_t) strlen(ti->value));
		ConnWrite(r->conn, CRLF, 2);
	}

	switch_snprintf(buf, sizeof(buf), "Connection: close\r\n");
	ConnWrite(r->conn, buf, (uint32_t) strlen(buf));

	if (html || text || xml) {
		ConnWrite(r->conn, "\r\n", 2);
	}

	if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) {
		command = "bgapi";
		api_str = "unload mod_xml_rpc";
	} else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", r->requestInfo.query)) {
		command = "bgapi";
		api_str = "reload mod_xml_rpc";
	} else {
		api_str = r->requestInfo.query;
	}

	if (switch_api_execute(command, api_str, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
		ResponseStatus(r, 200);
		r->responseStarted = TRUE;
		//r->done = TRUE;
	} else {
		ResponseStatus(r, 404);
		ResponseError(r);
	}

	//SocketClose(&(r->conn->socket));

	HTTPWriteEnd(r);
	//if (r->conn->channelP)
	//ConnKill(r->conn);
	//ChannelInterrupt(r->conn->channelP);
	//ConnClose(r->conn);
	//ChannelDestroy(r->conn->channelP);
	r->requestInfo.keepalive = 0;

  end:

	return ret;
}
Пример #16
0
BOOL VirusCheck(AVirusClient *client, const char *queueID, BOOL hasFlags, unsigned long msgFlags, unsigned long senderIp, char *senderUserName) {
    int ccode;
    long size;
    BOOL infected = FALSE;
    Connection *conn;

    conn = ConnAddressPoolConnect(&(AVirus.clamd.hosts), AVirus.clamd.connectionTimeout); 
    if (conn) {
	    Connection *data;
	    unsigned short port;
	    
	    ConnWrite(conn, "STREAM\r\n", strlen("STREAM\r\n"));
	    ConnFlush(conn);
	    ccode = ConnReadAnswer(conn, client->line, CONN_BUFSIZE);

	    if (!ccode || strncmp(client->line, "PORT ", strlen("PORT ")) != 0 || (port = atoi(client->line + strlen("PORT "))) == 0) {
		    ConnFree(conn);
		    return -1;
	    }
	    
	    data = ConnAlloc(TRUE);
	    if (!data) {
		    ConnFree(conn);
		    return -1;
	    }

	    memcpy(&data->socketAddress, &conn->socketAddress, sizeof(struct sockaddr_in));
	    data->socketAddress.sin_port = htons(port);
	    if (ConnConnectEx(data, NULL, 0, NULL, client->conn->trace.destination) < 0) {
		    ConnFree(conn);
		    ConnFree(data);
		    return -1;
	    }

	    size = 0;
	    if (((ccode = NMAPSendCommandF(client->conn, "QRETR %s MESSAGE\r\n", queueID)) != -1)
		&& ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != -1)
		&& ccode == 2023) {
		    char *ptr;

		    ptr = strchr (client->line, ' ');
		    if (ptr) {
		        *ptr = '\0';
		    }
		
		    size = atol(client->line);
	    }

	    if (size == 0) {
		    ConnFree(conn);
		    ConnFree(data);
		    return -1;
	    }

	    ccode = ConnReadToConn(client->conn, data, size);
	    
	    ConnFree(data);
	    
	    if ((ccode == -1) || ((ccode = NMAPReadAnswer(client->conn, client->line, CONN_BUFSIZE, TRUE)) != 1000)) {
            Log(LOG_DEBUG, "result: %d", ccode);
		    ConnFree(conn);
		    return -1;
	    }

	    while ((ccode = ConnReadAnswer(conn, client->line, CONN_BUFSIZE)) != -1) {
            char *ptr;

            ptr = strrchr(client->line, ' ');
            if (XplStrCaseCmp(ptr + 1, "FOUND") == 0) {
                *ptr = '\0';
                ptr = client->line + strlen("stream: ");

#if 0
                if(client->foundViruses.used == client->foundViruses.allocated) {
                    client->foundViruses.names = MemRealloc(client->foundViruses.names, sizeof(char*) * (client->foundViruses.allocated + MIME_REALLOC_SIZE));
                }
                client->foundViruses.names[client->foundViruses.used++] = MemStrdup(ptr);

                XplSafeIncrement(AVirus.stats.viruses);
#endif
                infected = TRUE;
            }
	    }
	    ConnFree(conn);
    }

    return infected;
}
Пример #17
0
abyss_bool handler_hook(TSession * r)
{
	switch_stream_handle_t stream = { 0 };
	char *command;
	int i;
	char *fs_user = NULL, *fs_domain = NULL;
	char *path_info = NULL;
	abyss_bool ret = TRUE;
	int html = 0, text = 0, xml = 0, api = 0;
	const char *api_str;
	const char *uri = 0;
	TRequestInfo *info = 0;
	switch_event_t *evnt = 0; /* shortcut to stream.param_event */

	if (!r || !(info = &r->requestInfo) || !(uri = info->uri)) {
		return FALSE;
	}

	stream.data = r;
	stream.write_function = http_stream_write;
	stream.raw_write_function = http_stream_raw_write;

	if ((command = strstr(uri, "/api/"))) {
		command += 5;
		api++;
	} else if ((command = strstr(uri, "/webapi/"))) {
		command += 8;
		html++;
	} else if ((command = strstr(uri, "/txtapi/"))) {
		command += 8;
		text++;
	} else if ((command = strstr(uri, "/xmlapi/"))) {
		command += 8;
		xml++;
	} else {
		return FALSE; /* 404 */
	}

	if ((path_info = strchr(command, '/'))) {
		*path_info++ = '\0';
	}

	for (i = 0; i < r->responseHeaderFields.size; i++) {
		TTableItem *ti = &r->responseHeaderFields.item[i];
		if (!strcasecmp(ti->name, "freeswitch-user")) {
			fs_user = ti->value;
		} else if (!strcasecmp(ti->name, "freeswitch-domain")) {
			fs_domain = ti->value;
		}
	}

	if (!is_authorized(r, command)) {
		ret = TRUE;
		goto end;
	}

/*  auth: */

	if (switch_event_create(&stream.param_event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
		const char *const content_length = RequestHeaderValue(r, "content-length");
		evnt = stream.param_event;

		if (html) {
			switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/html");
		} else if (text) {
			switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/plain");
		} else if (xml) {
			switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/xml");
		}
		if (api) {
			switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-API", "api");
		}
		if (fs_user)   switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user);
		if (fs_domain) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain);
		if (path_info) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info);

		if (info->host)        switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-HOST", info->host);
		if (info->from)        switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-FROM", info->from);
		if (info->useragent)   switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", info->useragent);
		if (info->referer)     switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REFERER", info->referer);
		if (info->requestline) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", info->requestline);
		if (info->user)        switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER", info->user);
		if (info->port)        switch_event_add_header(evnt, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", info->port);

		{
			char *q, *qd;
			char *next;
			char *query = (char *) info->query;
			char *name, *val;
			char qbuf[8192] = "";

			/* first finish reading from the socket if post method was used*/
			if (info->method == m_post && content_length) {
				int len = atoi(content_length);
				int qlen = 0;

				if (len > 0) {
					int succeeded = TRUE;
					char *qp = qbuf;
					char *readError;

					do {
						int blen = r->connP->buffersize - r->connP->bufferpos;

						if ((qlen + blen) > len) {
							blen = len - qlen;
						}

						qlen += blen;

						if (qlen > sizeof(qbuf)) {
							break;
						}

						memcpy(qp, r->connP->buffer.b + r->connP->bufferpos, blen);
						qp += blen;

						if (qlen >= len) {
							break;
						}

						ConnRead(r->connP, 2000, NULL, NULL, &readError);
		                if (readError) {
							succeeded = FALSE;
							free(readError);
						}

					} while (succeeded);

					query = qbuf;
				}
			}

			/* parse query and add kv-pairs as event headers  */
			/* a kv pair starts with '&', '+' or \0 mark the end */
			if (query) {
				switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query);
				qd = strdup(query);
			} else {
				qd = strdup(uri);
			}

			switch_assert(qd != NULL);

			q = qd;
			next = q;

			do {
				char *p;

				if (next = strchr(next, '&')) {
					if (!query) {
						/* pass kv pairs from uri to query       */
			            /* "?" is absent in url so parse uri     */
						*((char *)uri + (next - q - 1)) = '\0';
						query = next;
						switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", next);
						/* and strip uri                                     */
						/* the start of first kv pair marks the end of uri   */
						/* to prevent kv-pairs confusing fs api commands     */
						/* that have arguments separated by space            */
					}
					*next++ = '\0';
				}

				for (p = q; p && *p; p++) {
					if (*p == '+') {
						*p = ' ';
					}
				}
				/* hmmm, get method requests are already decoded ... */
				switch_url_decode(q);

				name = q;
				if ((val = strchr(name, '='))) {
					*val++ = '\0';
					switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, name, val);
				}
				q = next;
			} while (q != NULL);

			free(qd);
		}
	}

	switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-URI", uri);

	/* We made it this far, always OK */
	if (!HTTPWrite(r, "HTTP/1.1 200 OK\r\n", (uint32_t) strlen("HTTP/1.1 200 OK\r\n"))) {
		return TRUE;
	}

	ResponseAddField(r, "Connection", "close");

	/* generation of the date field */
	if (evnt)
	{
		ResponseAddField(r, "Date", switch_event_get_header(evnt, "Event-Date-GMT"));
	}
	else {
		const char *dateValue;

		DateToString(r->date, &dateValue);
		if (dateValue) {
			ResponseAddField(r, "Date", dateValue);
			free((void *)dateValue);
		}
	}

	/* Generation of the server field */
	ResponseAddField(r, "Server", "FreeSWITCH-" SWITCH_VERSION_FULL "-mod_xml_rpc");

	if (html) {
		ResponseAddField(r, "Content-Type", "text/html");
	} else if (text) {
		ResponseAddField(r, "Content-Type", "text/plain");
	} else if (xml) {
		ResponseAddField(r, "Content-Type", "text/xml");
	}

	for (i = 0; i < r->responseHeaderFields.size; i++) {
		TTableItem *ti = &r->responseHeaderFields.item[i];
		char *header = switch_mprintf("%s: %s\r\n", ti->name, ti->value);
		if (!ConnWrite(r->connP, header, (uint32_t) strlen(header))) {
			switch_safe_free(header);
			return TRUE;
		}
		switch_safe_free(header);
	}

	/* send end http header */
	if (html||text||xml) {
		if (!ConnWrite(r->connP, CRLF, 2)) {
			return TRUE;
		}
	}
	else {
		/* content-type and end of http header will be streamed by fs api or http_stream_write */
	}

	if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", info->query)) {
		command = "bgapi";
		api_str = "unload mod_xml_rpc";
	} else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", info->query)) {
		command = "bgapi";
		api_str = "reload mod_xml_rpc";
	} else {
		api_str = info->query;
	}

	/* TODO (maybe): take "refresh=xxx" out of query as to not confuse fs api commands         */

	/* execute actual fs api command                                                            */
	/* fs api command will write to stream,  calling http_stream_write / http_stream_raw_write	*/
	/* switch_api_execute will stream INVALID COMMAND before it fails					        */
	switch_api_execute(command, api_str, NULL, &stream);

	r->responseStarted = TRUE;
	ResponseStatus(r, 200);     /* we don't want an assertion failure */
	r->requestInfo.keepalive = 0;

  end:

	return ret;
}
Пример #18
0
bool
ConnWriteFromFile(TConn *       const connectionP,
                  const TFile * const fileP,
                  uint64_t      const start,
                  uint64_t      const last,
                  void *        const buffer,
                  uint32_t      const buffersize,
                  uint32_t      const rate) {
/*----------------------------------------------------------------------------
   Write the contents of the file stream *fileP, from offset 'start'
   up through 'last', to the HTTP connection *connectionP.

   Meter the reading so as not to read more than 'rate' bytes per second.

   Use the 'bufferSize' bytes at 'buffer' as an internal buffer for this.
-----------------------------------------------------------------------------*/
    bool retval;
    uint32_t waittime;
    bool success;
    uint32_t readChunkSize;
	uint32_t ChunkSize = 4096 * 2; /* read buffer size */

    if (rate > 0) {
        readChunkSize = MIN(buffersize, rate);  /* One second's worth */
        waittime = (1000 * buffersize) / rate;
    } else {
        readChunkSize = ChunkSize;
        waittime = 0;
    }

    success = FileSeek(fileP, start, SEEK_SET);
    if (!success)
        retval = FALSE;
    else {
        uint64_t const totalBytesToRead = last - start + 1;
        uint64_t bytesread = 0;

        int32_t bytesReadThisTime = 0;
        char * chunk = (char *) buffer; /* the beginning */
        do {

			if ((bytesReadThisTime = FileRead(fileP, chunk, readChunkSize)) <= 0 )
				break;
			
			bytesread += bytesReadThisTime;
			chunk += bytesReadThisTime;

			/* fix bug in ms ie as it doesn't render text/plain properly                    */
			/* if CRLFs are split between reassembled tcp packets,                          */
			/* ie "might" undeterministically render extra empty lines                      */
			/* if it ends in CR or LF, read an extra chunk until the buffer is full         */
			/* or end of file is reached. You may still have bad luck, complaints go to MS) */

/*			if (bytesReadThisTime == readChunkSize &&  chunk - (char *) buffer + readChunkSize < buffersize) { 
 *				char * end = chunk - 1;
 *				if (*end == CR || *end == LF) {
 *					continue;
 *				}
 *			}
 */				          
            if (!bytesReadThisTime || !ConnWrite(connectionP, buffer, chunk - (char *) buffer)) {
                break;
			}

			chunk = (char *) buffer; /* a new beginning */

			if (waittime > 0)
                xmlrpc_millisecond_sleep(waittime);
			
        } while (bytesReadThisTime == readChunkSize);

        retval = (bytesread >= totalBytesToRead);
    }
    return retval;
}