# url-xml.c

Go to the documentation of this file.

    00001
    00010 /* $Progeny$
    00011  *
    00012  * AUTHOR: John R. Daily <jdaily@progeny.com>
    00013  *
    00014  * Copyright 2002 Progeny Linux Systems, Inc.
    00015  * Copyright 2002 Hewlett-Packard Company
    00016  *
    00017  * Permission is hereby granted, free of charge, to any person obtaining a
    00018  * copy of this software and associated documentation files (the "Software"),
    00019  * to deal in the Software without restriction, including without limitation
    00020  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    00021  * and/or sell copies of the Software, and to permit persons to whom the
    00022  * Software is furnished to do so, subject to the following conditions:
    00023  *
    00024  * The above copyright notice and this permission notice shall be included in
    00025  * all copies or substantial portions of the Software.
    00026  *
    00027  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00028  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00029  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
    00030  * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00031  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    00032  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    00033  * DEALINGS IN THE SOFTWARE.
    00034  */
    00035
    00036 #include "config.h"
    00037
    00038 #include <assert.h>
    00039 #include <string.h>
    00040
    00041 #include <expat.h>
    00042
    00043 #include <discover/discover.h>
    00044 #include <discover/discover-conf.h>
    00045 #include <discover/discover-xml.h>
    00046
    00047 #include <discover/load-url.h>
    00048 #include <discover/url-xml.h>
    00049 #include <discover/utils.h>
    00050
    00052 enum state { START, DISCOVER_DATA };
    00053 struct context {
    00054     enum state state;
    00055
    00056     discover_xml_url_t *urls;
    00057     int unknown_level; /* How deep are we into unknown XML tags? */
    00058 };
    00059
    00060 static discover_xml_url_t *xml_urls = NULL;
    00061 static discover_xml_url_t *data_urls[BUS_COUNT][3];
    00062
    00063 static char *known_url_elements[] = {
    00064     "location",
    00065     "discover-data",
    00066     NULL
    00067 };
    00068
    00069
    00070 static bool
    00071 unknown_url_element(const XML_Char * const tag)
    00072 {
    00073     int i;
    00074     for (i = 0; known_url_elements[i] != NULL; i++) {
    00075         if (strcmp(tag, known_url_elements[i]) == 0)
    00076             return false;
    00077     }
    00078     return true;
    00079 }
    00080
    00081 static void
    00082 add_location(struct context *context, const XML_Char *attrs[])
    00083 {
    00084     discover_xml_url_t *new;
    00085     int i;
    00086
    00087     assert(context != NULL);
    00088     assert(attrs != NULL);
    00089
    00090     new = discover_xml_url_new();
    00091
    00092     for (i = 0; attrs[i]; i += 2) {
    00093         if (strcmp(attrs[i], "url") == 0) {
    00094             new->url = _discover_xstrdup(attrs[i + 1]);
    00095         } else if (strcmp(attrs[i], "bus") == 0) {
    00096             new->bus = _discover_xstrdup(attrs[i + 1]);
    00097         } else if (strcmp(attrs[i], "type") == 0) {
    00098             new->type = _discover_xstrdup(attrs[i + 1]);
    00099         }
    00100     }
    00101
    00102     if (context->urls) {
    00103         if (context->urls->last) {
    00104             context->urls->last->next = new;
    00105         } else {
    00106             context->urls->next = new;
    00107         }
    00108         context->urls->last = new;
    00109     } else {
    00110         context->urls = new;
    00111         context->urls->next = context->urls->last = NULL;
    00112     }
    00113 }
    00114
    00115 static void
    00116 start_element(void *ctx, const XML_Char *name, const XML_Char *attrs[])
    00117 {
    00118     struct context *context = ctx;
    00119
    00120     assert(context != NULL);
    00121     assert(name != NULL);
    00122
    00123     if (unknown_url_element(name)) {
    00124         context->unknown_level++;
    00125         return;
    00126     }
    00127
    00128     if (context->unknown_level > 0) {
    00129         return;
    00130     }
    00131
    00132     switch (context->state) {
    00133     case START:
    00134         if (strcmp(name, "discover-data") == 0) {
    00135             context->state = DISCOVER_DATA;
    00136         }
    00137         break;
    00138
    00139     case DISCOVER_DATA:
    00140         if (strcmp(name, "location") == 0) {
    00141             add_location(context, attrs);
    00142         }
    00143         break;
    00144     }
    00145 }
    00146
    00147 static void
    00148 end_element(void *ctx, const XML_Char *name)
    00149 {
    00150     struct context *context = ctx;
    00151
    00152     assert(context != NULL);
    00153     assert(name != NULL);
    00154
    00155     if (unknown_url_element(name)) {
    00156         context->unknown_level--;
    00157         return;
    00158     }
    00159
    00160     if (context->unknown_level > 0) {
    00161         return;
    00162     }
    00163
    00164     /*
    00165      * We don't have any end tags to worry about, but if we did, they
    00166      * would be handled here.
    00167      */
    00168 }
    00169
    00181 discover_xml_url_t *
    00182 discover_xml_get_urls(discover_error_t *status)
    00183 {
    00184     discover_xml_url_t *urls, *i;
    00185     XML_Parser parser;
    00186     struct context context;
    00187     int loaded_urls = 0;
    00188
    00189     assert(status != NULL);
    00190
    00191     status->code = 0;
    00192
    00193     if (!xml_urls) {
    00194         context.state = START;
    00195         context.urls = NULL;
    00196         context.unknown_level = 0;
    00197
    00198         urls = discover_conf_get_urls(status);
    00199         if (status->code != 0) {
    00200             return NULL;
    00201         }
    00202
    00203         for (i = urls;
    00204              i;
    00205              i = i->next) {
    00206             parser = XML_ParserCreate(NULL);
    00207             XML_SetElementHandler(parser, start_element, end_element);
    00208             XML_SetUserData(parser, &context);
    00209
    00210             if (_discover_load_url(i->url, parser)) {
    00211                 loaded_urls++;
    00212             }
    00213
    00214         }
    00215
    00216         if (loaded_urls == 0) {
    00217             discover_xml_url_free(context.urls);
    00218             XML_ParserFree(parser);
    00219             status->code = DISCOVER_EIO;
    00220             return NULL;
    00221         }
    00222
    00223         if (!XML_Parse(parser, "", 0, 1)) {
    00224             status->code = DISCOVER_EXML;
    00225         }
    00226
    00227         XML_ParserFree(parser);
    00228         xml_urls = context.urls;
    00229
    00230         /* This must be done here because there could be bogus status left
    00231          * over from the XML_Parse check above.  (We assume something good
    00232          * happened by this point.)
    00233          */
    00234         status->code = 0;
    00235     }
    00236
    00237     return xml_urls;
    00238 }
    00239
    00243 void
    00244 discover_xml_free_urls(void)
    00245 {
    00246     if (xml_urls) {
    00247         discover_xml_url_free(xml_urls);
    00248         xml_urls = NULL;
    00249     }
    00250 }
    00251
    00260 discover_xml_url_t *
    00261 discover_xml_get_data_urls(discover_bus_t bus, discover_filetype_t filetype,
    00262                            discover_error_t *status)
    00263 {
    00264     discover_xml_url_t *urls, *i, *new;
    00265     char *busname = discover_conf_get_bus_name(bus);
    00266     char *filetypename = discover_conf_get_filetype_name(filetype);
    00267
    00268     assert(status != NULL);
    00269     assert(busname != NULL);
    00270
    00271     status->code = 0;
    00272
    00273     if (!data_urls[bus][filetype]) {
    00274         urls = discover_xml_get_urls(status);
    00275         if (status->code != 0) {
    00276             return NULL;
    00277         }
    00278
    00279         status->code = DISCOVER_EDATANOTFOUND;
    00280         for (i = urls;
    00281              i;
    00282              i = i->next) {
    00283             if (strcmp(i->bus, busname) == 0
    00284                 && strcmp(i->type, filetypename) == 0) {
    00285
    00286                 status->code = 0;
    00287
    00288                 new = discover_xml_url_new();
    00289                 discover_xml_url_copy(i, new);
    00290
    00291                 if (data_urls[bus][filetype]) {
    00292                     data_urls[bus][filetype]->last->next = new;
    00293                     data_urls[bus][filetype]->last = new;
    00294                 } else {
    00295                     data_urls[bus][filetype] = new;
    00296                     data_urls[bus][filetype]->last = new;
    00297                     data_urls[bus][filetype]->next = NULL;
    00298                 }
    00299             }
    00300         }
    00301     }
    00302
    00303     return data_urls[bus][filetype];
    00304 }
    00305
    00309 void
    00310 discover_xml_free_data_urls(void)
    00311 {
    00312     int b, f;
    00313
    00314     for(b = 0; b < BUS_COUNT; b++) {
    00315         for(f = 0; f < 3; f++) {
    00316             discover_xml_url_free(data_urls[b][f]);
    00317             data_urls[b][f] = NULL;
    00318         }
    00319     }
    00320 }
    00321
    00325 discover_xml_url_t *
    00326 discover_xml_url_new(void)
    00327 {
    00328     discover_xml_url_t *new;
    00329
    00330     new = _discover_xmalloc(sizeof(discover_xml_url_t));
    00331
    00332     new->url = NULL;
    00333     new->bus = NULL;
    00334     new->type = NULL;
    00335     new->label = NULL;
    00336     new->next = NULL;
    00337     new->last = NULL;
    00338
    00339     return new;
    00340 }
    00341
    00348 void
    00349 discover_xml_url_copy(discover_xml_url_t *src,
    00350                       discover_xml_url_t *dst)
    00351 {
    00352     assert(src != NULL);
    00353     assert(dst != NULL);
    00354
    00355     if (src->url) {
    00356         dst->url = _discover_xstrdup(src->url);
    00357     }
    00358
    00359     if (src->bus) {
    00360         dst->bus = _discover_xstrdup(src->bus);
    00361     }
    00362
    00363     if (src->type) {
    00364         dst->type = _discover_xstrdup(src->type);
    00365     }
    00366
    00367     if (src->label) {
    00368         dst->label = _discover_xstrdup(src->label);
    00369     }
    00370 }
    00371
    00375 char *
    00376 discover_xml_url_get_url(discover_xml_url_t *url)
    00377 {
    00378     assert(url != NULL);
    00379
    00380     return url->url;
    00381 }
    00382
    00386 char *
    00387 discover_xml_url_get_label(discover_xml_url_t *url)
    00388 {
    00389     assert(url != NULL);
    00390
    00391     return url->label;
    00392 }
    00393
    00397 char *
    00398 discover_xml_url_get_bus(discover_xml_url_t *url)
    00399 {
    00400     assert(url != NULL);
    00401
    00402     return url->bus;
    00403 }
    00404
    00408 char *
    00409 discover_xml_url_get_type(discover_xml_url_t *url)
    00410 {
    00411     assert(url != NULL);
    00412
    00413     return url->type;
    00414 }
    00415
    00419 discover_xml_url_t *
    00420 discover_xml_url_get_next(discover_xml_url_t *url)
    00421 {
    00422     assert(url != NULL);
    00423
    00424     return url->next;
    00425 }
    00426
    00430 discover_xml_url_t *
    00431 discover_xml_url_get_last(discover_xml_url_t *url)
    00432 {
    00433     assert(url != NULL);
    00434
    00435     return url->last;
    00436 }
    00437
    00443 void
    00444 discover_xml_url_free(discover_xml_url_t *urls)
    00445 {
    00446     discover_xml_url_t *url, *last;
    00447
    00448     last = NULL;
    00449
    00450     for (url = urls;
    00451          url;
    00452          url = url->next) {
    00453         if (url->url) {
    00454             free(url->url);
    00455         }
    00456
    00457         if (url->bus) {
    00458             free(url->bus);
    00459         }
    00460
    00461         if (url->type) {
    00462             free(url->type);
    00463         }
    00464
    00465         if (url->label) {
    00466             free(url->label);
    00467         }
    00468
    00469         if (last) {
    00470             free(last);
    00471         }
    00472         last = url;
    00473     }
    00474
    00475     if (last) {
    00476         free(last);
    00477     }
    00478 }
    00479