Index: protocols/protocol_bugzilla.py
===================================================================
--- protocols/protocol_bugzilla.py	(révision 0)
+++ protocols/protocol_bugzilla.py	(révision 0)
@@ -0,0 +1,107 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import gtk, gobject
+import urllib, re, xml.dom.minidom, csv, urlparse
+import bug
+import BeautifulSoup
+
+Bug = bug.bug
+Comment = bug.comment
+
+class protocol:
+	@staticmethod
+	def Name():
+		return "Bugzilla"
+	
+	def __init__(self, account):
+		self.account = account
+	
+	def getBugUrl(self,nbr):
+		return self.__url('show_bug.cgi', id=nbr)
+	
+	def btsName(self):
+		return urlparse.urlsplit(self.account.url)[1]
+
+	def retrieveBug(self,nbr):
+		""" Get bug #nbr """
+		def tagval(parent,tag):
+			return parent.getElementsByTagName(tag)[0].firstChild.nodeValue
+		
+		fd = urllib.urlopen(self.__url('show_bug.cgi', id=nbr, ctype='xml'))
+		xbug = xml.dom.minidom.parse(fd).getElementsByTagName('bug')[0]
+		if xbug.getAttribute('error'):
+			return Bug(-1)
+		bug = Bug(nbr)
+		
+		comments = xbug.getElementsByTagName('long_desc')
+		bug.setPackage(tagval(xbug, 'product'))
+		bug.setTitle(tagval(xbug, 'short_desc'))
+		bug.setDescription(tagval(comments[0], 'thetext'))
+		bug.setStatus(tagval(xbug, 'bug_status'))
+		bug.setImportance(tagval(xbug, 'bug_severity'))
+		bug.setAssignee(tagval(xbug, 'assigned_to'))
+		bug.setCommentable(False) # fixme !
+		
+		for i, comment in enumerate(comments[1:]):
+			c_content = tagval(comment, 'thetext')
+			c_number = i+1
+			c_author = tagval(comment, 'who')
+			c_date = tagval(comment, 'bug_when')
+			
+			bug.addComment(Comment(c_number, c_content, c_author, "", c_date))
+		
+		return bug
+	
+	def genericSearch(self, string):
+		""" Search for a string """
+		return self.__searchResults(query=string, quicksearch=string)
+	
+	def packageSearch(self, pkg, string):
+		""" Search for a string, but only for bug of package "pkg"
+			Well, sin't meaningful for Gentoo BTS ;) """
+		return self.__searchResults(product=pkg, content=string, bug_status='__open__')
+	
+	def packageExist(self, pkg):
+		return False
+		#fixme!
+		potage = BeautifulSoup.BeautifulSoup(urllib.urlopen(self.__url('query.cgi', format="specific")))
+		products = potage.find('select', id='product').findAll('option')
+		print [p.string.strip() for p in products]
+		return pkg in products
+	
+	def advancedSearch(self, pkg):
+		# fixme !
+		pass
+	
+	def __searchResults(self, **kwargs):
+		url = self.__url('buglist.cgi', ctype='csv', **kwargs)
+		data = urllib.urlopen(url)
+		fmt = [x.replace('"', '').strip() for x in data.readline().split(',')]
+		indexes = (fmt.index('bug_id'), fmt.index('short_short_desc'), fmt.index('bug_severity'), fmt.index('bug_status'))
+		bugs = self.__newResult()
+		for bug in csv.reader(data, quoting=csv.QUOTE_NONNUMERIC):
+			bugs.append((int(bug[indexes[0]]), '', bug[indexes[1]], bug[indexes[2]], bug[indexes[3]]))
+		return bugs
+	
+	def __newResult(self) :
+		#private function to create a new result gtk.ListStore
+		# Bug id, package, title, importance, status
+		return gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
+	
+	def __url(self, base, **qs):
+		root = self.account.url
+		if not root.startswith('http://') and not root.startswith('https://'):
+			root = 'http://' + root
+		if not root.endswith('/'):
+			root += '/'
+		s_qs = urllib.urlencode(qs)
+		if s_qs:
+			s_qs = '?' + s_qs
+		return root + base + s_qs
+	
+	def availableStatus(self):
+		return ('UNCONFIRMED', 'NEW', 'ASSIGNED', 'REOPENED', 'RESOLVED', 'VERIFIED', 'CLOSED')
+	
+	def availableImportance(self):
+		return ('Blocker', 'Critical', 'Major', 'Minor', 'Trivial', 'Enhancement')
