00001
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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;
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
00166
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
00231
00232
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