You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
408 lines
12 KiB
408 lines
12 KiB
/*
|
|
This file is part of KBugBuster.
|
|
Copyright (c) 2002 Cornelius Schumacher <schumacher@kde.org>
|
|
|
|
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 <tqregexp.h>
|
|
#include <tqstylesheet.h>
|
|
|
|
#include <kdebug.h>
|
|
#include <kmdcodec.h>
|
|
|
|
#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::tqStatus 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()->bugtqStatus( 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::tqcurrentDateTime() );
|
|
}
|
|
|
|
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 <bug> tag found" );
|
|
|
|
BugDetailsPart::List parts;
|
|
TQValueList<BugDetailsImpl::AttachmentDetails> 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 = "<pre>" + wrapLines( text ).replace( TQRegExp( "(Created an attachment \\(id=([0-9]+)\\))" ),
|
|
"<a href=\"" + bugBaseURL + "/attachment.cgi?id=\\2&action=view\">\\1</a>" ) + "\n</pre>";
|
|
}
|
|
}
|
|
|
|
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 = "<pre>" + wrapLines( TQStyleSheet::escape(e2.text()) ) + "\n</pre>";
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* vim:sw=4:ts=4:et
|
|
*/
|