Beispiel #1
0
void *smtp_challenge (void *s,unsigned long *len)
{
  char tmp[MAILTMPLEN];
  void *ret = NIL;
  SENDSTREAM *stream = (SENDSTREAM *) s;
  if ((stream->replycode == SMTPAUTHREADY) &&
      !(ret = rfc822_base64 ((unsigned char *) stream->reply + 4,
			     strlen (stream->reply + 4),len))) {
    sprintf (tmp,"SMTP SERVER BUG (invalid challenge): %.80s",stream->reply+4);
    mm_log (tmp,ERROR);
  }
  return ret;
}
Beispiel #2
0
static Variant HHVM_FUNCTION(imap_base64, const String& text) {
  unsigned long newlength;

  char *decode = (char *)rfc822_base64((unsigned char *) text.data(),
                                        text.length(), &newlength);
  if (decode == NULL) {
    return false;
  }

  String ret = String(decode, newlength, CopyString);
  fs_give((void**) &decode);
  return ret;
}
FeriteVariable *create_ferite_content_object( FeriteScript *script, MAILSTREAM *stream, BODY *body, int msgno, char *sec )
{
	if( body != NULL ) {
		FeriteVariable *object = NULL,*v = NULL;
		FeriteNamespaceBucket *nsb = NULL;
		char *object_name = NULL;

		object_name = ( body->type == TYPEMULTIPART ) ? "Mail.MessageMultiPart" : "Mail.MessagePart" ;

		nsb = ferite_find_namespace( script, script->mainns, object_name , FENS_CLS );
		if( nsb == NULL )
			return NULL;
		object = ferite_build_object( script, (FeriteClass *)nsb->data );
		if( object == NULL )
			return NULL;

		v  = fe_new_lng("type",body->type);
		ferite_object_set_var(script, VAO(object), "type", v);
		output_printf(OUTPUT_DEBUG,"module.mail: setting type %d", body->type);
		if( body->subtype ) {
			v = fe_new_str( "subtype", body->subtype, 0, FE_CHARSET_DEFAULT );
			ferite_object_set_var( script, VAO(object), "subtype", v );
		}

		if( body->type == TYPEMULTIPART ) {
			PART *part = NULL;
			int i = 0;
			char sec2[200];
			FeriteVariable *ret = NULL, *parts = NULL;

			parts = ferite_hash_get(script,VAO(object)->variables->variables,"parts");
			part = body->nested.part;
			while( part ) {
				i++;
				if( sec ) {
					snprintf(sec2,200,"%s.%d",sec,i);
				} else {
					snprintf(sec2,200,"%d",i);
				}
				ret = create_ferite_content_object( script, stream, &part->body, msgno, sec2 );
				ferite_uarray_add( script, VAUA(parts), ret , NULL, FE_ARRAY_ADD_AT_END );
				part = part->next;
			}
			v = fe_new_lng("nparts", i);
			ferite_object_set_var(script, VAO(object), "nparts", v );
		}
		else
		{
			long len = 0,len2 = 0;
			unsigned char *buf = NULL, *buf2 = NULL;
			SIZEDTEXT src, dest;
			FeriteVariable *v = NULL;
			PARAMETER *param = NULL;
			int i = 0;

			if( sec == NULL )
				sec = "1";
			buf = mail_fetchbody( stream, msgno, sec, &len );

			switch(body->encoding){
				case ENCQUOTEDPRINTABLE:
					if( debug_cmail_module )
						output_printf(OUTPUT_DEBUG,"module.mail: Decoding from encoded quotable");
					buf2 = rfc822_qprint(buf,len,&len2);
					break;
				case ENCBASE64: 
					if( debug_cmail_module )
						output_printf(OUTPUT_DEBUG,"module.mail: Decoding from base64");
					buf2=rfc822_base64(buf,len,&len2);
					break;
				default: 
					buf2=buf;
					len2=len;
			}

			if( debug_cmail_module ) {
				output_printf(OUTPUT_DEBUG,"module.mail: id: %s, description: %s", body->id, body->description);
				output_printf(OUTPUT_DEBUG,"module.mail: block type: %d.%s", body->type, body->subtype);
			}
			if( body->parameter ) /* Try and get the content type correctly */ {
				PARAMETER *ptr = body->parameter;
				while( ptr != NULL ) {
					if( caseless_compare( ptr->attribute, "charset" ) ) {
						if( debug_cmail_module )
							output_printf(OUTPUT_DEBUG,"module.mail: Found content type for block: %s", ptr->value);
						v = fe_new_str("charset", ptr->value, 0, FE_CHARSET_DEFAULT);
						ferite_object_set_var(script, VAO(object), "charset", v);
					}
					ptr = ptr->next;
				}
			}
			v = fe_new_bin_str("content", buf2, len2, FE_CHARSET_DEFAULT );
			ferite_object_set_var(script, VAO(object), "content", v );

			v = fe_new_lng("encoding", body->encoding );
			ferite_object_set_var(script, VAO(object), "encoding", v );

			if( body->id ) {
				v = fe_new_str("ID", body->id, strlen(body->id), FE_CHARSET_DEFAULT);
				ferite_object_set_var(script, VAO(object), "ID", v);
			}
			
			if( body->disposition.type && strcasecmp(body->disposition.type, "attachment") == 0) {
				param = body->disposition.parameter;
				while(param){
					if( param->attribute && ((strcasecmp(param->attribute,"filename") == 0) ||
												(strcasecmp(param->attribute,"name") == 0) ||
												(strcasecmp(param->attribute,"name*") == 0) ||
												(strcasecmp(param->attribute,"filename*") == 0) )) {
						v = fe_new_str("filename", param->value, 0, FE_CHARSET_DEFAULT );
						ferite_object_set_var(script, VAO(object), "filename", v );
						break;
					}
					param=param->next;
				}
			}
			/* If filename was not found in Content-Disposition header search for it among the parameters */
			if( strcmp(VAS(ferite_object_get_var(script, VAO(object), "filename"))->data, "") == 0 ) {
				param = body->parameter;
				while(param){
					if( param->attribute && ((strcasecmp(param->attribute,"filename") == 0) || 
												(strcasecmp(param->attribute,"name") == 0))) {
						v = fe_new_str("filename", param->value, 0, FE_CHARSET_DEFAULT );
						ferite_object_set_var(script, VAO(object), "filename", v );
						break;
					}
					param = param->next;
				}
			}
		}
		return object;
	}
	return NULL;
}
Beispiel #4
0
/*
   See RFC 2047 for the description of the encodings used in the mail headers.
   Briefly, "encoded words" can be inserted which have the form of

      encoded-word = "=?" charset "?" encoding "?" encoded-text "?="

   where charset and encoding can't contain space, control chars or "specials"
   and encoded-text can't contain spaces nor "?".

   NB: don't be confused by 2 meanings of encoding here: it is both the
       charset encoding for us and also QP/Base64 encoding for RFC 2047
 */
static
String DecodeHeaderOnce(const String& in, wxFontEncoding *pEncoding)
{
   // we don't enforce the sanity checks on charset and encoding - should we?
   // const char *specials = "()<>@,;:\\\"[].?=";

   // there can be words in different encodings inside the same header so this
   // variable doesn't really make sense but in practice only one encoding will
   // be used in the entire header
   wxFontEncoding encodingHeader = wxFONTENCODING_SYSTEM;

   // if the header starts with an encoded word, preceding whitespace must be
   // ignored, so the flag must be set to true initially
   bool maybeBetweenEncodedWords = true;

   String out,
          space;
   // we can't define a valid "last" iterator below for empty string
   if ( in.empty() )
      return String();

   out.reserve(in.length());
   for ( wxString::const_iterator p = in.begin(),
                                end = in.end(),
                               last = in.end() - 1; p != end; ++p )
   {
      if ( *p == '=' && p != last && *(p + 1) == '?' )
      {
         // found encoded word

         // save the start of it
         const wxString::const_iterator encWordStart = p++;

         // get the charset
         String csName;
         for ( ++p; p != end && *p != '?'; ++p ) // initial "++" to skip '?'
         {
            csName += *p;
         }

         if ( p == end )
         {
            wxLogDebug(_T("Invalid encoded word syntax in '%s': missing charset."),
                       in.c_str());
            out += wxString(encWordStart, end);

            break;
         }

         // pass false to prevent asking the user from here: we can be called
         // during non-interactive operations and popping up a dialog for an
         // unknown charset can be inappropriate
         const wxFontEncoding encodingWord = wxFontMapperBase::Get()->
                                               CharsetToEncoding(csName, false);

         if ( encodingWord == wxFONTENCODING_SYSTEM )
         {
            wxLogDebug(_T("Unrecognized charset name \"%s\""), csName.mb_str());
         }

         // this is not a problem in Unicode build
#if !wxUSE_UNICODE
         if ( encodingHeader != wxFONTENCODING_SYSTEM &&
               encodingHeader != encodingWord )
         {
            // this is a bug (well, missing feature) in ANSI build of Mahogany
            wxLogDebug(_T("This header contains encoded words with different ")
                       _T("encodings and won't be rendered correctly."));
         }
#endif // !wxUSE_UNICODE

         encodingHeader = encodingWord;


         // get the encoding in RFC 2047 sense
         enum
         {
            Encoding_Unknown,
            Encoding_Base64,
            Encoding_QuotedPrintable
         } enc2047 = Encoding_Unknown;

         ++p; // skip '?'
         if ( *(p + 1) == '?' )
         {
            if ( *p == 'B' || *p == 'b' )
               enc2047 = Encoding_Base64;
            else if ( *p == 'Q' || *p == 'q' )
               enc2047 = Encoding_QuotedPrintable;
         }
         //else: multi letter encoding unrecognized

         if ( enc2047 == Encoding_Unknown )
         {
            wxLogDebug(_T("Unrecognized header encoding in '%s'."), in.c_str());

            // scan until the end of the encoded word
            const size_t posEncWordStart = p - in.begin();
            const size_t posEncWordEnd = in.find("?=", p - in.begin());
            if ( posEncWordEnd == wxString::npos )
            {
               wxLogDebug(_T("Missing encoded word end marker in '%s'."),
                          in.c_str());
               out += wxString(encWordStart, end);

               break;
            }

            // +1 to skip '?' of "?=" (don't skip '=', this will be accounted
            // for by p increment in the loop statement)
            p += posEncWordEnd - posEncWordStart + 1;

            // leave this word undecoded
            out += wxString(encWordStart, p + 1);

            continue;
         }

         p += 2; // skip "Q?" or "B?"

         // get the encoded text
         bool hasUnderscore = false;
         const wxString::const_iterator encTextStart = p;
         while ( p != last && (*p != '?' || *(p + 1) != '=') )
         {
            // this is needed for QP hack below
            if ( *p == '_' )
               hasUnderscore = true;

            ++p;
         }

         if ( p == last )
         {
            wxLogDebug(_T("Missing encoded word end marker in '%s'."),
                       in.c_str());
            out += wxString(encWordStart, end);

            break;
         }

         // convert the encoded word to char[] buffer for c-client
         wxCharBuffer encWord(wxString(encTextStart, p).To8BitData());

         // skip '=' following '?'
         ++p;

         String textDecoded;
         if ( encWord )
         {
            const unsigned long lenEncWord = strlen(encWord);

            // now decode the text using c-client functions
            unsigned long len;
            void *text;
            if ( enc2047 == Encoding_Base64 )
            {
               text = rfc822_base64(UCHAR_CCAST(encWord), lenEncWord, &len);
            }
            else // QP
            {
               // cclient rfc822_qprint() behaves correctly and leaves '_' in the
               // QP encoded text because this is what RFC says, however many
               // broken clients replace spaces with underscores and so we undo it
               // here -- in this case it's better to be user-friendly than
               // standard-conforming
               if ( hasUnderscore )
               {
                  for ( char *pc = encWord.data(); *pc; ++pc )
                  {
                     if ( *pc == '_' )
                        *pc = ' ';
                  }
               }

               text = rfc822_qprint(UCHAR_CCAST(encWord), lenEncWord, &len);
            }

            if ( text )
            {
               const char * const ctext = static_cast<char *>(text);

               if ( encodingWord == wxFONTENCODING_DEFAULT )
               {
                  // CharsetToEncoding() returns this for US-ASCII but
                  // wxCSConv() doesn't accept it
                  textDecoded = wxString::FromAscii(ctext, len);
               }
               else // real conversion needed
               {
                  textDecoded = wxString(ctext, wxCSConv(encodingWord), len);
               }

               fs_give(&text);
            }
         }

         if ( textDecoded.empty() )
         {
            // if decoding failed it is probably better to show undecoded
            // text than nothing at all
            textDecoded = wxString(encWordStart, p + 1);
         }

         // normally we leave the (8 bit) string as is and remember its
         // encoding so that we may choose the font for displaying it
         // correctly, but in case of UTF-7/8 we really need to transform it
         // here as we don't have any UTF-7/8 fonts, so we should display a
         // different string
#if !wxUSE_UNICODE
         if ( encodingHeader == wxFONTENCODING_UTF7 ||
                  encodingHeader == wxFONTENCODING_UTF8 )
         {
            encodingHeader = ConvertUTFToMB(&textDecoded, encodingHeader);
         }
#endif // !wxUSE_UNICODE

         out += textDecoded;

         // forget the space before this encoded word, it must be ignored
         space.clear();
         maybeBetweenEncodedWords = true;
      }
      else if ( maybeBetweenEncodedWords &&
                  (*p == ' ' || *p == '\r' || *p == '\n') )
      {
         // spaces separating the encoded words must be ignored according
         // to section 6.2 of the RFC 2047, so we don't output them immediately
         // but delay until we know that what follows is not an encoded word
         space += *p;
      }
      else // just another normal char
      {
         // if we got any delayed whitespace (see above), flush it now
         if ( !space.empty() )
         {
            out += space;
            space.clear();
         }

         out += *p;

         maybeBetweenEncodedWords = false;
      }
   }

   if ( pEncoding )
      *pEncoding = encodingHeader;

   return out;
}