00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00029 #include "bzrh.h"
00030
00034 BZRH::BZRH(BotKernel*b)
00035 {
00036 this->author = "eponyme";
00037 this->description = "Plugin that allows queries to bugzilla.redhat.com";
00038 this->version = VERSION;
00039 this->name = "bzrh";
00040 this->bindFunction("bzsearch",IN_COMMAND_HANDLER,"bzsearch",0,120);
00041 this->bindFunction("bug",IN_COMMAND_HANDLER,"bug",0,60);
00042 this->bindFunction("",IN_ALL_MSGS,"checkBug",0,60);
00043 }
00044
00051 vector<string> BZRH::searchBugs(string pattern,string max)
00052 {
00053 vector<string>results ;
00054 string bug_search = Tools::urlencode(pattern);
00055 const string URL_BZRH = "https://bugzilla.redhat.com/";
00056 const string BEGIN_BUGS = "<tr class=\"bz_bugitem";
00057 const string END_BUGS = "</table>";
00058 const string BEGIN_URL = "href=\"";
00059 const string BEGIN_DESC = "<td ";
00060 string URL = URL_BZRH+"buglist.cgi?quicksearch="+bug_search;
00061 CURL *curl;
00062 CURLcode result;
00063 string::size_type pos;
00064 string tmp;
00065 char errorBuffer[CURL_ERROR_SIZE];
00066 string buffer;
00067 curl = curl_easy_init();
00068 if (curl) {
00069 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
00070 curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
00071 curl_easy_setopt(curl, CURLOPT_HEADER, 0);
00072 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
00073 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, BZRH::writer);
00074 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
00075 result = curl_easy_perform(curl);
00076 curl_easy_cleanup(curl);
00077 if (result == CURLE_OK) {
00078 pos = buffer.find(BEGIN_BUGS);
00079 if ( pos == string::npos ) {
00080 results.clear();
00081 results.push_back("Zarro Boogs found.");
00082 return results;
00083 }
00084 buffer = buffer.substr(pos);
00085 pos = buffer.find(END_BUGS);
00086 if ( pos == string::npos ) {
00087 results.clear();
00088 results.push_back("* Parse error (1) *");
00089 return results;
00090 }
00091 buffer = buffer.substr(0,pos);
00092 while(pos != string::npos ) {
00093 pos = buffer.find(BEGIN_URL);
00094 if ( pos == string::npos ) {
00095 results.clear();
00096 results.push_back("* Parse error (2) *");
00097 return results;
00098 }
00099 buffer = buffer.substr(pos+BEGIN_URL.length());
00100 tmp=URL_BZRH+buffer.substr(0,buffer.find("\">"));
00101 for(unsigned int i = 0 ; i < 7 ; i ++ ) {
00102 pos = buffer.find(BEGIN_DESC);
00103 if ( pos == string::npos ) {
00104 results.clear();
00105 results.push_back("* Parse error (3) *");
00106 return results;
00107 }
00108 buffer=buffer.substr(pos+BEGIN_DESC.length());
00109 }
00110 results.push_back(tmp+" : "+Tools::cleanHTML(buffer.substr(1,buffer.find("\n")-1)));
00111 pos= buffer.find(BEGIN_URL);
00112 }
00113 if ( (max=="") || (max=="0") || (Tools::strToUnsignedInt(max)>=results.size()) ) {
00114 return results;
00115 }
00116 else {
00117 tmp = "Too many bugs ("+Tools::intToStr(results.size())+") ! Max is "+max+". Use bz's webiste : "+URL ;
00118 results.clear();
00119 results.push_back(tmp);
00120 return results;
00121 }
00122 }
00123 else {
00124 results.clear();
00125 results.push_back("* ERROR, try again later please *");
00126 return results;
00127 }
00128 }
00129 results.clear();
00130 results.push_back("curl init error");
00131 return results;
00132 }
00133
00140 string BZRH::getBugInfos(string bug,bool displayNotFound)
00141 {
00142 string bug_number;
00143 if (bug[0] == '#' ) {
00144 bug_number = bug.substr(1);
00145 }
00146 else {
00147 bug_number =bug;
00148 }
00149 const string URL = "https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id="+Tools::urlencode(bug_number);
00150 const string SHOW_BUG_URL = "http://bugzilla.redhat.com/show_bug.cgi?id=";
00151 const string SUMMARY = "<th>Summary:</th>";
00152 const string BEGIN_SUMMARY = "<td colspan=3>";
00153 const string ASSIGNEE = "Assignee:</th>";
00154 const string BEGIN_ASSIGNEE = "<td>";
00155 const string STATUS = "<th>Status:</th>";
00156 const string BEGIN_STATUS = "<td>";
00157 const string SEVERITY = "<th>Severity:</th>";
00158 const string BEGIN_SEVERITY = ">";
00159 const string PRIORITY = "<th>Priority:</th>";
00160 const string BEGIN_PRIORITY = ">";
00161 string summary,assignee,status,severity,priority;
00162 string::size_type pos;
00163 CURL *curl;
00164 CURLcode result;
00165 char errorBuffer[CURL_ERROR_SIZE];
00166 string buffer;
00167 curl = curl_easy_init();
00168 if (curl) {
00169 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
00170 curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
00171 curl_easy_setopt(curl, CURLOPT_HEADER, 0);
00172 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
00173 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,BZRH::writer);
00174 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
00175 result = curl_easy_perform(curl);
00176 curl_easy_cleanup(curl);
00177 if (result == CURLE_OK) {
00178 pos = buffer.find(SUMMARY);
00179 if ( pos == string::npos ) {
00180 if (displayNotFound)
00181 return "Bug not found";
00182 else
00183 return "";
00184 }
00185 buffer = buffer.substr(pos);
00186 pos = buffer.find(BEGIN_SUMMARY) +BEGIN_SUMMARY.length();
00187 summary = buffer.substr(pos, buffer.find("</td>") - pos );
00188 pos = buffer.find(ASSIGNEE);
00189 if ( pos == string::npos ) {
00190 return "parse error";
00191 }
00192 buffer = buffer.substr(pos);
00193 pos = buffer.find(BEGIN_ASSIGNEE) +BEGIN_ASSIGNEE.length();
00194 assignee = buffer.substr(pos, buffer.find("</td>") - pos );
00195 pos = buffer.find(STATUS);
00196 if ( pos == string::npos ) {
00197 return "parse error";
00198 }
00199 buffer = buffer.substr(pos);
00200 pos = buffer.find(BEGIN_STATUS) + BEGIN_STATUS.length();
00201 buffer = buffer.substr(pos);
00202 status = buffer.substr(0, buffer.find("\n"));
00203 pos = buffer.find(SEVERITY);
00204 if ( pos == string::npos ) {
00205 return "parse error";
00206 }
00207 buffer = buffer.substr(pos+SEVERITY.length());
00208 pos = buffer.find(BEGIN_SEVERITY) + BEGIN_SEVERITY.length();
00209 buffer = buffer.substr(pos);
00210 severity = buffer.substr(0, buffer.find("\n"));
00211 pos = buffer.find(PRIORITY);
00212 if ( pos == string::npos ) {
00213 return "parse error";
00214 }
00215 buffer = buffer.substr(pos+PRIORITY.length());
00216 pos = buffer.find(BEGIN_PRIORITY) + BEGIN_PRIORITY.length();
00217 buffer = buffer.substr(pos);
00218 priority = buffer.substr(0, buffer.find("\n"));
00219 return "bug "+SHOW_BUG_URL+bug_number+" : "+severity+", "+priority+", "+status+", "+Tools::cleanHTML(assignee)+", "+Tools::cleanHTML(summary);
00220 }
00221 else {
00222 return "* ERROR, try again later please *";
00223 }
00224 }
00225 return "curl init error";
00226 }
00227
00228 int BZRH::writer(char *data, size_t size, size_t nmemb,string *buffer)
00229 {
00230 int result = 0;
00231 if (buffer != NULL) {
00232 buffer->append(data, size * nmemb);
00233 result = size * nmemb;
00234 }
00235 return result;
00236 }
00237
00238 extern "C"
00239 {
00240 Plugin *contruct_bzrh(BotKernel*b)
00241 {
00242 return new BZRH(b);
00243 }
00244 void destroy_bzrh(Plugin*p)
00245 {
00246 delete p;
00247 }
00248 bool bzsearch (Message*m,Plugin*p,BotKernel*b)
00249 {
00250 BZRH*bz= (BZRH*)p;
00251 if ( m->isPublic() && (m->nbParts() >= 5) ) {
00252 b->send(IRCProtocol::sendMsg(m->getSource(),bz->searchBugs(Tools::vectorToString(m->getSplit()," ",4), b->getCONFF()->getValue(p->getName()+".maxbugs"))));
00253 }
00254 return true;
00255 }
00256 bool bug (Message*m,Plugin*p,BotKernel*b)
00257 {
00258 BZRH*bz= (BZRH*)p;
00259 if ( m->isPublic() && (m->nbParts() == 5) && (m->getPart(4)!="") ) {
00260 b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(4),true)));
00261 }
00262 return true;
00263 }
00264 bool checkBug(Message*m,Plugin*p,BotKernel*b)
00265 {
00266 const string BUG = "bug";
00267 const string URL1 = "https://bugzilla.redhat.com/show_bug.cgi?id=";
00268 const string URL2 = "http://bugzilla.redhat.com/show_bug.cgi?id=";
00269 BZRH*bz= (BZRH*)p;
00270 if (m->isPublic() && (b->getCONFF()->getValue(p->getName()+".autoreact")=="1")) {
00271 if ( m->getPart(3).find(":"+BUG) == 0 ) {
00272 b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(4),false)));
00273 }
00274 else if (m->getPart(3).find(":"+URL1) == 0 ) {
00275 b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(3).substr(URL1.length()+1),false)));
00276 }
00277 else if (m->getPart(3).find(":"+URL2) == 0 ) {
00278 b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(3).substr(URL2.length()+1),false)));
00279 }
00280 for (unsigned int i = 4 ; i < m->nbParts() ; i ++ ) {
00281 if ( m->getPart(i).find(BUG) == 0 ) {
00282 b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(i+1),false)));
00283 }
00284 else if (m->getPart(i).find(URL1) == 0 ) {
00285 b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(i).substr(URL1.length()),false)));
00286 }
00287 else if (m->getPart(i).find(URL2) == 0 ) {
00288 b->send(IRCProtocol::sendMsg(m->getSource(),bz->getBugInfos(m->getPart(i).substr(URL2.length()),false)));
00289 }
00290 }
00291 }
00292 return true;
00293 }
00294 }