|
|
|
|
|
|
|
#include "bugdetails.h"
|
|
|
|
|
|
|
|
#include "bugdetailsimpl.h"
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kmdcodec.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
|
|
|
|
BugDetails::BugDetails()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BugDetails::BugDetails( BugDetailsImpl *impl ) :
|
|
|
|
m_impl( impl )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BugDetails::BugDetails( const BugDetails &other )
|
|
|
|
{
|
|
|
|
(*this) = other;
|
|
|
|
}
|
|
|
|
|
|
|
|
BugDetails &BugDetails::operator=( const BugDetails &rhs )
|
|
|
|
{
|
|
|
|
m_impl = rhs.m_impl;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
BugDetails::~BugDetails()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString BugDetails::version() const
|
|
|
|
{
|
|
|
|
if ( !m_impl )
|
|
|
|
return TQString();
|
|
|
|
|
|
|
|
return m_impl->version;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString BugDetails::source() const
|
|
|
|
{
|
|
|
|
if ( !m_impl )
|
|
|
|
return TQString();
|
|
|
|
|
|
|
|
return m_impl->source;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString BugDetails::compiler() const
|
|
|
|
{
|
|
|
|
if ( !m_impl )
|
|
|
|
return TQString();
|
|
|
|
|
|
|
|
return m_impl->compiler;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString BugDetails::os() const
|
|
|
|
{
|
|
|
|
if ( !m_impl )
|
|
|
|
return TQString();
|
|
|
|
|
|
|
|
return m_impl->os;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDateTime BugDetails::submissionDate() const
|
|
|
|
{
|
|
|
|
if ( !m_impl ) return TQDateTime();
|
|
|
|
|
|
|
|
if ( m_impl->parts.count() > 0 ) {
|
|
|
|
return m_impl->parts.last().date;
|
|
|
|
}
|
|
|
|
return TQDateTime();
|
|
|
|
}
|
|
|
|
|
|
|
|
int BugDetails::age() const
|
|
|
|
{
|
|
|
|
if ( !m_impl )
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return submissionDate().daysTo( TQDateTime::currentDateTime() );
|
|
|
|
}
|
|
|
|
|
|
|
|
BugDetailsPart::List BugDetails::parts() const
|
|
|
|
{
|
|
|
|
if ( !m_impl )
|
|
|
|
return BugDetailsPart::List();
|
|
|
|
|
|
|
|
return m_impl->parts;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<BugDetailsImpl::AttachmentDetails> BugDetails::attachmentDetails() const
|
|
|
|
{
|
|
|
|
if ( m_impl )
|
|
|
|
return m_impl->attachments;
|
|
|
|
else
|
|
|
|
return TQValueList<BugDetailsImpl::AttachmentDetails>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BugDetails::addAttachmentDetails( const TQValueList<BugDetailsImpl::AttachmentDetails>& attch )
|
|
|
|
{
|
|
|
|
if ( m_impl )
|
|
|
|
m_impl->attachments = attch;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<BugDetails::Attachment> BugDetails::extractAttachments() const
|
|
|
|
{
|
|
|
|
TQValueList<BugDetails::Attachment> lst;
|
|
|
|
if ( !m_impl )
|
|
|
|
return lst;
|
|
|
|
BugDetailsPart::List parts = m_impl->parts;
|
|
|
|
for ( BugDetailsPart::List::ConstIterator it = parts.begin(); it != parts.end(); ++it ) {
|
|
|
|
lst += extractAttachments( (*it).text );
|
|
|
|
}
|
|
|
|
return lst;
|
|
|
|
}
|
|
|
|
|
|
|
|
//#define DEBUG_EXTRACT
|
|
|
|
|
|
|
|
TQValueList<BugDetails::Attachment> BugDetails::extractAttachments( const TQString& text )
|
|
|
|
{
|
|
|
|
TQValueList<BugDetails::Attachment> lst;
|
|
|
|
TQStringList lines = TQStringList::split( '\n', text );
|
|
|
|
#ifdef DEBUG_EXTRACT
|
|
|
|
kdDebug() << k_funcinfo << lines.count() << " lines." << endl;
|
|
|
|
#endif
|
|
|
|
TQString boundary;
|
|
|
|
for ( TQStringList::Iterator it = lines.begin() ; it != lines.end() ; ++it )
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_EXTRACT
|
|
|
|
kdDebug() << "Line: " << *it << endl;
|
|
|
|
#endif
|
|
|
|
if ( (*it).startsWith( " Content-Type" ) ) // ## leading space comes from khtml
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_EXTRACT
|
|
|
|
//kdDebug() << "BugDetails::extractAttachments going back, looking for empty or boundary=" << boundary << endl;
|
|
|
|
#endif
|
|
|
|
// Rewind until last empty line
|
|
|
|
TQStringList::Iterator rit = it;
|
|
|
|
for ( ; rit != lines.begin() ; --rit ) {
|
|
|
|
TQString line = *rit;
|
|
|
|
if ( line.endsWith( "<br />" ) )
|
|
|
|
line = line.left( line.length() - 6 );
|
|
|
|
while ( !line.isEmpty() && line[0] == ' ' )
|
|
|
|
line.remove( 0, 1 );
|
|
|
|
#ifdef DEBUG_EXTRACT
|
|
|
|
kdDebug() << "Back: '" << line << "'" << endl;
|
|
|
|
#endif
|
|
|
|
if ( line.isEmpty() ) {
|
|
|
|
++rit; // boundary is next line
|
|
|
|
boundary = *rit;
|
|
|
|
if ( boundary.endsWith( "<br />" ) )
|
|
|
|
boundary = boundary.left( boundary.length() - 6 );
|
|
|
|
if ( boundary[0] == ' ' )
|
|
|
|
boundary.remove( 0, 1 );
|
|
|
|
kdDebug() << "BugDetails::extractAttachments boundary=" << boundary << endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ( line == boundary )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Forward until next empty line (end of headers) - and parse filename
|
|
|
|
TQString filename;
|
|
|
|
TQString encoding;
|
|
|
|
rit = it;
|
|
|
|
for ( ; rit != lines.end() ; ++rit ) {
|
|
|
|
TQString header = *rit;
|
|
|
|
if ( header.endsWith( "<br />" ) )
|
|
|
|
header = header.left( header.length() - 6 );
|
|
|
|
if ( header[0] == ' ' )
|
|
|
|
header.remove( 0, 1 );
|
|
|
|
#ifdef DEBUG_EXTRACT
|
|
|
|
kdDebug() << "Header: '" << header << "'" << endl;
|
|
|
|
#endif
|
|
|
|
if ( header.isEmpty() )
|
|
|
|
break;
|
|
|
|
if ( header.startsWith( "Content-Disposition:" ) )
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_EXTRACT
|
|
|
|
kdDebug() << "BugDetails::extractAttachments found header " << *rit << endl;
|
|
|
|
#endif
|
|
|
|
// Taken from libtdenetwork/kmime_headers.cpp
|
|
|
|
int pos=header.find("filename=", 0, false);
|
|
|
|
TQString fn;
|
|
|
|
if(pos>-1) {
|
|
|
|
pos+=9;
|
|
|
|
fn=header.mid(pos, header.length()-pos);
|
|
|
|
if ( fn.startsWith( "\"" ) && fn.endsWith( "\"" ) )
|
|
|
|
fn = fn.mid( 1, fn.length() - 2 );
|
|
|
|
//filename=decodeRFC2047String(fn, &e_ncCS, defaultCS(), forceCS());
|
|
|
|
filename = fn; // hack
|
|
|
|
kdDebug() << "BugDetails::extractAttachments filename=" << filename << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else if ( header.startsWith( "Content-Transfer-Encoding:" ) )
|
|
|
|
{
|
|
|
|
encoding = header.mid( 26 ).lower();
|
|
|
|
while ( encoding[0] == ' ' )
|
|
|
|
encoding.remove( 0, 1 );
|
|
|
|
kdDebug() << "BugDetails::extractAttachments encoding=" << encoding << endl;
|
|
|
|
}
|
|
|
|
} //for
|
|
|
|
if ( rit == lines.end() )
|
|
|
|
break;
|
|
|
|
|
|
|
|
it = rit;
|
|
|
|
if ( rit != lines.end() && !filename.isEmpty() )
|
|
|
|
{
|
|
|
|
++it;
|
|
|
|
if ( it == lines.end() )
|
|
|
|
break;
|
|
|
|
// Read encoded contents
|
|
|
|
TQString contents;
|
|
|
|
for ( ; it != lines.end() ; ++it )
|
|
|
|
{
|
|
|
|
TQString line = *it;
|
|
|
|
if ( line.endsWith( "</tt>" ) )
|
|
|
|
line = line.left( line.length() - 5 );
|
|
|
|
if ( line.endsWith( "<br />" ) ) // necessary for the boundary check
|
|
|
|
line = line.left( line.length() - 6 );
|
|
|
|
while ( !line.isEmpty() && line[0] == ' ' )
|
|
|
|
line.remove( 0, 1 );
|
|
|
|
if ( line.isEmpty() || line == boundary ) // end of attachment
|
|
|
|
break;
|
|
|
|
if ( line == boundary+"--" ) // end of last attachment
|
|
|
|
{
|
|
|
|
boundary = TQString();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
contents += line; // no newline, because of linebreaking between <br and />
|
|
|
|
}
|
|
|
|
contents = contents.replace( TQRegExp("<br */>"), TQString() );
|
|
|
|
#ifdef DEBUG_EXTRACT
|
|
|
|
kdDebug() << "BugDetails::extractAttachments contents=***\n" << contents << "\n***" << endl;
|
|
|
|
#endif
|
|
|
|
kdDebug() << "BugDetails::extractAttachments creating attachment " << filename << endl;
|
|
|
|
Attachment a;
|
|
|
|
if ( encoding == "base64" )
|
|
|
|
KCodecs::base64Decode( contents.local8Bit(), a.contents /*out*/ );
|
|
|
|
else
|
|
|
|
//KCodecs::uudecode( contents.local8Bit(), a.contents /*out*/ );
|
|
|
|
KMessageBox::information( 0, i18n("Attachment %1 could not be decoded.\nEncoding: %2").arg(filename).arg(encoding) );
|
|
|
|
#ifdef DEBUG_EXTRACT
|
|
|
|
kdDebug() << "Result: ***\n" << TQCString( a.contents.data(), a.contents.size()+1 ) << "\n*+*" << endl;
|
|
|
|
#endif
|
|
|
|
a.filename = filename;
|
|
|
|
lst.append(a);
|
|
|
|
if ( it == lines.end() )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef DEBUG_EXTRACT
|
|
|
|
kdDebug() << "BugDetails::extractAttachments returning " << lst.count() << " attachments for this part." << endl;
|
|
|
|
#endif
|
|
|
|
return lst;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BugDetails::operator==( const BugDetails &rhs )
|
|
|
|
{
|
|
|
|
return m_impl == rhs.m_impl;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* vim:ts=4:sw=4:et
|
|
|
|
*/
|