Blame src/plugins/abrt_rh_support.c

Packit Service 779887
/*
Packit Service 779887
    Copyright (C) 2010  ABRT team
Packit Service 779887
    Copyright (C) 2010  RedHat Inc
Packit Service 779887
Packit Service 779887
    This program is free software; you can redistribute it and/or modify
Packit Service 779887
    it under the terms of the GNU General Public License as published by
Packit Service 779887
    the Free Software Foundation; either version 2 of the License, or
Packit Service 779887
    (at your option) any later version.
Packit Service 779887
Packit Service 779887
    This program is distributed in the hope that it will be useful,
Packit Service 779887
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 779887
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 779887
    GNU General Public License for more details.
Packit Service 779887
Packit Service 779887
    You should have received a copy of the GNU General Public License along
Packit Service 779887
    with this program; if not, write to the Free Software Foundation, Inc.,
Packit Service 779887
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service 779887
*/
Packit Service 779887
#include <libxml/encoding.h>
Packit Service 779887
#include <libxml/xmlwriter.h>
Packit Service 779887
#include <curl/curl.h>
Packit Service 779887
#include "internal_libreport.h"
Packit Service 779887
#include "libreport_curl.h"
Packit Service 779887
#include "abrt_rh_support.h"
Packit Service 779887
Packit Service 779887
struct reportfile {
Packit Service 779887
    xmlTextWriterPtr writer;
Packit Service 779887
    xmlBufferPtr     buf;
Packit Service 779887
};
Packit Service 779887
Packit Service 779887
static void __attribute__((__noreturn__))
Packit Service 779887
die_xml_oom(void)
Packit Service 779887
{
Packit Service 779887
    error_msg_and_die("Can't create XML attribute (out of memory?)");
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static xmlBufferPtr
Packit Service 779887
xxmlBufferCreate(void)
Packit Service 779887
{
Packit Service 779887
    xmlBufferPtr r = xmlBufferCreate();
Packit Service 779887
    if (!r)
Packit Service 779887
        die_xml_oom();
Packit Service 779887
    return r;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static xmlTextWriterPtr
Packit Service 779887
xxmlNewTextWriterMemory(xmlBufferPtr buf /*, int compression*/)
Packit Service 779887
{
Packit Service 779887
    xmlTextWriterPtr r = xmlNewTextWriterMemory(buf, /*compression:*/ 0);
Packit Service 779887
    if (!r)
Packit Service 779887
        die_xml_oom();
Packit Service 779887
    return r;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void
Packit Service 779887
xxmlTextWriterStartDocument(xmlTextWriterPtr writer,
Packit Service 779887
    const char * version,
Packit Service 779887
    const char * encoding,
Packit Service 779887
    const char * standalone)
Packit Service 779887
{
Packit Service 779887
    if (xmlTextWriterStartDocument(writer, version, encoding, standalone) < 0)
Packit Service 779887
        die_xml_oom();
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void
Packit Service 779887
xxmlTextWriterEndDocument(xmlTextWriterPtr writer)
Packit Service 779887
{
Packit Service 779887
    if (xmlTextWriterEndDocument(writer) < 0)
Packit Service 779887
        die_xml_oom();
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void
Packit Service 779887
xxmlTextWriterStartElement(xmlTextWriterPtr writer, const char *name)
Packit Service 779887
{
Packit Service 779887
    // these bright guys REDEFINED CHAR (!) to unsigned char...
Packit Service 779887
    if (xmlTextWriterStartElement(writer, (unsigned char*)name) < 0)
Packit Service 779887
        die_xml_oom();
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void
Packit Service 779887
xxmlTextWriterEndElement(xmlTextWriterPtr writer)
Packit Service 779887
{
Packit Service 779887
    if (xmlTextWriterEndElement(writer) < 0)
Packit Service 779887
        die_xml_oom();
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void
Packit Service 779887
xxmlTextWriterWriteElement(xmlTextWriterPtr writer, const char *name, const char *content)
Packit Service 779887
{
Packit Service 779887
    if (xmlTextWriterWriteElement(writer, (unsigned char*)name, (unsigned char*)content) < 0)
Packit Service 779887
        die_xml_oom();
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void
Packit Service 779887
xxmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const char *name, const char *content)
Packit Service 779887
{
Packit Service 779887
    if (xmlTextWriterWriteAttribute(writer, (unsigned char*)name, (unsigned char*)content) < 0)
Packit Service 779887
        die_xml_oom();
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
#if 0 //unused
Packit Service 779887
static void
Packit Service 779887
xxmlTextWriterWriteString(xmlTextWriterPtr writer, const char *content)
Packit Service 779887
{
Packit Service 779887
    if (xmlTextWriterWriteString(writer, (unsigned char*)content) < 0)
Packit Service 779887
        die_xml_oom();
Packit Service 779887
}
Packit Service 779887
#endif
Packit Service 779887
Packit Service 779887
//
Packit Service 779887
// Reportfile helpers
Packit Service 779887
//
Packit Service 779887
Packit Service 779887
// End the reportfile, and prepare it for delivery.
Packit Service 779887
// No more bindings can be added after this.
Packit Service 779887
static void
Packit Service 779887
close_writer(reportfile_t* file)
Packit Service 779887
{
Packit Service 779887
    if (!file->writer)
Packit Service 779887
        return;
Packit Service 779887
Packit Service 779887
    // close off the end of the xml file
Packit Service 779887
    xxmlTextWriterEndDocument(file->writer);
Packit Service 779887
    xmlFreeTextWriter(file->writer);
Packit Service 779887
    file->writer = NULL;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
// This allocates a reportfile_t structure and initializes it.
Packit Service 779887
reportfile_t*
Packit Service 779887
new_reportfile(void)
Packit Service 779887
{
Packit Service 779887
    // create a new reportfile_t
Packit Service 779887
    reportfile_t* file = (reportfile_t*)xmalloc(sizeof(*file));
Packit Service 779887
Packit Service 779887
    // set up a libxml 'buffer' and 'writer' to that buffer
Packit Service 779887
    file->buf = xxmlBufferCreate();
Packit Service 779887
    file->writer = xxmlNewTextWriterMemory(file->buf);
Packit Service 779887
Packit Service 779887
    // start a new xml document:
Packit Service 779887
    // <report xmlns="http://www.redhat.com/gss/strata">...
Packit Service 779887
    xxmlTextWriterStartDocument(file->writer, /*version:*/ NULL, /*encoding:*/ NULL, /*standalone:*/ NULL);
Packit Service 779887
    xxmlTextWriterStartElement(file->writer, "report");
Packit Service 779887
    xxmlTextWriterWriteAttribute(file->writer, "xmlns", "http://www.redhat.com/gss/strata");
Packit Service 779887
Packit Service 779887
    return file;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void
Packit Service 779887
internal_reportfile_start_binding(reportfile_t* file, const char* name, int isbinary, const char* filename)
Packit Service 779887
{
Packit Service 779887
    // 
Packit Service 779887
    xxmlTextWriterStartElement(file->writer, "binding");
Packit Service 779887
    xxmlTextWriterWriteAttribute(file->writer, "name", name);
Packit Service 779887
    if (filename)
Packit Service 779887
        xxmlTextWriterWriteAttribute(file->writer, "fileName", filename);
Packit Service 779887
    if (isbinary)
Packit Service 779887
        xxmlTextWriterWriteAttribute(file->writer, "type", "binary");
Packit Service 779887
    else
Packit Service 779887
        xxmlTextWriterWriteAttribute(file->writer, "type", "text");
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
// Add a new text binding
Packit Service 779887
void
Packit Service 779887
reportfile_add_binding_from_string(reportfile_t* file, const char* name, const char* value)
Packit Service 779887
{
Packit Service 779887
    // <binding name=NAME type=text value=VALUE>
Packit Service 779887
    internal_reportfile_start_binding(file, name, /*isbinary:*/ 0, /*filename:*/ NULL);
Packit Service 779887
    xxmlTextWriterWriteAttribute(file->writer, "value", value);
Packit Service 779887
    xxmlTextWriterEndElement(file->writer);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
// Add a new binding to a report whose value is represented as a file.
Packit Service 779887
void
Packit Service 779887
reportfile_add_binding_from_namedfile(reportfile_t* file,
Packit Service 779887
                const char* on_disk_filename, /* unused so far */
Packit Service 779887
                const char* binding_name,
Packit Service 779887
                const char* recorded_filename,
Packit Service 779887
                int isbinary)
Packit Service 779887
{
Packit Service 779887
    // 
Packit Service 779887
    internal_reportfile_start_binding(file, binding_name, isbinary, recorded_filename);
Packit Service 779887
    // ... href=content/NAME>
Packit Service 779887
    char *href_name = concat_path_file("content", binding_name);
Packit Service 779887
    xxmlTextWriterWriteAttribute(file->writer, "href", href_name);
Packit Service 779887
    free(href_name);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
// Return the contents of the reportfile as a string.
Packit Service 779887
const char*
Packit Service 779887
reportfile_as_string(reportfile_t* file)
Packit Service 779887
{
Packit Service 779887
    close_writer(file);
Packit Service 779887
    // unsigned char -> char
Packit Service 779887
    return (char*)file->buf->content;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void
Packit Service 779887
free_reportfile(reportfile_t* file)
Packit Service 779887
{
Packit Service 779887
    if (!file)
Packit Service 779887
        return;
Packit Service 779887
    close_writer(file);
Packit Service 779887
    xmlBufferFree(file->buf);
Packit Service 779887
    free(file);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
Packit Service 779887
void free_rhts_result(rhts_result_t *p)
Packit Service 779887
{
Packit Service 779887
    if (!p)
Packit Service 779887
        return;
Packit Service 779887
    free(p->url);
Packit Service 779887
    free(p->msg);
Packit Service 779887
    free(p->body);
Packit Service 779887
    free(p);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
//
Packit Service 779887
// Common
Packit Service 779887
//
Packit Service 779887
static const char *const text_plain_header[] = {
Packit Service 779887
    "Accept: text/plain",
Packit Service 779887
    NULL
Packit Service 779887
};
Packit Service 779887
Packit Service 779887
//
Packit Service 779887
// Creating new case
Packit Service 779887
// See
Packit Service 779887
// https://access.redhat.com/knowledge/docs/Red_Hat_Customer_Portal/integration_guide.html
Packit Service 779887
//
Packit Service 779887
// $ curl -X POST -H 'Content-Type: application/xml' --data
Packit Service 779887
//  '
Packit Service 779887
//   <case xmlns="http://www.redhat.com/gss/strata">
Packit Service 779887
//   <summary>Example Case</summary>
Packit Service 779887
//   <description>Example created with cURL</description>
Packit Service 779887
//   <product>Red Hat Enterprise Linux</product><version>6.0</version>
Packit Service 779887
//   </case>'
Packit Service 779887
//   https://api.access.redhat.com/rs/cases
Packit Service 779887
//
Packit Service 779887
static char*
Packit Service 779887
make_case_data(const char* summary, const char* description,
Packit Service 779887
               const char* product, const char* version,
Packit Service 779887
               const char* component)
Packit Service 779887
{
Packit Service 779887
    char* retval;
Packit Service 779887
    xmlTextWriterPtr writer;
Packit Service 779887
    xmlBufferPtr buf;
Packit Service 779887
Packit Service 779887
    buf = xxmlBufferCreate();
Packit Service 779887
    writer = xxmlNewTextWriterMemory(buf);
Packit Service 779887
Packit Service 779887
    xxmlTextWriterStartDocument(writer, NULL, "UTF-8", "yes");
Packit Service 779887
    xxmlTextWriterStartElement(writer, "case");
Packit Service 779887
    xxmlTextWriterWriteAttribute(writer, "xmlns",
Packit Service 779887
                                   "http://www.redhat.com/gss/strata");
Packit Service 779887
Packit Service 779887
    xxmlTextWriterWriteElement(writer, "summary", summary);
Packit Service 779887
    xxmlTextWriterWriteElement(writer, "description", description);
Packit Service 779887
    if (product) {
Packit Service 779887
        xxmlTextWriterWriteElement(writer, "product", product);
Packit Service 779887
    }
Packit Service 779887
    if (version) {
Packit Service 779887
        xxmlTextWriterWriteElement(writer, "version", version);
Packit Service 779887
    }
Packit Service 779887
    if (component) {
Packit Service 779887
        xxmlTextWriterWriteElement(writer, "component", component);
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    xxmlTextWriterEndDocument(writer);
Packit Service 779887
    retval = xstrdup((const char*)buf->content);
Packit Service 779887
    xmlFreeTextWriter(writer);
Packit Service 779887
    xmlBufferFree(buf);
Packit Service 779887
    return retval;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static rhts_result_t*
Packit Service 779887
post_case_to_url(const char* url,
Packit Service 779887
                const char* username,
Packit Service 779887
                const char* password,
Packit Service 779887
                bool ssl_verify,
Packit Service 779887
                const char **additional_headers,
Packit Service 779887
                const char* product,
Packit Service 779887
                const char* version,
Packit Service 779887
                const char* summary,
Packit Service 779887
                const char* description,
Packit Service 779887
                const char* component)
Packit Service 779887
{
Packit Service 779887
    rhts_result_t *result = xzalloc(sizeof(*result));
Packit Service 779887
    char *url_copy = NULL;
Packit Service 779887
Packit Service 779887
    char *case_data = make_case_data(summary, description,
Packit Service 779887
                                         product, version,
Packit Service 779887
                                         component);
Packit Service 779887
Packit Service 779887
    int redirect_count = 0;
Packit Service 779887
    char *errmsg;
Packit Service 779887
    post_state_t *post_state;
Packit Service 779887
Packit Service 779887
 redirect:
Packit Service 779887
    post_state = new_post_state(0
Packit Service 779887
            + POST_WANT_HEADERS
Packit Service 779887
            + POST_WANT_BODY
Packit Service 779887
            + POST_WANT_ERROR_MSG
Packit Service 779887
            + (ssl_verify ? POST_WANT_SSL_VERIFY : 0)
Packit Service 779887
    );
Packit Service 779887
    post_state->username = username;
Packit Service 779887
    post_state->password = password;
Packit Service 779887
Packit Service 779887
    post_string(post_state, url, "application/xml", additional_headers, case_data);
Packit Service 779887
Packit Service 779887
    char *location = find_header_in_post_state(post_state, "Location:");
Packit Service 779887
Packit Service 779887
    switch (post_state->http_resp_code)
Packit Service 779887
    {
Packit Service 779887
    case 404:
Packit Service 779887
        /* Not strictly necessary (default branch would deal with it too),
Packit Service 779887
         * but makes this typical error less cryptic:
Packit Service 779887
         * instead of returning html-encoded body, we show short concise message,
Packit Service 779887
         * and show offending URL (typos in which is a typical cause) */
Packit Service 779887
        result->error = -1;
Packit Service 779887
        result->msg = xasprintf("Error in HTTP POST, "
Packit Service 779887
                        "HTTP code: 404 (Not found), URL:'%s'", url);
Packit Service 779887
        break;
Packit Service 779887
Packit Service 779887
    case 301: /* "301 Moved Permanently" (for example, used to move http:// to https://) */
Packit Service 779887
    case 302: /* "302 Found" (just in case) */
Packit Service 779887
    case 305: /* "305 Use Proxy" */
Packit Service 779887
        if (++redirect_count < 10 && location)
Packit Service 779887
        {
Packit Service 779887
            free(url_copy);
Packit Service 779887
            url = url_copy = xstrdup(location);
Packit Service 779887
            free_post_state(post_state);
Packit Service 779887
            goto redirect;
Packit Service 779887
        }
Packit Service 779887
        /* fall through */
Packit Service 779887
Packit Service 779887
    default:
Packit Service 779887
        // TODO: error messages in headers
Packit Service 779887
        // are observed to be more informative than the body:
Packit Service 779887
        //
Packit Service 779887
        // 'HTTP/1.1 400 Bad Request'
Packit Service 779887
        // 'Date: Mon, 10 Oct 2011 13:31:56 GMT^M'
Packit Service 779887
        // 'Server: Apache^M'
Packit Service 779887
        // 'Strata-Message: The supplied parameter Fedora value  can not be processed^M'
Packit Service 779887
        // ^^^^^^^^^^^^^^^^^^^^^^^^^ useful message
Packit Service 779887
        // 'Strata-Code: BAD_PARAMETER^M'
Packit Service 779887
        // 'Content-Length: 1^M'
Packit Service 779887
        // 'Content-Type: text/plain; charset=UTF-8^M'
Packit Service 779887
        // 'Connection: close^M'
Packit Service 779887
        // '^M'
Packit Service 779887
        // ' '  <------ body is useless
Packit Service 779887
        result->error = -1;
Packit Service 779887
        errmsg = post_state->curl_error_msg;
Packit Service 779887
        if (errmsg && errmsg[0])
Packit Service 779887
        {
Packit Service 779887
            result->msg = xasprintf(_("Error in case creation at '%s': %s"),
Packit Service 779887
                    url, errmsg);
Packit Service 779887
        }
Packit Service 779887
        else
Packit Service 779887
        {
Packit Service 779887
            errmsg = find_header_in_post_state(post_state, "Strata-Message:");
Packit Service 779887
            if (!errmsg)
Packit Service 779887
                errmsg = post_state->body;
Packit Service 779887
            if (errmsg && errmsg[0])
Packit Service 779887
                result->msg = xasprintf(_("Error in case creation at '%s',"
Packit Service 779887
                        " HTTP code: %d, server says: '%s'"),
Packit Service 779887
                        url, post_state->http_resp_code, errmsg);
Packit Service 779887
            else
Packit Service 779887
                result->msg = xasprintf(_("Error in case creation at '%s',"
Packit Service 779887
                        " HTTP code: %d"),
Packit Service 779887
                        url, post_state->http_resp_code);
Packit Service 779887
        }
Packit Service 779887
        break;
Packit Service 779887
Packit Service 779887
    case 200:
Packit Service 779887
    case 201:
Packit Service 779887
        /* Created successfully */
Packit Service 779887
        result->url = xstrdup(location); /* note: xstrdup(NULL) returns NULL */
Packit Service 779887
    } /* switch (HTTP code) */
Packit Service 779887
Packit Service 779887
    result->http_resp_code = post_state->http_resp_code;
Packit Service 779887
    result->body = post_state->body;
Packit Service 779887
    post_state->body = NULL;
Packit Service 779887
Packit Service 779887
    free_post_state(post_state);
Packit Service 779887
    free(case_data);
Packit Service 779887
    free(url_copy);
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
rhts_result_t*
Packit Service 779887
create_new_case(const char* base_url,
Packit Service 779887
                const char* username,
Packit Service 779887
                const char* password,
Packit Service 779887
                bool ssl_verify,
Packit Service 779887
                const char* product,
Packit Service 779887
                const char* version,
Packit Service 779887
                const char* summary,
Packit Service 779887
                const char* description,
Packit Service 779887
                const char* component)
Packit Service 779887
{
Packit Service 779887
    char *url = concat_path_file(base_url, "cases");
Packit Service 779887
    rhts_result_t *result = post_case_to_url(url,
Packit Service 779887
                username,
Packit Service 779887
                password,
Packit Service 779887
                ssl_verify,
Packit Service 779887
                (const char **)text_plain_header,
Packit Service 779887
                product,
Packit Service 779887
                version,
Packit Service 779887
                summary,
Packit Service 779887
                description,
Packit Service 779887
                component
Packit Service 779887
    );
Packit Service 779887
Packit Service 779887
    if (!result->error && !result->url)
Packit Service 779887
    {
Packit Service 779887
        /* Case Creation returned valid code, but no location */
Packit Service 779887
        result->error = -1;
Packit Service 779887
        free(result->msg);
Packit Service 779887
        result->msg = xasprintf(_("Error in case creation at '%s':"
Packit Service 779887
                " no Location URL, HTTP code: %d"),
Packit Service 779887
                url, result->http_resp_code
Packit Service 779887
        );
Packit Service 779887
    }
Packit Service 779887
    free(url);
Packit Service 779887
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
//
Packit Service 779887
// Add case comment
Packit Service 779887
//
Packit Service 779887
// $ curl -X POST -H 'Content-Type: application/xml' --data
Packit Service 779887
//  '
Packit Service 779887
//   <comment xmlns="http://www.redhat.com/gss/strata">
Packit Service 779887
//   <text>Test comment!  This can contain lots of information, etc.</text>
Packit Service 779887
//   </comment>'
Packit Service 779887
//   https://api.access.redhat.com/rs/cases/NNNNNNN/comments
Packit Service 779887
//
Packit Service 779887
static char*
Packit Service 779887
make_comment_data(const char *comment_text)
Packit Service 779887
{
Packit Service 779887
    char *retval;
Packit Service 779887
    xmlTextWriterPtr writer;
Packit Service 779887
    xmlBufferPtr buf;
Packit Service 779887
Packit Service 779887
    buf = xxmlBufferCreate();
Packit Service 779887
    writer = xxmlNewTextWriterMemory(buf);
Packit Service 779887
Packit Service 779887
    xxmlTextWriterStartDocument(writer, NULL, "UTF-8", "yes");
Packit Service 779887
    xxmlTextWriterStartElement(writer, "comment");
Packit Service 779887
    xxmlTextWriterWriteAttribute(writer, "xmlns",
Packit Service 779887
                                   "http://www.redhat.com/gss/strata");
Packit Service 779887
Packit Service 779887
    xxmlTextWriterWriteElement(writer, "text", comment_text);
Packit Service 779887
Packit Service 779887
    xxmlTextWriterEndDocument(writer);
Packit Service 779887
    retval = xstrdup((const char*)buf->content);
Packit Service 779887
    xmlFreeTextWriter(writer);
Packit Service 779887
    xmlBufferFree(buf);
Packit Service 779887
    return retval;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static rhts_result_t*
Packit Service 779887
post_comment_to_url(const char *url,
Packit Service 779887
                const char *username,
Packit Service 779887
                const char *password,
Packit Service 779887
                bool ssl_verify,
Packit Service 779887
                const char **additional_headers,
Packit Service 779887
                const char *comment_text)
Packit Service 779887
{
Packit Service 779887
    rhts_result_t *result = xzalloc(sizeof(*result));
Packit Service 779887
    char *url_copy = NULL;
Packit Service 779887
Packit Service 779887
    char *xml = make_comment_data(comment_text);
Packit Service 779887
Packit Service 779887
    int redirect_count = 0;
Packit Service 779887
    char *errmsg;
Packit Service 779887
    post_state_t *post_state;
Packit Service 779887
Packit Service 779887
 redirect:
Packit Service 779887
    post_state = new_post_state(0
Packit Service 779887
            + POST_WANT_HEADERS
Packit Service 779887
            + POST_WANT_BODY
Packit Service 779887
            + POST_WANT_ERROR_MSG
Packit Service 779887
            + (ssl_verify ? POST_WANT_SSL_VERIFY : 0)
Packit Service 779887
    );
Packit Service 779887
    post_state->username = username;
Packit Service 779887
    post_state->password = password;
Packit Service 779887
Packit Service 779887
    post_string(post_state, url, "application/xml", additional_headers, xml);
Packit Service 779887
Packit Service 779887
    char *location = find_header_in_post_state(post_state, "Location:");
Packit Service 779887
Packit Service 779887
    switch (post_state->http_resp_code)
Packit Service 779887
    {
Packit Service 779887
    case 404:
Packit Service 779887
        /* Not strictly necessary (default branch would deal with it too),
Packit Service 779887
         * but makes this typical error less cryptic:
Packit Service 779887
         * instead of returning html-encoded body, we show short concise message,
Packit Service 779887
         * and show offending URL (typos in which is a typical cause) */
Packit Service 779887
        result->error = -1;
Packit Service 779887
        result->msg = xasprintf("Error in HTTP POST, "
Packit Service 779887
                        "HTTP code: 404 (Not found), URL:'%s'", url);
Packit Service 779887
        break;
Packit Service 779887
Packit Service 779887
    case 301: /* "301 Moved Permanently" (for example, used to move http:// to https://) */
Packit Service 779887
    case 302: /* "302 Found" (just in case) */
Packit Service 779887
    case 305: /* "305 Use Proxy" */
Packit Service 779887
        if (++redirect_count < 10 && location)
Packit Service 779887
        {
Packit Service 779887
            free(url_copy);
Packit Service 779887
            url = url_copy = xstrdup(location);
Packit Service 779887
            free_post_state(post_state);
Packit Service 779887
            goto redirect;
Packit Service 779887
        }
Packit Service 779887
        /* fall through */
Packit Service 779887
Packit Service 779887
    default:
Packit Service 779887
        result->error = -1;
Packit Service 779887
        errmsg = post_state->curl_error_msg;
Packit Service 779887
        if (errmsg && errmsg[0])
Packit Service 779887
        {
Packit Service 779887
            result->msg = xasprintf(_("Error in comment creation at '%s': %s"),
Packit Service 779887
                        url, errmsg);
Packit Service 779887
        }
Packit Service 779887
        else
Packit Service 779887
        {
Packit Service 779887
            errmsg = find_header_in_post_state(post_state, "Strata-Message:");
Packit Service 779887
            if (!errmsg)
Packit Service 779887
                errmsg = post_state->body;
Packit Service 779887
            if (errmsg && errmsg[0])
Packit Service 779887
                result->msg = xasprintf(_("Error in comment creation at '%s',"
Packit Service 779887
                        " HTTP code: %d, server says: '%s'"),
Packit Service 779887
                        url, post_state->http_resp_code, errmsg);
Packit Service 779887
            else
Packit Service 779887
                result->msg = xasprintf(_("Error in comment creation at '%s',"
Packit Service 779887
                        " HTTP code: %d"),
Packit Service 779887
                        url, post_state->http_resp_code);
Packit Service 779887
        }
Packit Service 779887
        break;
Packit Service 779887
Packit Service 779887
    case 200:
Packit Service 779887
    case 201:
Packit Service 779887
        /* Created successfully */
Packit Service 779887
        result->url = xstrdup(location); /* note: xstrdup(NULL) returns NULL */
Packit Service 779887
    } /* switch (HTTP code) */
Packit Service 779887
Packit Service 779887
    result->http_resp_code = post_state->http_resp_code;
Packit Service 779887
    result->body = post_state->body;
Packit Service 779887
    post_state->body = NULL;
Packit Service 779887
Packit Service 779887
    free_post_state(post_state);
Packit Service 779887
    free(xml);
Packit Service 779887
    free(url_copy);
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
rhts_result_t*
Packit Service 779887
add_comment_to_case(const char* base_url,
Packit Service 779887
                const char* username,
Packit Service 779887
                const char* password,
Packit Service 779887
                bool ssl_verify,
Packit Service 779887
                const char* comment_text)
Packit Service 779887
{
Packit Service 779887
    char *url = concat_path_file(base_url, "comments");
Packit Service 779887
    rhts_result_t *result = post_comment_to_url(url,
Packit Service 779887
                username,
Packit Service 779887
                password,
Packit Service 779887
                ssl_verify,
Packit Service 779887
    // NB! text_plain_header here was causing error 404 instead of 201 (Created)!
Packit Service 779887
    // NULL makes curl use "Accept: */*" instead and creation works.
Packit Service 779887
    // Likely a bug on the server!
Packit Service 779887
                (const char **) NULL, //text_plain_header,
Packit Service 779887
                comment_text
Packit Service 779887
    );
Packit Service 779887
Packit Service 779887
    if (!result->error && !result->url)
Packit Service 779887
    {
Packit Service 779887
        /* Creation returned valid code, but no location */
Packit Service 779887
        result->error = -1;
Packit Service 779887
        free(result->msg);
Packit Service 779887
        result->msg = xasprintf(_("Error in comment creation at '%s':"
Packit Service 779887
                " no Location URL, HTTP code: %d"),
Packit Service 779887
                url, result->http_resp_code
Packit Service 779887
        );
Packit Service 779887
    }
Packit Service 779887
    free(url);
Packit Service 779887
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
//
Packit Service 779887
// Attach file to case
Packit Service 779887
//
Packit Service 779887
static rhts_result_t*
Packit Service 779887
post_file_to_url(const char* url,
Packit Service 779887
                const char* username,
Packit Service 779887
                const char* password,
Packit Service 779887
                bool ssl_verify,
Packit Service 779887
                bool post_as_form,
Packit Service 779887
                const char **additional_headers,
Packit Service 779887
                const char *file_name)
Packit Service 779887
{
Packit Service 779887
    rhts_result_t *result = xzalloc(sizeof(*result));
Packit Service 779887
    char *url_copy = NULL;
Packit Service 779887
Packit Service 779887
    int redirect_count = 0;
Packit Service 779887
    char *errmsg;
Packit Service 779887
    post_state_t *atch_state;
Packit Service 779887
Packit Service 779887
 redirect_attach:
Packit Service 779887
    atch_state = new_post_state(0
Packit Service 779887
            + POST_WANT_HEADERS
Packit Service 779887
            + POST_WANT_BODY
Packit Service 779887
            + POST_WANT_ERROR_MSG
Packit Service 779887
            + (ssl_verify ? POST_WANT_SSL_VERIFY : 0)
Packit Service 779887
    );
Packit Service 779887
    atch_state->username = username;
Packit Service 779887
    atch_state->password = password;
Packit Service 779887
    if (post_as_form)
Packit Service 779887
    {
Packit Service 779887
        /* Sends data in multipart/mixed document. One detail is that
Packit Service 779887
	 * file *name* is also sent to the server.
Packit Service 779887
	 */
Packit Service 779887
        post_file_as_form(atch_state,
Packit Service 779887
            url,
Packit Service 779887
            "application/octet-stream",
Packit Service 779887
            additional_headers,
Packit Service 779887
            file_name
Packit Service 779887
        );
Packit Service 779887
    }
Packit Service 779887
    else
Packit Service 779887
    {
Packit Service 779887
        /* Sends file's raw contents */
Packit Service 779887
        post_file(atch_state,
Packit Service 779887
            url,
Packit Service 779887
            "application/octet-stream",
Packit Service 779887
            additional_headers,
Packit Service 779887
            file_name
Packit Service 779887
        );
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    char *atch_location = find_header_in_post_state(atch_state, "Location:");
Packit Service 779887
Packit Service 779887
    switch (atch_state->http_resp_code)
Packit Service 779887
    {
Packit Service 779887
    case 305: /* "305 Use Proxy" */
Packit Service 779887
        if (++redirect_count < 10 && atch_location)
Packit Service 779887
        {
Packit Service 779887
            free(url_copy);
Packit Service 779887
            url = url_copy = xstrdup(atch_location);
Packit Service 779887
            free_post_state(atch_state);
Packit Service 779887
            goto redirect_attach;
Packit Service 779887
        }
Packit Service 779887
        /* fall through */
Packit Service 779887
Packit Service 779887
    default:
Packit Service 779887
        /* Error */
Packit Service 779887
        result->error = -1;
Packit Service 779887
        errmsg = atch_state->curl_error_msg;
Packit Service 779887
        if (errmsg && errmsg[0])
Packit Service 779887
        {
Packit Service 779887
            result->msg = xasprintf("Error in file upload at '%s': %s",
Packit Service 779887
                    url, errmsg);
Packit Service 779887
        }
Packit Service 779887
        else
Packit Service 779887
        {
Packit Service 779887
            errmsg = atch_state->body;
Packit Service 779887
            if (errmsg && errmsg[0])
Packit Service 779887
                result->msg = xasprintf("Error in file upload at '%s',"
Packit Service 779887
                        " HTTP code: %d, server says: '%s'",
Packit Service 779887
                        url, atch_state->http_resp_code, errmsg);
Packit Service 779887
            else
Packit Service 779887
                result->msg = xasprintf("Error in file upload at '%s',"
Packit Service 779887
                        " HTTP code: %d",
Packit Service 779887
                        url, atch_state->http_resp_code);
Packit Service 779887
        }
Packit Service 779887
        break;
Packit Service 779887
Packit Service 779887
    case 200:
Packit Service 779887
    case 201:
Packit Service 779887
        result->url = xstrdup(atch_location); /* note: xstrdup(NULL) returns NULL */
Packit Service 779887
        //result->msg = xstrdup("File uploaded successfully");
Packit Service 779887
    } /* switch (HTTP code) */
Packit Service 779887
Packit Service 779887
    result->http_resp_code = atch_state->http_resp_code;
Packit Service 779887
    result->body = atch_state->body;
Packit Service 779887
    atch_state->body = NULL;
Packit Service 779887
Packit Service 779887
    free_post_state(atch_state);
Packit Service 779887
    free(url_copy);
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
rhts_result_t*
Packit Service 779887
attach_file_to_case(const char* base_url,
Packit Service 779887
                const char* username,
Packit Service 779887
                const char* password,
Packit Service 779887
                bool ssl_verify,
Packit Service 779887
                const char *file_name)
Packit Service 779887
{
Packit Service 779887
    char *url = concat_path_file(base_url, "attachments");
Packit Service 779887
    rhts_result_t *result = post_file_to_url(url,
Packit Service 779887
                username,
Packit Service 779887
                password,
Packit Service 779887
                ssl_verify,
Packit Service 779887
                /*post_as_form:*/ true,
Packit Service 779887
                (const char **) text_plain_header,
Packit Service 779887
                file_name
Packit Service 779887
    );
Packit Service 779887
    free(url);
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
//
Packit Service 779887
// Get hint
Packit Service 779887
//
Packit Service 779887
rhts_result_t*
Packit Service 779887
get_rhts_hints(const char* base_url,
Packit Service 779887
                const char* username,
Packit Service 779887
                const char* password,
Packit Service 779887
                bool ssl_verify,
Packit Service 779887
                const char* file_name)
Packit Service 779887
{
Packit Service 779887
    char *url = concat_path_file(base_url, "problems");
Packit Service 779887
//    rhts_result_t *result = post_case_to_url(url,
Packit Service 779887
//                username,
Packit Service 779887
//                password,
Packit Service 779887
//                ssl_verify,
Packit Service 779887
//                NULL,
Packit Service 779887
//                release,
Packit Service 779887
//                summary,
Packit Service 779887
//                description,
Packit Service 779887
//                component
Packit Service 779887
//    );
Packit Service 779887
    rhts_result_t *result = post_file_to_url(url,
Packit Service 779887
                username,
Packit Service 779887
                password,
Packit Service 779887
                ssl_verify,
Packit Service 779887
                /*post_as_form:*/ false,
Packit Service 779887
                /*headers:*/ NULL,
Packit Service 779887
                file_name
Packit Service 779887
    );
Packit Service 779887
    free(url);
Packit Service 779887
    return result;
Packit Service 779887
}