1.1 --- a/branches/gmyth-0.1b/src/gmyth_http.c Wed Feb 14 23:06:17 2007 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,343 +0,0 @@
1.4 -/**
1.5 - * GMyth Library
1.6 - *
1.7 - * @file gmyth/gmyth_http.c
1.8 - *
1.9 - * @brief <p> GMythHttp class provides a wrapper to access
1.10 - * data from the database using http+xml
1.11 - *
1.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
1.13 - * @author Artur Duque de Souza <@indt.org.br>
1.14 - *
1.15 - */
1.16 -/*
1.17 - *
1.18 - * This program is free software; you can redistribute it and/or modify
1.19 - * it under the terms of the GNU Lesser General Public License as published by
1.20 - * the Free Software Foundation; either version 2 of the License, or
1.21 - * (at your option) any later version.
1.22 - *
1.23 - * This program is distributed in the hope that it will be useful,
1.24 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.25 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.26 - * GNU General Public License for more details.
1.27 - *
1.28 - * You should have received a copy of the GNU Lesser General Public License
1.29 - * along with this program; if not, write to the Free Software
1.30 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.31 - */
1.32 -
1.33 -#ifdef HAVE_CONFIG_H
1.34 -#include "config.h"
1.35 -#endif
1.36 -
1.37 -#include <assert.h>
1.38 -#include <libxml/parser.h>
1.39 -#include <libxml/tree.h>
1.40 -#include <libxml/xpath.h>
1.41 -
1.42 -#include "gmyth_http.h"
1.43 -#include "gmyth_debug.h"
1.44 -#include "gmyth_socket.h"
1.45 -
1.46 -
1.47 -xmlXPathObjectPtr
1.48 -getnodeset(xmlDocPtr doc, xmlChar *xpath)
1.49 -{
1.50 -
1.51 - xmlXPathContextPtr context;
1.52 - xmlXPathObjectPtr result;
1.53 -
1.54 - context = xmlXPathNewContext(doc);
1.55 - result = xmlXPathEvalExpression(xpath, context);
1.56 -
1.57 - if(xmlXPathNodeSetIsEmpty(result->nodesetval))
1.58 - {
1.59 - g_fprintf(stderr, "Error: No result at XPath\n");
1.60 - return NULL;
1.61 - }
1.62 -
1.63 - xmlXPathFreeContext(context);
1.64 - return result;
1.65 -}
1.66 -
1.67 -
1.68 -xmlDocPtr XMLParse (const char *content, int length)
1.69 -{
1.70 - xmlDocPtr doc; /* the resulting document tree */
1.71 -
1.72 - doc = xmlReadMemory(content, length, NULL, NULL, 0);
1.73 - if (doc == NULL)
1.74 - {
1.75 - g_fprintf(stderr, "Error: Failed to parse XML document\n");
1.76 - return NULL;
1.77 - }
1.78 -
1.79 - return doc;
1.80 -}
1.81 -
1.82 -xmlXPathObjectPtr getXPath (xmlChar *xpath, xmlDocPtr doc)
1.83 -{
1.84 - xmlXPathObjectPtr result;
1.85 - result = getnodeset(doc, xpath);
1.86 - return result;
1.87 -}
1.88 -
1.89 -/** Retrieves the Progam List from the Channel
1.90 - *
1.91 - * @param nodeTab A pointer to a node inside the XML
1.92 - * @return A GSList containing a list of all the programs
1.93 - */
1.94 -GSList* get_Program_List(xmlNodePtr node)
1.95 -{
1.96 - GSList* program_list = NULL;
1.97 -
1.98 - while (node != NULL)
1.99 - {
1.100 - if (g_ascii_strcasecmp((char *)node->name, "text") != 0)
1.101 - {
1.102 - GMythProgram* program = (GMythProgram*)g_malloc(sizeof(struct _GMythProgram));
1.103 -
1.104 - program->title = g_string_new((char *)xmlGetProp(node, (xmlChar *)"title"));
1.105 - program->subtitle = g_string_new((char *)xmlGetProp(node, (xmlChar *)"subtitle"));
1.106 - program->catType = g_string_new((char *)xmlGetProp(node, (xmlChar *)"catType"));
1.107 - program->category = g_string_new((char *)xmlGetProp(node, (xmlChar *)"category"));
1.108 -
1.109 - sscanf ((char *)xmlGetProp(node, (xmlChar *)"repeat"), "%d", &(program->repeat));
1.110 -
1.111 - program->startTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(node, \
1.112 - (xmlChar *)"startTime"));
1.113 - program->endTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(node, \
1.114 - (xmlChar *)"endTime"));
1.115 -
1.116 - program_list = g_slist_append(program_list, program);
1.117 - }
1.118 -
1.119 - node = node->next;
1.120 - }
1.121 -
1.122 - return program_list;
1.123 -}
1.124 -
1.125 -/** Retrieves the Channel List from the ProgramGuide
1.126 - *
1.127 - * @param node A pointer to a node inside the XML
1.128 - * @param epg The struct where is the current epg
1.129 - * @return The epg from "param" updated
1.130 - */
1.131 -void get_Channel_List (xmlNodePtr node, GMythEpg* epg)
1.132 -{
1.133 - int i;
1.134 - epg->channelList = NULL;
1.135 -
1.136 - for (i=1; i <= epg->numOfChannels; i++)
1.137 - {
1.138 - GMythChannel* channel = (GMythChannel*)g_malloc(sizeof(struct _GMythChannel));
1.139 -
1.140 - channel->channelName = g_string_new((char *)xmlGetProp(node, (xmlChar *)"channelName"));
1.141 - channel->chanNum = g_string_new((char *)xmlGetProp(node, (xmlChar *)"chanNum"));
1.142 -
1.143 - sscanf ((char *)xmlGetProp(node, (xmlChar *)"chanId"), "%d", &(channel->chanId));
1.144 - sscanf ((char *)xmlGetProp(node, (xmlChar *)"callSign"), "%d", &(channel->callSign));
1.145 -
1.146 - channel->programList = get_Program_List(node->children);
1.147 -
1.148 - epg->channelList = g_slist_append(epg->channelList, channel);
1.149 - }
1.150 -}
1.151 -
1.152 -/** Retrieves the properties from the ProgramGuide
1.153 - *
1.154 - * @param nodeTab A pointer to a node inside the XML
1.155 - * @param epg The struct where is the current epg
1.156 - * @return The epg from "param" updated
1.157 - */
1.158 -void get_ProgramGuide_Properties (xmlNodePtr nodeTab, GMythEpg* epg)
1.159 -{
1.160 - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"startChanId"), "%d", &(epg->startChanId));
1.161 - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"endChanId"), "%d", &(epg->endChanId));
1.162 -
1.163 - epg->version = g_string_new((char *)xmlGetProp(nodeTab, (xmlChar *)"version"));
1.164 -
1.165 - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"protoVer"), "%d", &(epg->protoVer));
1.166 - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"totalCount"), "%d", &(epg->totalCount));
1.167 - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"numOfChannels"), "%d", &(epg->numOfChannels));
1.168 -
1.169 - epg->asOf = gmyth_util_string_to_time_val ((char *)xmlGetProp(nodeTab, (xmlChar *)"asOf"));
1.170 - epg->startTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(nodeTab, (xmlChar *)"startTime"));
1.171 - epg->endTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(nodeTab, (xmlChar *)"endTime"));
1.172 -
1.173 - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"details"), "%d", &(epg->details));
1.174 -
1.175 - // go to Channel section and retrieve Channels and Programs
1.176 - get_Channel_List(nodeTab->children->next->children->next, epg);
1.177 -}
1.178 -
1.179 -/** Aux function to retrieve the Eletronic Program Guide
1.180 - *
1.181 - * @param doc An XML document (xmlDocPtr)
1.182 - * @return The epg
1.183 - */
1.184 -void getEpg (xmlDocPtr doc, GMythEpg* epg)
1.185 -{
1.186 - xmlXPathObjectPtr result;
1.187 - xmlNodeSetPtr nodeset;
1.188 - xmlChar *keyword;
1.189 -
1.190 - int i;
1.191 - result = getXPath((xmlChar *)"/*", doc);
1.192 -
1.193 - if (result)
1.194 - {
1.195 - nodeset = result->nodesetval;
1.196 - for (i=0; i < nodeset->nodeNr; i++)
1.197 - {
1.198 - keyword = (xmlChar*)nodeset->nodeTab[i]->name;
1.199 - if (g_ascii_strcasecmp((char *)keyword, "ProgramGuide") == 0)
1.200 - get_ProgramGuide_Properties(nodeset->nodeTab[i], epg);
1.201 - }
1.202 - xmlXPathFreeObject (result);
1.203 - }
1.204 -
1.205 -}
1.206 -
1.207 -/** Retrieves the Eletronic Program Guide from the backend
1.208 - *
1.209 - * @param doc An XML document (xmlDocPtr)
1.210 - * @return The epg
1.211 - */
1.212 -GMythEpg retrieve_epg (GMythBackendInfo *backend_info, int port, \
1.213 - GTimeVal* StartTime, GTimeVal* EndTime, \
1.214 - gint StartChanId, gint NumOfChannels, \
1.215 - gchar* Details)
1.216 -{
1.217 - GMythEpg epg;
1.218 - MemoryStruct chunk;
1.219 -
1.220 - chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
1.221 - chunk.size = 0; /* no data at this point */
1.222 -
1.223 - gchar* starttime = (gchar*)g_malloc(sizeof(gchar)*20);
1.224 - starttime = gmyth_util_time_to_mythformat_from_time_val(StartTime);
1.225 -
1.226 - gchar* endtime = (gchar*)g_malloc(sizeof(gchar)*20);
1.227 - endtime = gmyth_util_time_to_mythformat_from_time_val(EndTime);
1.228 -
1.229 - GString* command = g_string_new("");
1.230 - g_string_printf(command, "getProgramGuide?StartTime=%s&EndTime=%s&StartChanId=%d"
1.231 - "&NumOfChannels=%d&Details=%s", starttime, endtime, \
1.232 - StartChanId, NumOfChannels, Details);
1.233 -
1.234 - chunk = gmyth_http_request(backend_info, command);
1.235 - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
1.236 - getEpg(doc, &epg);
1.237 - free(chunk.memory);
1.238 -
1.239 - return epg;
1.240 -}
1.241 -
1.242 -/* Aux functions got from libcurl */
1.243 -void *myrealloc (void *ptr, size_t size)
1.244 -{
1.245 - /* There might be a realloc() out there that doesn't like reallocing
1.246 - NULL pointers, so we take care of it here */
1.247 - if(ptr)
1.248 - return realloc(ptr, size);
1.249 - else
1.250 - return malloc(size);
1.251 -}
1.252 -
1.253 -size_t
1.254 -WriteMemoryCallback (void *ptr, size_t size, size_t nmemb, void *data)
1.255 -{
1.256 - size_t realsize = size * nmemb;
1.257 - MemoryStruct *mem = (struct _MemoryStruct *)data;
1.258 -
1.259 - mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1);
1.260 - if (mem->memory)
1.261 - {
1.262 - memcpy(&(mem->memory[mem->size]), ptr, realsize);
1.263 - mem->size += realsize;
1.264 - mem->memory[mem->size] = 0;
1.265 - }
1.266 -
1.267 - return realsize;
1.268 -}
1.269 -
1.270 -/** Create a String containing the URL with the command
1.271 - *
1.272 - * @param command A string with the command
1.273 - * @param variables Vars to use with their values \
1.274 - * MUST FINISH WITH NULL!!!
1.275 - * @return The response
1.276 - */
1.277 -GString* gmyth_http_create_command (GString *command, ...)
1.278 -{
1.279 - va_list args;
1.280 - va_start(args, command);
1.281 - gchar* s = NULL;
1.282 -
1.283 - g_string_append(command, "?");
1.284 -
1.285 - /* Sintax: var, value */
1.286 - while ( (s = va_arg(args, gchar *)) != NULL )
1.287 - {
1.288 - g_string_append(command, s);
1.289 - g_string_append(command, "=");
1.290 - s = va_arg(args, gchar *);
1.291 - g_string_append(command, s);
1.292 - g_string_append(command, "&");
1.293 - }
1.294 -
1.295 - free(s);
1.296 - va_end(args);
1.297 -
1.298 - return command;
1.299 -}
1.300 -
1.301 -/** Send HTTP Command and receives the result of it
1.302 - *
1.303 - * @return A string with the response from the server
1.304 - * NULL if there is no response.
1.305 - */
1.306 -MemoryStruct gmyth_http_request (GMythBackendInfo *backend_info, GString *command)
1.307 -{
1.308 - LIBXML_TEST_VERSION
1.309 -
1.310 - size_t size = strlen(backend_info->hostname) + strlen(command->str) + 13;
1.311 - gchar *URL = (gchar *)g_malloc(sizeof(gchar)*size);
1.312 - g_snprintf(URL, size+1, "http://%s:6544/%s", backend_info->hostname, command->str);
1.313 -
1.314 - CURL *curl_handle;
1.315 -
1.316 - MemoryStruct chunk;
1.317 -
1.318 - chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
1.319 - chunk.size = 0; /* no data at this point */
1.320 -
1.321 - curl_global_init(CURL_GLOBAL_ALL);
1.322 -
1.323 - /* init the curl session */
1.324 - curl_handle = curl_easy_init();
1.325 -
1.326 - /* specify URL to get */
1.327 - curl_easy_setopt(curl_handle, CURLOPT_URL, URL);
1.328 -
1.329 - /* send all data to this function */
1.330 - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
1.331 -
1.332 - /* we pass our 'chunk' struct to the callback function */
1.333 - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
1.334 -
1.335 - /* some servers don't like requests that are made without a user-agent
1.336 - field, so we provide one */
1.337 - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
1.338 -
1.339 - /* get it! */
1.340 - curl_easy_perform(curl_handle);
1.341 -
1.342 - /* cleanup curl stuff */
1.343 - curl_easy_cleanup(curl_handle);
1.344 -
1.345 - return chunk;
1.346 -}