From kfm-devel Mon Mar 13 15:45:21 2006 From: Allan Sandfeld Jensen Date: Mon, 13 Mar 2006 15:45:21 +0000 To: kfm-devel Subject: Re: content-disposition in HTTP headers Message-Id: <200603131645.22174.kde () carewolf ! com> X-MARC-Message: https://marc.info/?l=kfm-devel&m=114226477124781 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--Boundary-00=_SOZFElYC3bt4gMf" --Boundary-00=_SOZFElYC3bt4gMf Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Ok. Further testing showed that content-disposition: attachment is indeed not honoured, but my patch didn't fix it either. I've reopened bug #31662 (http://bugs.kde.org/show_bug.cgi?id=31662) The attached patch is updated and fixes the bug as far as I can tell, and should be safe for KDE 3.5.2. content-disposition headers are still not cached though. Regards `Allan --Boundary-00=_SOZFElYC3bt4gMf Content-Type: text/x-diff; charset="iso-8859-1"; name="contentdisposition.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="contentdisposition.diff" Index: kdelibs/kioslave/http/http.cc =================================================================== --- kdelibs/kioslave/http/http.cc (revision 517591) +++ kdelibs/kioslave/http/http.cc (working copy) @@ -2710,7 +2710,8 @@ QCString locationStr; // In case we get a redirect. QCString cookieStr; // In case we get a cookie. - QString disposition; // Incase we get a Content-Disposition + QString dispositionType; // In case we get a Content-Disposition type + QString dispositionFilename; // In case we get a Content-Disposition filename QString mediaValue; QString mediaAttribute; @@ -3245,7 +3246,7 @@ dispositionBuf--; if ( dispositionBuf > bufStart ) - disposition = QString::fromLatin1( bufStart, dispositionBuf-bufStart ); + dispositionFilename = QString::fromLatin1( bufStart, dispositionBuf-bufStart ); break; } @@ -3258,7 +3259,7 @@ dispositionBuf++; if ( dispositionBuf > bufStart ) - disposition = QString::fromLatin1( bufStart, dispositionBuf-bufStart ).stripWhiteSpace(); + dispositionType = QString::fromLatin1( bufStart, dispositionBuf-bufStart ).stripWhiteSpace(); while ( *dispositionBuf == ';' || *dispositionBuf == ' ' ) dispositionBuf++; @@ -3267,15 +3268,15 @@ // Content-Dispostion is not allowed to dictate directory // path, thus we extract the filename only. - if ( !disposition.isEmpty() ) + if ( !dispositionFilename.isEmpty() ) { - int pos = disposition.findRev( '/' ); + int pos = dispositionFilename.findRev( '/' ); if( pos > -1 ) - disposition = disposition.mid(pos+1); + dispositionFilename = dispositionFilename.mid(pos+1); - kdDebug(7113) << "(" << m_pid << ") Content-Disposition: " - << disposition<< endl; + kdDebug(7113) << "(" << m_pid << ") Content-Disposition: filename=" + << dispositionFilename<< endl; } } else if (strncasecmp(buf, "Proxy-Connection:", 17) == 0) @@ -3748,12 +3749,20 @@ } #endif - if( !disposition.isEmpty() ) + if( !dispositionType.isEmpty() ) { - kdDebug(7113) << "(" << m_pid << ") Setting Content-Disposition metadata to: " - << disposition << endl; - setMetaData("content-disposition", disposition); + kdDebug(7113) << "(" << m_pid << ") Setting Content-Disposition type to: " + << dispositionType << endl; + setMetaData("content-disposition-type", dispositionType); } + if( !dispositionFilename.isEmpty() ) + { + kdDebug(7113) << "(" << m_pid << ") Setting Content-Disposition filename to: " + << dispositionFilename << endl; + // ### KDE4: setting content-disposition to filename for pre 3.5.2 compatability + setMetaData("content-disposition", dispositionFilename); + setMetaData("content-disposition-filename", dispositionFilename); + } if (!m_request.lastModified.isEmpty()) setMetaData("modified", m_request.lastModified); Index: kdelibs/kparts/browserrun.h =================================================================== --- kdelibs/kparts/browserrun.h (revision 517591) +++ kdelibs/kparts/browserrun.h (working copy) @@ -75,22 +75,29 @@ //KParts::URLArgs urlArgs() const { return m_args; } //KParts::ReadOnlyPart* part() const { return m_part; } - + /** * @return the URL we're probing */ KURL url() const { return m_strURL; } - + /** * @return true if no dialog will be shown in case of errors */ bool hideErrorDialog() const; - + /** - * @return Suggested filename given by the server (e.g. HTTP content-disposition) + * @return Suggested filename given by the server (e.g. HTTP content-disposition filename) */ QString suggestedFilename() const { return m_suggestedFilename; } - + + /** + * @return Suggested disposition by the server (e.g. HTTP content-disposition) + */ + QString contentDisposition() const; + + bool serverSuggestsSave() const { return contentDisposition() == "attachment"; }; + enum AskSaveResult { Save, Open, Cancel }; /** * Ask the user whether to save or open a url in another application. @@ -101,6 +108,8 @@ * @return Save, Open or Cancel. */ static AskSaveResult askSave( const KURL & url, KService::Ptr offer, const QString& mimeType, const QString & suggestedFilename = QString::null ); + + enum AskEmbedOrSaveFlags { InlineDisposition = 0, AttachmentDisposition = 1 }; /** * Similar to askSave() but for the case where the current application is * able to embed the url itself (instead of passing it to another app). Index: kdelibs/kparts/browserrun.cpp =================================================================== --- kdelibs/kparts/browserrun.cpp (revision 517591) +++ kdelibs/kparts/browserrun.cpp (working copy) @@ -36,6 +36,7 @@ { public: bool m_bHideErrorDialog; + QString contentDisposition; }; BrowserRun::BrowserRun( const KURL& url, const KParts::URLArgs& args, @@ -185,7 +186,8 @@ m_strURL = job->url(); kdDebug(1000) << "slotBrowserMimetype: found " << type << " for " << m_strURL.prettyURL() << endl; - m_suggestedFilename = job->queryMetaData("content-disposition"); + m_suggestedFilename = job->queryMetaData("content-disposition-filename"); + d->contentDisposition = job->queryMetaData("content-disposition-type"); //kdDebug(1000) << "m_suggestedFilename=" << m_suggestedFilename << endl; // Make a copy to avoid a dead reference @@ -316,7 +318,7 @@ } //static -BrowserRun::AskSaveResult BrowserRun::askEmbedOrSave( const KURL & url, const QString& mimeType, const QString & suggestedFilename, int /*flags*/ ) +BrowserRun::AskSaveResult BrowserRun::askEmbedOrSave( const KURL & url, const QString& mimeType, const QString & suggestedFilename, int flags ) { // SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC SYNC // NOTE: Keep this funcion in sync with kdebase/kcontrol/filetypes/filetypedetails.cpp @@ -332,13 +334,14 @@ // - multipart/* ("server push", see kmultipart) // - other strange 'internal' mimetypes like print/manager... // KEEP IN SYNC!!! - if ( mime->is( "text/html" ) || + if (flags != (int)AttachmentDisposition && ( + mime->is( "text/html" ) || mime->is( "text/xml" ) || mime->is( "inode/directory" ) || mimeType.startsWith( "image" ) || mime->is( "multipart/x-mixed-replace" ) || mime->is( "multipart/replace" ) || - mimeType.startsWith( "print" ) ) + mimeType.startsWith( "print" ) ) ) return Open; QString question = makeQuestion( url, mimeType, suggestedFilename ); @@ -507,4 +510,8 @@ return d->m_bHideErrorDialog; } +QString BrowserRun::contentDisposition() const { + return d->contentDisposition; +} + #include "browserrun.moc" Index: kdebase/konqueror/konq_run.cc =================================================================== --- kdebase/konqueror/konq_run.cc (revision 517591) +++ kdebase/konqueror/konq_run.cc (working copy) @@ -79,12 +79,11 @@ m_req.args = m_args; bool tryEmbed = true; + // One case where we shouldn't try to embed, is when the server asks us to save - // ####### only if content-disposition doesn't say inline -#if 0 - if ( !m_suggestedFilename.isEmpty() ) + if ( serverSuggestsSave() ) tryEmbed = false; -#endif + if ( KonqMainWindow::isMimeTypeAssociatedWithSelf( mimeType ) ) m_req.forceAutoEmbed = true; @@ -115,8 +114,13 @@ if ( !m_bFinished && // only if we're going to open KonqMainWindow::isMimeTypeAssociatedWithSelf( mimeType ) ) { - KMessageBox::error( m_pMainWindow, i18n( "There appears to be a configuration error. You have associated Konqueror with %1, but it cannot handle this file type." ).arg( mimeType ) ); - m_bFinished = true; + + if (!tryEmbed) // try now + m_bFinished = m_pMainWindow->openView( mimeType, m_strURL, m_pView, m_req ); + if (!m_bFinished) { + KMessageBox::error( m_pMainWindow, i18n( "There appears to be a configuration error. You have associated Konqueror with %1, but it cannot handle this file type." ).arg( mimeType ) ); + m_bFinished = true; + } } if ( m_bFinished ) { Index: kdebase/konqueror/konq_mainwindow.cc =================================================================== --- kdebase/konqueror/konq_mainwindow.cc (revision 517591) +++ kdebase/konqueror/konq_mainwindow.cc (working copy) @@ -851,11 +851,14 @@ QString suggestedFilename; KonqRun* run = childView->run(); - if (run) + int attachment = 0; + if (run) { suggestedFilename = run->suggestedFilename(); + attachment = (run->serverSuggestsSave()) ? KParts::BrowserRun::AttachmentDisposition : KParts::BrowserRun::InlineDisposition; + } KParts::BrowserRun::AskSaveResult res = KParts::BrowserRun::askEmbedOrSave( - url, serviceType, suggestedFilename ); + url, serviceType, suggestedFilename, attachment ); if ( res == KParts::BrowserRun::Open ) forceAutoEmbed = true; else if ( res == KParts::BrowserRun::Cancel ) @@ -1396,7 +1399,7 @@ QStringList args = QStringList::split(' ', term); for ( QStringList::iterator it = args.begin(); it != args.end(); ++it ) cmd << *it; - + kdDebug(1202) << "slotOpenTerminal: directory " << dir << ", terminal:" << term << endl; cmd.start(KProcess::DontCare); --Boundary-00=_SOZFElYC3bt4gMf--