/* This file is part of KBugBuster. Copyright (c) 2002 Cornelius Schumacher This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of TQt, and distribute the resulting executable, without including the source code for TQt in the source distribution. */ #include "domprocessor.h" #include #include #include #include #include "bugserver.h" #include "packageimpl.h" #include "bugimpl.h" #include "bugdetailsimpl.h" #include "kbbprefs.h" DomProcessor::DomProcessor( BugServer *server ) : Processor( server ) { } DomProcessor::~DomProcessor() { } KBB::Error DomProcessor::parsePackageList( const TQByteArray &data, Package::List &packages ) { TQDomDocument doc; if ( !doc.setContent( data ) ) { return KBB::Error( "Error parsing xml response for package list request." ); } TQDomElement bugzilla = doc.documentElement(); if ( bugzilla.isNull() ) { return KBB::Error( "No document in xml response." ); } KBB::Error err = parseDomPackageList( bugzilla, packages ); return err; } KBB::Error DomProcessor::parseBugList( const TQByteArray &data, Bug::List &bugs ) { TQDomDocument doc; if ( !doc.setContent( data ) ) { return KBB::Error( "Error parsing xml response for bug list request" ); } TQDomElement bugzilla = doc.documentElement(); if ( bugzilla.isNull() ) { return KBB::Error( "No document in xml response." ); } KBB::Error err = parseDomBugList( bugzilla, bugs ); return err; } KBB::Error DomProcessor::parseBugDetails( const TQByteArray &data, BugDetails &bugDetails ) { TQDomDocument doc; if ( !doc.setContent( data ) ) { return KBB::Error( "Error parsing xml response for bug details request." ); } TQDomElement bugzilla = doc.documentElement(); if ( bugzilla.isNull() ) { return KBB::Error( "No document in xml response." ); } TQDomNode p; for ( p = bugzilla.firstChild(); !p.isNull(); p = p.nextSibling() ) { TQDomElement bug = p.toElement(); if ( bug.tagName() != "bug" ) continue; KBB::Error err = parseDomBugDetails( bug, bugDetails ); if ( err ) return err; } return KBB::Error(); } KBB::Error DomProcessor::parseDomPackageList( const TQDomElement &element, Package::List &packages ) { TQDomNode p; for ( p = element.firstChild(); !p.isNull(); p = p.nextSibling() ) { TQDomElement bug = p.toElement(); if ( bug.tagName() != "product" ) continue; TQString pkgName = bug.attribute( "name" ); uint bugCount = 999; Person maintainer; TQString description; TQStringList components; TQDomNode n; for( n = bug.firstChild(); !n.isNull(); n = n.nextSibling() ) { TQDomElement e = n.toElement(); if ( e.tagName() == "descr" ) description= e.text().stripWhiteSpace(); if ( e.tagName() == "component" ) components += e.text().stripWhiteSpace(); } Package pkg( new PackageImpl( pkgName, description, bugCount, maintainer, components ) ); if ( !pkg.isNull() ) { packages.append( pkg ); } } return KBB::Error(); } KBB::Error DomProcessor::parseDomBugList( const TQDomElement &topElement, Bug::List &bugs ) { TQDomElement element; if ( topElement.tagName() != "querybugids" ) { TQDomNode buglist = topElement.namedItem( "querybugids" ); element = buglist.toElement(); if ( element.isNull() ) { return KBB::Error( "No querybugids element found." ); } } else { element = topElement; } TQDomNode p; for ( p = element.firstChild(); !p.isNull(); p = p.nextSibling() ) { TQDomElement hit = p.toElement(); kdDebug() << "DomProcessor::parseDomBugList(): tag: " << hit.tagName() << endl; if ( hit.tagName() == "error" ) { return KBB::Error( "Error: " + hit.text() ); } else if ( hit.tagName() != "hit" ) continue; TQString title; TQString submitterName; TQString submitterEmail; TQString bugNr; Bug::Status status = Bug::StatusUndefined; Bug::Severity severity = Bug::SeverityUndefined; Person developerTodo; Bug::BugMergeList mergedList; uint age = 0xFFFFFFFF; TQDomNode n; for ( n = hit.firstChild(); !n.isNull(); n = n.nextSibling() ) { TQDomElement e = n.toElement(); if ( e.tagName() == "bugid" ) bugNr = e.text(); else if ( e.tagName() == "status" ) status = server()->bugStatus( e.text() ); else if ( e.tagName() == "descr" ) title = e.text(); else if ( e.tagName() == "reporter" ) submitterEmail = e.text(); else if ( e.tagName() == "reporterName" ) submitterName = e.text(); else if ( e.tagName() == "severity" ) severity = Bug::stringToSeverity( e.text() ); else if ( e.tagName() == "creationdate" ) age = ( TQDateTime::fromString( e.text(), Qt::ISODate ) ).daysTo( TQDateTime::currentDateTime() ); } Person submitter( submitterName, submitterEmail ); Bug bug( new BugImpl( title, submitter, bugNr, age, severity, developerTodo, status, mergedList ) ); if ( !bug.isNull() ) { bugs.append( bug ); } } return KBB::Error(); } KBB::Error DomProcessor::parseDomBugDetails( const TQDomElement &element, BugDetails &bugDetails ) { if ( element.tagName() != "bug" ) return KBB::Error( "No tag found" ); BugDetailsPart::List parts; TQValueList attachments; TQString versionXml; TQString osXml; TQString version; TQString source; TQString compiler; TQString os; TQDomNode n; for( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { TQDomElement e = n.toElement(); if ( e.tagName() == "version" ) versionXml = e.text().stripWhiteSpace(); if ( e.tagName() == "op_sys" ) osXml = e.text().stripWhiteSpace(); if ( e.tagName() == "long_desc" ) { TQString encoding = e.attribute( "encoding" ); Person sender; TQDateTime date; TQString text; TQDomNode n2; for( n2 = e.firstChild(); !n2.isNull(); n2 = n2.nextSibling() ) { TQDomElement e2 = n2.toElement(); if ( e2.tagName() == "who" ) { sender = Person::parseFromString( e2.text() ); } else if ( e2.tagName() == "bug_when" ) { date = parseDate( e2.text().stripWhiteSpace() ); } else if ( e2.tagName() == "thetext" ) { TQString in; if ( encoding == "base64" ) { in = KCodecs::base64Decode( TQCString(e2.text().latin1()) ); } else { in = e2.text(); } TQString raw = TQStyleSheet::escape( in ); if ( parts.isEmpty() ) { TQTextStream ts( &raw, IO_ReadOnly ); TQString line; while( !( line = ts.readLine() ).isNull() ) { if ( parseAttributeLine( line, "Version", version ) ) continue; if ( parseAttributeLine( line, "Installed from", source ) ) continue; if ( parseAttributeLine( line, "Compiler", compiler ) ) continue; if ( parseAttributeLine( line, "OS", os ) ) continue; text += line + "\n"; } } else { text += raw; } TQString bugBaseURL = server()->serverConfig().baseUrl().htmlURL(); text = "
" + wrapLines( text ).replace( TQRegExp( "(Created an attachment \\(id=([0-9]+)\\))" ),
              "\\1" ) + "\n
"; } } parts.prepend( BugDetailsPart( sender, date, text ) ); } if ( e.tagName() == "attachment" ) { TQString attachid, date, desc; for( TQDomNode node = e.firstChild(); !node.isNull(); node = node.nextSibling() ) { TQDomElement e2 = node.toElement(); if ( e2.tagName() == "attachid" ) { attachid = e2.text(); } else if ( e2.tagName() == "date" ) { date = e2.text().stripWhiteSpace(); } else if ( e2.tagName() == "desc" ) { desc = "
" + wrapLines( TQStyleSheet::escape(e2.text()) ) + "\n
"; } } attachments.append( BugDetailsImpl::AttachmentDetails( desc, date, attachid ) ); } } if ( version.isEmpty() ) version = versionXml; if ( os.isEmpty() ) os = osXml; bugDetails = BugDetails( new BugDetailsImpl( version, source, compiler, os, parts ) ); bugDetails.addAttachmentDetails( attachments ); return KBB::Error(); } void DomProcessor::setPackageListQuery( KURL &url ) { url.setFileName( "xml.cgi" ); url.setQuery( "?data=versiontable" ); } void DomProcessor::setBugListQuery( KURL &url, const Package &product, const TQString &component ) { if ( server()->serverConfig().bugzillaVersion() == "Bugworld" ) { url.setFileName( "bugworld.cgi" ); } else { url.setFileName( "xmlquery.cgi" ); } TQString user = server()->serverConfig().user(); if ( component.isEmpty() ) url.setQuery( "?user=" + user + "&product=" + product.name() ); else url.setQuery( "?user=" + user + "&product=" + product.name() + "&component=" + component ); if ( KBBPrefs::instance()->mShowClosedBugs ) url.addQueryItem( "addClosed", "1" ); } void DomProcessor::setBugDetailsQuery( KURL &url, const Bug &bug ) { url.setFileName( "xml.cgi" ); url.setQuery( "?id=" + bug.number() ); } TQString DomProcessor::wrapLines( const TQString &text ) { int wrap = KBBPrefs::instance()->mWrapColumn; TQStringList lines = TQStringList::split( '\n', text, true ); //kdDebug() << lines.count() << " lines." << endl; TQString out; bool removeBlankLines = true; for ( TQStringList::Iterator it = lines.begin() ; it != lines.end() ; ++it ) { TQString line = *it; if ( removeBlankLines ) { if ( line.isEmpty() ) continue; else removeBlankLines = false; } //kdDebug() << "BugDetailsJob::processNode IN line='" << line << "'" << endl; TQString wrappedLine; while ( line.length() > uint( wrap ) ) { int breakPoint = line.findRev( ' ', wrap ); //kdDebug() << "Breaking at " << breakPoint << endl; if( breakPoint == -1 ) { wrappedLine += line.left( wrap ) + '\n'; line = line.mid( wrap ); } else { wrappedLine += line.left( breakPoint ) + '\n'; line = line.mid( breakPoint + 1 ); } } wrappedLine += line; // the remainder //kdDebug() << "BugDetailsJob::processNode OUT wrappedLine='" << wrappedLine << "'" << endl; out += wrappedLine + "\n"; } return out; } bool DomProcessor::parseAttributeLine( const TQString &line, const TQString &key, TQString &result ) { if ( !result.isEmpty() ) return false; if ( !line.startsWith( key + ":" ) ) return false; TQString value = line.mid( key.length() + 1 ); value = value.stripWhiteSpace(); result = value; return true; } TQDateTime DomProcessor::parseDate( const TQString &dateStr ) { TQDateTime date = TQDateTime::fromString( dateStr, Qt::ISODate ); return date; }