/* * Copyright (c) 2003-2007 Andrea Luzzardi * * This file is part of the pam_usb project. pam_usb is free software; * you can redistribute it and/or modify it under the terms of the GNU General * Public License version 2, as published by the Free Software Foundation. * * pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin * Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "mem.h" #include "xpath.h" #include "log.h" static xmlXPathObject *pusb_xpath_match(xmlDocPtr doc, const char *path) { xmlXPathContext *context = NULL; xmlXPathObject *result = NULL; context = xmlXPathNewContext(doc); if (context == NULL) { log_error("Unable to create XML context\n"); return (NULL); } result = xmlXPathEvalExpression((xmlChar *)path, context); xmlXPathFreeContext(context); if (result == NULL) { log_error("Error in xmlXPathEvalExpression\n"); return (NULL); } if (xmlXPathNodeSetIsEmpty(result->nodesetval)) { xmlXPathFreeObject(result); return (NULL); } return (result); } static int pusb_xpath_strip_string(char *dest, const char *src, size_t size) { int first_char = -1; int last_char = -1; int i; for (i = 0; src[i]; ++i) { if (isspace(src[i])) continue ; if (first_char == -1) first_char = i; last_char = i; } if (first_char == -1 || last_char == -1) return (0); if ((last_char - first_char) > (size - 1)) { log_error("Device name is too long: %s", src); return (0); } memset(dest, 0x0, size); strncpy(dest, &(src[first_char]), last_char - first_char + 1); return (1); } int pusb_xpath_get_string(xmlDocPtr doc, const char *path, char *value, size_t size) { xmlXPathObject *result = NULL; xmlNode *node = NULL; xmlChar *result_string = NULL; if (!(result = pusb_xpath_match(doc, path))) return (0); if (result->nodesetval->nodeNr > 1) { xmlXPathFreeObject(result); log_debug("Syntax error: %s: more than one record found\n", path); return (0); } node = result->nodesetval->nodeTab[0]->xmlChildrenNode; result_string = xmlNodeListGetString(doc, node, 1); if (!result_string) { xmlXPathFreeObject(result); log_debug("Empty value for %s\n", path); return (0); } if (!pusb_xpath_strip_string(value, (const char *)result_string, size)) { xmlFree(result_string); xmlXPathFreeObject(result); log_debug("Result for %s (%s) is too long (max: %d)\n", path, (const char *)result_string, size); return (0); } xmlFree(result_string); xmlXPathFreeObject(result); return (1); } int pusb_xpath_get_string_from(xmlDocPtr doc, const char *base, const char *path, char *value, size_t size) { char *xpath = NULL; size_t xpath_size; int retval; xpath_size = strlen(base) + strlen(path) + 1; xpath = xmalloc(xpath_size); memset(xpath, 0x00, xpath_size); snprintf(xpath, xpath_size, "%s%s", base, path); retval = pusb_xpath_get_string(doc, xpath, value, size); if (retval) log_debug("%s%s -> %s\n", base, path, value); xfree(xpath); return (retval); } int pusb_xpath_get_bool(xmlDocPtr doc, const char *path, int *value) { char ret[6]; /* strlen("false") + 1 */ if (!pusb_xpath_get_string(doc, path, ret, sizeof(ret))) return (0); if (!strcmp(ret, "true")) { *value = 1; return (1); } if (!strcmp(ret, "false")) { *value = 0; return (1); } log_debug("Expecting a boolean, got %s\n", ret); return (0); } int pusb_xpath_get_bool_from(xmlDocPtr doc, const char *base, const char *path, int *value) { char *xpath = NULL; size_t xpath_size; int retval; xpath_size = strlen(base) + strlen(path) + 1; xpath = xmalloc(xpath_size); memset(xpath, 0x00, xpath_size); snprintf(xpath, xpath_size, "%s%s", base, path); retval = pusb_xpath_get_bool(doc, xpath, value); xfree(xpath); return (retval); } int pusb_xpath_get_time(xmlDocPtr doc, const char *path, time_t *value) { char ret[64]; char *last; int coef; if (!pusb_xpath_get_string(doc, path, ret, sizeof(ret))) return (0); last = &(ret[strlen(ret) - 1]); coef = 1; if (*last == 's') coef = 1; else if (*last == 'm') coef = 60; else if (*last == 'h') coef = 3600; else if (*last == 'd') coef = 3600 * 24; else if (!isdigit(*last)) { log_debug("Expecting a time modifier, got %c\n", *last); return (0); } if (!isdigit(*last)) *last = '\0'; *value = atoi(ret) * coef; return (0); } int pusb_xpath_get_time_from(xmlDocPtr doc, const char *base, const char *path, time_t *value) { char *xpath = NULL; size_t xpath_size; int retval; xpath_size = strlen(base) + strlen(path) + 1; xpath = xmalloc(xpath_size); memset(xpath, 0x00, xpath_size); snprintf(xpath, xpath_size, "%s%s", base, path); retval = pusb_xpath_get_time(doc, xpath, value); xfree(xpath); return (retval); } int pusb_xpath_get_int(xmlDocPtr doc, const char *path, int *value) { char ret[64]; if (!pusb_xpath_get_string(doc, path, ret, sizeof(ret))) return (0); *value = atoi(ret); return (1); } int pusb_xpath_get_int_from(xmlDocPtr doc, const char *base, const char *path, int *value) { char *xpath = NULL; size_t xpath_size; int retval; xpath_size = strlen(base) + strlen(path) + 1; xpath = xmalloc(xpath_size); memset(xpath, 0x00, xpath_size); snprintf(xpath, xpath_size, "%s%s", base, path); retval = pusb_xpath_get_int(doc, xpath, value); xfree(xpath); return (retval); }