Esempio n. 1
0
//returns: SyntaxError if there was an error in the uri. Or InternalServerError
QTSS_Error RTSPRequest::ParseURI(StringParser &parser)
{
    //read in the complete URL, set it to be the qtssAbsoluteURLParam
    StrPtrLen theAbsURL;

    //  RTSPRequestInterface::sPathURLStopConditions stop on ? as well as sURLStopConditions
    parser.ConsumeUntil(&theAbsURL, sURLStopConditions );

    // set qtssRTSPReqAbsoluteURL to the URL throught the path component; will be : <protocol>://<host-addr>/<path>
    this->SetVal(qtssRTSPReqAbsoluteURL, &theAbsURL);
    
    StringParser urlParser(&theAbsURL);
    
    //we always should have a slash before the uri.
    //If not, that indicates this is a full URI. Also, this could be a '*' OPTIONS request
    if ((*theAbsURL.Ptr != '/') && (*theAbsURL.Ptr != '*'))
    {
        //if it is a full URL, store the host name off in a separate parameter
        StrPtrLen theRTSPString;
        urlParser.ConsumeLength(&theRTSPString, 7); //consume "rtsp://"
        //assign the host field here to the proper QTSS param
        StrPtrLen theHost;
        urlParser.ConsumeUntil(&theHost, '/');
        fHeaderDictionary.SetVal(qtssHostHeader, &theHost);
    }
    
    // don't allow non-aggregate operations indicated by a url/media track=id
// might need this for rate adapt   if (qtssSetupMethod != fMethod && qtssOptionsMethod != fMethod && qtssSetParameterMethod != fMethod) // any method not a setup, options, or setparameter is not allowed to have a "/trackID=" in the url.
    if (qtssSetupMethod != fMethod) // any method not a setup is not allowed to have a "/trackID=" in the url.
    {
        StrPtrLenDel tempCStr(theAbsURL.GetAsCString()); 
        StrPtrLen nonaggregate(tempCStr.FindString("/trackID="));
        if (nonaggregate.Len > 0) // check for non-aggregate method and return error
            return QTSSModuleUtils::SendErrorResponse(this, qtssClientAggregateOptionAllowed, qtssMsgBadRTSPMethod, &theAbsURL);
    }

    // don't allow non-aggregate operations like a setup on a playing session
    if (qtssSetupMethod == fMethod) // if it is a setup but we are playing don't allow it
    {
        RTSPSession*  theSession =  (RTSPSession*)this->GetSession();
        if (theSession != NULL && theSession->IsPlaying())
            return QTSSModuleUtils::SendErrorResponse(this, qtssClientAggregateOptionAllowed, qtssMsgBadRTSPMethod, &theAbsURL);
    }

    //
    // In case there is no URI at all... we have to fake it.
    static char* sSlashURI = "/";
        
    //whatever is in this position in the URL must be the URI. Store that
    //in the qtssURLParam. Confused?
    UInt32 uriLen = urlParser.GetDataReceivedLen() - urlParser.GetDataParsedLen();
    if (uriLen > 0)
        this->SetVal(qtssRTSPReqURI, urlParser.GetCurrentPosition(), urlParser.GetDataReceivedLen() - urlParser.GetDataParsedLen());
    else
        //
        // This might happen if there is nothing after the host at all, not even
        // a '/'. This is legal (RFC 2326, Sec 3.2). If so, just pretend that there
        // is a '/'
        this->SetVal(qtssRTSPReqURI, sSlashURI, 1);

    // parse the query string from the url if present.
    // init qtssRTSPReqQueryString dictionary to an empty string
    StrPtrLen queryString;
    this->SetVal(qtssRTSPReqQueryString, queryString.Ptr, queryString.Len);
    
    if ( parser.GetDataRemaining() > 0 )
    {   
        if ( parser.PeekFast() == '?' )
        {       
            // we've got some CGI param
            parser.ConsumeLength(&queryString, 1); // toss '?'
            
            // consume the rest of the line..
            parser.ConsumeUntilWhitespace(&queryString);
            
            this->SetVal(qtssRTSPReqQueryString, queryString.Ptr, queryString.Len);
        }
    }
 
 
    //
    // If the is a '*', return right now because '*' is not a path
    // so the below functions don't make any sense.
    if ((*theAbsURL.Ptr == '*') && (theAbsURL.Len == 1))
    {
		this->SetValue(qtssRTSPReqFilePath, 0, theAbsURL.Ptr, theAbsURL.Len, QTSSDictionary::kDontObeyReadOnly);
		
        return QTSS_NoErr;
    }
    
    //path strings are statically allocated. Therefore, if they are longer than
    //this length we won't be able to handle the request.
    StrPtrLen* theURLParam = this->GetValue(qtssRTSPReqURI);
    if (theURLParam->Len > RTSPRequestInterface::kMaxFilePathSizeInBytes)
        return QTSSModuleUtils::SendErrorResponse(this, qtssClientBadRequest, qtssMsgURLTooLong, theURLParam);

    //decode the URL, put the result in the separate buffer for the file path,
    //set the file path StrPtrLen to the proper value
    SInt32 theBytesWritten = StringTranslator::DecodeURL(theURLParam->Ptr, theURLParam->Len,
                                                fFilePath, RTSPRequestInterface::kMaxFilePathSizeInBytes);
    //if negative, an error occurred, reported as an QTSS_Error
    //we also need to leave room for a terminator.
    if ((theBytesWritten < 0) || (theBytesWritten == RTSPRequestInterface::kMaxFilePathSizeInBytes))
    {
        return QTSSModuleUtils::SendErrorResponse(this, qtssClientBadRequest, qtssMsgURLInBadFormat, theURLParam);
    }

    // Convert from a / delimited path to a local file system path
    StringTranslator::DecodePath(fFilePath, theBytesWritten);
    
    //setup the proper QTSS param
    fFilePath[theBytesWritten] = '\0';
    //this->SetVal(qtssRTSPReqFilePath, fFilePath, theBytesWritten);
	this->SetValue(qtssRTSPReqFilePath, 0, fFilePath, theBytesWritten, QTSSDictionary::kDontObeyReadOnly);



    return QTSS_NoErr;
}
Esempio n. 2
0
nsresult nsOutlookMail::ImportMailbox( PRUint32 *pDoneSoFar, PRBool *pAbort, PRInt32 index, const PRUnichar *pName, nsIFile *pDest, PRInt32 *pMsgCount)
{
  if ((index < 0) || (index >= m_folderList.GetSize())) {
    IMPORT_LOG0( "*** Bad mailbox identifier, unable to import\n");
    *pAbort = PR_TRUE;
    return( NS_ERROR_FAILURE);
  }

  PRInt32    dummyMsgCount = 0;
  if (pMsgCount)
    *pMsgCount = 0;
  else
    pMsgCount = &dummyMsgCount;

  CMapiFolder *pFolder = m_folderList.GetItem( index);
  OpenMessageStore( pFolder);
  if (!m_lpMdb) {
    IMPORT_LOG1( "*** Unable to obtain mapi message store for mailbox: %S\n", pName);
    return( NS_ERROR_FAILURE);
  }

  if (pFolder->IsStore())
    return( NS_OK);

  nsresult  rv;

  nsOutlookCompose    compose;
  SimpleBufferTonyRCopiedTwice      copy;

  copy.Allocate( kCopyBufferSize);

  // now what?
  CMapiFolderContents    contents( m_lpMdb, pFolder->GetCBEntryID(), pFolder->GetEntryID());

  BOOL    done = FALSE;
  ULONG    cbEid;
  LPENTRYID  lpEid;
  ULONG    oType;
  LPMESSAGE  lpMsg = nsnull;
  int      attachCount;
  ULONG    totalCount;
  PRFloat64  doneCalc;
  nsCString  fromLine;
  int      fromLen;
  PRBool    lostAttach = PR_FALSE;

  nsCOMPtr<nsIOutputStream> destOutputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(destOutputStream), pDest, -1, 0600);
  NS_ENSURE_SUCCESS(rv, rv);

  while (!done) {
    if (!contents.GetNext( &cbEid, &lpEid, &oType, &done)) {
      IMPORT_LOG1( "*** Error iterating mailbox: %S\n", pName);
      return( NS_ERROR_FAILURE);
    }

    totalCount = contents.GetCount();
    doneCalc = *pMsgCount;
    doneCalc /= totalCount;
    doneCalc *= 1000;
    if (pDoneSoFar) {
      *pDoneSoFar = (PRUint32) doneCalc;
      if (*pDoneSoFar > 1000)
        *pDoneSoFar = 1000;
    }

    if (!done && (oType == MAPI_MESSAGE)) {
      if (!m_mapi.OpenMdbEntry( m_lpMdb, cbEid, lpEid, (LPUNKNOWN *) &lpMsg)) {
        IMPORT_LOG1( "*** Error opening messages in mailbox: %S\n", pName);
        return( NS_ERROR_FAILURE);
      }

      CMapiMessage  msg( lpMsg);

      BOOL bResult = msg.FetchHeaders();
      if (bResult)
        bResult = msg.FetchBody();
      if (bResult)
        fromLine = msg.GetFromLine( fromLen);

      attachCount = msg.CountAttachments();
      BuildAttachments( msg, attachCount);

      if (!bResult) {
        IMPORT_LOG1( "*** Error reading message from mailbox: %S\n", pName);
        return( NS_ERROR_FAILURE);
      }

      // --------------------------------------------------------------
      compose.SetBody( msg.GetBody());

      // Need to convert all headers to unicode (for i18n).
      // Init header here since 'composes' is used for all msgs.
      compose.SetHeaders("");

      nsAutoString newheader;
      nsCAutoString tempCStr(msg.GetHeaders(), msg.GetHeaderLen());

      rv = nsMsgI18NConvertToUnicode(nsMsgI18NFileSystemCharset(),
        tempCStr, newheader);
      NS_ASSERTION(NS_SUCCEEDED(rv), "failed to convert headers to utf8");
      if (NS_SUCCEEDED(rv))
        compose.SetHeaders(NS_ConvertUTF16toUTF8(newheader).get());

      compose.SetAttachments( &m_attachments);

      // See if it's a drafts folder. Outlook doesn't allow drafts
      // folder to be configured so it's ok to hard code it here.
      nsAutoString folderName(pName);
      nsMsgDeliverMode mode = nsIMsgSend::nsMsgDeliverNow;
      mode = nsIMsgSend::nsMsgSaveAsDraft;
      if ( folderName.LowerCaseEqualsLiteral("drafts") )
        mode = nsIMsgSend::nsMsgSaveAsDraft;

      /*
      If I can't get no headers,
      I can't get no satisfaction
      */
      if (msg.GetHeaderLen()) {
        nsCAutoString cType;
        SetDefaultContentType(msg, cType);
        nsCOMPtr<nsIFile> compositionFile;
        rv = compose.SendTheMessage(mode, cType, getter_AddRefs(compositionFile));
        if (NS_SUCCEEDED( rv)) {
          rv = compose.CopyComposedMessage( fromLine, compositionFile, destOutputStream, copy);
          DeleteFile( compositionFile);
          if (NS_FAILED( rv)) {
            IMPORT_LOG0( "*** Error copying composed message to destination mailbox\n");
            return( rv);
          }
          (*pMsgCount)++;
        }
      }
      else
        rv = NS_OK;

      // The following code to write msg to folder when compose.SendTheMessage() fails is commented
      // out for now because the code doesn't handle attachments and users will complain anyway so
      // until we fix the code to handle all kinds of msgs correctly we should not even make users
      // think that all msgs are imported ok. This will also help users to identify which msgs are
      // not imported and help to debug the problem.
#if 0
      if (NS_FAILED( rv)) {

        /* NS_PRECONDITION( FALSE, "Manual breakpoint"); */

        IMPORT_LOG1( "Message #%d failed.\n", (int) (*pMsgCount));
        DumpAttachments();

        // --------------------------------------------------------------

        // This is the OLD way of writing out the message which uses
        // all kinds of crufty old crap for attachments.
        // Since we now use Compose to send attachments,
        // this is only fallback error stuff.

        // Attachments get lost.

        if (attachCount) {
          lostAttach = PR_TRUE;
          attachCount = 0;
        }

        BOOL needsTerminate = FALSE;
        if (!WriteMessage( destOutputStream, &msg, attachCount, &needsTerminate)) {
          IMPORT_LOG0( "*** Error writing message\n");
          *pAbort = PR_TRUE;
          return( NS_ERROR_FAILURE);
        }

        if (needsTerminate) {
          if (!WriteMimeBoundary( destOutputStream, &msg, TRUE)) {
            IMPORT_LOG0( "*** Error writing message mime boundary\n");
            *pAbort = PR_TRUE;
            return( NS_ERROR_FAILURE);
          }
        }
      }
#endif

      // Just for YUCKS, let's try an extra endline
      WriteData( destOutputStream, "\x0D\x0A", 2);
    }
  }

  return( NS_OK);
}