Blame SOURCES/1000-reporter-mantisbt-first-version-of-the-reporter-mant.patch

Matej Habrnal 5c8df3
From 220e7bb13328371bf5020da1d43a26871d91b96e Mon Sep 17 00:00:00 2001
Matej Habrnal 5c8df3
From: Matej Habrnal <mhabrnal@redhat.com>
Matej Habrnal 5c8df3
Date: Tue, 13 Jan 2015 19:30:27 -0500
Matej Habrnal 5c8df3
Subject: [PATCH 1000/1001] reporter-mantisbt: first version of the
Matej Habrnal 5c8df3
 reporter-mantisbt
Matej Habrnal 5c8df3
Matej Habrnal 5c8df3
Related to #272
Matej Habrnal 5c8df3
Matej Habrnal 5c8df3
Signed-off-by: Matej Habrnal <mhabrnal@redhat.com>
Matej Habrnal 5c8df3
---
Matej Habrnal 5c8df3
 configure.ac                                   |   33 +
Matej Habrnal 5c8df3
 po/POTFILES.in                                 |   11 +
Matej Habrnal 5c8df3
 src/plugins/Makefile.am                        |   43 +-
Matej Habrnal 5c8df3
 src/plugins/centos_report_event.conf           |   37 +
Matej Habrnal 5c8df3
 src/plugins/mantisbt.c                         | 1111 ++++++++++++++++++++++++
Matej Habrnal 5c8df3
 src/plugins/mantisbt.conf                      |    8 +
Matej Habrnal 5c8df3
 src/plugins/mantisbt.h                         |  140 +++
Matej Habrnal 5c8df3
 src/plugins/mantisbt_format.conf               |   59 ++
Matej Habrnal 5c8df3
 src/plugins/mantisbt_formatdup.conf            |   65 ++
Matej Habrnal 5c8df3
 src/plugins/report_CentOSBugTracker.conf       |    4 +
Matej Habrnal 5c8df3
 src/plugins/report_CentOSBugTracker.xml.in     |   65 ++
Matej Habrnal 5c8df3
 src/plugins/reporter-mantisbt.c                |  696 +++++++++++++++
Matej Habrnal 5c8df3
 src/workflows/Makefile.am                      |   15 +-
Matej Habrnal 5c8df3
 src/workflows/report_centos.conf               |   31 +
Matej Habrnal 5c8df3
 src/workflows/workflow_CentOSCCpp.xml.in       |   12 +
Matej Habrnal 5c8df3
 src/workflows/workflow_CentOSJava.xml.in       |   11 +
Matej Habrnal 5c8df3
 src/workflows/workflow_CentOSKerneloops.xml.in |   11 +
Matej Habrnal 5c8df3
 src/workflows/workflow_CentOSLibreport.xml.in  |    9 +
Matej Habrnal 5c8df3
 src/workflows/workflow_CentOSPython.xml.in     |   11 +
Matej Habrnal 5c8df3
 src/workflows/workflow_CentOSPython3.xml.in    |   11 +
Matej Habrnal 5c8df3
 src/workflows/workflow_CentOSVmcore.xml.in     |   12 +
Matej Habrnal 5c8df3
 src/workflows/workflow_CentOSXorg.xml.in       |    9 +
Matej Habrnal 5c8df3
 22 files changed, 2402 insertions(+), 2 deletions(-)
Matej Habrnal 5c8df3
 create mode 100644 src/plugins/centos_report_event.conf
Matej Habrnal 5c8df3
 create mode 100644 src/plugins/mantisbt.c
Matej Habrnal 5c8df3
 create mode 100644 src/plugins/mantisbt.conf
Matej Habrnal 5c8df3
 create mode 100644 src/plugins/mantisbt.h
Matej Habrnal 5c8df3
 create mode 100644 src/plugins/mantisbt_format.conf
Matej Habrnal 5c8df3
 create mode 100644 src/plugins/mantisbt_formatdup.conf
Matej Habrnal 5c8df3
 create mode 100644 src/plugins/report_CentOSBugTracker.conf
Matej Habrnal 5c8df3
 create mode 100644 src/plugins/report_CentOSBugTracker.xml.in
Matej Habrnal 5c8df3
 create mode 100644 src/plugins/reporter-mantisbt.c
Matej Habrnal 5c8df3
 create mode 100644 src/workflows/report_centos.conf
Matej Habrnal 5c8df3
 create mode 100644 src/workflows/workflow_CentOSCCpp.xml.in
Matej Habrnal 5c8df3
 create mode 100644 src/workflows/workflow_CentOSJava.xml.in
Matej Habrnal 5c8df3
 create mode 100644 src/workflows/workflow_CentOSKerneloops.xml.in
Matej Habrnal 5c8df3
 create mode 100644 src/workflows/workflow_CentOSLibreport.xml.in
Matej Habrnal 5c8df3
 create mode 100644 src/workflows/workflow_CentOSPython.xml.in
Matej Habrnal 5c8df3
 create mode 100644 src/workflows/workflow_CentOSPython3.xml.in
Matej Habrnal 5c8df3
 create mode 100644 src/workflows/workflow_CentOSVmcore.xml.in
Matej Habrnal 5c8df3
 create mode 100644 src/workflows/workflow_CentOSXorg.xml.in
Matej Habrnal 5c8df3
Matej Habrnal 5c8df3
diff --git a/configure.ac b/configure.ac
Matej Habrnal 5c8df3
index df88240..692ee81 100644
Matej Habrnal 5c8df3
--- a/configure.ac
Matej Habrnal 5c8df3
+++ b/configure.ac
Matej Habrnal 5c8df3
@@ -131,6 +131,39 @@ do
Matej Habrnal 5c8df3
 done
Matej Habrnal 5c8df3
 fi dnl end NO_BUGZILLA
Matej Habrnal 5c8df3
 
Matej Habrnal 5c8df3
+AC_ARG_WITH(mantisbt,
Matej Habrnal 5c8df3
+AS_HELP_STRING([--with-mantisbt],[use MantisBT plugin (default is YES)]),
Matej Habrnal 5c8df3
+LIBREPORT_PARSE_WITH([mantisbt]))
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+if test -z "$NO_MANTISBT"; then
Matej Habrnal 5c8df3
+AM_CONDITIONAL(BUILD_MANTISBT, true)
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+# enable mantisbt & deps translations
Matej Habrnal 5c8df3
+for FILE in `grep -e "#.*antisbt.*" -e "#.*naconda.*" po/POTFILES.in`
Matej Habrnal 5c8df3
+do
Matej Habrnal 5c8df3
+  sed -ie "s,$FILE,${FILE:1}," po/POTFILES.in
Matej Habrnal 5c8df3
+  sed -ie "\,^${FILE:1}$,d" po/POTFILES.skip
Matej Habrnal 5c8df3
+done
Matej Habrnal 5c8df3
+else
Matej Habrnal 5c8df3
+AM_CONDITIONAL(BUILD_MANTISBT, false)
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+# disablie mantisbt & deps translations
Matej Habrnal 5c8df3
+for FILE in `grep -e "antisbt" -e "naconda" po/POTFILES.in`
Matej Habrnal 5c8df3
+do
Matej Habrnal 5c8df3
+  if test "${FILE:0:1}" = "#"
Matej Habrnal 5c8df3
+  then
Matej Habrnal 5c8df3
+    continue
Matej Habrnal 5c8df3
+  fi
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+  sed -ie "s,$FILE,#$FILE," po/POTFILES.in
Matej Habrnal 5c8df3
+  grep "$FILE" po/POTFILES.skip > /dev/null 2>&1
Matej Habrnal 5c8df3
+  if test $?
Matej Habrnal 5c8df3
+  then
Matej Habrnal 5c8df3
+    echo "$FILE" >> po/POTFILES.skip
Matej Habrnal 5c8df3
+  fi
Matej Habrnal 5c8df3
+done
Matej Habrnal 5c8df3
+fi dnl end NO_MANTISBT
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
 AC_PATH_PROG([PYTHON_CONFIG], [python-config], [no])
Matej Habrnal 5c8df3
 [if test "$PYTHON_CONFIG" = "no"]
Matej Habrnal 5c8df3
 [then]
Matej Habrnal 5c8df3
diff --git a/po/POTFILES.in b/po/POTFILES.in
Matej Habrnal 5c8df3
index 5588540..3415b03 100644
Matej Habrnal 5c8df3
--- a/po/POTFILES.in
Matej Habrnal 5c8df3
+++ b/po/POTFILES.in
Matej Habrnal 5c8df3
@@ -36,6 +36,8 @@ src/plugins/reporter-print.c
Matej Habrnal 5c8df3
 src/plugins/reporter-rhtsupport.c
Matej Habrnal 5c8df3
 src/plugins/reporter-rhtsupport-parse.c
Matej Habrnal 5c8df3
 src/plugins/reporter-upload.c
Matej Habrnal 5c8df3
+src/plugins/reporter-mantisbt.c
Matej Habrnal 5c8df3
+src/plugins/report_CentOSBugTracker.xml.in
Matej Habrnal 5c8df3
 src/plugins/report_Kerneloops.xml.in
Matej Habrnal 5c8df3
 src/plugins/report_Logger.xml.in
Matej Habrnal 5c8df3
 src/plugins/report_Mailx.xml.in
Matej Habrnal 5c8df3
@@ -44,12 +46,21 @@ src/plugins/report_Uploader.xml.in
Matej Habrnal 5c8df3
 src/plugins/report_uReport.xml.in
Matej Habrnal 5c8df3
 src/plugins/report_EmergencyAnalysis.xml.in
Matej Habrnal 5c8df3
 src/plugins/rhbz.c
Matej Habrnal 5c8df3
+src/plugins/mantisbt.c
Matej Habrnal 5c8df3
 src/plugins/reporter-ureport.c
Matej Habrnal 5c8df3
 src/report-newt/report-newt.c
Matej Habrnal 5c8df3
 src/workflows/workflow_AnacondaFedora.xml.in
Matej Habrnal 5c8df3
 src/workflows/workflow_AnacondaRHEL.xml.in
Matej Habrnal 5c8df3
 src/workflows/workflow_AnacondaRHELBugzilla.xml.in
Matej Habrnal 5c8df3
 src/workflows/workflow_AnacondaUpload.xml.in
Matej Habrnal 5c8df3
+src/workflows/workflow_CentOSCCpp.xml.in
Matej Habrnal 5c8df3
+src/workflows/workflow_CentOSJava.xml.in
Matej Habrnal 5c8df3
+src/workflows/workflow_CentOSKerneloops.xml.in
Matej Habrnal 5c8df3
+src/workflows/workflow_CentOSLibreport.xml.in
Matej Habrnal 5c8df3
+src/workflows/workflow_CentOSPython.xml.in
Matej Habrnal 5c8df3
+src/workflows/workflow_CentOSPython3.xml.in
Matej Habrnal 5c8df3
+src/workflows/workflow_CentOSVmcore.xml.in
Matej Habrnal 5c8df3
+src/workflows/workflow_CentOSXorg.xml.in
Matej Habrnal 5c8df3
 src/workflows/workflow_FedoraCCpp.xml.in
Matej Habrnal 5c8df3
 src/workflows/workflow_FedoraKerneloops.xml.in
Matej Habrnal 5c8df3
 src/workflows/workflow_FedoraPython.xml.in
Matej Habrnal 5c8df3
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
Matej Habrnal 5c8df3
index 7ec08d7..d70b4db 100644
Matej Habrnal 5c8df3
--- a/src/plugins/Makefile.am
Matej Habrnal 5c8df3
+++ b/src/plugins/Makefile.am
Matej Habrnal 5c8df3
@@ -7,6 +7,11 @@ reporters_bin += \
Matej Habrnal 5c8df3
     report
Matej Habrnal 5c8df3
 endif
Matej Habrnal 5c8df3
 
Matej Habrnal 5c8df3
+if BUILD_MANTISBT
Matej Habrnal 5c8df3
+reporters_bin += \
Matej Habrnal 5c8df3
+    reporter-mantisbt
Matej Habrnal 5c8df3
+endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
 if BUILD_UREPORT
Matej Habrnal 5c8df3
 reporters_bin +=  reporter-ureport
Matej Habrnal 5c8df3
 endif
Matej Habrnal 5c8df3
@@ -34,6 +39,12 @@ reporters_plugin_format_conf += bugzilla_format.conf \
Matej Habrnal 5c8df3
     bugzilla_formatdup_anaconda.conf
Matej Habrnal 5c8df3
 endif
Matej Habrnal 5c8df3
 
Matej Habrnal 5c8df3
+if BUILD_MANTISBT
Matej Habrnal 5c8df3
+reporters_plugin_conf += mantisbt.conf
Matej Habrnal 5c8df3
+reporters_plugin_format_conf += mantisbt_format.conf \
Matej Habrnal 5c8df3
+    mantisbt_formatdup.conf
Matej Habrnal 5c8df3
+endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
 defaultreportpluginsconfdir = $(DEFAULT_REPORT_PLUGINS_CONF_DIR)
Matej Habrnal 5c8df3
 dist_defaultreportpluginsconf_DATA = $(reporters_plugin_conf) \
Matej Habrnal 5c8df3
     rhtsupport.conf \
Matej Habrnal 5c8df3
@@ -53,6 +64,12 @@ reporters_events += report_Bugzilla.xml
Matej Habrnal 5c8df3
 reporters_events_conf += report_Bugzilla.conf
Matej Habrnal 5c8df3
 endif
Matej Habrnal 5c8df3
 
Matej Habrnal 5c8df3
+if BUILD_MANTISBT
Matej Habrnal 5c8df3
+reporters_events += report_CentOSBugTracker.xml
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+reporters_events_conf += report_CentOSBugTracker.conf
Matej Habrnal 5c8df3
+endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
 if BUILD_UREPORT
Matej Habrnal 5c8df3
 reporters_events += report_uReport.xml
Matej Habrnal 5c8df3
 endif
Matej Habrnal 5c8df3
@@ -77,7 +94,8 @@ dist_eventsdef_DATA = \
Matej Habrnal 5c8df3
     print_event.conf \
Matej Habrnal 5c8df3
     rhtsupport_event.conf \
Matej Habrnal 5c8df3
     uploader_event.conf \
Matej Habrnal 5c8df3
-    emergencyanalysis_event.conf
Matej Habrnal 5c8df3
+    emergencyanalysis_event.conf \
Matej Habrnal 5c8df3
+    centos_report_event.conf
Matej Habrnal 5c8df3
 
Matej Habrnal 5c8df3
 reporters_extra_dist =
Matej Habrnal 5c8df3
 if BUILD_BUGZILLA
Matej Habrnal 5c8df3
@@ -125,6 +143,29 @@ reporter_bugzilla_LDADD = \
Matej Habrnal 5c8df3
     ../lib/libreport.la
Matej Habrnal 5c8df3
 endif
Matej Habrnal 5c8df3
 
Matej Habrnal 5c8df3
+if BUILD_MANTISBT
Matej Habrnal 5c8df3
+reporter_mantisbt_SOURCES = \
Matej Habrnal 5c8df3
+    reporter-mantisbt.c mantisbt.c mantisbt.h
Matej Habrnal 5c8df3
+reporter_mantisbt_CPPFLAGS = \
Matej Habrnal 5c8df3
+    -I$(srcdir)/../include \
Matej Habrnal 5c8df3
+    -I$(srcdir)/../lib \
Matej Habrnal 5c8df3
+    -DBIN_DIR=\"$(bindir)\" \
Matej Habrnal 5c8df3
+    -DCONF_DIR=\"$(CONF_DIR)\" \
Matej Habrnal 5c8df3
+    -DLOCALSTATEDIR='"$(localstatedir)"' \
Matej Habrnal 5c8df3
+    -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
Matej Habrnal 5c8df3
+    -DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \
Matej Habrnal 5c8df3
+    -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \
Matej Habrnal 5c8df3
+    -DPLUGINS_CONF_DIR=\"$(REPORT_PLUGINS_CONF_DIR)\" \
Matej Habrnal 5c8df3
+    $(GLIB_CFLAGS) \
Matej Habrnal 5c8df3
+    $(LIBREPORT_CFLAGS) \
Matej Habrnal 5c8df3
+    $(LIBXML_CFLAGS) \
Matej Habrnal 5c8df3
+    -D_GNU_SOURCE
Matej Habrnal 5c8df3
+reporter_mantisbt_LDADD = \
Matej Habrnal 5c8df3
+    $(GLIB_LIBS) \
Matej Habrnal 5c8df3
+    ../lib/libreport-web.la \
Matej Habrnal 5c8df3
+    ../lib/libreport.la
Matej Habrnal 5c8df3
+endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
 reporter_rhtsupport_SOURCES = \
Matej Habrnal 5c8df3
     abrt_rh_support.h abrt_rh_support.c \
Matej Habrnal 5c8df3
     reporter-rhtsupport.h \
Matej Habrnal 5c8df3
diff --git a/src/plugins/centos_report_event.conf b/src/plugins/centos_report_event.conf
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..53f12d8
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/plugins/centos_report_event.conf
Matej Habrnal 5c8df3
@@ -0,0 +1,37 @@
Matej Habrnal 5c8df3
+EVENT=report_CentOSBugTracker analyzer=xorg
Matej Habrnal 5c8df3
+    reporter-mantisbt
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=report_CentOSBugTracker analyzer=Kerneloops
Matej Habrnal 5c8df3
+    reporter-mantisbt
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=report_CentOSBugTracker analyzer=vmcore
Matej Habrnal 5c8df3
+        reporter-mantisbt
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=report_CentOSBugTracker analyzer=Python component!=anaconda
Matej Habrnal 5c8df3
+        test -f component || abrt-action-save-package-data
Matej Habrnal 5c8df3
+        reporter-mantisbt \
Matej Habrnal 5c8df3
+                -c /etc/libreport/plugins/mantisbt.conf \
Matej Habrnal 5c8df3
+                -F /etc/libreport/plugins/mantisbt_format.conf \
Matej Habrnal 5c8df3
+                -A /etc/libreport/plugins/mantisbt_formatdup.conf
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=report_CentOSBugTracker analyzer=Python3 component!=anaconda
Matej Habrnal 5c8df3
+        test -f component || abrt-action-save-package-data
Matej Habrnal 5c8df3
+        reporter-mantisbt \
Matej Habrnal 5c8df3
+                -c /etc/libreport/plugins/mantisbt.conf \
Matej Habrnal 5c8df3
+                -F /etc/libreport/plugins/mantisbt_format.conf \
Matej Habrnal 5c8df3
+                -A /etc/libreport/plugins/mantisbt_formatdup.conf
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=report_CentOSBugTracker analyzer=CCpp duphash!=
Matej Habrnal 5c8df3
+        test -f component || abrt-action-save-package-data
Matej Habrnal 5c8df3
+        component="`cat component`"
Matej Habrnal 5c8df3
+        format="mantisbt_format.conf"
Matej Habrnal 5c8df3
+        test -f "/etc/libreport/plugins/mantisbt_format_$component.conf" \
Matej Habrnal 5c8df3
+                && format="mantisbt_format_$component.conf"
Matej Habrnal 5c8df3
+        formatdup="mantisbt_formatdup.conf"
Matej Habrnal 5c8df3
+        test -f "/etc/libreport/plugins/mantisbt_formatdup_$component.conf" \
Matej Habrnal 5c8df3
+                && formatdup="mantisbt_formatdup_$component.conf"
Matej Habrnal 5c8df3
+        reporter-mantisbt \
Matej Habrnal 5c8df3
+                -c /etc/libreport/plugins/mantisbt.conf \
Matej Habrnal 5c8df3
+                -F "/etc/libreport/plugins/$format" \
Matej Habrnal 5c8df3
+                -A "/etc/libreport/plugins/$formatdup"
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
diff --git a/src/plugins/mantisbt.c b/src/plugins/mantisbt.c
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..1c496b4
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/plugins/mantisbt.c
Matej Habrnal 5c8df3
@@ -0,0 +1,1111 @@
Matej Habrnal 5c8df3
+/*
Matej Habrnal 5c8df3
+    Copyright (C) 2014  ABRT team
Matej Habrnal 5c8df3
+    Copyright (C) 2014  RedHat Inc
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    This program is free software; you can redistribute it and/or modify
Matej Habrnal 5c8df3
+    it under the terms of the GNU General Public License as published by
Matej Habrnal 5c8df3
+    the Free Software Foundation; either version 2 of the License, or
Matej Habrnal 5c8df3
+    (at your option) any later version.
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    This program is distributed in the hope that it will be useful,
Matej Habrnal 5c8df3
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
Matej Habrnal 5c8df3
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Matej Habrnal 5c8df3
+    GNU General Public License for more details.
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    You should have received a copy of the GNU General Public License along
Matej Habrnal 5c8df3
+    with this program; if not, write to the Free Software Foundation, Inc.,
Matej Habrnal 5c8df3
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Matej Habrnal 5c8df3
+*/
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#include <curl/curl.h>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#include <libxml/xmlreader.h>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#include "internal_libreport.h"
Matej Habrnal 5c8df3
+#include "libreport_curl.h"
Matej Habrnal 5c8df3
+#include "mantisbt.h"
Matej Habrnal 5c8df3
+#include "client.h"
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+/*
Matej Habrnal 5c8df3
+ * SOAP
Matej Habrnal 5c8df3
+*/
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#define XML_VERSION ""
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+/* fprint string */
Matej Habrnal 5c8df3
+#define SOAP_TEMPLATE \
Matej Habrnal 5c8df3
+    "
Matej Habrnal 5c8df3
+        "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" " \
Matej Habrnal 5c8df3
+        "xmlns:ns0=\"http://schemas.xmlsoap.org/soap/encoding/\" " \
Matej Habrnal 5c8df3
+        "xmlns:ns1=\"http://schemas.xmlsoap.org/soap/envelope/\" " \
Matej Habrnal 5c8df3
+        "xmlns:ns2=\"http://www.w3.org/2001/XMLSchema\" " \
Matej Habrnal 5c8df3
+        "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
Matej Habrnal 5c8df3
+        "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" " \
Matej Habrnal 5c8df3
+        "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" \
Matej Habrnal 5c8df3
+    "<SOAP-ENV:Header/>" \
Matej Habrnal 5c8df3
+    "<ns1:Body>" \
Matej Habrnal 5c8df3
+        "<ns3:%s>" \
Matej Habrnal 5c8df3
+        "</ns3:%s>" \
Matej Habrnal 5c8df3
+    "</ns1:Body>" \
Matej Habrnal 5c8df3
+    "</SOAP-ENV:Envelope>"
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#define MAX_SUMMARY_LENGTH  128
Matej Habrnal 5c8df3
+#define CUSTOMFIELD_DUPHASH "abrt_hash"
Matej Habrnal 5c8df3
+#define CUSTOMFIELD_URL "URL"
Matej Habrnal 5c8df3
+#define MAX_HOPS 5
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+/* MantisBT limit is 2MB by default
Matej Habrnal 5c8df3
+ */
Matej Habrnal 5c8df3
+#define MANTISBT_MAX_FILE_UPLOAD_SIZE (2 * 1024 * 1024)
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+typedef struct mantisbt_custom_fields
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    char *cf_abrt_hash_id;
Matej Habrnal 5c8df3
+    char *cf_url_id;
Matej Habrnal 5c8df3
+} mantisbt_custom_fields_t;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+/*
Matej Habrnal 5c8df3
+ * MantisBT settings issue info
Matej Habrnal 5c8df3
+ */
Matej Habrnal 5c8df3
+void
Matej Habrnal 5c8df3
+mantisbt_settings_free(mantisbt_settings_t *s)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (s == NULL)
Matej Habrnal 5c8df3
+        return;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    free(s->m_login);
Matej Habrnal 5c8df3
+    free(s->m_password);
Matej Habrnal 5c8df3
+    free(s->m_project);
Matej Habrnal 5c8df3
+    free(s->m_project_id);
Matej Habrnal 5c8df3
+    free(s->m_project_version);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+/*
Matej Habrnal 5c8df3
+ * MantisBT issue info
Matej Habrnal 5c8df3
+ */
Matej Habrnal 5c8df3
+mantisbt_issue_info_t *
Matej Habrnal 5c8df3
+mantisbt_issue_info_new()
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    mantisbt_issue_info_t *info = xzalloc(sizeof(mantisbt_issue_info_t));
Matej Habrnal 5c8df3
+    info->mii_id = -1;
Matej Habrnal 5c8df3
+    info->mii_dup_id = -1;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return info;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void
Matej Habrnal 5c8df3
+mantisbt_issue_info_free(mantisbt_issue_info_t *info)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (info == NULL)
Matej Habrnal 5c8df3
+        return;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    free(info->mii_status);
Matej Habrnal 5c8df3
+    free(info->mii_resolution);
Matej Habrnal 5c8df3
+    free(info->mii_reporter);
Matej Habrnal 5c8df3
+    free(info->mii_project);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    list_free_with_free(info->mii_notes);
Matej Habrnal 5c8df3
+    list_free_with_free(info->mii_attachments);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    free(info);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+mantisbt_issue_info_t *
Matej Habrnal 5c8df3
+mantisbt_find_origin_bug_closed_duplicate(mantisbt_settings_t *settings, mantisbt_issue_info_t *info)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    mantisbt_issue_info_t *info_tmp = mantisbt_issue_info_new();
Matej Habrnal 5c8df3
+    info_tmp->mii_id = info->mii_id;
Matej Habrnal 5c8df3
+    info_tmp->mii_dup_id = info->mii_dup_id;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    for (int ii = 0; ii <= MAX_HOPS; ii++)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        if (ii == MAX_HOPS)
Matej Habrnal 5c8df3
+            error_msg_and_die(_("MantisBT couldn't find parent of issue %d"), info->mii_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        log("Issue %d is a duplicate, using parent issue %d", info_tmp->mii_id, info_tmp->mii_dup_id);
Matej Habrnal 5c8df3
+        int issue_id = info_tmp->mii_dup_id;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        mantisbt_issue_info_free(info_tmp);
Matej Habrnal 5c8df3
+        info_tmp = mantisbt_get_issue_info(settings, issue_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        // found a issue which is not CLOSED as DUPLICATE
Matej Habrnal 5c8df3
+        if (info_tmp->mii_dup_id == -1)
Matej Habrnal 5c8df3
+            break;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return info_tmp;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+/*
Matej Habrnal 5c8df3
+ * SOAP request
Matej Habrnal 5c8df3
+ */
Matej Habrnal 5c8df3
+static soap_request_t *
Matej Habrnal 5c8df3
+soap_request_new()
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    soap_request_t *req = xzalloc(sizeof(*req));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return req;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void
Matej Habrnal 5c8df3
+soap_request_free(soap_request_t *req)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (req == NULL)
Matej Habrnal 5c8df3
+        return;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (req->sr_root != NULL)
Matej Habrnal 5c8df3
+        xmlFreeDoc(req->sr_root->doc);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    free(req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static xmlNodePtr
Matej Habrnal 5c8df3
+soap_node_get_next_element_node(xmlNodePtr node)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    for (; node != NULL; node = node->next)
Matej Habrnal 5c8df3
+        if (node->type == XML_ELEMENT_NODE)
Matej Habrnal 5c8df3
+            break;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return node;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static xmlNodePtr
Matej Habrnal 5c8df3
+soap_node_get_child_element(xmlNodePtr node)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (node == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to get child element because of no parent."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return soap_node_get_next_element_node(node->xmlChildrenNode);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static xmlNodePtr
Matej Habrnal 5c8df3
+soap_node_get_next_sibling(xmlNodePtr node)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (node == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to get next element because of no node."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return soap_node_get_next_element_node(node->next);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static xmlNodePtr
Matej Habrnal 5c8df3
+soap_node_get_child_node(xmlNodePtr parent, const char *name)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (parent == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to get child node because of no parent."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlNodePtr node;
Matej Habrnal 5c8df3
+    for (node = soap_node_get_child_element(parent); node != NULL; node = soap_node_get_next_sibling(node))
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        if (xmlStrcmp(node->name, BAD_CAST name) == 0)
Matej Habrnal 5c8df3
+            return node;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return NULL;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+soap_request_t *
Matej Habrnal 5c8df3
+soap_request_new_for_method(const char *method)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    char *xml_str = xasprintf(SOAP_TEMPLATE, method, method);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlDocPtr doc = xmlParseDoc(BAD_CAST xml_str);
Matej Habrnal 5c8df3
+    free(xml_str);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (doc == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to parse xml during creating request."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_request_t *req = soap_request_new();
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    req->sr_root = xmlDocGetRootElement(doc);
Matej Habrnal 5c8df3
+    if (req->sr_root == NULL)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        soap_request_free(req);
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to get xml root element."));
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    req->sr_body = soap_node_get_child_node(req->sr_root, "Body");
Matej Habrnal 5c8df3
+    req->sr_method = soap_node_get_child_node(req->sr_body, method);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return req;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static xmlNodePtr
Matej Habrnal 5c8df3
+soap_node_add_child_node(xmlNodePtr node, const char *name, const char *type, const char *value)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (node == NULL || name == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to add a new child node because of no node or no child name."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlNodePtr new_node = xmlNewTextChild(node, /* namespace */ NULL, BAD_CAST name, BAD_CAST value);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (new_node == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to create a new xml child item."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (type != NULL)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        if (xmlNewProp(new_node, BAD_CAST "xsi:type", BAD_CAST type) == NULL)
Matej Habrnal 5c8df3
+            error_msg_and_die(_("SOAP: Failed to create a new property."));
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return new_node;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void
Matej Habrnal 5c8df3
+soap_request_add_method_parameter(soap_request_t *req, const char *name, const char *type, const char *value)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (req == NULL || req->sr_method == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to add method parametr."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_node_add_child_node(req->sr_method, name, type, value);
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void
Matej Habrnal 5c8df3
+soap_request_add_credentials_parameter(soap_request_t *req, const mantisbt_settings_t *settings)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "username", SOAP_STRING, settings->m_login);
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "password", SOAP_STRING, settings->m_password);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+soap_add_new_issue_parameters(soap_request_t *req,
Matej Habrnal 5c8df3
+                               const char *project,
Matej Habrnal 5c8df3
+                               const char *version,
Matej Habrnal 5c8df3
+                               const char *category,
Matej Habrnal 5c8df3
+                               const char *summary,
Matej Habrnal 5c8df3
+                               const char *description,
Matej Habrnal 5c8df3
+                               const char *additional_information,
Matej Habrnal 5c8df3
+                               bool private,
Matej Habrnal 5c8df3
+                               mantisbt_custom_fields_t *fields,
Matej Habrnal 5c8df3
+                               const char *duphash,
Matej Habrnal 5c8df3
+                               const char *tracker_url)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (req == NULL || req->sr_method == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to add new issue parametrs."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (project == NULL || category == NULL || summary == NULL || description == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to add new issue parameters because the required items are missing."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlNodePtr issue_node = soap_node_add_child_node(req->sr_method, "issue", SOAP_ISSUEDATA, /* content */ NULL);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    // project
Matej Habrnal 5c8df3
+    xmlNodePtr project_node = soap_node_add_child_node(issue_node, "project", SOAP_OBJECTREF, /* content */ NULL);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(project_node, "name", SOAP_STRING, project);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    // view status
Matej Habrnal 5c8df3
+    xmlNodePtr view_node = soap_node_add_child_node(issue_node, "view_state", SOAP_OBJECTREF, /* content */ NULL);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(view_node, "name", SOAP_STRING, (private) ? "private" : "public");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* if any custom field exists */
Matej Habrnal 5c8df3
+    int custom_fields_count = 0;
Matej Habrnal 5c8df3
+    xmlNodePtr duphash_node;
Matej Habrnal 5c8df3
+    if (fields->cf_abrt_hash_id != NULL || fields->cf_url_id != NULL)
Matej Habrnal 5c8df3
+        duphash_node = soap_node_add_child_node(issue_node, "custom_fields", SOAP_CUSTOMFIELD_ARRAY, /* content */ NULL);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    // custom fields (duphash and URL to tracker)
Matej Habrnal 5c8df3
+    xmlNodePtr item_node, field_node;
Matej Habrnal 5c8df3
+    if (fields->cf_abrt_hash_id != NULL)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        item_node = soap_node_add_child_node(duphash_node, "item", SOAP_CUSTOMFIELD, /* content */ NULL);
Matej Habrnal 5c8df3
+        field_node = soap_node_add_child_node(item_node, "field", SOAP_OBJECTREF, /* content */ NULL);
Matej Habrnal 5c8df3
+        soap_node_add_child_node(field_node, "id", SOAP_INTEGER, /* custom_field id */ fields->cf_abrt_hash_id);
Matej Habrnal 5c8df3
+        soap_node_add_child_node(item_node, "value", SOAP_STRING, duphash);
Matej Habrnal 5c8df3
+        ++custom_fields_count;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    // if tracker url exists, attach it to the issue
Matej Habrnal 5c8df3
+    if (tracker_url != NULL && fields->cf_url_id != NULL)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        item_node = soap_node_add_child_node(duphash_node, "item", SOAP_CUSTOMFIELD, /* content */ NULL);
Matej Habrnal 5c8df3
+        field_node = soap_node_add_child_node(item_node, "field", SOAP_OBJECTREF, /* content */ NULL);
Matej Habrnal 5c8df3
+        soap_node_add_child_node(field_node, "id", SOAP_INTEGER, /* custom_field */ fields->cf_url_id);
Matej Habrnal 5c8df3
+        soap_node_add_child_node(item_node, "value", SOAP_STRING, tracker_url);
Matej Habrnal 5c8df3
+        ++custom_fields_count;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (custom_fields_count > 0)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        char *type = xasprintf("%s[%i]", SOAP_CUSTOMFIELD, custom_fields_count);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (xmlNewProp(duphash_node, BAD_CAST "ns3:arrayType", BAD_CAST type) == NULL)
Matej Habrnal 5c8df3
+            error_msg_and_die(_("SOAP: Failed to create a new property in custom fields."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        free(type);
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_node_add_child_node(issue_node, "os_build", SOAP_STRING, version);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(issue_node, "category", SOAP_STRING, category);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(issue_node, "summary", SOAP_STRING, summary);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(issue_node, "description", SOAP_STRING, description);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(issue_node, "additional_information", SOAP_STRING, additional_information);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+char *
Matej Habrnal 5c8df3
+soap_request_to_str(const soap_request_t *req)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (req == NULL || req->sr_root == NULL || req->sr_root->doc == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to create SOAP string because of invalid function arguments."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlBufferPtr buffer = xmlBufferCreate();
Matej Habrnal 5c8df3
+    int err = xmlNodeDump(buffer, req->sr_root->doc, req->sr_root, 1, /* formatting */ 0);
Matej Habrnal 5c8df3
+    if (err == -1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        xmlBufferFree(buffer);
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to dump xml node."));
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    char *ret = xasprintf("%s%s", XML_VERSION, (const char *) xmlBufferContent(buffer));
Matej Habrnal 5c8df3
+    xmlBufferFree(buffer);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return ret;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#if 0
Matej Habrnal 5c8df3
+void
Matej Habrnal 5c8df3
+soap_request_print(soap_request_t *req)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (req == NULL || req->sr_root == NULL || req->sr_root->doc == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to print SOAP string."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlBufferPtr buffer = xmlBufferCreate();
Matej Habrnal 5c8df3
+    int err = xmlNodeDump(buffer, req->sr_root->doc, req->sr_root, 1, /* formatting */ 0);
Matej Habrnal 5c8df3
+    if (err == -1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        xmlBufferFree(buffer);
Matej Habrnal 5c8df3
+        error_msg_and_die(_("Failed to dump xml node."));
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    puts((const char *) xmlBufferContent(buffer));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlBufferFree(buffer);
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+#endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static bool
Matej Habrnal 5c8df3
+reader_move_reader_if_node_type_is_element_with_name_and_verify_its_value(xmlTextReaderPtr reader, const char *name)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    /* is not element node */
Matej Habrnal 5c8df3
+    if (xmlTextReaderNodeType(reader) != XML_ELEMENT_NODE)
Matej Habrnal 5c8df3
+        return false;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* is not required name */
Matej Habrnal 5c8df3
+    if (xmlStrcmp(xmlTextReaderConstName(reader), BAD_CAST name) != 0)
Matej Habrnal 5c8df3
+        return false;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* read next node */
Matej Habrnal 5c8df3
+    if (xmlTextReaderRead(reader) != 1)
Matej Habrnal 5c8df3
+        return false;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* no value node */
Matej Habrnal 5c8df3
+    if (xmlTextReaderHasValue(reader) == 0)
Matej Habrnal 5c8df3
+        return false;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* no text node */
Matej Habrnal 5c8df3
+    if (xmlTextReaderNodeType(reader) != XML_TEXT_NODE)
Matej Habrnal 5c8df3
+        return false;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return true;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+reader_find_element_by_name(xmlTextReaderPtr reader, const char *name)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    while (xmlTextReaderRead(reader) == 1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        /* is not element node */
Matej Habrnal 5c8df3
+        if (xmlTextReaderNodeType(reader) != XML_ELEMENT_NODE)
Matej Habrnal 5c8df3
+            continue;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        /* is not required name */
Matej Habrnal 5c8df3
+        if (xmlStrcmp(xmlTextReaderConstName(reader), BAD_CAST name) != 0)
Matej Habrnal 5c8df3
+            continue;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        break;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+/* It is not possible to search only by name because the response contains
Matej Habrnal 5c8df3
+ * different node with the same name. (e.g. id - user id, project id, issue id etc.)
Matej Habrnal 5c8df3
+ * We are interested in only about issues id which is located at a different depth than others.
Matej Habrnal 5c8df3
+ * ...
Matej Habrnal 5c8df3
+ *   <item xsi:type="ns1:IssueData">
Matej Habrnal 5c8df3
+ *      <id xsi:type="xsd:integer">10</id>      <-- This is issue ID (required)
Matej Habrnal 5c8df3
+ *      <view_state xsi:type="ns1:ObjectRef">
Matej Habrnal 5c8df3
+ *          <id xsi:type="xsd:integer">10</id>  <-- This is view_state ID (not required)
Matej Habrnal 5c8df3
+ *          <name xsi:type="xsd:string">public</name>
Matej Habrnal 5c8df3
+ *      </view_state>
Matej Habrnal 5c8df3
+ *      <project xsi:type="ns1:ObjectRef">
Matej Habrnal 5c8df3
+ *          <id xsi:type="xsd:integer">1</id>   <-- This is project ID (not required)
Matej Habrnal 5c8df3
+ *          <name xsi:type="xsd:string">test</name>
Matej Habrnal 5c8df3
+ *      </project>
Matej Habrnal 5c8df3
+ * ...
Matej Habrnal 5c8df3
+ */
Matej Habrnal 5c8df3
+static GList *
Matej Habrnal 5c8df3
+response_values_at_depth_by_name(const char *xml, const char *name, int depth)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    xmlDocPtr doc = xmlParseDoc(BAD_CAST xml);
Matej Habrnal 5c8df3
+    if (doc == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to parse xml (searching value at depth by name)."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlTextReaderPtr reader = xmlReaderWalker(doc);
Matej Habrnal 5c8df3
+    if (reader == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to create xml text reader."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    GList *result = NULL;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const xmlChar *value;
Matej Habrnal 5c8df3
+    while (xmlTextReaderRead(reader) == 1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        /* is not right depth */
Matej Habrnal 5c8df3
+        if (depth != -1 && xmlTextReaderDepth(reader) != depth)
Matej Habrnal 5c8df3
+            continue;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (reader_move_reader_if_node_type_is_element_with_name_and_verify_its_value(reader, name) == false)
Matej Habrnal 5c8df3
+            continue;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if ((value = xmlTextReaderConstValue(reader)) != NULL)
Matej Habrnal 5c8df3
+            result = g_list_append(result, xstrdup((const char *) value));
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    xmlFreeTextReader(reader);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return result;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+/*
Matej Habrnal 5c8df3
+ * Finds an element named 'elem' and returns a text of a child named 'name'
Matej Habrnal 5c8df3
+ *
Matej Habrnal 5c8df3
+ * Example:
Matej Habrnal 5c8df3
+ *  For
Matej Habrnal 5c8df3
+ *  <elem>
Matej Habrnal 5c8df3
+ *      <id>1</id>
Matej Habrnal 5c8df3
+ *      <name>foo</name>
Matej Habrnal 5c8df3
+ *  </elem>
Matej Habrnal 5c8df3
+ *
Matej Habrnal 5c8df3
+ *  returns "foo"
Matej Habrnal 5c8df3
+ */
Matej Habrnal 5c8df3
+static char *
Matej Habrnal 5c8df3
+response_get_name_value_of_element(const char *xml, const char *element)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    xmlDocPtr doc = xmlParseDoc(BAD_CAST xml);
Matej Habrnal 5c8df3
+    if (doc == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to parse xml."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlTextReaderPtr reader = xmlReaderWalker(doc);
Matej Habrnal 5c8df3
+    if (reader == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to create xml text reader."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const xmlChar *value = NULL;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    reader_find_element_by_name(reader, element);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* find 'name' element and return its text */
Matej Habrnal 5c8df3
+    while (xmlTextReaderRead(reader) == 1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        if (reader_move_reader_if_node_type_is_element_with_name_and_verify_its_value(reader, "name") == false)
Matej Habrnal 5c8df3
+            continue;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if ((value = xmlTextReaderConstValue(reader)) != NULL)
Matej Habrnal 5c8df3
+            break;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    xmlFreeTextReader(reader);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return (char *) value;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static int
Matej Habrnal 5c8df3
+response_get_id_of_relatedto_issue(const char *xml)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    xmlDocPtr doc = xmlParseDoc(BAD_CAST xml);
Matej Habrnal 5c8df3
+    if (doc == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to parse xml (get related to issue)."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlTextReaderPtr reader = xmlReaderWalker(doc);
Matej Habrnal 5c8df3
+    if (reader == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("SOAP: Failed to create xml text reader."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const xmlChar *value = NULL;
Matej Habrnal 5c8df3
+    const xmlChar *id = NULL;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* find relationships section */
Matej Habrnal 5c8df3
+    reader_find_element_by_name(reader, "relationships");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* find "name" value of 'name' element */
Matej Habrnal 5c8df3
+    while (xmlTextReaderRead(reader) == 1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        /* find type of relattionship */
Matej Habrnal 5c8df3
+        if (reader_move_reader_if_node_type_is_element_with_name_and_verify_its_value(reader, "name") == false)
Matej Habrnal 5c8df3
+            continue;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if ((value = xmlTextReaderConstValue(reader)) == NULL)
Matej Habrnal 5c8df3
+            continue;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        /* we need 'duplicate of' realtionship type */
Matej Habrnal 5c8df3
+        if (xmlStrcmp(value, BAD_CAST "duplicate of") != 0)
Matej Habrnal 5c8df3
+            continue;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        /* find id of duplicate issues */
Matej Habrnal 5c8df3
+        reader_find_element_by_name(reader, "target_id");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        /* verify target_id node */
Matej Habrnal 5c8df3
+        if (reader_move_reader_if_node_type_is_element_with_name_and_verify_its_value(reader, "target_id") == false)
Matej Habrnal 5c8df3
+            continue;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        /* get its value */
Matej Habrnal 5c8df3
+        if ((id = xmlTextReaderConstValue(reader)) != NULL)
Matej Habrnal 5c8df3
+            break;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    xmlFreeTextReader(reader);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return (id == NULL) ? -1 : atoi((const char *) id);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+GList *
Matej Habrnal 5c8df3
+response_get_main_ids_list(const char *xml)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    return response_values_at_depth_by_name(xml, "id", 5);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+int
Matej Habrnal 5c8df3
+response_get_main_id(const char *xml)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    GList *l = response_values_at_depth_by_name(xml, "id", 5);
Matej Habrnal 5c8df3
+    return (l != NULL) ? atoi(l->data) : -1;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static int
Matej Habrnal 5c8df3
+response_get_return_value(const char *xml)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    GList *l = response_values_at_depth_by_name(xml, "return", 3);
Matej Habrnal 5c8df3
+    return (l != NULL) ? atoi(l->data) : -1;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static char*
Matej Habrnal 5c8df3
+response_get_return_value_as_string(const char *xml)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    GList *l = response_values_at_depth_by_name(xml, "return", 3);
Matej Habrnal 5c8df3
+    return (l != NULL) ? l->data : NULL;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static char *
Matej Habrnal 5c8df3
+response_get_error_msg(const char *xml)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    GList *l = response_values_at_depth_by_name(xml, "faultstring", 3);
Matej Habrnal 5c8df3
+    return (l != NULL) ? xstrdup(l->data) : NULL;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static char *
Matej Habrnal 5c8df3
+response_get_additioanl_information(const char *xml)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    GList *l = response_values_at_depth_by_name(xml, "additional_information", -1);
Matej Habrnal 5c8df3
+    return (l != NULL) ? xstrdup(l->data) : NULL;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void
Matej Habrnal 5c8df3
+response_values_free(GList *values)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    g_list_free_full(values, free);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+/*
Matej Habrnal 5c8df3
+ * POST
Matej Habrnal 5c8df3
+ */
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void
Matej Habrnal 5c8df3
+mantisbt_result_free(mantisbt_result_t *result)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (result == NULL)
Matej Habrnal 5c8df3
+        return;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    free(result->mr_url);
Matej Habrnal 5c8df3
+    free(result->mr_msg);
Matej Habrnal 5c8df3
+    free(result->mr_body);
Matej Habrnal 5c8df3
+    free(result);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+mantisbt_result_t *
Matej Habrnal 5c8df3
+mantisbt_soap_call(const mantisbt_settings_t *settings, const soap_request_t *req)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    char *request = soap_request_to_str(req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const char *url = settings->m_mantisbt_soap_url;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_t *result = xzalloc(sizeof(*result));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (url == NULL || request == NULL)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        result->mr_error = -2;
Matej Habrnal 5c8df3
+        result->mr_msg = xasprintf(_("Url or request isn't specified."));
Matej Habrnal 5c8df3
+        free(request);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        return result;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    char *url_copy = NULL;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    int redirect_count = 0;
Matej Habrnal 5c8df3
+    char *errmsg;
Matej Habrnal 5c8df3
+    post_state_t *post_state;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+redirect:
Matej Habrnal 5c8df3
+    post_state = new_post_state(0
Matej Habrnal 5c8df3
+            + POST_WANT_HEADERS
Matej Habrnal 5c8df3
+            + POST_WANT_BODY
Matej Habrnal 5c8df3
+            + POST_WANT_ERROR_MSG
Matej Habrnal 5c8df3
+            + (settings->m_ssl_verify ? POST_WANT_SSL_VERIFY : 0)
Matej Habrnal 5c8df3
+    );
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    post_string(post_state, settings->m_mantisbt_soap_url, "text/xml", NULL, request);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    char *location = find_header_in_post_state(post_state, "Location:");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    switch (post_state->http_resp_code)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+    case 404:
Matej Habrnal 5c8df3
+        result->mr_error = -1;
Matej Habrnal 5c8df3
+        result->mr_msg = xasprintf(_("Error in HTTP POST, "
Matej Habrnal 5c8df3
+                        "HTTP code: 404 (Not found), URL:'%s'"), url);
Matej Habrnal 5c8df3
+        break;
Matej Habrnal 5c8df3
+    case 500:
Matej Habrnal 5c8df3
+        result->mr_error = -1;
Matej Habrnal 5c8df3
+        result->mr_msg = response_get_error_msg(post_state->body);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        break;
Matej Habrnal 5c8df3
+    case 301: /* "301 Moved Permanently" (for example, used to move http:// to https://) */
Matej Habrnal 5c8df3
+    case 302: /* "302 Found" (just in case) */
Matej Habrnal 5c8df3
+    case 305: /* "305 Use Proxy" */
Matej Habrnal 5c8df3
+        if (++redirect_count < 10 && location)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            free(url_copy);
Matej Habrnal 5c8df3
+            url = url_copy = xstrdup(location);
Matej Habrnal 5c8df3
+            free_post_state(post_state);
Matej Habrnal 5c8df3
+            goto redirect;
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+        /* fall through */
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    default:
Matej Habrnal 5c8df3
+        result->mr_error = -1;
Matej Habrnal 5c8df3
+        errmsg = post_state->curl_error_msg;
Matej Habrnal 5c8df3
+        if (errmsg && errmsg[0])
Matej Habrnal 5c8df3
+            result->mr_msg = xasprintf(_("Error in MantisBT request at '%s': %s"), url, errmsg);
Matej Habrnal 5c8df3
+        else
Matej Habrnal 5c8df3
+            result->mr_msg = xasprintf(_("Error in MantisBT request at '%s'"), url);
Matej Habrnal 5c8df3
+        break;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    case 200:
Matej Habrnal 5c8df3
+    case 201:
Matej Habrnal 5c8df3
+        /* sent successfully */
Matej Habrnal 5c8df3
+        result->mr_url = xstrdup(location); /* note: xstrdup(NULL) returns NULL */
Matej Habrnal 5c8df3
+    } /* switch (HTTP code) */
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    result->mr_http_resp_code = post_state->http_resp_code;
Matej Habrnal 5c8df3
+    result->mr_body = post_state->body;
Matej Habrnal 5c8df3
+    post_state->body = NULL;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    free_post_state(post_state);
Matej Habrnal 5c8df3
+    free(url_copy);
Matej Habrnal 5c8df3
+    free(request);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return result;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+int
Matej Habrnal 5c8df3
+mantisbt_attach_data(const mantisbt_settings_t *settings, const char *bug_id,
Matej Habrnal 5c8df3
+                    const char *att_name, const char *data, int size)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    soap_request_t *req = soap_request_new_for_method("mc_issue_attachment_add");
Matej Habrnal 5c8df3
+    soap_request_add_credentials_parameter(req, settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "issue_id", SOAP_INTEGER, bug_id);
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "name", SOAP_STRING, att_name);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "file_type", SOAP_STRING, "text");
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "content", SOAP_BASE64, encode_base64(data, size));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_t *result = mantisbt_soap_call(settings, req);
Matej Habrnal 5c8df3
+    soap_request_free(req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (result->mr_http_resp_code != 200)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        int ret = -1;
Matej Habrnal 5c8df3
+        if (strcmp(result->mr_msg, "Duplicate filename.") == 0)
Matej Habrnal 5c8df3
+            ret = -2;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        error_msg(_("Failed to attach file: '%s'"), result->mr_msg);
Matej Habrnal 5c8df3
+        mantisbt_result_free(result);
Matej Habrnal 5c8df3
+        return ret;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    int id = response_get_return_value(result->mr_body);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_free(result);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return id;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static int
Matej Habrnal 5c8df3
+mantisbt_attach_fd(const mantisbt_settings_t *settings, const char *bug_id,
Matej Habrnal 5c8df3
+                const char *att_name, int fd)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    off_t size = lseek(fd, 0, SEEK_END);
Matej Habrnal 5c8df3
+    if (size < 0)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        perror_msg(_("Can't lseek '%s'"), att_name);
Matej Habrnal 5c8df3
+        return -1;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (size >= MANTISBT_MAX_FILE_UPLOAD_SIZE)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        error_msg(_("Can't upload '%s', it's too large (%llu bytes)"), att_name, (long long)size);
Matej Habrnal 5c8df3
+        return -1;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    lseek(fd, 0, SEEK_SET);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    char *data = xmalloc(size + 1);
Matej Habrnal 5c8df3
+    ssize_t r = full_read(fd, data, size);
Matej Habrnal 5c8df3
+    if (r < 0)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        free(data);
Matej Habrnal 5c8df3
+        perror_msg(_("Can't read '%s'"), att_name);
Matej Habrnal 5c8df3
+        return -1;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    int res = mantisbt_attach_data(settings, bug_id, att_name, data, size);
Matej Habrnal 5c8df3
+    free(data);
Matej Habrnal 5c8df3
+    return res;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+int
Matej Habrnal 5c8df3
+mantisbt_attach_file(const mantisbt_settings_t *settings, const char *bug_id,
Matej Habrnal 5c8df3
+                    const char *att_name, const char *path)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    int fd = open(path, O_RDONLY);
Matej Habrnal 5c8df3
+    if (fd < 0)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        perror_msg(_("Can't open '%s'"), path);
Matej Habrnal 5c8df3
+        return 0;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    errno = 0;
Matej Habrnal 5c8df3
+    struct stat st;
Matej Habrnal 5c8df3
+    if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode))
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        perror_msg("'%s': not a regular file", path);
Matej Habrnal 5c8df3
+        close(fd);
Matej Habrnal 5c8df3
+        return 0;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    log_debug("attaching '%s' as file", att_name);
Matej Habrnal 5c8df3
+    int ret = mantisbt_attach_fd(settings, bug_id, att_name, fd);
Matej Habrnal 5c8df3
+    close(fd);
Matej Habrnal 5c8df3
+    return ret;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+soap_filter_add_new_array_parameter(xmlNodePtr filter_node, const char *name, const char *type, const char *value)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    const char *array_type = NULL;
Matej Habrnal 5c8df3
+    if( strcmp(type, SOAP_INTEGER) == 0 )
Matej Habrnal 5c8df3
+        array_type = SOAP_INTEGERARRAY;
Matej Habrnal 5c8df3
+    else
Matej Habrnal 5c8df3
+        array_type = SOAP_STRINGARRAY;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlNodePtr filter_item = soap_node_add_child_node(filter_node, name, array_type, /* content */ NULL);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(filter_item, "item", type, value);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+soap_filter_custom_fields_add_new_item(xmlNodePtr filter_node, const char *custom_field_name, const char *value)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    xmlNodePtr item_node = soap_node_add_child_node(filter_node, "item", SOAP_FILTER_CUSTOMFIELD, /* content */ NULL);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlNodePtr field_node = soap_node_add_child_node(item_node, "field", SOAP_OBJECTREF, /* content */ NULL);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(field_node, "name", SOAP_STRING, custom_field_name);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlNodePtr value_node = soap_node_add_child_node(item_node, "value", SOAP_STRINGARRAY, /* content */ NULL);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(value_node, "item", SOAP_STRING, value);
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+GList *
Matej Habrnal 5c8df3
+mantisbt_search_by_abrt_hash(mantisbt_settings_t *settings, const char *abrt_hash)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    soap_request_t *req = soap_request_new_for_method("mc_filter_search_issues");
Matej Habrnal 5c8df3
+    soap_request_add_credentials_parameter(req, settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlNodePtr filter_node = soap_node_add_child_node(req->sr_method, "filter", SOAP_FILTER_SEARCH_DATA, /* content */ NULL);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* 'hide_status_is : -2' means, searching within all status */
Matej Habrnal 5c8df3
+    soap_filter_add_new_array_parameter(filter_node, "hide_status_id", SOAP_INTEGERARRAY, "-2");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    // custom fields
Matej Habrnal 5c8df3
+    xmlNodePtr custom_fields_node = soap_node_add_child_node(filter_node, "custom_fields", SOAP_FILTER_CUSTOMFIELD_ARRAY, /* content */ NULL);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    // custom field 'abrt_hash'
Matej Habrnal 5c8df3
+    soap_filter_custom_fields_add_new_item(custom_fields_node, "abrt_hash", abrt_hash);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "page_number", SOAP_INTEGER, "1");
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "per_page", SOAP_INTEGER, /* -1 means get all issues */ "-1");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_t *result = mantisbt_soap_call(settings, req);
Matej Habrnal 5c8df3
+    soap_request_free(req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (result->mr_error == -1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        error_msg(_("Failed to search MantisBT issue by duphash: '%s'"), result->mr_msg);
Matej Habrnal 5c8df3
+        mantisbt_result_free(result);
Matej Habrnal 5c8df3
+        return NULL;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    GList *ids = response_get_main_ids_list(result->mr_body);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return ids;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+GList *
Matej Habrnal 5c8df3
+mantisbt_search_duplicate_issues(mantisbt_settings_t *settings, const char *category,
Matej Habrnal 5c8df3
+                                     const char *version, const char *abrt_hash)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    soap_request_t *req = soap_request_new_for_method("mc_filter_search_issues");
Matej Habrnal 5c8df3
+    soap_request_add_credentials_parameter(req, settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlNodePtr filter_node = soap_node_add_child_node(req->sr_method, "filter", SOAP_FILTER_SEARCH_DATA, /* content */ NULL);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_filter_add_new_array_parameter(filter_node, "project_id", SOAP_INTEGERARRAY, settings->m_project_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* 'hide_status_is : -2' means, searching within all status */
Matej Habrnal 5c8df3
+    soap_filter_add_new_array_parameter(filter_node, "hide_status_id", SOAP_INTEGERARRAY, "-2");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_filter_add_new_array_parameter(filter_node, "category", SOAP_STRINGARRAY, category);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    // custom fields
Matej Habrnal 5c8df3
+    xmlNodePtr custom_fields_node = soap_node_add_child_node(filter_node, "custom_fields", SOAP_FILTER_CUSTOMFIELD_ARRAY, /* content */ NULL);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    // custom field 'abrt_hash'
Matej Habrnal 5c8df3
+    soap_filter_custom_fields_add_new_item(custom_fields_node, "abrt_hash", abrt_hash);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    // version
Matej Habrnal 5c8df3
+    if (version != NULL)
Matej Habrnal 5c8df3
+        soap_filter_add_new_array_parameter(filter_node, "os_build", SOAP_STRINGARRAY, version);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "page_number", SOAP_INTEGER, "1");
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "per_page", SOAP_INTEGER, /* -1 means get all issues */ "-1");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_t *result = mantisbt_soap_call(settings, req);
Matej Habrnal 5c8df3
+    soap_request_free(req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (result->mr_error == -1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        error_msg(_("Failed to search MantisBT duplicate issue: '%s'"), result->mr_msg);
Matej Habrnal 5c8df3
+        mantisbt_result_free(result);
Matej Habrnal 5c8df3
+        return NULL;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    GList *ids = response_get_main_ids_list(result->mr_body);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return ids;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static char *
Matej Habrnal 5c8df3
+custom_field_get_id_from_name(GList *ids, GList *names, const char *name)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    GList *i = ids;
Matej Habrnal 5c8df3
+    GList *n = names;
Matej Habrnal 5c8df3
+    for (; i != NULL; i = i->next, n = n->next)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        if (strcmp(n->data, name) == 0)
Matej Habrnal 5c8df3
+            return i->data;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return NULL;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+custom_field_ask(const char *name)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    char *msg = xasprintf(_("CentOS Bug Tracker doesn't contain custom field '%s', which is required for full functionality of the reporter. Do you still want to create a new issue?"), name);
Matej Habrnal 5c8df3
+    int yes = ask_yes_no(msg);
Matej Habrnal 5c8df3
+    free(msg);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (!yes)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        set_xfunc_error_retval(EXIT_CANCEL_BY_USER);
Matej Habrnal 5c8df3
+        xfunc_die();
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+mantisbt_get_custom_fields(const mantisbt_settings_t *settings, mantisbt_custom_fields_t *fields, const char *project_id)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    soap_request_t *req = soap_request_new_for_method("mc_project_get_custom_fields");
Matej Habrnal 5c8df3
+    soap_request_add_credentials_parameter(req, settings);
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "project_id", SOAP_INTEGER, project_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_t *result = mantisbt_soap_call(settings, req);
Matej Habrnal 5c8df3
+    soap_request_free(req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (result->mr_http_resp_code != 200)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("Failed to get custom fields for '%s' project"), settings->m_project);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    GList *ids = response_values_at_depth_by_name(result->mr_body, "id", -1);
Matej Habrnal 5c8df3
+    GList *names = response_values_at_depth_by_name(result->mr_body, "name", -1);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_free(result);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if ((fields->cf_abrt_hash_id = custom_field_get_id_from_name(ids, names, CUSTOMFIELD_DUPHASH)) == NULL)
Matej Habrnal 5c8df3
+        custom_field_ask(CUSTOMFIELD_DUPHASH);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if ((fields->cf_url_id = custom_field_get_id_from_name(ids, names, CUSTOMFIELD_URL)) == NULL)
Matej Habrnal 5c8df3
+        custom_field_ask(CUSTOMFIELD_URL);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+int
Matej Habrnal 5c8df3
+mantisbt_create_new_issue(const mantisbt_settings_t *settings,
Matej Habrnal 5c8df3
+                   problem_data_t *problem_data,
Matej Habrnal 5c8df3
+                   const problem_report_t *pr,
Matej Habrnal 5c8df3
+                   const char *tracker_url)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const char *category = problem_data_get_content_or_NULL(problem_data, FILENAME_COMPONENT);
Matej Habrnal 5c8df3
+    const char *duphash = problem_data_get_content_or_NULL(problem_data, FILENAME_DUPHASH);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    char *summary = shorten_string_to_length(problem_report_get_summary(pr), MAX_SUMMARY_LENGTH);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const char *description = problem_report_get_description(pr);
Matej Habrnal 5c8df3
+    const char *additional_information = problem_report_get_section(pr, PR_SEC_ADDITIONAL_INFO);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_custom_fields_t fields;
Matej Habrnal 5c8df3
+    mantisbt_get_custom_fields(settings, &fields, settings->m_project_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_request_t *req = soap_request_new_for_method("mc_issue_add");
Matej Habrnal 5c8df3
+    soap_request_add_credentials_parameter(req, settings);
Matej Habrnal 5c8df3
+    soap_add_new_issue_parameters(req, settings->m_project, settings->m_project_version, category, summary, description, additional_information, settings->m_create_private, &fields, duphash, tracker_url);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_t *result = mantisbt_soap_call(settings, req);
Matej Habrnal 5c8df3
+    soap_request_free(req);
Matej Habrnal 5c8df3
+    free(summary);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (result->mr_error == -1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        error_msg(_("Failed to create a new issue: '%s'"), result->mr_msg);
Matej Habrnal 5c8df3
+        mantisbt_result_free(result);
Matej Habrnal 5c8df3
+        return -1;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    int id = response_get_return_value(result->mr_body);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_free(result);
Matej Habrnal 5c8df3
+    return id;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+mantisbt_issue_info_t *
Matej Habrnal 5c8df3
+mantisbt_get_issue_info(const mantisbt_settings_t *settings, int issue_id)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    soap_request_t *req = soap_request_new_for_method("mc_issue_get");
Matej Habrnal 5c8df3
+    soap_request_add_credentials_parameter(req, settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    char *issue_id_str = xasprintf("%d", issue_id);
Matej Habrnal 5c8df3
+    soap_request_add_method_parameter(req, "issue_id", SOAP_INTEGER, issue_id_str);
Matej Habrnal 5c8df3
+    free(issue_id_str);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_t *result = mantisbt_soap_call(settings, req);
Matej Habrnal 5c8df3
+    soap_request_free(req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (result->mr_error == -1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        error_msg(_("Failed to get MantisBT issue: '%s'"), result->mr_msg);
Matej Habrnal 5c8df3
+        mantisbt_result_free(result);
Matej Habrnal 5c8df3
+        return NULL;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_issue_info_t *issue_info = mantisbt_issue_info_new();
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    issue_info->mii_id = issue_id;
Matej Habrnal 5c8df3
+    issue_info->mii_status = response_get_name_value_of_element(result->mr_body, "status");
Matej Habrnal 5c8df3
+    issue_info->mii_resolution = response_get_name_value_of_element(result->mr_body, "resolution");
Matej Habrnal 5c8df3
+    issue_info->mii_reporter = response_get_name_value_of_element(result->mr_body, "reporter");
Matej Habrnal 5c8df3
+    issue_info->mii_project = response_get_name_value_of_element(result->mr_body, "project");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (strcmp(issue_info->mii_status, "closed") == 0 && !issue_info->mii_resolution)
Matej Habrnal 5c8df3
+        error_msg(_("Issue %i is CLOSED, but it has no RESOLUTION"), issue_info->mii_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    issue_info->mii_dup_id = response_get_id_of_relatedto_issue(result->mr_body);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (strcmp(issue_info->mii_status, "closed") == 0
Matej Habrnal 5c8df3
+        && strcmp(issue_info->mii_resolution, "duplicate") == 0
Matej Habrnal 5c8df3
+        && issue_info->mii_dup_id == -1 )
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        error_msg(_("Issue %i is CLOSED as DUPLICATE, but it has no DUPLICATE_ID"),
Matej Habrnal 5c8df3
+                            issue_info->mii_id);
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* notes are stored in <text> element */
Matej Habrnal 5c8df3
+    issue_info->mii_notes = response_values_at_depth_by_name(result->mr_body, "text", -1);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* looking for bt rating in additional information too */
Matej Habrnal 5c8df3
+    char *add_info = response_get_additioanl_information(result->mr_body);
Matej Habrnal 5c8df3
+    if (add_info != NULL)
Matej Habrnal 5c8df3
+        issue_info->mii_notes = g_list_append (issue_info->mii_notes, add_info);
Matej Habrnal 5c8df3
+    issue_info->mii_attachments = response_values_at_depth_by_name(result->mr_body, "filename", -1);
Matej Habrnal 5c8df3
+    issue_info->mii_best_bt_rating = comments_find_best_bt_rating(issue_info->mii_notes);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_free(result);
Matej Habrnal 5c8df3
+    return issue_info;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+int
Matej Habrnal 5c8df3
+mantisbt_add_issue_note(const mantisbt_settings_t *settings, int issue_id, const char *note)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    soap_request_t *req = soap_request_new_for_method("mc_issue_note_add");
Matej Habrnal 5c8df3
+    soap_request_add_credentials_parameter(req, settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    char *issue_id_str = xasprintf("%i", issue_id);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(req->sr_method, "issue_id", SOAP_INTEGER, issue_id_str);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    xmlNodePtr note_node = soap_node_add_child_node(req->sr_method, "note", SOAP_ISSUENOTE, /* content */ NULL);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(note_node, "text", SOAP_STRING, note);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_t *result = mantisbt_soap_call(settings, req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    free(issue_id_str);
Matej Habrnal 5c8df3
+    soap_request_free(req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (result->mr_error == -1)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        error_msg(_("Failed to add MantisBT issue note: '%s'"), result->mr_msg);
Matej Habrnal 5c8df3
+        mantisbt_result_free(result);
Matej Habrnal 5c8df3
+        return -1;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    int id = response_get_return_value(result->mr_body);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_free(result);
Matej Habrnal 5c8df3
+    return id;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void
Matej Habrnal 5c8df3
+mantisbt_get_project_id_from_name(mantisbt_settings_t *settings)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (settings->m_project == NULL)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("The MantisBT project has not been deretmined."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    soap_request_t *req = soap_request_new_for_method("mc_project_get_id_from_name");
Matej Habrnal 5c8df3
+    soap_request_add_credentials_parameter(req, settings);
Matej Habrnal 5c8df3
+    soap_node_add_child_node(req->sr_method, "project_name", SOAP_STRING, settings->m_project);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_result_t *result = mantisbt_soap_call(settings, req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (result->mr_http_resp_code != 200)
Matej Habrnal 5c8df3
+        error_msg_and_die(_("Failed to get project id from name"));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    settings->m_project_id = response_get_return_value_as_string(result->mr_body);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
diff --git a/src/plugins/mantisbt.conf b/src/plugins/mantisbt.conf
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..15a1065
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/plugins/mantisbt.conf
Matej Habrnal 5c8df3
@@ -0,0 +1,8 @@
Matej Habrnal 5c8df3
+# MantisBT URL
Matej Habrnal 5c8df3
+MantisbtURL = https://bugs.centos.org/
Matej Habrnal 5c8df3
+# yes means that ssl certificates will be checked
Matej Habrnal 5c8df3
+SSLVerify = yes
Matej Habrnal 5c8df3
+# your login has to exist, if you don have any, please create one
Matej Habrnal 5c8df3
+Login =
Matej Habrnal 5c8df3
+# your password
Matej Habrnal 5c8df3
+Password =
Matej Habrnal 5c8df3
diff --git a/src/plugins/mantisbt.h b/src/plugins/mantisbt.h
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..c31c174
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/plugins/mantisbt.h
Matej Habrnal 5c8df3
@@ -0,0 +1,140 @@
Matej Habrnal 5c8df3
+/*
Matej Habrnal 5c8df3
+    Copyright (C) 2014  ABRT team
Matej Habrnal 5c8df3
+    Copyright (C) 2014  RedHat Inc
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    This program is free software; you can redistribute it and/or modify
Matej Habrnal 5c8df3
+    it under the terms of the GNU General Public License as published by
Matej Habrnal 5c8df3
+    the Free Software Foundation; either version 2 of the License, or
Matej Habrnal 5c8df3
+    (at your option) any later version.
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    This program is distributed in the hope that it will be useful,
Matej Habrnal 5c8df3
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
Matej Habrnal 5c8df3
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Matej Habrnal 5c8df3
+    GNU General Public License for more details.
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    You should have received a copy of the GNU General Public License along
Matej Habrnal 5c8df3
+    with this program; if not, write to the Free Software Foundation, Inc.,
Matej Habrnal 5c8df3
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Matej Habrnal 5c8df3
+*/
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#ifndef MANTISBT_H
Matej Habrnal 5c8df3
+#define MANTISBT_H
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#ifdef __cplusplus
Matej Habrnal 5c8df3
+extern "C" {
Matej Habrnal 5c8df3
+#endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#include <libxml/encoding.h>
Matej Habrnal 5c8df3
+#include "problem_report.h"
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#define SOAP_STRING "ns2:string"
Matej Habrnal 5c8df3
+#define SOAP_INTEGER "ns2:integer"
Matej Habrnal 5c8df3
+#define SOAP_INTEGERARRAY "ns2:IntegerArray"
Matej Habrnal 5c8df3
+#define SOAP_STRINGARRAY "ns2:StringArray"
Matej Habrnal 5c8df3
+#define SOAP_ISSUEDATA "ns3:IssueData"
Matej Habrnal 5c8df3
+#define SOAP_OBJECTREF "ns3:ObjectRef"
Matej Habrnal 5c8df3
+#define SOAP_CUSTOMFIELD_ARRAY "ns2:CustomFieldValueForIssueDataArray"
Matej Habrnal 5c8df3
+#define SOAP_FILTER_CUSTOMFIELD "ns2:FilterCustomField"
Matej Habrnal 5c8df3
+#define SOAP_FILTER_CUSTOMFIELD_ARRAY "ns2:FilterCustomFieldArray"
Matej Habrnal 5c8df3
+#define SOAP_FILTER_SEARCH_DATA "ns2:FilterSearchData"
Matej Habrnal 5c8df3
+#define SOAP_CUSTOMFIELD "ns2:CustomFieldValueForIssueData"
Matej Habrnal 5c8df3
+#define SOAP_BASE64 "SOAP-ENC:base64"
Matej Habrnal 5c8df3
+#define SOAP_ISSUENOTE "ns3:IssueNoteData"
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#define PR_SEC_ADDITIONAL_INFO "Additional info"
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+typedef struct soap_request
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    xmlNodePtr sr_root;
Matej Habrnal 5c8df3
+    xmlNodePtr sr_body;
Matej Habrnal 5c8df3
+    xmlNodePtr sr_method;
Matej Habrnal 5c8df3
+} soap_request_t;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+typedef struct mantisbt_settings
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    char *m_login;
Matej Habrnal 5c8df3
+    char *m_password;
Matej Habrnal 5c8df3
+    const char *m_mantisbt_url;
Matej Habrnal 5c8df3
+    const char *m_mantisbt_soap_url;
Matej Habrnal 5c8df3
+    char *m_project;
Matej Habrnal 5c8df3
+    char *m_project_id;
Matej Habrnal 5c8df3
+    char *m_project_version;
Matej Habrnal 5c8df3
+    const char *m_DontMatchComponents;
Matej Habrnal 5c8df3
+    int         m_ssl_verify;
Matej Habrnal 5c8df3
+    int         m_create_private;
Matej Habrnal 5c8df3
+} mantisbt_settings_t;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+typedef struct mantisbt_result
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    int mr_http_resp_code;
Matej Habrnal 5c8df3
+    int mr_error;
Matej Habrnal 5c8df3
+    char *mr_msg;
Matej Habrnal 5c8df3
+    char *mr_url;
Matej Habrnal 5c8df3
+    char *mr_body;
Matej Habrnal 5c8df3
+} mantisbt_result_t;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+typedef struct mantisbt_issue_info
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    int mii_id;
Matej Habrnal 5c8df3
+    int mii_dup_id;
Matej Habrnal 5c8df3
+    unsigned mii_best_bt_rating;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    char *mii_status;
Matej Habrnal 5c8df3
+    char *mii_resolution;
Matej Habrnal 5c8df3
+    char *mii_reporter;
Matej Habrnal 5c8df3
+    char *mii_project;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    GList *mii_notes;
Matej Habrnal 5c8df3
+    GList *mii_attachments;
Matej Habrnal 5c8df3
+} mantisbt_issue_info_t;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void mantisbt_settings_free(mantisbt_settings_t *settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+mantisbt_issue_info_t * mantisbt_issue_info_new();
Matej Habrnal 5c8df3
+void mantisbt_issue_info_free(mantisbt_issue_info_t *info);
Matej Habrnal 5c8df3
+mantisbt_issue_info_t * mantisbt_find_origin_bug_closed_duplicate(mantisbt_settings_t *settings, mantisbt_issue_info_t *info);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void soap_request_free(soap_request_t *req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+soap_request_t *soap_request_new_for_method(const char *method);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void soap_request_add_method_parameter(soap_request_t *req, const char *name, const char *type, const char *value);
Matej Habrnal 5c8df3
+void soap_request_add_credentials_parameter(soap_request_t *req, const mantisbt_settings_t *settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+char *soap_request_to_str(const soap_request_t *req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#if 0
Matej Habrnal 5c8df3
+void soap_request_print(soap_request_t *req);
Matej Habrnal 5c8df3
+#endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+GList * response_get_main_ids_list(const char *xml);
Matej Habrnal 5c8df3
+int response_get_main_id(const char *xml);
Matej Habrnal 5c8df3
+void response_values_free(GList *values);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void mantisbt_result_free(mantisbt_result_t *result);
Matej Habrnal 5c8df3
+mantisbt_result_t *mantisbt_soap_call(const mantisbt_settings_t *settings, const soap_request_t *req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+int mantisbt_attach_data(const mantisbt_settings_t *settings, const char *bug_id,
Matej Habrnal 5c8df3
+                         const char *att_name, const char *data, int size);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+int mantisbt_attach_file(const mantisbt_settings_t *settings, const char *bug_id,
Matej Habrnal 5c8df3
+                    const char *att_name, const char *data);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+GList * mantisbt_search_by_abrt_hash(mantisbt_settings_t *settings, const char *abrt_hash);
Matej Habrnal 5c8df3
+GList * mantisbt_search_duplicate_issues(mantisbt_settings_t *settings, const char *category,
Matej Habrnal 5c8df3
+                    const char *version, const char *abrt_hash);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+int mantisbt_create_new_issue(const mantisbt_settings_t *settings, problem_data_t *problem_data,
Matej Habrnal 5c8df3
+                       const problem_report_t *pr, const char *tracker_url);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+mantisbt_issue_info_t * mantisbt_get_issue_info(const mantisbt_settings_t *settings, int issue_id);
Matej Habrnal 5c8df3
+int mantisbt_add_issue_note(const mantisbt_settings_t *settings, int issue_id, const char *note);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+void mantisbt_get_project_id_from_name(mantisbt_settings_t *settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#ifdef __cplusplus
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+#endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
diff --git a/src/plugins/mantisbt_format.conf b/src/plugins/mantisbt_format.conf
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..da08aa6
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/plugins/mantisbt_format.conf
Matej Habrnal 5c8df3
@@ -0,0 +1,59 @@
Matej Habrnal 5c8df3
+# Lines starting with # are ignored.
Matej Habrnal 5c8df3
+# Lines can be continued on the next line using trailing backslash.
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+# Format:
Matej Habrnal 5c8df3
+# %summary:: summary format
Matej Habrnal 5c8df3
+# section:: element1[,element2]...
Matej Habrnal 5c8df3
+# The literal text line to be added to Bugzilla comment. Can be empty.
Matej Habrnal 5c8df3
+# (IOW: empty lines are NOT ignored!)
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+# Summary format is a line of text, where %element% is replaced by
Matej Habrnal 5c8df3
+# text element's content, and [[...%element%...]] block is used only if
Matej Habrnal 5c8df3
+# %element% exists. [[...]] blocks can nest.
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+# Sections can be:
Matej Habrnal 5c8df3
+# - %summary: bug summary format string.
Matej Habrnal 5c8df3
+# - %attach: a list of elements to attach.
Matej Habrnal 5c8df3
+# - text, double colon (::) and the list of comma-separated elements.
Matej Habrnal 5c8df3
+#   Text can be empty (":: elem1, elem2, elem3" works),
Matej Habrnal 5c8df3
+#   in this case "Text:" header line will be omitted.
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+# Elements can be:
Matej Habrnal 5c8df3
+# - problem directory element names, which get formatted as
Matej Habrnal 5c8df3
+#   <element_name>: <contents>
Matej Habrnal 5c8df3
+#   or
Matej Habrnal 5c8df3
+#   <element_name>:
Matej Habrnal 5c8df3
+#   :<contents>
Matej Habrnal 5c8df3
+#   :<contents>
Matej Habrnal 5c8df3
+#   :<contents>
Matej Habrnal 5c8df3
+# - problem directory element names prefixed by "%bare_",
Matej Habrnal 5c8df3
+#   which is formatted as-is, without "<element_name>:" and colons
Matej Habrnal 5c8df3
+# - %oneline, %multiline, %text wildcards, which select all corresponding
Matej Habrnal 5c8df3
+#   elements for output or attachment
Matej Habrnal 5c8df3
+# - %binary wildcard, valid only for %attach section, instructs to attach
Matej Habrnal 5c8df3
+#   binary elements
Matej Habrnal 5c8df3
+# - problem directory element names prefixed by "-",
Matej Habrnal 5c8df3
+#   which excludes given element from all wildcards
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+#   Nonexistent elements are silently ignored.
Matej Habrnal 5c8df3
+#   If none of elements exists, the section will not be created.
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+%summary:: [abrt] %pkg_name%[[: %crash_function%()]][[: %reason%]][[: TAINTED %tainted_short%]]
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+Description of problem:: %bare_comment
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+Version-Release number of selected component:: %bare_package
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+Truncated backtrace:: %bare_%short_backtrace
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+%Additional info::
Matej Habrnal 5c8df3
+:: -pkg_arch,-pkg_epoch,-pkg_name,-pkg_release,-pkg_version,\
Matej Habrnal 5c8df3
+		-component,-architecture,\
Matej Habrnal 5c8df3
+	-analyzer,-count,-duphash,-uuid,-abrt_version,\
Matej Habrnal 5c8df3
+	-username,-hostname,-os_release,-os_info,\
Matej Habrnal 5c8df3
+	-time,-pid,-pwd,-last_occurrence,-ureports_counter,\
Matej Habrnal 5c8df3
+	%reporter,\
Matej Habrnal 5c8df3
+	%oneline
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+%attach:: -comment,-reason,-reported_to,-event_log,%multiline,\
Matej Habrnal 5c8df3
+	-coredump,%binary
Matej Habrnal 5c8df3
diff --git a/src/plugins/mantisbt_formatdup.conf b/src/plugins/mantisbt_formatdup.conf
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..b1552ac
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/plugins/mantisbt_formatdup.conf
Matej Habrnal 5c8df3
@@ -0,0 +1,65 @@
Matej Habrnal 5c8df3
+# Lines starting with # are ignored.
Matej Habrnal 5c8df3
+# Lines can be continued on the next line using trailing backslash.
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+# Format:
Matej Habrnal 5c8df3
+# %summary:: summary format
Matej Habrnal 5c8df3
+# section:: element1[,element2]...
Matej Habrnal 5c8df3
+# The literal text line to be added to Bugzilla comment. Can be empty.
Matej Habrnal 5c8df3
+# (IOW: empty lines are NOT ignored!)
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+# Summary format is a line of text, where %element% is replaced by
Matej Habrnal 5c8df3
+# text element's content, and [[...%element%...]] block is used only if
Matej Habrnal 5c8df3
+# %element% exists. [[...]] blocks can nest.
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+# Sections can be:
Matej Habrnal 5c8df3
+# - %summary: bug summary format string.
Matej Habrnal 5c8df3
+# - %attach: a list of elements to attach.
Matej Habrnal 5c8df3
+# - text, double colon (::) and the list of comma-separated elements.
Matej Habrnal 5c8df3
+#   Text can be empty (":: elem1, elem2, elem3" works),
Matej Habrnal 5c8df3
+#   in this case "Text:" header line will be omitted.
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+# Elements can be:
Matej Habrnal 5c8df3
+# - problem directory element names, which get formatted as
Matej Habrnal 5c8df3
+#   <element_name>: <contents>
Matej Habrnal 5c8df3
+#   or
Matej Habrnal 5c8df3
+#   <element_name>:
Matej Habrnal 5c8df3
+#   :<contents>
Matej Habrnal 5c8df3
+#   :<contents>
Matej Habrnal 5c8df3
+#   :<contents>
Matej Habrnal 5c8df3
+# - problem directory element names prefixed by "%bare_",
Matej Habrnal 5c8df3
+#   which is formatted as-is, without "<element_name>:" and colons
Matej Habrnal 5c8df3
+# - %oneline, %multiline, %text wildcards, which select all corresponding
Matej Habrnal 5c8df3
+#   elements for output or attachment
Matej Habrnal 5c8df3
+# - %binary wildcard, valid only for %attach section, instructs to attach
Matej Habrnal 5c8df3
+#   binary elements
Matej Habrnal 5c8df3
+# - problem directory element names prefixed by "-",
Matej Habrnal 5c8df3
+#   which excludes given element from all wildcards
Matej Habrnal 5c8df3
+#
Matej Habrnal 5c8df3
+#   Nonexistent elements are silently ignored.
Matej Habrnal 5c8df3
+#   If none of elements exists, the section will not be created.
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+# When we add a comment to an existing BZ, %summary is ignored
Matej Habrnal 5c8df3
+# (it specifies *new bug* summary field):
Matej Habrnal 5c8df3
+# %summary:: blah blah
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+# When dup is detected, BZ reporter adds a comment to it.
Matej Habrnal 5c8df3
+# This comment may interrupt an ongoing conversation in the BZ.
Matej Habrnal 5c8df3
+# (Three people independently filed a bug against abrt about this).
Matej Habrnal 5c8df3
+# Need to clearly explain what this comment is, to prevent confusion.
Matej Habrnal 5c8df3
+# Hopefully, this line would suffice:
Matej Habrnal 5c8df3
+Another user experienced a similar problem:
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+# If user filled out comment field, show it:
Matej Habrnal 5c8df3
+:: %bare_comment
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+# var_log_messages has too much variance (time/date),
Matej Habrnal 5c8df3
+# we exclude it from message so that dup message elimination has more chances to work
Matej Habrnal 5c8df3
+:: \
Matej Habrnal 5c8df3
+	-pkg_arch,-pkg_epoch,-pkg_name,-pkg_release,-pkg_version,\
Matej Habrnal 5c8df3
+		-component,-architecture,\
Matej Habrnal 5c8df3
+	-analyzer,-count,-duphash,-uuid,-abrt_version,\
Matej Habrnal 5c8df3
+	-username,-hostname,-os_release,-os_info,\
Matej Habrnal 5c8df3
+	-time,-pid,-pwd,-last_occurrence,-ureports_counter,\
Matej Habrnal 5c8df3
+	-var_log_messages,\
Matej Habrnal 5c8df3
+	%reporter,\
Matej Habrnal 5c8df3
+	%oneline
Matej Habrnal 5c8df3
diff --git a/src/plugins/report_CentOSBugTracker.conf b/src/plugins/report_CentOSBugTracker.conf
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..04cab13
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/plugins/report_CentOSBugTracker.conf
Matej Habrnal 5c8df3
@@ -0,0 +1,4 @@
Matej Habrnal 5c8df3
+Mantisbt_MantisbtURL = https://bugs.centos.org
Matej Habrnal 5c8df3
+Mantisbt_Login =
Matej Habrnal 5c8df3
+Mantisbt_Password
Matej Habrnal 5c8df3
+Mantisbt_SSLVerify = yes
Matej Habrnal 5c8df3
diff --git a/src/plugins/report_CentOSBugTracker.xml.in b/src/plugins/report_CentOSBugTracker.xml.in
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..81f909b
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/plugins/report_CentOSBugTracker.xml.in
Matej Habrnal 5c8df3
@@ -0,0 +1,65 @@
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+<event>
Matej Habrnal 5c8df3
+    <_name>CentOS Bug Tracker</_name>
Matej Habrnal 5c8df3
+    <_description>Report to CentOS Bug Tracker</_description>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <requires-items>component,duphash,os_release</requires-items>
Matej Habrnal 5c8df3
+    <exclude-items-by-default>coredump,count,event_log,reported_to,vmcore</exclude-items-by-default>
Matej Habrnal 5c8df3
+    <exclude-items-always></exclude-items-always>
Matej Habrnal 5c8df3
+    <exclude-binary-items>no</exclude-binary-items>
Matej Habrnal 5c8df3
+    <include-items-by-default></include-items-by-default>
Matej Habrnal 5c8df3
+    <minimal-rating>3</minimal-rating>
Matej Habrnal 5c8df3
+    <gui-review-elements>yes</gui-review-elements>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <options>
Matej Habrnal 5c8df3
+        <option type="text" name="Mantisbt_Login">
Matej Habrnal 5c8df3
+            <_label>User name</_label>
Matej Habrnal 5c8df3
+            <allow-empty>no</allow-empty>
Matej Habrnal 5c8df3
+            <_description>CentOS Bug Tracker account user name</_description>
Matej Habrnal 5c8df3
+            <_note-html>You can create bugs.centos.org account <a href="https://bugs.centos.org/signup_page.php">here</a></_note-html>
Matej Habrnal 5c8df3
+        </option>
Matej Habrnal 5c8df3
+        <option type="password" name="Mantisbt_Password">
Matej Habrnal 5c8df3
+            <_label>Password</_label>
Matej Habrnal 5c8df3
+            <allow-empty>no</allow-empty>
Matej Habrnal 5c8df3
+            <_description>CentOS Bug Tracker account password</_description>
Matej Habrnal 5c8df3
+        </option>
Matej Habrnal 5c8df3
+        <advanced-options>
Matej Habrnal 5c8df3
+            <option type="text" name="Mantisbt_MantisbtURL">
Matej Habrnal 5c8df3
+                <_label>CentOS Bug Tracker URL</_label>
Matej Habrnal 5c8df3
+                <allow-empty>no</allow-empty>
Matej Habrnal 5c8df3
+                <_note-html>Address of CentOS Bug Tracker server</_note-html>
Matej Habrnal 5c8df3
+                <default-value>https://bugs.centos.org</default-value>
Matej Habrnal 5c8df3
+            </option>
Matej Habrnal 5c8df3
+            <option type="bool" name="Mantisbt_SSLVerify">
Matej Habrnal 5c8df3
+                <_label>Verify SSL</_label>
Matej Habrnal 5c8df3
+                <_note-html>Check SSL key validity</_note-html>
Matej Habrnal 5c8df3
+                <default-value>yes</default-value>
Matej Habrnal 5c8df3
+            </option>
Matej Habrnal 5c8df3
+            <option type="text" name="Mantisbt_Project">
Matej Habrnal 5c8df3
+                <_label>CentOS Bug Tracker project</_label>
Matej Habrnal 5c8df3
+                <allow-empty>yes</allow-empty>
Matej Habrnal 5c8df3
+                <_note-html>Specify this only if you needed different project than specified in /etc/os-release</_note-html>
Matej Habrnal 5c8df3
+            </option>
Matej Habrnal 5c8df3
+            <option type="text" name="Mantisbt_ProjectVersion">
Matej Habrnal 5c8df3
+                <_label>CentOS Bug Tracker project version</_label>
Matej Habrnal 5c8df3
+                <allow-empty>yes</allow-empty>
Matej Habrnal 5c8df3
+                <_note-html>Specify this only if you needed different project version than specified in /etc/os-release</_note-html>
Matej Habrnal 5c8df3
+            </option>
Matej Habrnal 5c8df3
+            <option type="text" name="http_proxy">
Matej Habrnal 5c8df3
+                <_label>HTTP Proxy</_label>
Matej Habrnal 5c8df3
+                <allow-empty>yes</allow-empty>
Matej Habrnal 5c8df3
+                <_note-html>Sets the proxy server to use for HTTP</_note-html>
Matej Habrnal 5c8df3
+            </option>
Matej Habrnal 5c8df3
+            <option type="text" name="HTTPS_PROXY">
Matej Habrnal 5c8df3
+                <_label>HTTPS Proxy</_label>
Matej Habrnal 5c8df3
+                <allow-empty>yes</allow-empty>
Matej Habrnal 5c8df3
+                <_note-html>Sets the proxy server to use for HTTPS</_note-html>
Matej Habrnal 5c8df3
+            </option>
Matej Habrnal 5c8df3
+            <option type="bool" name="Mantisbt_CreatePrivate">
Matej Habrnal 5c8df3
+                <_label>Restrict access</_label>
Matej Habrnal 5c8df3
+                <_note-html>Restrict access to the created CentOS Bug Tracker issue allowing only users from specified groups to view it (see advanced settings for more details)</_note-html>
Matej Habrnal 5c8df3
+                <default-value>no</default-value>
Matej Habrnal 5c8df3
+            </option>
Matej Habrnal 5c8df3
+        </advanced-options>
Matej Habrnal 5c8df3
+    </options>
Matej Habrnal 5c8df3
+</event>
Matej Habrnal 5c8df3
diff --git a/src/plugins/reporter-mantisbt.c b/src/plugins/reporter-mantisbt.c
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..d281cdb
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/plugins/reporter-mantisbt.c
Matej Habrnal 5c8df3
@@ -0,0 +1,696 @@
Matej Habrnal 5c8df3
+/*
Matej Habrnal 5c8df3
+    Copyright (C) 2014  ABRT team
Matej Habrnal 5c8df3
+    Copyright (C) 2014  RedHat Inc
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    This program is free software; you can redistribute it and/or modify
Matej Habrnal 5c8df3
+    it under the terms of the GNU General Public License as published by
Matej Habrnal 5c8df3
+    the Free Software Foundation; either version 2 of the License, or
Matej Habrnal 5c8df3
+    (at your option) any later version.
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    This program is distributed in the hope that it will be useful,
Matej Habrnal 5c8df3
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
Matej Habrnal 5c8df3
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Matej Habrnal 5c8df3
+    GNU General Public License for more details.
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    You should have received a copy of the GNU General Public License along
Matej Habrnal 5c8df3
+    with this program; if not, write to the Free Software Foundation, Inc., 51
Matej Habrnal 5c8df3
+    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Matej Habrnal 5c8df3
+*/
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+#include "internal_libreport.h"
Matej Habrnal 5c8df3
+#include "client.h"
Matej Habrnal 5c8df3
+#include "mantisbt.h"
Matej Habrnal 5c8df3
+#include "problem_report.h"
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+parse_osinfo_for_mantisbt(map_string_t *osinfo, char** project, char** version)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    const char *name = get_map_string_item_or_NULL(osinfo, "CENTOS_MANTISBT_PROJECT");
Matej Habrnal 5c8df3
+    if (!name)
Matej Habrnal 5c8df3
+        name = get_map_string_item_or_NULL(osinfo, OSINFO_NAME);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const char *version_id = get_map_string_item_or_NULL(osinfo, "CENTOS_MANTISBT_PROJECT_VERSION");
Matej Habrnal 5c8df3
+    if (!version_id)
Matej Habrnal 5c8df3
+        version_id = get_map_string_item_or_NULL(osinfo, OSINFO_VERSION_ID);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (name && version_id)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        *project = xstrdup(name);
Matej Habrnal 5c8df3
+        *version = xstrdup(version_id);
Matej Habrnal 5c8df3
+        return;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* something bad happend */
Matej Habrnal 5c8df3
+    *project = NULL;
Matej Habrnal 5c8df3
+    *version = NULL;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static char *
Matej Habrnal 5c8df3
+ask_mantisbt_login(const char *message)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    char *login = ask(message);
Matej Habrnal 5c8df3
+    if (login == NULL || login[0] == '\0')
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        set_xfunc_error_retval(EXIT_CANCEL_BY_USER);
Matej Habrnal 5c8df3
+        error_msg_and_die(_("Can't continue without login"));
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return login;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static char *
Matej Habrnal 5c8df3
+ask_mantisbt_password(const char *message)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    char *password = ask_password(message);
Matej Habrnal 5c8df3
+    /* TODO: this should be fixed in ask_password() as other tools have the same problem */
Matej Habrnal 5c8df3
+    putchar('\n');
Matej Habrnal 5c8df3
+    if (password == NULL || password[0] == '\0')
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        set_xfunc_error_retval(EXIT_CANCEL_BY_USER);
Matej Habrnal 5c8df3
+        error_msg_and_die(_("Can't continue without password"));
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return password;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+ask_mantisbt_credentials(mantisbt_settings_t *settings, const char *pre_message)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    free(settings->m_login);
Matej Habrnal 5c8df3
+    free(settings->m_password);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    char *question = xasprintf("%s %s", pre_message, _("Please enter your CentOS Bug Tracker login:"));
Matej Habrnal 5c8df3
+    settings->m_login = ask_mantisbt_login(question);
Matej Habrnal 5c8df3
+    free(question);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    question = xasprintf("%s %s '%s':", pre_message, _("Please enter the password for"), settings->m_login);
Matej Habrnal 5c8df3
+    settings->m_password = ask_mantisbt_password(question);
Matej Habrnal 5c8df3
+    free(question);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    return;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+verify_credentials(mantisbt_settings_t *settings)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    if (settings->m_login[0] == '\0' || settings->m_password[0] == '\0')
Matej Habrnal 5c8df3
+        ask_mantisbt_credentials(settings, _("Credentials are not provided by configuration."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    while (true)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        soap_request_t *req = soap_request_new_for_method("mc_login");
Matej Habrnal 5c8df3
+        soap_request_add_credentials_parameter(req, settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        mantisbt_result_t *result = mantisbt_soap_call(settings, req);
Matej Habrnal 5c8df3
+        soap_request_free(req);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (g_verbose > 2)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            GList *ids = response_get_main_ids_list(result->mr_body);
Matej Habrnal 5c8df3
+            if (ids != NULL)
Matej Habrnal 5c8df3
+                log("%s", (char *)ids->data);
Matej Habrnal 5c8df3
+            response_values_free(ids);
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        int result_val = result->mr_http_resp_code;
Matej Habrnal 5c8df3
+        mantisbt_result_free(result);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (result_val == 200)
Matej Habrnal 5c8df3
+            return;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        ask_mantisbt_credentials(settings, _("Invalid password or login."));
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+static void
Matej Habrnal 5c8df3
+set_settings(mantisbt_settings_t *m, map_string_t *settings, struct dump_dir *dd)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    const char *environ;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    environ = getenv("Mantisbt_Login");
Matej Habrnal 5c8df3
+    m->m_login = xstrdup(environ ? environ : get_map_string_item_or_empty(settings, "Login"));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    environ = getenv("Mantisbt_Password");
Matej Habrnal 5c8df3
+    m->m_password = xstrdup(environ ? environ : get_map_string_item_or_empty(settings, "Password"));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    environ = getenv("Mantisbt_MantisbtURL");
Matej Habrnal 5c8df3
+    m->m_mantisbt_url = environ ? environ : get_map_string_item_or_empty(settings, "MantisbtURL");
Matej Habrnal 5c8df3
+    if (!m->m_mantisbt_url[0])
Matej Habrnal 5c8df3
+        m->m_mantisbt_url = "https://bugs.centos.org/";
Matej Habrnal 5c8df3
+    else
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        /* We don't want trailing '/': "https://host/dir/" -> "https://host/dir" */
Matej Habrnal 5c8df3
+        char *last_slash = strrchr(m->m_mantisbt_url, '/');
Matej Habrnal 5c8df3
+        if (last_slash && last_slash[1] == '\0')
Matej Habrnal 5c8df3
+            *last_slash = '\0';
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    m->m_mantisbt_soap_url = concat_path_file(m->m_mantisbt_url, "api/soap/mantisconnect.php");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    environ = getenv("Mantisbt_Project");
Matej Habrnal 5c8df3
+    if (environ)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        m->m_project = xstrdup(environ);
Matej Habrnal 5c8df3
+        environ = getenv("Mantisbt_ProjectVersion");
Matej Habrnal 5c8df3
+        if (environ)
Matej Habrnal 5c8df3
+            m->m_project_version = xstrdup(environ);
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    else
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        const char *option = get_map_string_item_or_NULL(settings, "Project");
Matej Habrnal 5c8df3
+        if (option)
Matej Habrnal 5c8df3
+            m->m_project = xstrdup(option);
Matej Habrnal 5c8df3
+        option = get_map_string_item_or_NULL(settings, "ProjectVersion");
Matej Habrnal 5c8df3
+        if (option)
Matej Habrnal 5c8df3
+            m->m_project_version = xstrdup(option);
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (!m->m_project || !*m->m_project) /* if not overridden or empty... */
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        free(m->m_project);
Matej Habrnal 5c8df3
+        free(m->m_project_version);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (dd != NULL)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            map_string_t *osinfo = new_map_string();
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            char *os_info_data = dd_load_text(dd, FILENAME_OS_INFO);
Matej Habrnal 5c8df3
+            parse_osinfo(os_info_data, osinfo);
Matej Habrnal 5c8df3
+            free(os_info_data);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            parse_osinfo_for_mantisbt(osinfo, &m->m_project, &m->m_project_version);
Matej Habrnal 5c8df3
+            free_map_string(osinfo);
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    environ = getenv("Mantisbt_SSLVerify");
Matej Habrnal 5c8df3
+    m->m_ssl_verify = string_to_bool(environ ? environ : get_map_string_item_or_empty(settings, "SSLVerify"));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    environ = getenv("Mantisbt_DontMatchComponents");
Matej Habrnal 5c8df3
+    m->m_DontMatchComponents = environ ? environ : get_map_string_item_or_empty(settings, "DontMatchComponents");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    environ = getenv(CREATE_PRIVATE_TICKET);
Matej Habrnal 5c8df3
+    if (environ)
Matej Habrnal 5c8df3
+        m->m_create_private = string_to_bool(environ);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (!m->m_create_private)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        environ = getenv("Mantisbt_CreatePrivate");
Matej Habrnal 5c8df3
+        m->m_create_private = string_to_bool(environ ? environ : get_map_string_item_or_empty(settings, "CreatePrivate"));
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+    log_notice("create private CentOS Bug Tracker ticket: '%s'", m->m_create_private ? "YES": "NO");
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+int main(int argc, char **argv)
Matej Habrnal 5c8df3
+{
Matej Habrnal 5c8df3
+    abrt_init(argv);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* I18n */
Matej Habrnal 5c8df3
+    setlocale(LC_ALL, "");
Matej Habrnal 5c8df3
+#if ENABLE_NLS
Matej Habrnal 5c8df3
+    bindtextdomain(PACKAGE, LOCALEDIR);
Matej Habrnal 5c8df3
+    textdomain(PACKAGE);
Matej Habrnal 5c8df3
+#endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const char *program_usage_string = _(
Matej Habrnal 5c8df3
+        "\n& [-vf] [-c CONFFILE]... [-F FMTFILE] [-A FMTFILE2] -d DIR"
Matej Habrnal 5c8df3
+        "\nor:"
Matej Habrnal 5c8df3
+        "\n& [-v] [-c CONFFILE]... [-d DIR] -t[ID] FILE..."
Matej Habrnal 5c8df3
+        "\nor:"
Matej Habrnal 5c8df3
+        "\n& [-v] [-c CONFFILE]... [-d DIR] -t[ID] -w"
Matej Habrnal 5c8df3
+        "\nor:"
Matej Habrnal 5c8df3
+        "\n& [-v] [-c CONFFILE]... -h DUPHASH"
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nReports problem to CentOS Bug Tracker."
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nThe tool reads DIR. Then it tries to find an issue"
Matej Habrnal 5c8df3
+        "\nwith the same abrt_hash in custom field 'abrt_hash'."
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nIf such issue is not found, then a new issue is created. Elements of DIR"
Matej Habrnal 5c8df3
+        "\nare stored in the issue as part of issue description or as attachments,"
Matej Habrnal 5c8df3
+        "\ndepending on their type and size."
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nOtherwise, if such issue is found and it is marked as CLOSED DUPLICATE,"
Matej Habrnal 5c8df3
+        "\nthe tool follows the chain of duplicates until it finds a non-DUPLICATE issue."
Matej Habrnal 5c8df3
+        "\nThe tool adds a new comment to found issue."
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nThe URL to new or modified issue is printed to stdout and recorded in"
Matej Habrnal 5c8df3
+        "\n'reported_to' element."
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nOption -t uploads FILEs to the already created issue on CentOS Bug Tracker site."
Matej Habrnal 5c8df3
+        "\nThe issue ID is retrieved from directory specified by -d DIR."
Matej Habrnal 5c8df3
+        "\nIf problem data in DIR was never reported to CentOS Bug Tracker, upload will fail."
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nOption -tID uploads FILEs to the issue with specified ID on CentOS Bug Tracker site."
Matej Habrnal 5c8df3
+        "\n-d DIR is ignored."
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nOption -r sets the last url from reporter_to element which is prefixed with"
Matej Habrnal 5c8df3
+        "\nTRACKER_NAME to URL field. This option is applied only when a new issue is to be"
Matej Habrnal 5c8df3
+        "\nfiled. The default value is 'ABRT Server'"
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nIf not specified, CONFFILE defaults to "CONF_DIR"/plugins/mantisb.conf"
Matej Habrnal 5c8df3
+        "\nIts lines should have 'PARAM = VALUE' format."
Matej Habrnal 5c8df3
+        "\nRecognized string parameters: MantisbtURL, Login, Password, Project, ProjectVersion."
Matej Habrnal 5c8df3
+        "\nRecognized boolean parameter (VALUE should be 1/0, yes/no): SSLVerify, CreatePrivate."
Matej Habrnal 5c8df3
+        "\nParameters can be overridden via $Mantisbt_PARAM environment variables."
Matej Habrnal 5c8df3
+        "\n"
Matej Habrnal 5c8df3
+        "\nFMTFILE and FMTFILE2 default to "CONF_DIR"/plugins/mantisbt_format.conf"
Matej Habrnal 5c8df3
+    );
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    enum {
Matej Habrnal 5c8df3
+        OPT_v = 1 << 0,
Matej Habrnal 5c8df3
+        OPT_d = 1 << 1,
Matej Habrnal 5c8df3
+        OPT_c = 1 << 2,
Matej Habrnal 5c8df3
+        OPT_F = 1 << 3,
Matej Habrnal 5c8df3
+        OPT_A = 1 << 4,
Matej Habrnal 5c8df3
+        OPT_t = 1 << 5,
Matej Habrnal 5c8df3
+        OPT_f = 1 << 6,
Matej Habrnal 5c8df3
+        OPT_h = 1 << 7,
Matej Habrnal 5c8df3
+        OPT_r = 1 << 8,
Matej Habrnal 5c8df3
+        OPT_D = 1 << 9,
Matej Habrnal 5c8df3
+    };
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const char *dump_dir_name = ".";
Matej Habrnal 5c8df3
+    GList *conf_file = NULL;
Matej Habrnal 5c8df3
+    const char *fmt_file = CONF_DIR"/plugins/mantisbt_format.conf";
Matej Habrnal 5c8df3
+    const char *fmt_file2 = fmt_file;
Matej Habrnal 5c8df3
+    char *abrt_hash = NULL;
Matej Habrnal 5c8df3
+    char *ticket_no = NULL;
Matej Habrnal 5c8df3
+    const char *tracker_str = "ABRT Server";
Matej Habrnal 5c8df3
+    char *debug_str = NULL;
Matej Habrnal 5c8df3
+    mantisbt_settings_t mbt_settings = { 0 };
Matej Habrnal 5c8df3
+    /* Keep enum above and order of options below in sync! */
Matej Habrnal 5c8df3
+    struct options program_options[] = {
Matej Habrnal 5c8df3
+        OPT__VERBOSE(&g_verbose),
Matej Habrnal 5c8df3
+        OPT_STRING(   'd', NULL, &dump_dir_name , "DIR"    , _("Problem directory")),
Matej Habrnal 5c8df3
+        OPT_LIST(     'c', NULL, &conf_file     , "FILE"   , _("Configuration file (may be given many times)")),
Matej Habrnal 5c8df3
+        OPT_STRING(   'F', NULL, &fmt_file      , "FILE"   , _("Formatting file for initial comment")),
Matej Habrnal 5c8df3
+        OPT_STRING(   'A', NULL, &fmt_file2     , "FILE"   , _("Formatting file for duplicates")),
Matej Habrnal 5c8df3
+        OPT_OPTSTRING('t', "ticket", &ticket_no , "ID"     , _("Attach FILEs [to issue with this ID]")),
Matej Habrnal 5c8df3
+        OPT_BOOL(     'f', NULL, NULL,                       _("Force reporting even if this problem is already reported")),
Matej Habrnal 5c8df3
+        OPT_STRING(   'h', "duphash", &abrt_hash, "DUPHASH", _("Print BUG_ID which has given DUPHASH")),
Matej Habrnal 5c8df3
+        OPT_STRING(   'r', "tracker", &tracker_str, "TRACKER_NAME", _("A name of bug tracker for an additional URL from 'reported_to'")),
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        OPT_OPTSTRING('D', "debug", &debug_str  , "STR"    , _("Debug")),
Matej Habrnal 5c8df3
+        OPT_END()
Matej Habrnal 5c8df3
+    };
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
Matej Habrnal 5c8df3
+    argv += optind;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    export_abrt_envvars(0);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    map_string_t *settings = new_map_string();
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        if (!conf_file)
Matej Habrnal 5c8df3
+            conf_file = g_list_append(conf_file, (char*) CONF_DIR"/plugins/mantisbt.conf");
Matej Habrnal 5c8df3
+        while (conf_file)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            char *fn = (char *)conf_file->data;
Matej Habrnal 5c8df3
+            log_notice("Loading settings from '%s'", fn);
Matej Habrnal 5c8df3
+            load_conf_file(fn, settings, /*skip key w/o values:*/ false);
Matej Habrnal 5c8df3
+            log_debug("Loaded '%s'", fn);
Matej Habrnal 5c8df3
+            conf_file = g_list_delete_link(conf_file, conf_file);
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        struct dump_dir *dd = NULL;
Matej Habrnal 5c8df3
+        if (abrt_hash == NULL)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
Matej Habrnal 5c8df3
+            if (!dd)
Matej Habrnal 5c8df3
+                error_msg_and_die(_("Can't open problem dir '%s'."), dump_dir_name);
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        set_settings(&mbt_settings, settings, dd);
Matej Habrnal 5c8df3
+        dd_close(dd);
Matej Habrnal 5c8df3
+        /* WRONG! set_settings() does not copy the strings, it merely sets up pointers
Matej Habrnal 5c8df3
+         * to settings[] dictionary:
Matej Habrnal 5c8df3
+         */
Matej Habrnal 5c8df3
+        /*free_map_string(settings);*/
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* No connection is opened between client and server. Users authentication
Matej Habrnal 5c8df3
+     * is performed on every SOAP method call. In the first step we verify the
Matej Habrnal 5c8df3
+     * credentials by calling 'mc_login' method.  In the case the credentials are
Matej Habrnal 5c8df3
+     * correctly applies the reporter uses them in the next requests. It is not
Matej Habrnal 5c8df3
+     * necessary to call 'mc_login' method because the method provides only
Matej Habrnal 5c8df3
+     * verification of credentials.
Matej Habrnal 5c8df3
+     */
Matej Habrnal 5c8df3
+    verify_credentials(&mbt_settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (abrt_hash)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        log(_("Looking for similar problems in CentOS Bug Tracker"));
Matej Habrnal 5c8df3
+        GList *ids = mantisbt_search_by_abrt_hash(&mbt_settings, abrt_hash);
Matej Habrnal 5c8df3
+        mantisbt_settings_free(&mbt_settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (ids == NULL)
Matej Habrnal 5c8df3
+            return EXIT_FAILURE;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        puts(ids->data);
Matej Habrnal 5c8df3
+        response_values_free(ids);
Matej Habrnal 5c8df3
+        return EXIT_SUCCESS;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_get_project_id_from_name(&mbt_settings);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (opts & OPT_t)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        if (!argv[0])
Matej Habrnal 5c8df3
+            show_usage_and_die(program_usage_string, program_options);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (!ticket_no)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
Matej Habrnal 5c8df3
+            if (!dd)
Matej Habrnal 5c8df3
+                xfunc_die();
Matej Habrnal 5c8df3
+            report_result_t *reported_to = find_in_reported_to(dd, "CentOS Bug Tracker");
Matej Habrnal 5c8df3
+            dd_close(dd);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            if (!reported_to || !reported_to->url)
Matej Habrnal 5c8df3
+                error_msg_and_die(_("Can't get MantisBT ID because this problem has not yet been reported to MantisBT."));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            char *url = reported_to->url;
Matej Habrnal 5c8df3
+            reported_to->url = NULL;
Matej Habrnal 5c8df3
+            free_report_result(reported_to);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            if (prefixcmp(url, mbt_settings.m_mantisbt_url) != 0)
Matej Habrnal 5c8df3
+                error_msg_and_die(_("This problem has been reported to MantisBT '%s' which differs from the configured MantisBT '%s'."), url, mbt_settings.m_mantisbt_url);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            ticket_no = strrchr(url, '=');
Matej Habrnal 5c8df3
+            if (!ticket_no)
Matej Habrnal 5c8df3
+                error_msg_and_die(_("Malformed url to MantisBT '%s'."), url);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            /* won't ever call free on it - it simplifies the code a lot */
Matej Habrnal 5c8df3
+            ticket_no = xstrdup(ticket_no + 1);
Matej Habrnal 5c8df3
+            log(_("Using CentOS Bug Tracker ID '%s'"), ticket_no);
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        /* Attach files to existing MantisBT issues */
Matej Habrnal 5c8df3
+        while (*argv)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            const char *path = *argv++;
Matej Habrnal 5c8df3
+            char *filename = basename(path);
Matej Habrnal 5c8df3
+            log(_("Attaching file '%s' to issue %s"), filename, ticket_no);
Matej Habrnal 5c8df3
+            mantisbt_attach_file(&mbt_settings, ticket_no, filename, path);
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        return 0;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* Create new issue in MantisBT */
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (!(opts & OPT_f))
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
Matej Habrnal 5c8df3
+        if (!dd)
Matej Habrnal 5c8df3
+            xfunc_die();
Matej Habrnal 5c8df3
+        report_result_t *reported_to = find_in_reported_to(dd, "CentOS Bug Tracker");
Matej Habrnal 5c8df3
+        dd_close(dd);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (reported_to && reported_to->url)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            char *msg = xasprintf(_("This problem was already reported to CentOS Bug Tracker (see '%s')."
Matej Habrnal 5c8df3
+                            " Do you still want to create a new issue?"),
Matej Habrnal 5c8df3
+                            reported_to->url);
Matej Habrnal 5c8df3
+            int yes = ask_yes_no(msg);
Matej Habrnal 5c8df3
+            free(msg);
Matej Habrnal 5c8df3
+            if (!yes)
Matej Habrnal 5c8df3
+                return 0;
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+        free_report_result(reported_to);
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    problem_data_t *problem_data = create_problem_data_for_reporting(dump_dir_name);
Matej Habrnal 5c8df3
+    if (!problem_data)
Matej Habrnal 5c8df3
+        xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    const char *category = problem_data_get_content_or_die(problem_data, FILENAME_COMPONENT);
Matej Habrnal 5c8df3
+    const char *duphash   = problem_data_get_content_or_die(problem_data, FILENAME_DUPHASH);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    if (opts & OPT_D)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        problem_formatter_t *pf = problem_formatter_new();
Matej Habrnal 5c8df3
+        problem_formatter_add_section(pf, PR_SEC_ADDITIONAL_INFO, /* optional section */ 0);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (problem_formatter_load_file(pf, fmt_file))
Matej Habrnal 5c8df3
+            error_msg_and_die("Invalid format file: %s", fmt_file);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        problem_report_t *pr = NULL;
Matej Habrnal 5c8df3
+        if (problem_formatter_generate_report(pf, problem_data, &pr))
Matej Habrnal 5c8df3
+            error_msg_and_die("Failed to format issue report from problem data");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        printf("summary: %s\n"
Matej Habrnal 5c8df3
+                "\n"
Matej Habrnal 5c8df3
+                "Description:\n%s\n"
Matej Habrnal 5c8df3
+                "Additional info:\n%s\n"
Matej Habrnal 5c8df3
+                , problem_report_get_summary(pr)
Matej Habrnal 5c8df3
+                , problem_report_get_description(pr)
Matej Habrnal 5c8df3
+                , problem_report_get_section(pr, PR_SEC_ADDITIONAL_INFO)
Matej Habrnal 5c8df3
+        );
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        puts("attachments:");
Matej Habrnal 5c8df3
+        for (GList *a = problem_report_get_attachments(pr); a != NULL; a = g_list_next(a))
Matej Habrnal 5c8df3
+            printf(" %s\n", (const char *)a->data);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        problem_report_free(pr);
Matej Habrnal 5c8df3
+        problem_formatter_free(pf);
Matej Habrnal 5c8df3
+        exit(0);
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+     int bug_id = 0;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* If REMOTE_RESULT contains "DUPLICATE 12345", we consider it a dup of 12345
Matej Habrnal 5c8df3
+     * and won't search on MantisBT server.
Matej Habrnal 5c8df3
+     */
Matej Habrnal 5c8df3
+    char *remote_result;
Matej Habrnal 5c8df3
+    remote_result = problem_data_get_content_or_NULL(problem_data, FILENAME_REMOTE_RESULT);
Matej Habrnal 5c8df3
+    if (remote_result)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        char *cmd = strtok(remote_result, " \n");
Matej Habrnal 5c8df3
+        char *id = strtok(NULL, " \n");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (!prefixcmp(cmd, "DUPLICATE"))
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            errno = 0;
Matej Habrnal 5c8df3
+            char *e;
Matej Habrnal 5c8df3
+            bug_id = strtoul(id, &e, 10);
Matej Habrnal 5c8df3
+            if (errno || id == e || *e != '\0' || bug_id > INT_MAX)
Matej Habrnal 5c8df3
+            {
Matej Habrnal 5c8df3
+                /* error / no digits / illegal trailing chars / too big a number */
Matej Habrnal 5c8df3
+                bug_id = 0;
Matej Habrnal 5c8df3
+            }
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_issue_info_t *ii;
Matej Habrnal 5c8df3
+    if (!bug_id)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        log(_("Checking for duplicates"));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        int existing_id = -1;
Matej Habrnal 5c8df3
+        int crossver_id = -1;
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            /* Figure out whether we want to match category
Matej Habrnal 5c8df3
+             * when doing dup search.
Matej Habrnal 5c8df3
+             */
Matej Habrnal 5c8df3
+            const char *category_substitute = is_in_comma_separated_list(category, mbt_settings.m_DontMatchComponents) ? NULL : category;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            /* We don't do dup detection across versions (see below why),
Matej Habrnal 5c8df3
+             * but we do add a note if cross-version potential dup exists.
Matej Habrnal 5c8df3
+             * For that, we search for cross version dups first:
Matej Habrnal 5c8df3
+             */
Matej Habrnal 5c8df3
+            // SOAP API searching method is not in the final version, it's possible the project will be string
Matej Habrnal 5c8df3
+            GList *crossver_bugs_ids = mantisbt_search_duplicate_issues(&mbt_settings, category_substitute, /*version*/ NULL, duphash);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            unsigned crossver_bugs_count = g_list_length(crossver_bugs_ids);
Matej Habrnal 5c8df3
+            log_debug("CentOS Bug Tracker has %i reports with duphash '%s' including cross-version ones",
Matej Habrnal 5c8df3
+                    crossver_bugs_count, duphash);
Matej Habrnal 5c8df3
+            if (crossver_bugs_count > 0)
Matej Habrnal 5c8df3
+                crossver_id = atoi(g_list_first(crossver_bugs_ids)->data);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            if (crossver_bugs_count > 0)
Matej Habrnal 5c8df3
+            {
Matej Habrnal 5c8df3
+                // SOAP API searching method is not in the final version, it's possible the project will be string
Matej Habrnal 5c8df3
+                GList *dup_bugs_ids = mantisbt_search_duplicate_issues(&mbt_settings, category_substitute, mbt_settings.m_project_version, duphash);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+                unsigned dup_bugs_count =  g_list_length(dup_bugs_ids);
Matej Habrnal 5c8df3
+                log_debug("CentOS Bug Tracker has %i reports with duphash '%s'",
Matej Habrnal 5c8df3
+                        dup_bugs_count, duphash);
Matej Habrnal 5c8df3
+                if (dup_bugs_count > 0)
Matej Habrnal 5c8df3
+                    existing_id = atoi(g_list_first(dup_bugs_ids)->data);
Matej Habrnal 5c8df3
+            }
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (existing_id < 0)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            /* Create new issue */
Matej Habrnal 5c8df3
+            log(_("Creating a new issue"));
Matej Habrnal 5c8df3
+            problem_formatter_t *pf = problem_formatter_new();
Matej Habrnal 5c8df3
+            problem_formatter_add_section(pf, PR_SEC_ADDITIONAL_INFO, 0);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            if (problem_formatter_load_file(pf, fmt_file))
Matej Habrnal 5c8df3
+                error_msg_and_die(_("Invalid format file: %s"), fmt_file);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            problem_report_t *pr = NULL;
Matej Habrnal 5c8df3
+            if (problem_formatter_generate_report(pf, problem_data, &pr))
Matej Habrnal 5c8df3
+                error_msg_and_die(_("Failed to format problem data"));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            if (crossver_id >= 0)
Matej Habrnal 5c8df3
+                problem_report_buffer_printf(
Matej Habrnal 5c8df3
+                        problem_report_get_buffer(pr, PR_SEC_DESCRIPTION),
Matej Habrnal 5c8df3
+                        "\nPotential duplicate: issue %u\n", crossver_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            problem_formatter_free(pf);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            /* get tracker URL if exists */
Matej Habrnal 5c8df3
+            struct dump_dir *dd = dd_opendir(dump_dir_name, 0);
Matej Habrnal 5c8df3
+            char *tracker_url = NULL;
Matej Habrnal 5c8df3
+            if (dd)
Matej Habrnal 5c8df3
+            {
Matej Habrnal 5c8df3
+                report_result_t *reported_to = find_in_reported_to(dd, tracker_str);
Matej Habrnal 5c8df3
+                dd_close(dd);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+                if (reported_to && reported_to->url)
Matej Habrnal 5c8df3
+                {
Matej Habrnal 5c8df3
+                    log(_("Adding External URL to issue"));
Matej Habrnal 5c8df3
+                    tracker_url = xstrdup(reported_to->url);
Matej Habrnal 5c8df3
+                    free_report_result(reported_to);
Matej Habrnal 5c8df3
+                }
Matej Habrnal 5c8df3
+            }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            int new_id = mantisbt_create_new_issue(&mbt_settings, problem_data, pr, tracker_url);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            free(tracker_url);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            if (new_id == -1)
Matej Habrnal 5c8df3
+                return EXIT_FAILURE;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            log(_("Adding attachments to issue %i"), new_id);
Matej Habrnal 5c8df3
+            char *new_id_str = xasprintf("%u", new_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            for (GList *a = problem_report_get_attachments(pr); a != NULL; a = g_list_next(a))
Matej Habrnal 5c8df3
+            {
Matej Habrnal 5c8df3
+                const char *item_name = (const char *)a->data;
Matej Habrnal 5c8df3
+                struct problem_item *item = problem_data_get_item_or_NULL(problem_data, item_name);
Matej Habrnal 5c8df3
+                if (!item)
Matej Habrnal 5c8df3
+                    continue;
Matej Habrnal 5c8df3
+                else if (item->flags & CD_FLAG_TXT)
Matej Habrnal 5c8df3
+                    mantisbt_attach_data(&mbt_settings, new_id_str, item_name, item->content, strlen(item->content));
Matej Habrnal 5c8df3
+                else if (item->flags & CD_FLAG_BIN)
Matej Habrnal 5c8df3
+                    mantisbt_attach_file(&mbt_settings, new_id_str, item_name, item->content);
Matej Habrnal 5c8df3
+            }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            free(new_id_str);
Matej Habrnal 5c8df3
+            problem_report_free(pr);
Matej Habrnal 5c8df3
+            ii = mantisbt_issue_info_new();
Matej Habrnal 5c8df3
+            ii->mii_id = new_id;
Matej Habrnal 5c8df3
+            ii->mii_status = xstrdup("new");
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            goto finish;
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        bug_id = existing_id;
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    ii = mantisbt_get_issue_info(&mbt_settings, bug_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    log(_("Bug is already reported: %i"), ii->mii_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* Follow duplicates */
Matej Habrnal 5c8df3
+    if ((strcmp(ii->mii_status, "closed") == 0)
Matej Habrnal 5c8df3
+     && (strcmp(ii->mii_resolution, "duplicate") == 0)
Matej Habrnal 5c8df3
+    ) {
Matej Habrnal 5c8df3
+        mantisbt_issue_info_t *origin = mantisbt_find_origin_bug_closed_duplicate(&mbt_settings, ii);
Matej Habrnal 5c8df3
+        if (origin)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            mantisbt_issue_info_free(ii);
Matej Habrnal 5c8df3
+            ii = origin;
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* TODO CC list
Matej Habrnal 5c8df3
+     * Is no MantisBT SOAP API method which allows adding users to CC list
Matej Habrnal 5c8df3
+     * without updating issue.
Matej Habrnal 5c8df3
+     */
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    /* Add comment and bt */
Matej Habrnal 5c8df3
+    const char *comment = problem_data_get_content_or_NULL(problem_data, FILENAME_COMMENT);
Matej Habrnal 5c8df3
+    if (comment && comment[0])
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        problem_formatter_t *pf = problem_formatter_new();
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        if (problem_formatter_load_file(pf, fmt_file2))
Matej Habrnal 5c8df3
+            error_msg_and_die(_("Invalid duplicate format file: '%s"), fmt_file2);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        problem_report_t *pr;
Matej Habrnal 5c8df3
+        if (problem_formatter_generate_report(pf, problem_data, &pr))
Matej Habrnal 5c8df3
+            error_msg_and_die(_("Failed to format duplicate comment from problem data"));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        const char *mbtcomment = problem_report_get_description(pr);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        int dup_comment = is_comment_dup(ii->mii_notes, mbtcomment);
Matej Habrnal 5c8df3
+        if (!dup_comment)
Matej Habrnal 5c8df3
+        {
Matej Habrnal 5c8df3
+            log(_("Adding new comment to issue %d"), ii->mii_id);
Matej Habrnal 5c8df3
+            mantisbt_add_issue_note(&mbt_settings, ii->mii_id, mbtcomment);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+            const char *bt = problem_data_get_content_or_NULL(problem_data, FILENAME_BACKTRACE);
Matej Habrnal 5c8df3
+            unsigned rating = 0;
Matej Habrnal 5c8df3
+            const char *rating_str = problem_data_get_content_or_NULL(problem_data, FILENAME_RATING);
Matej Habrnal 5c8df3
+            /* python doesn't have rating file */
Matej Habrnal 5c8df3
+            if (rating_str)
Matej Habrnal 5c8df3
+                rating = xatou(rating_str);
Matej Habrnal 5c8df3
+            if (bt && rating > ii->mii_best_bt_rating)
Matej Habrnal 5c8df3
+            {
Matej Habrnal 5c8df3
+                char *bug_id_str = xasprintf("%i", ii->mii_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+                log(_("Attaching better backtrace"));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+                // find unique filename of attachment
Matej Habrnal 5c8df3
+                char *name = NULL;
Matej Habrnal 5c8df3
+                for (int i = 0;; ++i)
Matej Habrnal 5c8df3
+                {
Matej Habrnal 5c8df3
+                    if (i == 0)
Matej Habrnal 5c8df3
+                        name = xasprintf("%s", FILENAME_BACKTRACE);
Matej Habrnal 5c8df3
+                    else
Matej Habrnal 5c8df3
+                        name = xasprintf("%s%d", FILENAME_BACKTRACE, i);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+                    if (g_list_find_custom(ii->mii_attachments, name, (GCompareFunc) strcmp) == NULL)
Matej Habrnal 5c8df3
+                        break;
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+                    free(name);
Matej Habrnal 5c8df3
+                }
Matej Habrnal 5c8df3
+                mantisbt_attach_data(&mbt_settings, bug_id_str, name, bt, strlen(bt));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+                free(name);
Matej Habrnal 5c8df3
+                free(bug_id_str);
Matej Habrnal 5c8df3
+            }
Matej Habrnal 5c8df3
+        }
Matej Habrnal 5c8df3
+        else
Matej Habrnal 5c8df3
+            log(_("Found the same comment in the issue history, not adding a new one"));
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+        problem_report_free(pr);
Matej Habrnal 5c8df3
+        problem_formatter_free(pf);
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+finish:
Matej Habrnal 5c8df3
+    log(_("Status: %s%s%s %s/view.php?id=%u"),
Matej Habrnal 5c8df3
+                ii->mii_status,
Matej Habrnal 5c8df3
+                ii->mii_resolution ? " " : "",
Matej Habrnal 5c8df3
+                ii->mii_resolution ? ii->mii_resolution : "",
Matej Habrnal 5c8df3
+                mbt_settings.m_mantisbt_url,
Matej Habrnal 5c8df3
+                ii->mii_id);
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
Matej Habrnal 5c8df3
+    if (dd)
Matej Habrnal 5c8df3
+    {
Matej Habrnal 5c8df3
+        char *msg = xasprintf("CentOS Bug Tracker: URL=%s/view.php?id=%u", mbt_settings.m_mantisbt_url, ii->mii_id);
Matej Habrnal 5c8df3
+        add_reported_to(dd, msg);
Matej Habrnal 5c8df3
+        free(msg);
Matej Habrnal 5c8df3
+        dd_close(dd);
Matej Habrnal 5c8df3
+    }
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    mantisbt_settings_free(&mbt_settings);
Matej Habrnal 5c8df3
+    return 0;
Matej Habrnal 5c8df3
+}
Matej Habrnal 5c8df3
diff --git a/src/workflows/Makefile.am b/src/workflows/Makefile.am
Matej Habrnal 5c8df3
index 0fc1019..5b8376a 100644
Matej Habrnal 5c8df3
--- a/src/workflows/Makefile.am
Matej Habrnal 5c8df3
+++ b/src/workflows/Makefile.am
Matej Habrnal 5c8df3
@@ -22,6 +22,18 @@ dist_workflows_DATA = \
Matej Habrnal 5c8df3
     workflow_Logger.xml \
Matej Habrnal 5c8df3
     workflow_LoggerCCpp.xml
Matej Habrnal 5c8df3
 
Matej Habrnal 5c8df3
+if BUILD_MANTISBT
Matej Habrnal 5c8df3
+dist_workflows_DATA += \
Matej Habrnal 5c8df3
+    workflow_CentOSCCpp.xml \
Matej Habrnal 5c8df3
+    workflow_CentOSKerneloops.xml \
Matej Habrnal 5c8df3
+    workflow_CentOSPython.xml \
Matej Habrnal 5c8df3
+    workflow_CentOSPython3.xml \
Matej Habrnal 5c8df3
+    workflow_CentOSVmcore.xml \
Matej Habrnal 5c8df3
+    workflow_CentOSXorg.xml \
Matej Habrnal 5c8df3
+    workflow_CentOSLibreport.xml \
Matej Habrnal 5c8df3
+    workflow_CentOSJava.xml
Matej Habrnal 5c8df3
+endif
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
 if BUILD_BUGZILLA
Matej Habrnal 5c8df3
 dist_workflows_DATA += \
Matej Habrnal 5c8df3
     workflow_AnacondaFedora.xml \
Matej Habrnal 5c8df3
@@ -44,7 +56,8 @@ dist_workflowsdef_DATA =\
Matej Habrnal 5c8df3
     report_rhel.conf \
Matej Habrnal 5c8df3
     report_mailx.conf \
Matej Habrnal 5c8df3
     report_logger.conf \
Matej Habrnal 5c8df3
-    report_uploader.conf
Matej Habrnal 5c8df3
+    report_uploader.conf \
Matej Habrnal 5c8df3
+    report_centos.conf
Matej Habrnal 5c8df3
 
Matej Habrnal 5c8df3
 if BUILD_BUGZILLA
Matej Habrnal 5c8df3
 dist_workflowsdef_DATA += \
Matej Habrnal 5c8df3
diff --git a/src/workflows/report_centos.conf b/src/workflows/report_centos.conf
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..07b0d40
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/workflows/report_centos.conf
Matej Habrnal 5c8df3
@@ -0,0 +1,31 @@
Matej Habrnal 5c8df3
+EVENT=workflow_CentOSLibreport analyzer=libreport
Matej Habrnal 5c8df3
+# this is just a meta event which consists of other events
Matej Habrnal 5c8df3
+# the list is defined in the xml file
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=workflow_CentOSCCpp analyzer=CCpp
Matej Habrnal 5c8df3
+# this is just a meta event which consists of other events
Matej Habrnal 5c8df3
+# the list is defined in the xml file
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=workflow_CentOSPython analyzer=Python component!=anaconda
Matej Habrnal 5c8df3
+# this is just a meta event which consists of other events
Matej Habrnal 5c8df3
+# the list is defined in the xml file
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=workflow_CentOSPython3 analyzer=Python3 component!=anaconda
Matej Habrnal 5c8df3
+# this is just a meta event which consists of other events
Matej Habrnal 5c8df3
+# the list is defined in the xml file
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=workflow_CentOSKerneloops analyzer=Kerneloops
Matej Habrnal 5c8df3
+# this is just a meta event which consists of other events
Matej Habrnal 5c8df3
+# the list is defined in the xml file
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=workflow_CentOSVmcore analyzer=vmcore
Matej Habrnal 5c8df3
+# this is just a meta event which consists of other events
Matej Habrnal 5c8df3
+# the list is defined in the xml file
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=workflow_CentOSXorg analyzer=xorg
Matej Habrnal 5c8df3
+# this is just a meta event which consists of other events
Matej Habrnal 5c8df3
+# the list is defined in the xml file
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+EVENT=workflow_CentOSJava analyzer=Java
Matej Habrnal 5c8df3
+# this is just a meta event which consists of other events
Matej Habrnal 5c8df3
+# the list is defined in the xml file
Matej Habrnal 5c8df3
diff --git a/src/workflows/workflow_CentOSCCpp.xml.in b/src/workflows/workflow_CentOSCCpp.xml.in
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..ea94d56
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/workflows/workflow_CentOSCCpp.xml.in
Matej Habrnal 5c8df3
@@ -0,0 +1,12 @@
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+<workflow>
Matej Habrnal 5c8df3
+    <_name>Report to CentOS Bug Tracker</_name>
Matej Habrnal 5c8df3
+    <_description>Process the C/C++ crash using the CentOS infrastructure</_description>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <events>
Matej Habrnal 5c8df3
+        <event>report_uReport</event>
Matej Habrnal 5c8df3
+        <event>collect_*</event>
Matej Habrnal 5c8df3
+        <event>analyze_CCpp</event>
Matej Habrnal 5c8df3
+        <event>report_CentOSBugTracker</event>
Matej Habrnal 5c8df3
+    </events>
Matej Habrnal 5c8df3
+</workflow>
Matej Habrnal 5c8df3
diff --git a/src/workflows/workflow_CentOSJava.xml.in b/src/workflows/workflow_CentOSJava.xml.in
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..89f9295
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/workflows/workflow_CentOSJava.xml.in
Matej Habrnal 5c8df3
@@ -0,0 +1,11 @@
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+<workflow>
Matej Habrnal 5c8df3
+    <_name>Report to CentOS Bug Tracker</_name>
Matej Habrnal 5c8df3
+    <_description>Process the Java exception using the CentOS infrastructure</_description>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <events>
Matej Habrnal 5c8df3
+        <event>report_uReport</event>
Matej Habrnal 5c8df3
+        <event>collect_*</event>
Matej Habrnal 5c8df3
+        <event>report_CentOSBugTracker</event>
Matej Habrnal 5c8df3
+    </events>
Matej Habrnal 5c8df3
+</workflow>
Matej Habrnal 5c8df3
diff --git a/src/workflows/workflow_CentOSKerneloops.xml.in b/src/workflows/workflow_CentOSKerneloops.xml.in
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..c43c681
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/workflows/workflow_CentOSKerneloops.xml.in
Matej Habrnal 5c8df3
@@ -0,0 +1,11 @@
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+<workflow>
Matej Habrnal 5c8df3
+    <_name>Report to CentOS Bug Tracker</_name>
Matej Habrnal 5c8df3
+    <_description>Process the kerneloops using the CentOS infrastructure</_description>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <events>
Matej Habrnal 5c8df3
+        <event>report_uReport</event>
Matej Habrnal 5c8df3
+        <event>collect_*</event>
Matej Habrnal 5c8df3
+        <event>report_CentOSBugTracker</event>
Matej Habrnal 5c8df3
+    </events>
Matej Habrnal 5c8df3
+</workflow>
Matej Habrnal 5c8df3
diff --git a/src/workflows/workflow_CentOSLibreport.xml.in b/src/workflows/workflow_CentOSLibreport.xml.in
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..2f6ed82
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/workflows/workflow_CentOSLibreport.xml.in
Matej Habrnal 5c8df3
@@ -0,0 +1,9 @@
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+<workflow>
Matej Habrnal 5c8df3
+    <_name>Report to CentOS Bug Tracker</_name>
Matej Habrnal 5c8df3
+    <_description>Process the problem using the CentOS infrastructure</_description>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <events>
Matej Habrnal 5c8df3
+        <event>report_CentOSBugTracker</event>
Matej Habrnal 5c8df3
+    </events>
Matej Habrnal 5c8df3
+</workflow>
Matej Habrnal 5c8df3
diff --git a/src/workflows/workflow_CentOSPython.xml.in b/src/workflows/workflow_CentOSPython.xml.in
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..7e26c6c
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/workflows/workflow_CentOSPython.xml.in
Matej Habrnal 5c8df3
@@ -0,0 +1,11 @@
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+<workflow>
Matej Habrnal 5c8df3
+    <_name>Report to CentOS Bug Tracker</_name>
Matej Habrnal 5c8df3
+    <_description>Process the python exception using the CentOS infrastructure</_description>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <events>
Matej Habrnal 5c8df3
+        <event>report_uReport</event>
Matej Habrnal 5c8df3
+        <event>collect_*</event>
Matej Habrnal 5c8df3
+        <event>report_CentOSBugTracker</event>
Matej Habrnal 5c8df3
+    </events>
Matej Habrnal 5c8df3
+</workflow>
Matej Habrnal 5c8df3
diff --git a/src/workflows/workflow_CentOSPython3.xml.in b/src/workflows/workflow_CentOSPython3.xml.in
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..f1dd8a9
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/workflows/workflow_CentOSPython3.xml.in
Matej Habrnal 5c8df3
@@ -0,0 +1,11 @@
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+<workflow>
Matej Habrnal 5c8df3
+    <_name>Report to CentOS Bug Tracker</_name>
Matej Habrnal 5c8df3
+    <_description>Process the python 3 exception using the CentOS infrastructure</_description>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <events>
Matej Habrnal 5c8df3
+        <event>report_uReport</event>
Matej Habrnal 5c8df3
+        <event>collect_*</event>
Matej Habrnal 5c8df3
+        <event>report_CentOSBugTracker</event>
Matej Habrnal 5c8df3
+    </events>
Matej Habrnal 5c8df3
+</workflow>
Matej Habrnal 5c8df3
diff --git a/src/workflows/workflow_CentOSVmcore.xml.in b/src/workflows/workflow_CentOSVmcore.xml.in
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..c876594
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/workflows/workflow_CentOSVmcore.xml.in
Matej Habrnal 5c8df3
@@ -0,0 +1,12 @@
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+<workflow>
Matej Habrnal 5c8df3
+    <_name>Report to CentOS Bug Tracker</_name>
Matej Habrnal 5c8df3
+    <_description>Process the kernel crash using the CentOS infrastructure</_description>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <events>
Matej Habrnal 5c8df3
+        <event>analyze_VMcore</event>
Matej Habrnal 5c8df3
+        <event>report_uReport</event>
Matej Habrnal 5c8df3
+        <event>collect_*</event>
Matej Habrnal 5c8df3
+        <event>report_CentOSBugTracker</event>
Matej Habrnal 5c8df3
+    </events>
Matej Habrnal 5c8df3
+</workflow>
Matej Habrnal 5c8df3
diff --git a/src/workflows/workflow_CentOSXorg.xml.in b/src/workflows/workflow_CentOSXorg.xml.in
Matej Habrnal 5c8df3
new file mode 100644
Matej Habrnal 5c8df3
index 0000000..bf52221
Matej Habrnal 5c8df3
--- /dev/null
Matej Habrnal 5c8df3
+++ b/src/workflows/workflow_CentOSXorg.xml.in
Matej Habrnal 5c8df3
@@ -0,0 +1,9 @@
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+<workflow>
Matej Habrnal 5c8df3
+    <_name>Report to CentOS Bug Tracker</_name>
Matej Habrnal 5c8df3
+    <_description>Process the X Server problem using the CentOS infrastructure</_description>
Matej Habrnal 5c8df3
+
Matej Habrnal 5c8df3
+    <events>
Matej Habrnal 5c8df3
+        <event>report_CentOSBugTracker</event>
Matej Habrnal 5c8df3
+    </events>
Matej Habrnal 5c8df3
+</workflow>
Matej Habrnal 5c8df3
-- 
Matej Habrnal 5c8df3
1.8.3.1
Matej Habrnal 5c8df3