viruri.c 3.9 KB
Newer Older
M
Martin Kletzander 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * viruri.c: URI parsing wrappers for libxml2 functions
 *
 * Copyright (C) 2012 Red Hat, Inc.
 *
 * See COPYING.LIB for the License of this software
 */

#include <config.h>

#include "viruri.h"

#include "memory.h"
#include "util.h"
15 16 17 18 19 20 21 22
#include "virterror_internal.h"

#define VIR_FROM_THIS VIR_FROM_URI

#define virURIReportError(code, ...)                                    \
    virReportErrorHelper(VIR_FROM_THIS, code, __FILE__,                 \
                         __FUNCTION__, __LINE__, __VA_ARGS__)

M
Martin Kletzander 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

/**
 * virURIParse:
 * @uri: URI to parse
 *
 * Wrapper for xmlParseURI
 *
 * Unfortunately there are few things that should be managed after
 * parsing the URI. Fortunately there is only one thing now and its
 * removing of square brackets around IPv6 addresses.
 *
 * @returns the parsed uri object with some fixes
 */
virURIPtr
virURIParse(const char *uri)
{
39 40
    xmlURIPtr xmluri;
    virURIPtr ret = NULL;
M
Martin Kletzander 已提交
41

42 43 44
    xmluri = xmlParseURI(uri);

    if (!xmluri) {
45 46 47 48 49 50
        /* libxml2 does not tell us what failed. Grr :-( */
        virURIReportError(VIR_ERR_INTERNAL_ERROR,
                          "Unable to parse URI %s", uri);
        return NULL;
    }

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
    if (VIR_ALLOC(ret) < 0)
        goto no_memory;

    if (xmluri->scheme &&
        !(ret->scheme = strdup(xmluri->scheme)))
        goto no_memory;
    if (xmluri->server &&
        !(ret->server = strdup(xmluri->server)))
        goto no_memory;
    ret->port = xmluri->port;
    if (xmluri->path &&
        !(ret->path = strdup(xmluri->path)))
        goto no_memory;
#ifdef HAVE_XMLURI_QUERY_RAW
    if (xmluri->query_raw &&
        !(ret->query = strdup(xmluri->query_raw)))
        goto no_memory;
#else
    if (xmluri->query &&
        !(ret->query = strdup(xmluri->query)))
        goto no_memory;
#endif
    if (xmluri->fragment &&
        !(ret->fragment = strdup(xmluri->fragment)))
        goto no_memory;


M
Martin Kletzander 已提交
78
    /* First check: does it even make sense to jump inside */
79
    if (ret->server != NULL &&
M
Martin Kletzander 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
        ret->server[0] == '[') {
        size_t length = strlen(ret->server);

        /* We want to modify the server string only if there are
         * square brackets on both ends and inside there is IPv6
         * address. Otherwise we could make a mistake by modifying
         * something other than an IPv6 address. */
        if (ret->server[length - 1] == ']' && strchr(ret->server, ':')) {
            memmove(&ret->server[0], &ret->server[1], length - 2);
            ret->server[length - 2] = '\0';
        }
        /* Even after such modification, it is completely ok to free
         * the uri with xmlFreeURI() */
    }

95 96
    xmlFreeURI(xmluri);

M
Martin Kletzander 已提交
97
    return ret;
98 99 100 101 102 103

no_memory:
    virReportOOMError();
    xmlFreeURI(xmluri);
    virURIFree(ret);
    return NULL;
M
Martin Kletzander 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116 117
}

/**
 * virURIFormat:
 * @uri: URI to format
 *
 * Wrapper for xmlSaveUri
 *
 * This function constructs back everything that @ref virURIParse
 * changes after parsing
 *
 * @returns the constructed uri as a string
 */
char *
118
virURIFormat(virURIPtr uri)
M
Martin Kletzander 已提交
119
{
120
    xmlURI xmluri;
M
Martin Kletzander 已提交
121 122 123
    char *tmpserver = NULL;
    char *ret;

124 125 126 127 128 129 130 131 132
    memset(&xmluri, 0, sizeof(xmluri));

    xmluri.scheme = uri->scheme;
    xmluri.server = uri->server;
    xmluri.port = uri->port;
    xmluri.path = uri->path;
    xmluri.query = uri->query;
    xmluri.fragment = uri->fragment;

M
Martin Kletzander 已提交
133
    /* First check: does it make sense to do anything */
134 135
    if (xmluri.server != NULL &&
        strchr(xmluri.server, ':') != NULL) {
M
Martin Kletzander 已提交
136

137
        if (virAsprintf(&tmpserver, "[%s]", xmluri.server) < 0)
M
Martin Kletzander 已提交
138 139
            return NULL;

140
        xmluri.server = tmpserver;
M
Martin Kletzander 已提交
141 142
    }

143
    ret = (char *)xmlSaveUri(&xmluri);
144 145 146 147
    if (!ret) {
        virReportOOMError();
        goto cleanup;
    }
M
Martin Kletzander 已提交
148

149
cleanup:
150
    VIR_FREE(tmpserver);
M
Martin Kletzander 已提交
151 152 153

    return ret;
}
154 155 156 157 158 159 160 161 162 163


/**
 * virURIFree:
 * @uri: uri to free
 *
 * Frees the URI
 */
void virURIFree(virURIPtr uri)
{
164 165 166 167 168 169 170 171
    if (!uri)
        return;

    VIR_FREE(uri->scheme);
    VIR_FREE(uri->server);
    VIR_FREE(uri->path);
    VIR_FREE(uri->query);
    VIR_FREE(uri);
172
}