void Multipart::appendAnyPart( EString &r, const Bodypart * bp, ContentType * ct, bool avoidUtf8 ) const { ContentType * childct = bp->header()->contentType(); EString::Encoding e = EString::Binary; ContentTransferEncoding * cte = bp->header()->contentTransferEncoding(); if ( cte ) e = cte->encoding(); if ( ( childct && childct->type() == "message" ) || ( ct && ct->type() == "multipart" && ct->subtype() == "digest" && !childct ) ) { if ( childct && childct->subtype() != "rfc822" ) appendTextPart( r, bp, childct ); else r.append( bp->message()->rfc822( avoidUtf8 ) ); } else if ( !childct || childct->type().lower() == "text" ) { appendTextPart( r, bp, childct ); } else if ( childct->type() == "multipart" ) { bp->appendMultipart( r, avoidUtf8 ); } else { r.append( bp->data().encoded( e, 72 ) ); } }
bool MediaPlayer::load(const URL& url, const ContentType& contentType, const String& keySystem) { m_contentMIMEType = contentType.type().lower(); m_contentTypeCodecs = contentType.parameter(codecs()); m_url = url; m_keySystem = keySystem.lower(); m_contentMIMETypeWasInferredFromExtension = false; #if ENABLE(MEDIA_SOURCE) m_mediaSource = 0; #endif // If the MIME type is missing or is not meaningful, try to figure it out from the URL. if (m_contentMIMEType.isEmpty() || m_contentMIMEType == applicationOctetStream() || m_contentMIMEType == textPlain()) { if (m_url.protocolIsData()) m_contentMIMEType = mimeTypeFromDataURL(m_url.string()); else { String lastPathComponent = url.lastPathComponent(); size_t pos = lastPathComponent.reverseFind('.'); if (pos != notFound) { String extension = lastPathComponent.substring(pos + 1); String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(extension); if (!mediaType.isEmpty()) { m_contentMIMEType = mediaType; m_contentMIMETypeWasInferredFromExtension = true; } } } } loadWithNextMediaEngine(0); return m_currentMediaEngine; }
void substituer(MimeEntity * mimeEntity, const string url, const string affectations, const string affectations_html) { // Substitue _URL_ et _AFFECTATIONS_ dans toutes les parties text/plain et text/html ContentType contentType = mimeEntity->header().contentType(); if ( contentType.type() == "text" and ( contentType.subtype() == "plain" or contentType.subtype() == "html") ) { Body& body = mimeEntity->body(); string::size_type position; while((position = body.find("_URL_")) != string::npos) { body.replace(position, sizeof("_URL_") - 1, url); } while((position = body.find("_AFFECTATIONS_")) != string::npos) { body.replace(position, sizeof("_AFFECTATIONS_") - 1, (contentType.subtype() == "html" ? affectations_html : affectations)); } } else { MimeEntityList::iterator sous_partie_iterator = mimeEntity->body().parts().begin(), fin = mimeEntity->body().parts().end(); for(;sous_partie_iterator!=fin;++sous_partie_iterator) { substituer(*sous_partie_iterator, url, affectations, affectations_html); } } }
void MediaPlayer::load(const String& url, const ContentType& contentType) { String type = contentType.type().lower(); String typeCodecs = contentType.parameter(codecs()); // If the MIME type is missing or is not meaningful, try to figure it out from the URL. if (type.isEmpty() || type == applicationOctetStream() || type == textPlain()) { if (protocolIs(url, "data")) type = mimeTypeFromDataURL(url); else { size_t pos = url.reverseFind('.'); if (pos != notFound) { String extension = url.substring(pos + 1); String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(extension); if (!mediaType.isEmpty()) type = mediaType; } } } m_url = url; m_contentMIMEType = type; m_contentTypeCodecs = typeCodecs; loadWithNextMediaEngine(0); }
ContentType ContentType::fromString(const QString & value) { ContentType contentType; contentType.parse(value); return contentType; }
MediaPlayer::SupportsType MediaPlayer::supportsType(ContentType contentType) { String type = contentType.type(); String codecs = contentType.parameter("codecs"); MediaPlayerFactory* engine = chooseBestEngineForTypeAndCodecs(type, codecs); if (!engine) return IsNotSupported; return engine->supportsTypeAndCodecs(type, codecs); }
bool MediaPlayer::load(const URL& url, const ContentType& contentType, MediaSourcePrivateClient* mediaSource) { ASSERT(mediaSource); m_mediaSource = mediaSource; m_contentMIMEType = contentType.type().lower(); m_contentTypeCodecs = contentType.parameter(codecs()); m_url = url; m_keySystem = ""; m_contentMIMETypeWasInferredFromExtension = false; loadWithNextMediaEngine(0); return m_currentMediaEngine; }
EString::Encoding Bodypart::contentTransferEncoding() const { ContentTransferEncoding * cte = header()->contentTransferEncoding(); if ( !cte && parent() ) { ContentType * ct = parent()->header()->contentType(); if ( !ct || ( ct->type() != "multipart" && ct->type() != "message" ) ) cte = parent()->header()->contentTransferEncoding(); } if ( cte ) return cte->encoding(); return EString::Binary; }
MediaSourcePrivate::AddStatus MockMediaSourcePrivate::addSourceBuffer(const ContentType& contentType, RefPtr<SourceBufferPrivate>& outPrivate) { MediaEngineSupportParameters parameters; parameters.isMediaSource = true; parameters.type = contentType.type(); parameters.codecs = contentType.parameter(ASCIILiteral("codecs")); if (MockMediaPlayerMediaSource::supportsType(parameters) == MediaPlayer::IsNotSupported) return NotSupported; m_sourceBuffers.append(MockSourceBufferPrivate::create(this)); outPrivate = m_sourceBuffers.last(); return Ok; }
bool MediaPlayer::load(const URL& url, const ContentType& contentType, MediaSourcePrivateClient* mediaSource) { ASSERT(!m_reloadTimer.isActive()); ASSERT(mediaSource); m_mediaSource = mediaSource; m_contentMIMEType = contentType.type().convertToASCIILowercase(); m_contentTypeCodecs = contentType.parameter(codecs()); m_url = url; m_keySystem = emptyString(); m_contentMIMETypeWasInferredFromExtension = false; loadWithNextMediaEngine(0); return m_currentMediaEngine; }
MediaPlayer::SupportsType MediaPlayer::supportsType(const ContentType& contentType) { String type = contentType.type().lower(); String typeCodecs = contentType.parameter(codecs()); // 4.8.10.3 MIME types - The canPlayType(type) method must return the empty string if type is a type that the // user agent knows it cannot render or is the type "application/octet-stream" if (type == applicationOctetStream()) return IsNotSupported; MediaPlayerFactory* engine = bestMediaEngineForTypeAndCodecs(type, typeCodecs); if (!engine) return IsNotSupported; return engine->supportsTypeAndCodecs(type, typeCodecs); }
void Message::fix8BitHeaderFields() { EString charset; EString fallback = "us-ascii"; bool conflict = false; List<Bodypart>::Iterator i( allBodyparts() ); while ( i ) { ContentType * ct = 0; if ( i->header() ) ct = i->header()->contentType(); if ( ct && ct->type() == "text" ) { EString cs = ct->parameter( "charset" ).lower(); if ( cs == "windows-1252" ) cs = "iso-8859-1"; if ( cs.isEmpty() ) ; // no conclusion from this part else if ( charset.isEmpty() ) charset = cs; // use this charset...? else if ( cs != charset ) conflict = true; if ( ct && ct->subtype() == "html" ) fallback = "iso-8859-1"; } ++i; } Codec * c = 0; if ( !charset.isEmpty() ) c = Codec::byName( charset ); else c = Codec::byString( badFields( header() ) ); if ( !c ) c = Codec::byName( fallback ); if ( conflict || !c ) c = new AsciiCodec; header()->fix8BitFields( c ); i = allBodyparts()->first(); while ( i ) { if ( i->header() ) i->header()->fix8BitFields( c ); if ( i->message() && i->message()->header() ) i->message()->header()->fix8BitFields( c ); ++i; } }
int contentType() { ContentType* type = ContentType::Parse("text/plain ; charset = utf-8"); //Check it is parsed corretly if (!type) return Error("ContentType not parsed correctly\n"); Debug("ContentType: \"%s\"\n" , type->ToString().c_str()); //Clone ContentType* cloned = type->Clone(); Debug("ContentType: \"%s\"\n" , cloned->ToString().c_str()); delete cloned; delete type; }
ContentType * Bodypart::contentType() const { ContentType * ct = header()->contentType(); if ( ct ) return ct; if ( !parent() ) return 0; ct = parent()->header()->contentType(); if ( ct ) { if ( ct->type() == "multipart" ) { ct = 0; } else if ( ct->type() == "message" && ct->subtype() == "rfc822" ) { Bodypart * bp = parent()->children()->firstElement(); ct = bp->header()->contentType(); } } return ct; }
EString Message::body() const { EString r; ContentType *ct = header()->contentType(); if ( ct && ct->type() == "multipart" ) { appendMultipart( r ); } else { // XXX: Is this the right place to restore this linkage? Bodypart * firstChild = children()->first(); if ( firstChild ) { firstChild->setHeader( header() ); appendAnyPart( r, firstChild, ct ); } } return r; }
void MediaPlayer::load(const String& url, const ContentType& contentType) { String type = contentType.type(); String codecs = contentType.parameter("codecs"); // if we don't know the MIME type, see if the extension can help if (type.isEmpty() || type == "application/octet-stream" || type == "text/plain") { int pos = url.reverseFind('.'); if (pos >= 0) { String extension = url.substring(pos + 1); String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(extension); if (!mediaType.isEmpty()) type = mediaType; } } MediaPlayerFactory* engine = 0; if (!type.isEmpty()) engine = chooseBestEngineForTypeAndCodecs(type, codecs); // if we didn't find an engine that claims the MIME type, just use the first engine if (!engine && !installedMediaEngines().isEmpty()) engine = installedMediaEngines()[0]; // don't delete and recreate the player unless it comes from a different engine if (engine && m_currentMediaEngine != engine) { m_currentMediaEngine = engine; m_private.clear(); m_private.set(engine->constructor(this)); #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) m_private->setMediaPlayerProxy(m_playerProxy); #endif m_private->setAutobuffer(autobuffer()); m_private->setPreservesPitch(preservesPitch()); } if (m_private) m_private->load(url); else m_private.set(createNullMediaPlayer(this)); }
EString Bodypart::asText( bool avoidUtf8 ) const { EString r; Codec *c = 0; ContentType *ct = header()->contentType(); if ( ct && !ct->parameter( "charset" ).isEmpty() ) c = Codec::byName( ct->parameter( "charset" ) ); if ( !c ) c = new AsciiCodec; if ( !children()->isEmpty() ) appendMultipart( r, avoidUtf8 ); else if ( !header()->contentType() || header()->contentType()->type() == "text" ) r = c->fromUnicode( text() ); else r = d->data.e64( 72 ); return r; }
void Multipart::appendMultipart( EString &r, bool avoidUtf8 ) const { ContentType * ct = header()->contentType(); EString delim = ct->parameter( "boundary" ); if ( ! this ) ::log( "Fetch::bodyStructure - FATAL, cannnot determine message", Log::Error ); else { if ( this->parent() && this->parent()->isMessage() ) { Message *msg = (Message *)this->parent(); if ( msg->hasPGPsignedPart() ) { appendAnyPart( r, children()->first(), ct, avoidUtf8 ); return; } } else if ( this->isMessage() ) { Message *msg = (Message *)this; if ( msg->hasPGPsignedPart() ) { appendAnyPart( r, children()->first(), ct, avoidUtf8 ); return; } } } List<Bodypart>::Iterator it( children() ); r.append( "--" + delim ); while ( it ) { r.append( crlf ); Bodypart * bp = it; ++it; r.append( bp->header()->asText( avoidUtf8 ) ); r.append( crlf ); appendAnyPart( r, bp, ct, avoidUtf8 ); r.append( crlf ); r.append( "--" ); r.append( delim ); } r.append( "--" ); r.append( crlf ); }
static void headerSummary( Header * h, int n ) { EStringList l; ContentType * ct = h->contentType(); if ( ct ) l.append( ct->type() + "/" + ct->subtype() ); ContentTransferEncoding * cte = h->contentTransferEncoding(); if ( cte ) { EString s; switch ( cte->encoding() ) { case EString::QP: s = "quoted-printable"; break; case EString::Base64: s = "base64"; break; case EString::Uuencode: s = "x-uuencode"; break; case EString::Binary: s = "7bit"; break; } l.append( s ); } HeaderField * cd = h->field( HeaderField::ContentDescription ); if ( cd ) l.append( cd->rfc822( false ) ); if ( !l.isEmpty() ) { spaces( n ); fprintf( stderr, "%s\n", l.join( ";" ).cstr() ); } }
void Message::parse( const EString & rfc2822 ) { uint i = 0; children()->clear(); setHeader( parseHeader( i, rfc2822.length(), rfc2822, Header::Rfc2822 ) ); header()->repair(); header()->repair( this, rfc2822.mid( i ) ); ContentType * ct = header()->contentType(); if ( ct && ct->type() == "multipart" ) { Bodypart::parseMultipart( i, rfc2822.length(), rfc2822, ct->parameter( "boundary" ), ct->subtype() == "digest", children(), this ); } else { Bodypart * bp = Bodypart::parseBodypart( i, rfc2822.length(), rfc2822, header(), this ); children()->append( bp ); } fix8BitHeaderFields(); header()->simplify(); EString e = d->error; recomputeError(); if ( d->error.isEmpty() ) d->error = e; if ( !d->error.isEmpty() ) return; setAddressesFetched(); setHeadersFetched(); setBodiesFetched(); }
Bodypart * Bodypart::parseBodypart( uint start, uint end, const EString & rfc2822, Header * h, Multipart * parent ) { if ( rfc2822[start] == 13 ) start++; if ( rfc2822[start] == 10 ) start++; Bodypart * bp = new Bodypart; bp->setParent( parent ); bp->setHeader( h ); EString body; if ( end > start ) body = rfc2822.mid( start, end-start ); if ( !body.contains( '=' ) ) { // sometimes people send c-t-e: q-p _and_ c-t-e: 7bit or 8bit. // if they are equivalent we can accept it. uint i = 0; bool any = false; HeaderField * f = 0; while ( (f=h->field(HeaderField::ContentTransferEncoding,i)) != 0 ) { if ( ((ContentTransferEncoding*)f)->encoding() == EString::QP ) any = true; i++; } if ( any && i > 1 ) h->removeField( HeaderField::ContentTransferEncoding ); } EString::Encoding e = EString::Binary; ContentTransferEncoding * cte = h->contentTransferEncoding(); if ( cte ) e = cte->encoding(); if ( !body.isEmpty() ) { if ( e == EString::Base64 || e == EString::Uuencode ) body = body.decoded( e ); else body = body.crlf().decoded( e ); } ContentType * ct = h->contentType(); if ( !ct ) { switch ( h->defaultType() ) { case Header::TextPlain: h->add( "Content-Type", "text/plain" ); break; case Header::MessageRfc822: h->add( "Content-Type", "message/rfc822" ); break; } ct = h->contentType(); } if ( ct->type() == "text" ) { bool specified = false; bool unknown = false; Codec * c = 0; if ( ct ) { EString csn = ct->parameter( "charset" ); if ( csn.lower() == "default" ) csn = ""; if ( !csn.isEmpty() ) specified = true; c = Codec::byName( csn ); if ( !c ) unknown = true; if ( c && c->name().lower() == "us-ascii" ) { // Some MTAs appear to say this in case there is no // Content-Type field - without checking whether the // body actually is ASCII. If it isn't, we'd better // call our charset guesser. (void)c->toUnicode( body ); if ( !c->valid() ) specified = false; // Not pretty. } } if ( !c ) c = new AsciiCodec; bp->d->hasText = true; bp->d->text = c->toUnicode( body.crlf() ); if ( c->name() == "GB2312" || c->name() == "ISO-2022-JP" || c->name() == "KS_C_5601-1987" ) { // undefined code point usage in GB2312 spam is much too // common. (GB2312 spam is much too common, but that's // another matter.) Gb2312Codec turns all undefined code // points into U+FFFD, so here, we can take the unicode // form and say it's the canonical form. when a client // later reads the message, it gets the text in unicode, // including U+FFFD. bool bad = !c->valid(); // the header may contain some unencoded gb2312. we bang // it by hand, ignoring errors. List<HeaderField>::Iterator hf( h->fields() ); while ( hf ) { if ( !hf->valid() && hf->type() == HeaderField::Subject ) { // is it right to bang only Subject? c->reset(); hf->setValue( c->toUnicode( hf->unparsedValue() ) ); } ++hf; } // if the body was bad, we prefer the (unicode) in // bp->d->text and pretend it arrived as UTF-8: if ( bad ) { c = new Utf8Codec; body = c->fromUnicode( bp->d->text ); } } if ( ( !specified && ( !c->wellformed() || ct->subtype() == "html" ) ) || ( specified && ( !c->valid() ) ) ) { Codec * g = 0; if ( ct->subtype() == "html" ) g = guessHtmlCodec( body ); else g = guessTextCodec( body ); UString guessed; if ( g ) guessed = g->toUnicode( body.crlf() ); if ( !g ) { // if we couldn't guess anything, keep what we had if // it's valid or explicitly specified, else use // unknown-8bit. if ( !specified && !c->valid() ) { c = new Unknown8BitCodec; bp->d->text = c->toUnicode( body.crlf() ); } } else { // if we could guess something, is our guess better // than what we had? if ( g->wellformed() && !c->wellformed() ) { c = g; bp->d->text = guessed; } } } if ( specified && c->state() == Codec::Invalid ) { // the codec was specified, and the specified codec // resulted in an error, but did not abort conversion. we // respond by forgetting the error, using the conversion // result (probably including one or more U+FFFD) and // labelling the message as UTF-8. c = new Utf8Codec; body = c->fromUnicode( bp->d->text ); } else if ( !specified && c->state() == Codec::Invalid ) { // the codec was not specified, and we couldn't find // anything. we call it unknown-8bit. c = new Unknown8BitCodec; bp->d->text = c->toUnicode( body ); } // if we ended up using a 16-bit codec and were using q-p, we // need to reevaluate without any trailing CRLF if ( e == EString::QP && c->name().startsWith( "UTF-16" ) ) bp->d->text = c->toUnicode( body.stripCRLF() ); if ( !c->valid() && bp->d->error.isEmpty() ) { bp->d->error = "Could not convert body to Unicode"; if ( specified ) { EString cs; if ( ct ) cs = ct->parameter( "charset" ); if ( cs.isEmpty() ) cs = c->name(); bp->d->error.append( " from " + cs ); } if ( specified && unknown ) bp->d->error.append( ": Character set not implemented" ); else if ( !c->error().isEmpty() ) bp->d->error.append( ": " + c->error() ); } if ( c->name().lower() != "us-ascii" ) ct->addParameter( "charset", c->name().lower() ); else if ( ct ) ct->removeParameter( "charset" ); body = c->fromUnicode( bp->d->text ); bool qp = body.needsQP(); if ( cte ) { if ( !qp ) { h->removeField( HeaderField::ContentTransferEncoding ); cte = 0; } else if ( cte->encoding() != EString::QP ) { cte->setEncoding( EString::QP ); } } else if ( qp ) { h->add( "Content-Transfer-Encoding", "quoted-printable" ); cte = h->contentTransferEncoding(); } } else { bp->d->data = body; if ( ct->type() != "multipart" && ct->type() != "message" ) { e = EString::Base64; // there may be exceptions. cases where some format really // needs another content-transfer-encoding: if ( ct->type() == "application" && ct->subtype().startsWith( "pgp-" ) && !body.needsQP() ) { // seems some PGP things need "Version: 1" unencoded e = EString::Binary; } else if ( ct->type() == "application" && ct->subtype() == "octet-stream" && body.contains( "BEGIN PGP MESSAGE" ) ) { // mutt cannot handle PGP in base64 (what a crock) e = EString::Binary; } // change c-t-e to match the encoding decided above if ( e == EString::Binary ) { h->removeField( HeaderField::ContentTransferEncoding ); cte = 0; } else if ( cte ) { cte->setEncoding( e ); } else { h->add( "Content-Transfer-Encoding", "base64" ); cte = h->contentTransferEncoding(); } } } if ( ct->type() == "multipart" ) { parseMultipart( start, end, rfc2822, ct->parameter( "boundary" ), ct->subtype() == "digest", bp->children(), bp, false ); } else if ( ct->type() == "message" && ct->subtype() == "rfc822" ) { // There are sometimes blank lines before the message. while ( rfc2822[start] == 13 || rfc2822[start] == 10 ) start++; Message * m = new Message; m->setParent( bp ); m->parse( rfc2822.mid( start, end-start ) ); List<Bodypart>::Iterator it( m->children() ); while ( it ) { bp->children()->append( it ); it->setParent( bp ); ++it; } bp->setMessage( m ); body = m->rfc822( false ); } bp->d->numBytes = body.length(); if ( cte ) body = body.encoded( cte->encoding(), 72 ); bp->d->numEncodedBytes = body.length(); if ( bp->d->hasText || ( ct->type() == "message" && ct->subtype() == "rfc822" ) ) { uint n = 0; uint i = 0; uint l = body.length(); while ( i < l ) { if ( body[i] == '\n' ) n++; i++; } if ( l && body[l-1] != '\n' ) n++; bp->setNumEncodedLines( n ); } h->simplify(); return bp; }