Exemple #1
0
unsigned rhbz_version(struct abrt_xmlrpc *ax)
{
    func_entry();

    xmlrpc_value *result;
    result = abrt_xmlrpc_call(ax, "Bugzilla.version", "()");
    char *version = NULL;
    if (result)
        version = rhbz_bug_read_item("version", result, RHBZ_READ_STR);
    if (!result || !version)
        error_msg_and_die("Can't determine %s", "Bugzilla.version");
    xmlrpc_DECREF(result);

    strchrnul(version, '-')[0] = '\0';

    /* format must be x.y.z */
    char *vp;
    int i = 0, v[3] = {0, 0, 0};

    for (vp = version; i < 3; vp = NULL, ++i)
    {
        char *tok = strtok(vp, ".");
        if (!tok)
            break;

        v[i] = strtoul(tok, NULL, 10);
    }

    free(version);

    return BUGZILLA_VERSION(v[0], v[1], v[2]);
}
Exemple #2
0
/* die or return bug id; each bug must have bug id otherwise xml is corrupted */
int rhbz_get_bug_id_from_array0(xmlrpc_value* xml, unsigned ver)
{
    func_entry();

    xmlrpc_env env;
    xmlrpc_env_init(&env);

    xmlrpc_value *item = NULL;
    xmlrpc_array_read_item(&env, xml, 0, &item);
    if (env.fault_occurred)
        abrt_xmlrpc_die(&env);

    const char *id;
    if (ver >= BUGZILLA_VERSION(4,2,0))
        id = "id";
    else
        id = "bug_id";

    xmlrpc_value *bug;
    bug = rhbz_get_member(id, item);
    xmlrpc_DECREF(item);
    if (!bug)
        error_msg_and_die("Can't get member '%s' from bug data", id);

    int bug_id = -1;
    xmlrpc_read_int(&env, bug, &bug_id);
    xmlrpc_DECREF(bug);
    if (env.fault_occurred)
        abrt_xmlrpc_die(&env);

    VERB3 log("found bug_id %i", bug_id);
    return bug_id;
}
Exemple #3
0
bool rhbz_login(struct abrt_xmlrpc *ax, const char *login, const char *password)
{
    func_entry();

    xmlrpc_env env;
    xmlrpc_value *result = abrt_xmlrpc_call_full(&env, ax, "User.login", "({s:s,s:s})",
                                                 "login", login, "password", password);

    if (env.fault_occurred)
    {
        /* 300 (Invalid Username or Password) - https://wiki.mozilla.org/Bugzilla:WebServices:Errors */
        if (env.fault_code != 300)
            abrt_xmlrpc_die(&env);

        VERB1 log("xmlrpc fault: (%d) %s", env.fault_code, env.fault_string);
        return false;
    }

//TODO: with URL like http://bugzilla.redhat.com (that is, with http: instead of https:)
//we are getting this error:
//Logging into Bugzilla at http://bugzilla.redhat.com
//Can't login. Server said: HTTP response code is 301, not 200
//But this is a 301 redirect! We _can_ follow it if we configure curl to understand that!
    xmlrpc_DECREF(result);
    return true;
}
Exemple #4
0
struct bug_info *new_bug_info()
{
    func_entry();

    struct bug_info *bi = xzalloc(sizeof(struct bug_info));
    bi->bi_dup_id = -1;

    return bi;
}
Exemple #5
0
/* The only way this can fail is if arrayP is not actually an array XML-RPC
 * value. So it is usually not worth checking *envP.
 * die or return size of array
 */
unsigned rhbz_array_size(xmlrpc_value *xml)
{
    func_entry();

    xmlrpc_env env;
    xmlrpc_env_init(&env);

    unsigned size = xmlrpc_array_size(&env, xml);
    if (env.fault_occurred)
        abrt_xmlrpc_die(&env);

    return size;
}
Exemple #6
0
static char *trim_all_whitespace(const char *str)
{
    func_entry();

    char *trim = xzalloc(sizeof(char) * strlen(str) + 1);
    int i = 0;
    while (*str)
    {
        if (!isspace(*str))
            trim[i++] = *str;
        str++;
    }

    return trim;
}
Exemple #7
0
void free_bug_info(struct bug_info *bi)
{
    func_entry();

    if (!bi)
        return;

    free(bi->bi_status);
    free(bi->bi_resolution);
    free(bi->bi_reporter);
    free(bi->bi_product);

    list_free_with_free(bi->bi_cc_list);

    free(bi);
}
Exemple #8
0
xmlrpc_value *rhbz_array_item_at(xmlrpc_value *xml, int pos)
{
    func_entry();

    xmlrpc_env env;
    xmlrpc_env_init(&env);

    xmlrpc_value* item = NULL;
    xmlrpc_array_read_item(&env, xml, pos, &item);
    if (env.fault_occurred)
        abrt_xmlrpc_die(&env);

    xmlrpc_env_clean(&env);

    return item;
}
Exemple #9
0
// TODO: npajkovs: add flag to read xmlrpc_read_array_item first
void *rhbz_bug_read_item(const char *memb, xmlrpc_value *xml, int flags)
{
    func_entry();

    xmlrpc_env env;
    xmlrpc_env_init(&env);

    xmlrpc_value *member = rhbz_get_member(memb, xml);

    const char *string = NULL;

    if (!member)
        goto die;

    if (IS_READ_STR(flags))
    {
        xmlrpc_read_string(&env, member, &string);
        xmlrpc_DECREF(member);
        if (env.fault_occurred)
            abrt_xmlrpc_die(&env);

        if (!*string)
            goto die;

        VERB3 log("found %s: '%s'", memb, string);
        return (void*)string;
    }

    if (IS_READ_INT(flags))
    {
        int *integer = xmalloc(sizeof(int));
        xmlrpc_read_int(&env, member, integer);
        xmlrpc_DECREF(member);
        if (env.fault_occurred)
            abrt_xmlrpc_die(&env);

        VERB3 log("found %s: '%i'", memb, *integer);
        return (void*)integer;
    }
die:
    free((void*)string);
    if (IS_MANDATORY(flags))
        error_msg_and_die(_("Looks like corrupted xml response, because '%s'"
                            " member is missing."), memb);

    return NULL;
}
Exemple #10
0
int is_comment_dup(GList *comments, const char *comment)
{
    func_entry();

    char * const trim_comment = trim_all_whitespace(comment);
    bool same_comments = false;

    for (GList *l = comments; l && !same_comments; l = l->next)
    {
        const char * const comment_body = (const char *) l->data;
        char * const trim_comment_body = trim_all_whitespace(comment_body);
        same_comments = (strcmp(trim_comment_body, trim_comment) == 0);
        free(trim_comment_body);
    }

    free(trim_comment);
    return same_comments;
}
Exemple #11
0
GList *rhbz_bug_cc(xmlrpc_value* result_xml)
{
    func_entry();

    xmlrpc_env env;
    xmlrpc_env_init(&env);

    xmlrpc_value* cc_member = rhbz_get_member("cc", result_xml);
    if (!cc_member)
        return NULL;

    unsigned array_size = rhbz_array_size(cc_member);

    VERB3 log("count members on cc %i", array_size);
    GList *cc_list = NULL;

    for (unsigned i = 0; i < array_size; ++i)
    {
        xmlrpc_value* item = NULL;
        xmlrpc_array_read_item(&env, cc_member, i, &item);
        if (env.fault_occurred)
            abrt_xmlrpc_die(&env);

        if (!item)
            continue;

        const char* cc = NULL;
        xmlrpc_read_string(&env, item, &cc);
        xmlrpc_DECREF(item);
        if (env.fault_occurred)
            abrt_xmlrpc_die(&env);

        if (*cc != '\0')
        {
            cc_list = g_list_append(cc_list, (char*)cc);
            VERB3 log("member on cc is %s", cc);
            continue;
        }
        free((char*)cc);
    }
    xmlrpc_DECREF(cc_member);
    return cc_list;
}
Exemple #12
0
static unsigned find_best_bt_rating_in_comments(GList *comments)
{
    func_entry();

    if (!comments)
        return 0;

    int best_bt_rating = 0;

    for (GList *l = comments; l; l = l->next)
    {
        char *comment_body = (char *) l->data;

        char *start_rating_line = strstr(comment_body, FILENAME_RATING": ");
        if (!start_rating_line)
        {
            VERB3 error_msg("comment does not contain rating");
            continue;
        }

        start_rating_line += strlen(FILENAME_RATING": ");

        errno = 0;
        char *e;
        long rating = strtoul(start_rating_line, &e, 10);
        /*
         * Note: we intentionally check for '\n'. Any other terminator
         * (even '\0') is not ok in this case.
         */
        if (errno || e == start_rating_line || *e != '\n' || (unsigned long)rating > UINT_MAX)
        {
            /* error / no digits / illegal trailing chars */
            continue;
        }

        if (rating > best_bt_rating)
            best_bt_rating = rating;
    }

    return best_bt_rating;
}
Exemple #13
0
/*************************************************************************
    HandleVendorRequest
    ===================
**************************************************************************/
static BOOL HandleVendorRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData)
{
    IAP func_entry;

    func_entry = (IAP) IAP_LOCATION;

    if (pSetup->wIndex != 0) {
        DBG("Invalid idx %X\n", pSetup->wIndex);
        return FALSE;
    }
    if (pSetup->wValue != 0) {
        DBG("Invalid val %X\n", pSetup->wValue);
        return FALSE;
    }

    switch (pSetup->bRequest) {

    // commands
    case REQ_IAP_COMMAND:
        /* fallthrough */
    case REQ_ISP_COMMAND:
        /* fallthrough */
    case REQ_BTL_COMMAND:
        if (pSetup->bRequest == REQ_IAP_COMMAND) func_entry = (IAP) IAP_LOCATION;
        if (pSetup->bRequest == REQ_ISP_COMMAND) func_entry = isp_entry;
        if (pSetup->bRequest == REQ_BTL_COMMAND) func_entry = btl_entry;

        if (REQTYPE_GET_DIR(pSetup->bmRequestType) == REQTYPE_DIR_TO_HOST) {
            // send result
            *ppbData = (U8*) rescmd;
            *piLen = 32; // TODO remove
            if (*piLen != 32) return FALSE;
        }
        else {
            // start command
            if (*piLen != 20) return FALSE;
            memcpy(&rescmd[3], *ppbData, 20);
            func_entry(&rescmd[3], rescmd);
        }
        break;

    // data transfer
    case REQ_DATA_TRANSFER:
        if (REQTYPE_GET_DIR(pSetup->bmRequestType) == REQTYPE_DIR_TO_HOST) {
            // check if data to read
            if (*piLen > read_mem_len) return FALSE;
            *ppbData = (U8*) read_mem_adr;
            read_mem_adr += *piLen;
            read_mem_len -= *piLen;
        }
        else {
            // data is already written, adjust pointers
            if (*piLen > write_ram_len) return FALSE;
            write_ram_adr += *piLen;
            write_ram_len -= *piLen;
        }
        break;

    default:
        DBG("Unhandled vendor\n");
        return FALSE;
    }
    return TRUE;
}
Exemple #14
0
static GList *rhbz_comments(struct abrt_xmlrpc *ax, int bug_id)
{
    func_entry();

    /* http://www.bugzilla.org/docs/4.2/en/html/api/Bugzilla/WebService/Bug.html#comments */
    /*
     * <methodResponse>
     *   <params><param>
     *     <value><struct>
     *       <member><name>bugs</name>
     *       <value><struct>
     *         <member><name>BUG_ID</name>
     *         <value><struct>
     *           <member><name>comments</name>
     *           <value><array>
     * ...
     */
    xmlrpc_value *xml_response = abrt_xmlrpc_call(ax, "Bug.comments", "({s:(i)})",
                                                                      "ids", bug_id);
    /* bugs
     *     This is used for bugs specified in ids. This is a hash, where the
     *     keys are the numeric ids of the bugs, and the value is a hash with a
     *     single key, comments, which is an array of comments.
     */
    xmlrpc_value *bugs_memb = rhbz_get_member("bugs", xml_response);

    /* Get hash value assigned to bug_id key */
    char *item = xasprintf("%d", bug_id);
    xmlrpc_value *item_memb = rhbz_get_member(item, bugs_memb);
    free(item);

    /* Get array of comments */
    xmlrpc_value *comments_memb = rhbz_get_member("comments", item_memb);

    xmlrpc_env env;
    xmlrpc_env_init(&env);

    int comments_memb_size = rhbz_array_size(comments_memb);

    GList *comments = NULL;
    for (int i = 0; i < comments_memb_size; ++i)
    {
        xmlrpc_value* item = NULL;
        xmlrpc_array_read_item(&env, comments_memb, i, &item);
        if (env.fault_occurred)
            abrt_xmlrpc_die(&env);

        char *comment_body = rhbz_bug_read_item("text", item, RHBZ_READ_STR);
        /* attachments are sometimes without comments -- skip them */
        if (comment_body)
            comments = g_list_prepend(comments, comment_body);

        xmlrpc_DECREF(item);
    }

    xmlrpc_env_clean(&env);

    xmlrpc_DECREF(comments_memb);
    xmlrpc_DECREF(item_memb);
    xmlrpc_DECREF(bugs_memb);
    xmlrpc_DECREF(xml_response);

    return g_list_reverse(comments);
}
Exemple #15
0
struct bug_info *rhbz_bug_info(struct abrt_xmlrpc *ax, int bug_id)
{
    func_entry();

    struct bug_info *bz = new_bug_info();

    /* http://www.bugzilla.org/docs/4.2/en/html/api/Bugzilla/WebService/Bug.html#get
     *
     * <methodResponse>
     * <params>
     *   <param><value><struct>
     *     <member><name>faults</name><value><array><data/></array></value></member>
     *     <member><name>bugs</name>
     *        <value><array><data>
     *        ...
     */
    xmlrpc_value *xml_bug_response = abrt_xmlrpc_call(ax, "Bug.get", "({s:(i)})",
                                                          "ids", bug_id);

    xmlrpc_value *bugs_memb = rhbz_get_member("bugs", xml_bug_response);
    xmlrpc_value *bug_item = rhbz_array_item_at(bugs_memb, 0);

    int *ret = (int*)rhbz_bug_read_item("id", bug_item,
                                        RHBZ_MANDATORY_MEMB | RHBZ_READ_INT);
    bz->bi_id = *ret;
    free(ret);
    bz->bi_product = rhbz_bug_read_item("product", bug_item,
                                        RHBZ_MANDATORY_MEMB | RHBZ_READ_STR);
    bz->bi_reporter = rhbz_bug_read_item("creator", bug_item,
                                         RHBZ_MANDATORY_MEMB | RHBZ_READ_STR);
    bz->bi_status = rhbz_bug_read_item("status", bug_item,
                                       RHBZ_MANDATORY_MEMB | RHBZ_READ_STR);
    bz->bi_resolution = rhbz_bug_read_item("resolution", bug_item,
                                           RHBZ_READ_STR);
    bz->bi_platform = rhbz_bug_read_item("platform", bug_item,
                                           RHBZ_READ_STR);

    if (strcmp(bz->bi_status, "CLOSED") == 0 && !bz->bi_resolution)
        error_msg_and_die(_("Bug %i is CLOSED, but it has no RESOLUTION"), bz->bi_id);

    ret = (int*)rhbz_bug_read_item("dupe_of", bug_item,
                                   RHBZ_READ_INT);
    if (strcmp(bz->bi_status, "CLOSED") == 0
        && strcmp(bz->bi_resolution, "DUPLICATE") == 0
        && !ret)
    {
        error_msg_and_die(_("Bug %i is CLOSED as DUPLICATE, but it has no DUP_ID"),
                            bz->bi_id);
    }

    bz->bi_dup_id = (ret) ? *ret: -1;
    free(ret);

    bz->bi_cc_list = rhbz_bug_cc(bug_item);

    bz->bi_comments = rhbz_comments(ax, bug_id);
    bz->bi_best_bt_rating = find_best_bt_rating_in_comments(bz->bi_comments);

    xmlrpc_DECREF(bugs_memb);
    xmlrpc_DECREF(bug_item);
    xmlrpc_DECREF(xml_bug_response);

    return bz;
}
Exemple #16
0
/*
 * c_entries --
 *	read .c and .h files and call appropriate routines
 */
void
c_entries(void)
{
	int	c;			/* current character */
	int	level;			/* brace level */
	int	token;			/* if reading a token */
	int	t_def;			/* if reading a typedef */
	int	t_level;		/* typedef's brace level */
	char	*sp;			/* buffer pointer */
	char	tok[MAXTOKEN];		/* token buffer */

	lineftell = ftell(inf);
	sp = tok; token = t_def = NO; t_level = -1; level = 0; lineno = 1;
	while (GETC(!=, EOF)) {
		switch (c) {
		/*
		 * Here's where it DOESN'T handle: {
		 *	foo(a)
		 *	{
		 *	#ifdef notdef
		 *		}
		 *	#endif
		 *		if (a)
		 *			puts("hello, world");
		 *	}
		 */
		case '{':
			++level;
			goto endtok;
		case '}':
			/*
			 * if level goes below zero, try and fix
			 * it, even though we've already messed up
			 */
			if (--level < 0)
				level = 0;
			goto endtok;

		case '\n':
			SETLINE;
			/*
			 * the above 3 cases are similar in that they
			 * are special characters that also end tokens.
			 */
	endtok:			if (sp > tok) {
				*sp = EOS;
				token = YES;
				sp = tok;
			}
			else
				token = NO;
			continue;

		/*
		 * We ignore quoted strings and character constants
		 * completely.
		 */
		case '"':
		case '\'':
			skip_string(c);
			break;

		/*
		 * comments can be fun; note the state is unchanged after
		 * return, in case we found:
		 *	"foo() XX comment XX { int bar; }"
		 */
		case '/':
			if (GETC(==, '*') || c == '/') {
				skip_comment(c);
				continue;
			}
			(void)ungetc(c, inf);
			c = '/';
			goto storec;

		/* hash marks flag #define's. */
		case '#':
			if (sp == tok) {
				hash_entry();
				break;
			}
			goto storec;

		/*
		 * if we have a current token, parenthesis on
		 * level zero indicates a function.
		 */
		case '(':
			if (!level && token) {
				int	curline;

				if (sp != tok)
					*sp = EOS;
				/*
				 * grab the line immediately, we may
				 * already be wrong, for example,
				 *	foo\n
				 *	(arg1,
				 */
				getline();
				curline = lineno;
				if (func_entry()) {
					++level;
					pfnote(tok, curline);
				}
				break;
			}
			goto storec;

		/*
		 * semi-colons indicate the end of a typedef; if we find a
		 * typedef we search for the next semi-colon of the same
		 * level as the typedef.  Ignoring "structs", they are
		 * tricky, since you can find:
		 *
		 *	"typedef long time_t;"
		 *	"typedef unsigned int u_int;"
		 *	"typedef unsigned int u_int [10];"
		 *
		 * If looking at a typedef, we save a copy of the last token
		 * found.  Then, when we find the ';' we take the current
		 * token if it starts with a valid token name, else we take
		 * the one we saved.  There's probably some reasonable
		 * alternative to this...
		 */
		case ';':
			if (t_def && level == t_level) {
				t_def = NO;
				getline();
				if (sp != tok)
					*sp = EOS;
				pfnote(tok, lineno);
				break;
			}
			goto storec;

		/*
		 * store characters until one that can't be part of a token
		 * comes along; check the current token against certain
		 * reserved words.
		 */
		default:
			/* ignore whitespace */
			if (c == ' ' || c == '\t') {
				int save = c;
				while (GETC(!=, EOF) && (c == ' ' || c == '\t'))
					;
				if (c == EOF)
					return;
				(void)ungetc(c, inf);
				c = save;
			}
	storec:		if (!intoken(c)) {
				if (sp == tok)
					break;
				*sp = EOS;
				if (tflag) {
					/* no typedefs inside typedefs */
					if (!t_def &&
						   !memcmp(tok, "typedef",8)) {
						t_def = YES;
						t_level = level;
						break;
					}
					/* catch "typedef struct" */
					if ((!t_def || t_level < level)
					    && (!memcmp(tok, "struct", 7)
					    || !memcmp(tok, "union", 6)
					    || !memcmp(tok, "enum", 5))) {
						/*
						 * get line immediately;
						 * may change before '{'
						 */
						getline();
						if (str_entry(c))
							++level;
						break;
						/* } */
					}
				}
				sp = tok;
			}
			else if (sp != tok || begtoken(c)) {
				if (sp == tok + sizeof tok - 1)
					/* Too long -- truncate it */
					*sp = EOS;
				else 
					*sp++ = c;
				token = YES;
			}
			continue;
		}

		sp = tok;
		token = NO;
	}