Huggle  build:^490^dce1e5c
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
core.cpp
1 //This program is free software: you can redistribute it and/or modify
2 //it under the terms of the GNU General Public License as published by
3 //the Free Software Foundation, either version 3 of the License, or
4 //(at your option) any later version.
5 
6 //This program is distributed in the hope that it will be useful,
7 //but WITHOUT ANY WARRANTY; without even the implied warranty of
8 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 //GNU General Public License for more details.
10 
11 #include "core.hpp"
12 
13 using namespace Huggle;
14 
15 // definitions
16 #ifdef PYTHONENGINE
17 PythonEngine *Core::Python = NULL;
18 #endif
19 
20 QString Core::HtmlHeader = "";
21 QString Core::HtmlFooter = "</table></body></html>";
22 
23 MainWindow *Core::Main = NULL;
24 Login *Core::f_Login = NULL;
27 QStringList Core::RingLog;
28 QList<Query*> Core::RunningQueries;
29 QList<WikiEdit*> Core::ProcessingEdits;
31 QList<Message*> Core::Messages;
32 QList<EditQuery*> Core::PendingMods;
33 QDateTime Core::StartupTime = QDateTime::currentDateTime();
34 bool Core::Running = true;
35 QList<iExtension*> Core::Extensions;
36 WikiPage *Core::AIVP = NULL;
37 WikiPage *Core::UAAP = NULL;
38 QList<Language*> Core::LocalizationData;
39 QList<HuggleQueueFilter *> Core::FilterDB;
40 
41 void Core::Init()
42 {
44  {
45  Core::Log("DEBUG: Huggle is running in a safe mode");
46  }
48  QFile *vf;
49 #if QT_VERSION >= 0x050000
50  QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
51 #else
52  QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
53 #endif
54  vf = new QFile(":/huggle/resources/Resources/Header.txt");
55  vf->open(QIODevice::ReadOnly);
56  Core::HtmlHeader = QString(vf->readAll());
57  vf->close();
58  delete vf;
59  Core::Log("Huggle 3 QT-LX, version " + Configuration::HuggleVersion);
60  Core::Log("Loading configuration");
61  Processor = new ProcessorThread();
62  Processor->start();
64  Core::DebugLog("Loading defs");
66  Configuration::LocalConfig_IgnorePatterns.append("/sandbox");
67  Configuration::LocalConfig_IgnorePatterns.append("/Sandbox");
68  Configuration::LocalConfig_RevertSummaries.append("Test edits;Reverted edits by [[Special:Contributions/$1|$1]] identified as test edits");
69 #ifdef PYTHONENGINE
70  Core::Log("Loading python engine");
71  Core::Python = new PythonEngine();
72 #endif
73  Core::DebugLog("Loading wikis");
74  Core::LoadDB();
75  Core::LoadLocalizations();
76  Core::DebugLog("Loading queue");
77  HuggleQueueFilter::Filters.append(HuggleQueueFilter::DefaultFilter);
79  {
80  Core::Log("Loading plugins");
82  } else
83  {
84  Core::Log("Not loading plugins in a safe mode");
85  }
86  Core::Log("Loaded in " + QString::number(Core::StartupTime.msecsTo(QDateTime::currentDateTime())));
87 }
88 
89 void Core::LoadDB()
90 {
93  QString text = "";
94  if (QFile::exists(Configuration::WikiDB))
95  {
96  QFile db(Configuration::WikiDB);
97  if (!db.open(QIODevice::ReadOnly | QIODevice::Text))
98  {
99  Core::Log("ERROR: Unable to read " + Configuration::WikiDB);
100  return;
101  }
102  text = QString(db.readAll());
103  db.close();
104  }
105 
106  if (text == "")
107  {
108  QFile vf(":/huggle/resources/Resources/Definitions.txt");
109  vf.open(QIODevice::ReadOnly);
110  text = QString(vf.readAll());
111  vf.close();
112  }
113 
114  QDomDocument d;
115  d.setContent(text);
116  QDomNodeList list = d.elementsByTagName("wiki");
117  int xx=0;
118  while (xx < list.count())
119  {
120  QDomElement e = list.at(xx).toElement();
121  if (!e.attributes().contains("name"))
122  {
123  continue;
124  }
125  if (!e.attributes().contains("url"))
126  {
127  continue;
128  }
129  WikiSite *site = new WikiSite(e.attribute("name"), e.attribute("url"));
130  site->IRCChannel = "";
131  site->SupportOAuth = false;
132  site->SupportHttps = false;
133  site->WhiteList = "test";
134  // name="testwiki" url="test.wikipedia.org/" path="wiki/" script="w/" https="true" oauth="true" channel="#test.wikipedia" wl="test
135  if (e.attributes().contains("path"))
136  {
137  site->LongPath = e.attribute("path");
138  }
139  if (e.attributes().contains("wl"))
140  {
141  site->WhiteList = e.attribute("wl");
142  }
143  if (e.attributes().contains("script"))
144  {
145  site->ScriptPath = e.attribute("script");
146  }
147  if (e.attributes().contains("https"))
148  {
149  site->SupportHttps = Configuration::SafeBool(e.attribute("https"));
150  }
151  if (e.attributes().contains("oauth"))
152  {
153  site->SupportOAuth = Configuration::SafeBool(e.attribute("oauth"));
154  }
155  if (e.attributes().contains("channel"))
156  {
157  site->IRCChannel = e.attribute("channel");
158  }
159  Configuration::ProjectList.append(site);
160  xx++;
161  }
162 }
163 
164 QString Core::Trim(QString text)
165 {
166  while (text.startsWith(" "))
167  {
168  if (text == "")
169  {
170  break;
171  }
172  text = text.mid(1);
173  }
174 
175  return text;
176 }
177 
179 {
180  if (edit == NULL)
181  {
182  return;
183  }
184 
185  if (edit->Previous != NULL && edit->Next != NULL)
186  {
187  edit->Previous->Next = edit->Next;
188  edit->Next->Previous = edit->Previous;
189  edit->UnregisterConsumer("MainForm");
190  return;
191  }
192 
193  if (edit->Previous != NULL)
194  {
195  edit->Previous->Next = NULL;
196  }
197 
198  if (edit->Next != NULL)
199  {
200  edit->Next->Previous = NULL;
201  }
202 
203  edit->UnregisterConsumer("MainForm");
204 }
205 
206 QString Core::GetSummaryOfWarningTypeFromWarningKey(QString key)
207 {
208  int id=0;
209  while (id<Configuration::LocalConfig_RevertSummaries.count())
210  {
211  QString line = Configuration::LocalConfig_RevertSummaries.at(id);
212  if (line.startsWith(key + ";"))
213  {
214  return Core::GetValueFromKey(line);
215  }
216  id++;
217  }
218  return Configuration::DefaultRevertSummary;
219 }
220 
221 QString Core::GetNameOfWarningTypeFromWarningKey(QString key)
222 {
223  int id=0;
224  while (id<Configuration::LocalConfig_WarningTypes.count())
225  {
226  QString line = Configuration::LocalConfig_WarningTypes.at(id);
227  if (line.startsWith(key) + ";")
228  {
229  return Core::GetValueFromKey(line);
230  }
231  id++;
232  }
233  return key;
234 }
235 
236 QString Core::GetKeyOfWarningTypeFromWarningName(QString id)
237 {
238  int i=0;
239  while (i<Configuration::LocalConfig_WarningTypes.count())
240  {
241  QString line = Configuration::LocalConfig_WarningTypes.at(i);
242  if (line.endsWith(id) || line.endsWith(id + ","))
243  {
244  return Core::GetKeyFromValue(line);
245  }
246  i++;
247  }
248  return id;
249 }
250 
251 void Core::ParsePats(QString text)
252 {
253  Configuration::LocalConfig_ScoreParts.clear();
254  while (text.contains("score-parts("))
255  {
256  text = text.mid(text.indexOf("score-parts(") + 12);
257  if (!text.contains(")"))
258  {
259  return;
260  }
261  int score = text.mid(0, text.indexOf(")")).toInt();
262 
263  if (score == 0)
264  {
265  continue;
266  }
267 
268  QStringList word;
269 
270  if (!text.contains(":"))
271  {
272  return;
273  }
274 
275  text = text.mid(text.indexOf(":") + 1);
276 
277  QStringList lines = text.split("\n");
278 
279  int line = 1;
280  while (line < lines.count())
281  {
282  QString l = lines.at(line);
283  QStringList items = l.split(",");
284  int CurrentItem = 0;
285  while ( CurrentItem < items.count() )
286  {
287  QString w = Core::Trim(items.at(CurrentItem));
288  if (w == "")
289  {
290  CurrentItem++;
291  continue;
292  }
293  word.append(w);
294  CurrentItem++;
295  }
296  if (!l.endsWith(",") || Core::Trim(l) == "")
297  {
298  break;
299  }
300  line++;
301  }
302 
303  line = 0;
304  while (line < word.count())
305  {
306  Configuration::LocalConfig_ScoreParts.append(ScoreWord(word.at(line), score));
307  line++;
308  }
309  }
310 }
311 
313 {
314  QFile file(Configuration::GetConfigurationPath() + "users.xml");
315  if (QFile(Configuration::GetConfigurationPath() + "users.xml").exists())
316  {
317  QFile(Configuration::GetConfigurationPath() + "users.xml").copy(Configuration::GetConfigurationPath() + "users.xml~");
318  QFile(Configuration::GetConfigurationPath() + "users.xml").remove();
319  }
320  if (!file.open(QIODevice::Truncate | QIODevice::WriteOnly))
321  {
322  Core::Log("ERROR: can't open " + Configuration::GetConfigurationPath() + "users.xml");
323  return;
324  }
325  QString xx = "<definitions>\n";
327  int x = 0;
328  WikiUser::ProblematicUserListLock.lock();
329  while (x<WikiUser::ProblematicUsers.count())
330  {
331  xx += "<user name=\"" + WikiUser::ProblematicUsers.at(x)->Username + "\" badness=\"" +
332  QString::number(WikiUser::ProblematicUsers.at(x)->getBadnessScore()) +"\"></user>\n";
333  x++;
334  }
335  WikiUser::ProblematicUserListLock.unlock();
336  xx += "</definitions>";
337  file.write(xx.toUtf8());
338  file.close();
339  QFile().remove(Configuration::GetConfigurationPath() + "users.xml~");
340 }
341 
342 QString Core::GetValueFromKey(QString item)
343 {
344  if (item.contains(";"))
345  {
346  QString type = item.mid(item.indexOf(";") + 1);
347  if (type.endsWith(","))
348  {
349  type = type.mid(0, type.length() - 1);
350  }
351  return type;
352  }
353  return item;
354 }
355 
356 QString Core::GetKeyFromValue(QString item)
357 {
358  if (item.contains(";"))
359  {
360  QString type = item.mid(0, item.indexOf(";"));
361  return type;
362  }
363  return item;
364 }
365 
366 void Core::ParseWords(QString text)
367 {
368  Configuration::LocalConfig_ScoreWords.clear();
369  while (text.contains("score-words("))
370  {
371  text = text.mid(text.indexOf("score-words(") + 12);
372  if (!text.contains(")"))
373  {
374  return;
375  }
376  int score = text.mid(0, text.indexOf(")")).toInt();
377 
378  if (score == 0)
379  {
380  continue;
381  }
382 
383  QStringList word;
384 
385  if (!text.contains(":"))
386  {
387  return;
388  }
389 
390  text = text.mid(text.indexOf(":") + 1);
391 
392  QStringList lines = text.split("\n");
393 
394  int line = 1;
395  while (line < lines.count())
396  {
397  QString l = lines.at(line);
398  QStringList items = l.split(",");
399  int CurrentItem = 0;
400  while ( CurrentItem < items.count() )
401  {
402  QString w = Core::Trim(items.at(CurrentItem));
403  if (w == "")
404  {
405  CurrentItem++;
406  continue;
407  }
408  word.append(w);
409  CurrentItem++;
410  }
411  if (!l.endsWith(",") || Core::Trim(l) == "")
412  {
413  break;
414  }
415  line++;
416  }
417 
418  line = 0;
419  while (line < word.count())
420  {
421  Configuration::LocalConfig_ScoreWords.append(ScoreWord(word.at(line), score));
422  line++;
423  }
424  }
425 }
426 
427 Message *Core::MessageUser(WikiUser *user, QString message, QString title, QString summary, bool section, Query *dependency)
428 {
429  if (user == NULL)
430  {
431  Core::Log("Cowardly refusing to message NULL user");
432  return NULL;
433  }
434 
435  Message *m = new Message(user, message, summary);
436  m->title = title;
437  m->Dependency = dependency;
438  m->Section = section;
439  Core::Messages.append(m);
440  m->Send();
441  Core::Log("Sending message to user " + user->Username);
442 
443  return m;
444 }
445 
447 {
448  QFile defs(Configuration::GetConfigurationPath() + "users.xml");
449  if (QFile(Configuration::GetConfigurationPath() + "users.xml~").exists())
450  {
451  Core::Log("WARNING: recovering definitions from last session");
452  QFile(Configuration::GetConfigurationPath() + "users.xml").remove();
454  + "users.xml~").copy(Configuration::GetConfigurationPath()
455  + "users.xml"))
456  {
457  QFile().remove(Configuration::GetConfigurationPath() + "users.xml~");
458  } else
459  {
460  Core::Log("WARNING: Unable to recover the definitions");
461  }
462  }
463  if (!defs.exists())
464  {
465  return;
466  }
467  defs.open(QIODevice::ReadOnly);
468  QString Contents(defs.readAll());
469  QDomDocument list;
470  list.setContent(Contents);
471  QDomNodeList l = list.elementsByTagName("user");
472  if (l.count() > 0)
473  {
474  int i=0;
475  while (i<l.count())
476  {
477  WikiUser *user;
478  QDomElement e = l.at(i).toElement();
479  if (!e.attributes().contains("name"))
480  {
481  i++;
482  continue;
483  }
484  user = new WikiUser();
485  user->Username = e.attribute("name");
486  if (e.attributes().contains("badness"))
487  {
488  user->setBadnessScore(e.attribute("badness").toInt());
489  }
490  WikiUser::ProblematicUsers.append(user);
491  i++;
492  }
493  }
494  defs.close();
495 }
496 
497 void Core::FinalizeMessages()
498 {
499  if (Core::Messages.count() < 1)
500  {
501  return;
502  }
503  int x=0;
504  QList<Message*> list;
505  while (x<Core::Messages.count())
506  {
507  if (Core::Messages.at(x)->Finished())
508  {
509  list.append(Core::Messages.at(x));
510  }
511  x++;
512  }
513  x=0;
514  while (x<list.count())
515  {
516  Core::Messages.removeOne(list.at(x));
517  x++;
518  }
519 }
520 
521 QString Core::RetrieveTemplateToWarn(QString type)
522 {
523  int x=0;
524  while (x < Configuration::LocalConfig_WarningTemplates.count())
525  {
526  if (Core::GetKeyFromValue(Configuration::LocalConfig_WarningTemplates.at(x)) == type)
527  {
528  return Core::GetValueFromKey(Configuration::LocalConfig_WarningTemplates.at(x));
529  }
530  x++;
531  }
532  return "";
533 }
534 
535 EditQuery *Core::EditPage(WikiPage *page, QString text, QString summary, bool minor)
536 {
537  if (page == NULL)
538  {
539  return NULL;
540  }
541  // retrieve a token
542  EditQuery *_e = new EditQuery();
543  if (!summary.endsWith(Configuration::EditSuffixOfHuggle))
544  {
545  summary = summary + " " + Configuration::EditSuffixOfHuggle;
546  }
547  _e->RegisterConsumer("Core::EditPage");
548  _e->page = page->PageName;
549  Core::PendingMods.append(_e);
550  _e->text = text;
551  _e->summary = summary;
552  _e->Minor = minor;
553  _e->Process();
554  return _e;
555 }
556 
558 {
559  item->RegisterConsumer("core");
560  Core::RunningQueries.append(item);
561 }
562 
563 void Core::Log(QString Message)
564 {
565  Message = "<" + QDateTime::currentDateTime().toString() + "> " + Message;
566  std::cout << Message.toStdString() << std::endl;
567  Core::InsertToRingLog(Message);
568  if (Core::Main != NULL)
569  {
570  Core::Main->lUnwrittenLogs.lock();
571  Core::Main->UnwrittenLogs.append(Message);
572  Core::Main->lUnwrittenLogs.unlock();
573  }
574 }
575 
577 {
578  if (QDir().exists(EXTENSION_PATH))
579  {
580  QDir d(EXTENSION_PATH);
581  QStringList extensions = d.entryList();
582  int xx = 0;
583  while (xx < extensions.count())
584  {
585  QString name = extensions.at(xx).toLower();
586  if (name.endsWith(".so") || name.endsWith(".dll"))
587  {
588  name = QString(EXTENSION_PATH) + QDir::separator() + extensions.at(xx);
589  QPluginLoader *extension = new QPluginLoader(name);
590  if (extension->load())
591  {
592  QObject* root = extension->instance();
593  if (root)
594  {
595  iExtension *interface = qobject_cast<iExtension*>(root);
596  if (!interface)
597  {
598  Core::Log("Unable to cast the library to extension");
599  }else
600  {
601  if (interface->Register())
602  {
603  Core::Extensions.append(interface);
604  Core::Log("Successfully loaded: " + extensions.at(xx));
605  }
606  else
607  {
608  Core::Log("Unable to register: " + extensions.at(xx));
609  }
610  }
611  }
612  } else
613  {
614  Core::Log("Failed to load (reason: " + extension->errorString() + "): " + extensions.at(xx));
615  delete extension;
616  }
617  }
618  xx++;
619  }
620  } else
621  {
622  Core::Log("There is no extensions folder, skipping load");
623  }
624  Core::Log("Extensions: " + QString::number(Core::Extensions.count()));
625 }
626 
628 {
629  QFile *vf = new QFile(":/huggle/git/version.txt");
630  vf->open(QIODevice::ReadOnly);
631  QString version(vf->readAll());
632  version = version.replace("\n", "");
633  Configuration::HuggleVersion += " " + version;
634 #ifdef PRODUCTION_BUILD
635  Configuration::HuggleVersion += " production";
636 #endif
637  vf->close();
638  delete vf;
639 }
640 
641 void Core::DebugLog(QString Message, unsigned int Verbosity)
642 {
643  if (Configuration::Verbosity >= Verbosity)
644  {
645  Core::Log("DEBUG[" + QString::number(Verbosity) + "]: " + Message);
646  }
647 }
648 
650 {
651  return Configuration::GetURLProtocolPrefix() + Project.URL;
652 }
653 
655 {
656  return Core::GetProjectURL(Project) + Project.LongPath;
657 }
658 
660 {
661  return Core::GetProjectURL(Project) + Project.ScriptPath;
662 }
663 
665 {
666  return Configuration::GetURLProtocolPrefix() + Configuration::Project.URL;
667 }
668 
670 {
671  return Core::GetProjectURL(Configuration::Project) + Configuration::Project.LongPath;
672 }
673 
675 {
676  return Core::GetProjectURL(Configuration::Project) + Configuration::Project.ScriptPath;
677 }
678 
679 void Core::ProcessEdit(WikiEdit *e)
680 {
682 }
683 
685 {
686  Running = false;
687  // grace time for subthreads to finish
688  if (Core::Main != NULL)
689  {
690  Core::Main->hide();
691  }
692 #if QT_VERSION >= 0x050000
693  QThread::usleep(200000);
694 #endif
695  if (Processor->isRunning())
696  {
697  Processor->exit();
698  }
699  //delete Processor;
700  Processor = NULL;
701  Core::SaveDefs();
703 #ifdef PYTHONENGINE
704  Core::Log("Unloading python");
705  delete Core::Python;
706 #endif
707  delete Core::f_Login;
708  Core::f_Login = NULL;
709  QApplication::quit();
710 }
711 
713 {
714  int i = 0;
715  QString text = "";
716  while (i<Core::RingLog.size())
717  {
718  text = Core::RingLog.at(i) + "\n" + text;
719  i++;
720  }
721  return text;
722 }
723 
725 {
726  return QStringList(Core::RingLog);
727 }
728 
729 void Core::InsertToRingLog(QString text)
730 {
732  {
733  Core::RingLog.removeAt(0);
734  }
735  Core::RingLog.append(text);
736 }
737 
739 {
740  QMessageBox *mb = new QMessageBox();
741  mb->setWindowTitle("Function is restricted now");
742  mb->setText("You can't perform this action in developer mode, because you aren't logged into the wiki");
743  mb->exec();
744  delete mb;
745 }
746 
748 {
749  if (_e == NULL)
750  {
751  throw new Exception("NULL edit");
752  }
753 
754  if (_e->Status == StatusProcessed)
755  {
756  return;
757  }
758 
759  if (_e->User == NULL)
760  {
761  throw new Exception("Edit user was NULL in Core::PreProcessEdit");
762  }
763 
764  if (_e->Bot)
765  {
766  _e->User->SetBot(true);
767  }
768 
770 
771  _e->Status = StatusProcessed;
772 }
773 
775 {
776  if (_e == NULL)
777  {
778  throw new Exception("NULL edit in PostProcessEdit(WikiEdit *_e) is not a valid edit");
779  }
780  _e->RegisterConsumer(HUGGLECONSUMER_CORE_POSTPROCESS);
781  _e->UnregisterConsumer(HUGGLECONSUMER_WIKIEDIT);
782  _e->PostProcess();
783  Core::ProcessingEdits.append(_e);
784 }
785 
787 {
788  int curr = 0;
789  if (Core::PendingMods.count() > 0)
790  {
791  while (curr < Core::PendingMods.count())
792  {
793  if (Core::PendingMods.at(curr)->Processed())
794  {
795  EditQuery *e = Core::PendingMods.at(curr);
796  Core::PendingMods.removeAt(curr);
797  e->UnregisterConsumer("Core::EditPage");
798  } else
799  {
800  curr++;
801  }
802  }
803  }
804  curr = 0;
805  if (Core::RunningQueries.count() < 1)
806  {
807  return;
808  }
809  QList<Query*> Finished;
810  while (curr < Core::RunningQueries.count())
811  {
812  Query *q = Core::RunningQueries.at(curr);
814  if (q->Processed())
815  {
816  Finished.append(q);
817  Core::DebugLog("Query finished with: " + q->Result->Data, 6);
820  }
821  curr++;
822  }
823  curr = 0;
824  while (curr < Finished.count())
825  {
826  Query *item = Finished.at(curr);
827  Core::RunningQueries.removeOne(item);
828  item->Lock();
829  item->UnregisterConsumer("core");
830  item->SafeDelete();
831  curr++;
832  }
833 }
834 
836 {
837  if (_e == NULL)
838  {
839  throw new Exception("NULL edit in PreflightCheck(WikiEdit *_e) is not a valid edit");
840  }
841  if (Configuration::WarnUserSpaceRoll && _e->Page->IsUserpage())
842  {
843  QMessageBox::StandardButton q = QMessageBox::question(NULL, "Revert edit"
844  , "This page is in userspace, so even if it looks like it is a vandalism,"\
845  " it may not be, are you sure you want to revert it?"
846  , QMessageBox::Yes|QMessageBox::No);
847  if (q == QMessageBox::No)
848  {
849  return false;
850  }
851  }
852  return true;
853 }
854 
855 RevertQuery *Core::RevertEdit(WikiEdit *_e, QString summary, bool minor, bool rollback, bool keep)
856 {
857  if (_e == NULL)
858  {
859  throw new Exception("NULL edit in RevertEdit(WikiEdit *_e, QString summary, bool minor, bool rollback, bool keep) is not a valid edit");
860  }
861  if (_e->User == NULL)
862  {
863  throw new Exception("Object user was NULL in Core::Revert");
864  }
865  _e->RegisterConsumer("Core::RevertEdit");
866  if (_e->Page == NULL)
867  {
868  throw new Exception("Object page was NULL");
869  }
870 
871  RevertQuery *query = new RevertQuery(_e);
872  if (summary != "")
873  {
874  query->Summary = summary;
875  }
876  query->MinorEdit = minor;
877  Core::AppendQuery(query);
879  {
880  query->UsingSR = true;
881  } else
882  {
883  query->UsingSR = !rollback;
884  }
885  query->Process();
886 
887  if (keep)
888  {
889  query->RegisterConsumer("keep");
890  }
891 
892  return query;
893 }
894 
895 void Core::ExceptionHandler(Exception *exception)
896 {
897  ExceptionWindow *w = new ExceptionWindow(exception);
898  w->exec();
899  delete w;
900 }
901 
902 Language *Core::MakeLanguage(QString text, QString name)
903 {
904  Core::Log("Loading language: " + name);
905  Language *l = new Language(name);
906  QStringList keys = text.split("\n");
907  int p = 0;
908  while (p < keys.count())
909  {
910  if (keys.at(p).contains(":"))
911  {
912  QString line = keys.at(p);
913  while (line.startsWith(" "))
914  {
915  line = line.mid(1);
916  }
917  QString key = line.mid(0, line.indexOf(":"));
918  QString lang = line.mid(line.indexOf(":") + 1);
919  while (lang.startsWith(" "))
920  {
921  lang = lang.mid(1);
922  }
923  if (!l->Messages.contains(key))
924  {
925  l->Messages.insert(key, lang);
926  }
927  }
928  p++;
929  }
930  if (l->Messages.contains("name"))
931  {
932  l->LanguageID = l->Messages["name"];
933  }
934  return l;
935 }
936 
937 void Core::LocalInit(QString name)
938 {
939  QFile *f = new QFile(":/huggle/text/Localization/" + name + ".txt");
940  f->open(QIODevice::ReadOnly);
941  Core::LocalizationData.append(Core::MakeLanguage(QString(f->readAll()), name));
942  f->close();
943  delete f;
944 }
945 
946 QString Core::Localize(QString key)
947 {
948  QString id = key;
949  if (id.endsWith("]]"))
950  {
951  id = key.mid(0, key.length() - 2);
952  }
953  if (id.startsWith("[["))
954  {
955  id = id.mid(2);
956  }
957  if (Core::LocalizationData.count() > 0)
958  {
959  int c=0;
960  while (c<Core::LocalizationData.count())
961  {
962  if (Core::LocalizationData.at(c)->LanguageName == Configuration::Language)
963  {
964  Language *l = Core::LocalizationData.at(c);
965  if (l->Messages.contains(id))
966  {
967  return l->Messages[id];
968  }
969  // performance tweak
970  break;
971  }
972  c++;
973  }
974  if (Core::LocalizationData.at(0)->Messages.contains(id))
975  {
976  return Core::LocalizationData.at(0)->Messages[id];
977  }
978  }
979  return key;
980 }
981 
982 void Core::LoadLocalizations()
983 {
984  Core::LocalInit("en");
986  {
987  Core::Log("Skipping load of other languages, because of safe mode");
988  return;
989  }
990  Core::LocalInit("ar");
991  Core::LocalInit("bg");
992  Core::LocalInit("bn");
993  Core::LocalInit("es");
994  Core::LocalInit("de");
995  Core::LocalInit("fa");
996  Core::LocalInit("fr");
997  Core::LocalInit("hi");
998  Core::LocalInit("it");
999  Core::LocalInit("ja");
1000  Core::LocalInit("ka");
1001  Core::LocalInit("km");
1002  Core::LocalInit("kn");
1003  Core::LocalInit("ko");
1004  Core::LocalInit("ml");
1005  Core::LocalInit("mr");
1006  Core::LocalInit("nl");
1007  Core::LocalInit("no");
1008  Core::LocalInit("oc");
1009  Core::LocalInit("or");
1010  Core::LocalInit("pt");
1011  Core::LocalInit("ptb");
1012  Core::LocalInit("ru");
1013  Core::LocalInit("sv");
1014  Core::LocalInit("zh");
1015 }
1016 
1017 bool Core::ReportPreFlightCheck()
1018 {
1020  {
1021  return true;
1022  }
1023  QMessageBox::StandardButton q = QMessageBox::question(NULL, "Report user"
1024  , "This user has already reached warning level 4, so no further templates will be "\
1025  "delivered to them. You can report them now, but please, make sure that they already reached the proper "\
1026  "number of recent warnings! You can do so by clicking the \"talk page\" button in following form. "\
1027  "Keep in mind that this form and this warning is displayed no matter if your revert was successful "\
1028  "or not, so you might conflict with other users here (double check if user isn't already reported) "\
1029  "Do you want to report this user?"
1030  , QMessageBox::Yes|QMessageBox::No);
1031  if (q == QMessageBox::No)
1032  {
1033  return false;
1034  }
1035  return true;
1036 }
1037 
1038 int Core::RunningQueriesGetCount()
1039 {
1040  return RunningQueries.count();
1041 }
1042 
1043 Language::Language(QString name)
1044 {
1045  LanguageName = name;
1046  LanguageID = name;
1047 }
1048 
1049 
1050 bool HgApplication::notify(QObject *receiver, QEvent *event)
1051 {
1052  bool done = true;
1053  try
1054  {
1055  done = QApplication::notify(receiver, event);
1056  }catch (Huggle::Exception *ex)
1057  {
1058  Core::ExceptionHandler(ex);
1059  }catch (Huggle::Exception &ex)
1060  {
1061  Core::ExceptionHandler(&ex);
1062  }
1063  return done;
1064 }
static QString HuggleVersion
Version.
static QString GetProjectScriptURL()
Return a script url like http://en.wikipedia.org/w/.
Definition: core.cpp:674
virtual bool SafeDelete()
Use this if you are not sure if you can delete this object in this moment.
Definition: collectable.cpp:38
QString title
Title.
Definition: message.hpp:38
QString WhiteList
Definition: wikisite.hpp:36
static QString WikiDB
Path to a file where information about wikis are stored.
static QString GetProjectWikiURL()
Return a full url like http://en.wikipedia.org/wiki/.
Definition: core.cpp:669
Primary huggle window.
Definition: mainwindow.hpp:110
static WikiPage * AIVP
Pointer to AIV page.
Definition: core.hpp:133
The ScoreWord class.
static void Log(QString Message)
Write text to terminal as well as ring log.
Definition: core.cpp:563
The Language class.
Definition: core.hpp:87
static WikiPage * UAAP
Pointer to UAA page.
Definition: core.hpp:135
static QString GetConfigurationPath()
Return a configuration path.
static void SaveDefs()
Store a definitions of problematic users, see WikiUser::ProblematicUsers for details.
Definition: core.cpp:312
static QString HtmlHeader
This string contains a html header.
Definition: core.hpp:115
void Process()
Execute query.
Definition: editquery.cpp:35
QString LongPath
long article path (wiki/ for example on english wp)
Definition: wikisite.hpp:27
static QString GetProjectURL()
Return a base url of current project.
Definition: core.cpp:664
static void PostProcessEdit(WikiEdit *_e)
Definition: core.cpp:774
bool UsingSR
Whether software rollback should be used instead of regular rollback.
Definition: revertquery.hpp:45
static QString RingLogToText()
Return a ring log represented as 1 huge string.
Definition: core.cpp:712
static QString HtmlFooter
This string contains a html footer.
Definition: core.hpp:117
QString summary
Edit summary.
Definition: editquery.hpp:37
virtual bool Processed()
Returns true in case that query is processed.
Definition: query.cpp:45
void UnregisterConsumer(const int consumer)
This function will remove a string which prevent the object from being removed.
Definition: collectable.cpp:68
bool Minor
Whether the edit is minor or not.
Definition: editquery.hpp:39
static QString GetURLProtocolPrefix()
Return a prefix for url.
void RegisterConsumer(const int consumer)
Registers a consumer.
Definition: collectable.cpp:57
QString page
Page that is going to be edited.
Definition: editquery.hpp:33
Feed provider stub class every provider must be derived from this one.
Definition: hugglefeed.hpp:22
void ProcessEdit(WikiEdit *e, bool IgnoreHistory=false)
Recreate interface, should be called everytime you do anything with main form.
Definition: mainwindow.cpp:258
Language(QString name)
Definition: core.cpp:1043
static void AppendQuery(Query *item)
Insert a query to internal list of running queries, so that they can be watched This will insert it t...
Definition: core.cpp:557
The RevertQuery class can be used to rollback any edit.
Definition: revertquery.hpp:32
static void VersionRead()
VersionRead - read the version from embedded git file.
Definition: core.cpp:627
QString Username
Username.
Definition: wikiuser.hpp:52
static Message * MessageUser(WikiUser *user, QString message, QString title, QString summary, bool section=true, Query *dependency=NULL)
MessageUser Message user.
Definition: core.cpp:427
QString LanguageName
This is a short language name which is used by system.
Definition: core.hpp:94
static QList< EditQuery * > PendingMods
Pending changes.
Definition: core.hpp:126
static ProcessorThread * Processor
This is a post-processor for edits.
Definition: core.hpp:259
QString IRCChannel
IRC channel of this site, if it doesn&#39;t have a channel leave it empty.
Definition: wikisite.hpp:33
bool SupportHttps
Whether the site supports the ssl.
Definition: wikisite.hpp:38
static void DeleteEdit(WikiEdit *edit)
Remove edit in proper manner.
Definition: core.cpp:178
static void CheckQueries()
Check if all running queries are finished and if so it removes them from list.
Definition: core.cpp:786
static void LoadConfig()
Load the local configuration from disk.
Window that is displayed as first when huggle is started.
Definition: login.hpp:56
This is similar to query, just it&#39;s more simple, you can use it to deliver messages to users...
Definition: message.hpp:26
static HuggleFeed * SecondaryFeedProvider
Pointer to secondary feed provider.
Definition: core.hpp:121
static bool WarnUserSpaceRoll
Warn you in case you want to revert a user page.
static void Shutdown()
Terminate the process, call this after you release all resources and finish all queries.
Definition: core.cpp:684
Mediawiki page.
Definition: wikipage.hpp:43
Edits are post processed in this thread.
Definition: wikiedit.hpp:50
static RevertQuery * RevertEdit(WikiEdit *_e, QString summary="", bool minor=false, bool rollback=true, bool keep=false)
RevertEdit Reverts the edit.
Definition: core.cpp:855
QString Summary
Summary of edit.
Definition: wikiedit.hpp:110
void RemoveQuery(Query *q)
Remove a query from list no matter if it finished or not.
Definition: processlist.cpp:68
static void PreProcessEdit(WikiEdit *_e)
Definition: core.cpp:747
static HuggleFeed * PrimaryFeedProvider
Pointer to primary feed provider.
Definition: core.hpp:119
static void LocalInit(QString name)
Initializes a localization with given name.
Definition: core.cpp:937
QString ScriptPath
short path
Definition: wikisite.hpp:29
Extension interface.
Definition: iextension.hpp:29
static QString Language
Language selected by user this is only a language of interface.
void PostProcess()
This function is called by internals of huggle.
Definition: wikiedit.cpp:254
bool EditMadeByHuggle
If this is true the edit was made by huggle.
Definition: wikiedit.hpp:114
QStringList UnwrittenLogs
Definition: mainwindow.hpp:140
ProcessList * Queries
Pointer to processes.
Definition: mainwindow.hpp:137
static QList< WikiUser * > ProblematicUsers
List of users that are scored in this instance of huggle.
Definition: wikiuser.hpp:35
Every exception raised by huggle is defined by this class.
Definition: exception.hpp:20
Query * Dependency
If this dependency is not a NULL then a message is sent after it is Processed (see Query::Processed()...
Definition: message.hpp:36
QString text
Text a page will be replaced with.
Definition: editquery.hpp:35
static void Init()
Function which is called as one of first when huggle is loaded.
Definition: core.cpp:41
static unsigned int Verbosity
Verbosity for debugging to terminal etc, can be switched with parameter –verbosity.
static void DeveloperError()
Display a message box telling user that function is not allowed during developer mode.
Definition: core.cpp:738
QMutex lUnwrittenLogs
Mutex we lock unwritten logs with so that only 1 thread can write to it.
Definition: mainwindow.hpp:144
Modifications of mediawiki pages can be done using this query.
Definition: editquery.hpp:25
static WikiSite Project
currently selected project
static QList< WikiEdit * > ProcessingEdits
Definition: core.hpp:124
static QList< Query * > RunningQueries
List of all running queries.
Definition: core.hpp:255
static QString EditSuffixOfHuggle
Suffix used by huggle.
void Process()
Execute query.
Definition: revertquery.cpp:53
static int RingLogMaxSize
Maximum size of ringlog.
WikiUser * User
User who changed the page.
Definition: wikiedit.hpp:89
static bool Running
Change this to false when you want to terminate all threads properly (you will need to wait few ms) ...
Definition: core.hpp:137
static void DebugLog(QString Message, unsigned int Verbosity=1)
This log is only shown if verbosity is same or larger than requested verbosity.
Definition: core.cpp:641
static void ParsePats(QString text)
Parse a part patterns for score words.
Definition: core.cpp:251
static QList< Message * > Messages
List of all messages that are being sent.
Definition: core.hpp:261
QString URL
URL of wiki, no http prefix must be present.
Definition: wikisite.hpp:25
static QList< iExtension * > Extensions
List of extensions loaded in huggle.
Definition: core.hpp:128
static QStringList RingLog
Ring log is a buffer that contains system messages.
Definition: core.hpp:257
static QList< Language * > LocalizationData
Languages D:
Definition: core.hpp:131
static void ExtensionLoad()
Load extensions (libraries as well as python)
Definition: core.cpp:576
static Login * f_Login
Login form.
Definition: core.hpp:113
Wiki edit.
Definition: wikiedit.hpp:67
static QStringList RingLogToQStringList()
Return a ring log as qstring list.
Definition: core.cpp:724
void Send()
Send a message to user.
Definition: message.cpp:35
QString LanguageID
Long identifier of language that is seen by user.
Definition: core.hpp:96
static QList< WikiSite * > ProjectList
List of projects.
void Lock()
Lock this object so that other threads can&#39;t change consumers or modify its properties.
static void TrimProblematicUsersList()
Delete all users that have badness score 0 these users aren&#39;t necessary to be stored in a list...
Definition: wikiuser.cpp:40
static bool _SafeMode
If this is true some functionalities will be disabled.
static bool PreflightCheck(WikiEdit *_e)
Check if we can revert this edit.
Definition: core.cpp:835
static MainWindow * Main
Pointer to main.
Definition: core.hpp:111
QString PageName
Name of page.
Definition: wikipage.hpp:48
static QString Trim(QString text)
Remove leading and finishing space of string.
Definition: core.cpp:164
bool Bot
Edit is a bot edit.
Definition: wikiedit.hpp:93
static void SaveConfig()
Save the local configuration to file.
static void LoadDefs()
Load a definitions of problematic users, see WikiUser::ProblematicUsers for details.
Definition: core.cpp:446
WikiPage * Page
Page that was changed by edit.
Definition: wikiedit.hpp:87
bool Section
If edit will be created in new section.
Definition: message.hpp:42
void UpdateQuery(Query *q)
Update information about query in list.
Definition: processlist.cpp:78
QString Data
Data retrieved by query.
Definition: queryresult.hpp:25
static bool AskUserBeforeReport
Ask user if they really want to report someone.
Query base class for all http queries executed by huggle.
Definition: query.hpp:64
QueryResult * Result
Result of query, see documentation of QueryResult for more.
Definition: query.hpp:68
static bool EnforceManualSoftwareRollback
If this is true huggle will always use software rollback even if user has the rollback privileges...