00001
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
00037 #include "config.h"
00038
00039 #include <sys/types.h>
00040
00041 #include <assert.h>
00042 #include <limits.h>
00043 #include <stdio.h>
00044 #include <string.h>
00045
00046 #include <expat.h>
00047
00048 #include <discover/discover.h>
00049 #include <discover/discover-xml.h>
00050
00051 #include <discover/load-url.h>
00052 #include <discover/utils.h>
00053
00055 struct discover_xml_vendor {
00056 char *id;
00057 char *name;
00058 discover_xml_vendor_t *next;
00059 };
00060
00061 static discover_xml_vendor_t *vendors[BUS_COUNT];
00062
00064 struct context {
00065 discover_xml_vendor_t **vlist;
00066
00067 int unknown_level;
00068 };
00069
00070 static char *known_vendor_elements[] = {
00071 "vendor",
00072 "vendor_list",
00073 NULL
00074 };
00075
00076
00077 static bool
00078 unknown_vendor_element(const XML_Char * const tag)
00079 {
00080 int i;
00081 for (i = 0; known_vendor_elements[i] != NULL; i++) {
00082 if (strcmp(tag, known_vendor_elements[i]) == 0)
00083 return false;
00084 }
00085 return true;
00086 }
00087
00088 static void
00089 start_element(void *ctx, const XML_Char *name, const XML_Char *attrs[])
00090 {
00091 struct context *context = ctx;
00092 int i;
00093 char *vid, *vname;
00094 discover_xml_vendor_t *next, **vlist;
00095
00096 assert(context != NULL);
00097 assert(name != NULL);
00098 assert(attrs != NULL);
00099
00100 if (unknown_vendor_element(name)) {
00101 context->unknown_level++;
00102 return;
00103 }
00104
00105 if (context->unknown_level > 0) {
00106 return;
00107 }
00108
00109 if (strcmp(name, "vendor") == 0) {
00110 vid = vname = NULL;
00111 for (i = 0; attrs[i]; i += 2) {
00112 if (strcmp(attrs[i], "id") == 0) {
00113 vid = (char *) attrs[i + 1];
00114 } else if (strcmp(attrs[i], "name") == 0) {
00115 vname = (char *) attrs[i + 1];
00116 }
00117 }
00118
00119 assert(vid != NULL);
00120 assert(vname != NULL);
00121
00122 vlist = context->vlist;
00123 next = *vlist;
00124 *vlist = discover_xml_vendor_new();
00125 (*vlist)->id = _discover_xstrdup(vid);
00126 (*vlist)->name = _discover_xstrdup(vname);
00127 (*vlist)->next = next;
00128 }
00129 }
00130
00131 static void
00132 end_element(void *ctx, const XML_Char *name)
00133 {
00134 struct context *context = ctx;
00135
00136 assert(context != NULL);
00137 assert(name != NULL);
00138
00139 if (unknown_vendor_element(name)) {
00140 context->unknown_level--;
00141 return;
00142 }
00143
00144 if (context->unknown_level > 0) {
00145 return;
00146 }
00147
00148
00149
00150
00151
00152 }
00153
00166
00167
00168
00169
00170
00171
00172 void
00173 discover_xml_merge_vendor_url(discover_xml_vendor_t **vlist,
00174 char *url, discover_error_t *status)
00175 {
00176 XML_Parser parser;
00177 struct context context;
00178
00179 assert(url != NULL);
00180 assert(status != NULL);
00181
00182 status->code = 0;
00183
00184 context.vlist = vlist;
00185 context.unknown_level = 0;
00186
00187 parser = XML_ParserCreate(NULL);
00188 XML_SetElementHandler(parser, start_element, end_element);
00189 XML_SetUserData(parser, &context);
00190
00191 if (!_discover_load_url(url, parser)) {
00192 XML_ParserFree(parser);
00193 status->code = DISCOVER_EIO;
00194 return;
00195 }
00196
00197 if (!XML_Parse(parser, "", 0, 1)) {
00198 XML_ParserFree(parser);
00199 status->code = DISCOVER_EXML;
00200 return;
00201 }
00202
00203 XML_ParserFree(parser);
00204
00205 return;
00206 }
00207
00214 discover_xml_vendor_t *
00215 discover_xml_get_vendors(discover_bus_t bus, discover_error_t *status)
00216 {
00217 discover_xml_url_t *urls, *i;
00218 char *url;
00219
00220 assert(status != NULL);
00221
00222 status->code = 0;
00223
00224 if (!vendors[bus]) {
00225 urls = discover_xml_get_data_urls(bus, VENDOR_TYPE, status);
00226 if (status->code != 0) {
00227 return NULL;
00228 }
00229
00230 for (i = urls;
00231 i;
00232 i = discover_xml_url_get_next(i)) {
00233 url = discover_xml_url_get_url(i);
00234 discover_xml_merge_vendor_url(&(vendors[bus]), url, status);
00235 if (status->code != 0) {
00236 return NULL;
00237 }
00238 }
00239 }
00240
00241 return vendors[bus];
00242 }
00243
00247 void
00248 discover_xml_free_vendors(void)
00249 {
00250 int i;
00251 for (i = 0; i < BUS_COUNT; i++) {
00252 discover_xml_vendor_free(vendors[i]);
00253 vendors[i] = NULL;
00254 }
00255 }
00256
00263 char *
00264 discover_xml_vendor_id2name(discover_xml_vendor_t *vendors, char *id)
00265 {
00266 discover_xml_vendor_t *vendor;
00267 char *name;
00268
00269 assert(vendors != NULL);
00270 assert(id != NULL);
00271
00272 name = NULL;
00273
00274 for (vendor = vendors;
00275 vendor;
00276 vendor = vendor->next) {
00277 if (strcmp(id, vendor->id) == 0) {
00278 name = vendor->name;
00279 break;
00280 }
00281 }
00282
00283 return name;
00284 }
00285
00289 char *
00290 discover_xml_vendor_get_id(discover_xml_vendor_t *vendor)
00291 {
00292 assert(vendor != NULL);
00293
00294 return vendor->id;
00295 }
00296
00300 char *
00301 discover_xml_vendor_get_name(discover_xml_vendor_t *vendor)
00302 {
00303 assert(vendor != NULL);
00304
00305 return vendor->name;
00306 }
00307
00311 discover_xml_vendor_t *
00312 discover_xml_vendor_get_next(discover_xml_vendor_t *vendor)
00313 {
00314 assert(vendor != NULL);
00315
00316 return vendor->next;
00317 }
00318
00322 discover_xml_vendor_t *
00323 discover_xml_vendor_new(void)
00324 {
00325 discover_xml_vendor_t *new;
00326
00327 new = _discover_xmalloc(sizeof(discover_xml_vendor_t));
00328
00329 new->id = NULL;
00330 new->name = NULL;
00331 new->next = NULL;
00332
00333 return new;
00334 }
00335
00341 void
00342 discover_xml_vendor_free(discover_xml_vendor_t *vendors)
00343 {
00344 discover_xml_vendor_t *vendor, *last;
00345
00346 last = NULL;
00347
00348 for (vendor = vendors;
00349 vendor;
00350 vendor = vendor->next) {
00351 if (vendor->id) {
00352 free(vendor->id);
00353 }
00354
00355 if (vendor->name) {
00356 free(vendor->name);
00357 }
00358
00359 if (last) {
00360 free(last);
00361 }
00362 last = vendor;
00363 }
00364
00365 if (last) {
00366 free(last);
00367 }
00368 }
00369
00372
00373
00374
00375
00376
00377
00378