diff -r 28c358053693 -r 8aa32fa19a8f branches/gmyth-0.1b/src/gmyth_http.c --- a/branches/gmyth-0.1b/src/gmyth_http.c Wed Feb 14 23:06:17 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,343 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_http.c - * - * @brief

GMythHttp class provides a wrapper to access - * data from the database using http+xml - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza <@indt.org.br> - * - */ -/* - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include - -#include "gmyth_http.h" -#include "gmyth_debug.h" -#include "gmyth_socket.h" - - -xmlXPathObjectPtr -getnodeset(xmlDocPtr doc, xmlChar *xpath) -{ - - xmlXPathContextPtr context; - xmlXPathObjectPtr result; - - context = xmlXPathNewContext(doc); - result = xmlXPathEvalExpression(xpath, context); - - if(xmlXPathNodeSetIsEmpty(result->nodesetval)) - { - g_fprintf(stderr, "Error: No result at XPath\n"); - return NULL; - } - - xmlXPathFreeContext(context); - return result; -} - - -xmlDocPtr XMLParse (const char *content, int length) -{ - xmlDocPtr doc; /* the resulting document tree */ - - doc = xmlReadMemory(content, length, NULL, NULL, 0); - if (doc == NULL) - { - g_fprintf(stderr, "Error: Failed to parse XML document\n"); - return NULL; - } - - return doc; -} - -xmlXPathObjectPtr getXPath (xmlChar *xpath, xmlDocPtr doc) -{ - xmlXPathObjectPtr result; - result = getnodeset(doc, xpath); - return result; -} - -/** Retrieves the Progam List from the Channel - * - * @param nodeTab A pointer to a node inside the XML - * @return A GSList containing a list of all the programs - */ -GSList* get_Program_List(xmlNodePtr node) -{ - GSList* program_list = NULL; - - while (node != NULL) - { - if (g_ascii_strcasecmp((char *)node->name, "text") != 0) - { - GMythProgram* program = (GMythProgram*)g_malloc(sizeof(struct _GMythProgram)); - - program->title = g_string_new((char *)xmlGetProp(node, (xmlChar *)"title")); - program->subtitle = g_string_new((char *)xmlGetProp(node, (xmlChar *)"subtitle")); - program->catType = g_string_new((char *)xmlGetProp(node, (xmlChar *)"catType")); - program->category = g_string_new((char *)xmlGetProp(node, (xmlChar *)"category")); - - sscanf ((char *)xmlGetProp(node, (xmlChar *)"repeat"), "%d", &(program->repeat)); - - program->startTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(node, \ - (xmlChar *)"startTime")); - program->endTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(node, \ - (xmlChar *)"endTime")); - - program_list = g_slist_append(program_list, program); - } - - node = node->next; - } - - return program_list; -} - -/** Retrieves the Channel List from the ProgramGuide - * - * @param node A pointer to a node inside the XML - * @param epg The struct where is the current epg - * @return The epg from "param" updated - */ -void get_Channel_List (xmlNodePtr node, GMythEpg* epg) -{ - int i; - epg->channelList = NULL; - - for (i=1; i <= epg->numOfChannels; i++) - { - GMythChannel* channel = (GMythChannel*)g_malloc(sizeof(struct _GMythChannel)); - - channel->channelName = g_string_new((char *)xmlGetProp(node, (xmlChar *)"channelName")); - channel->chanNum = g_string_new((char *)xmlGetProp(node, (xmlChar *)"chanNum")); - - sscanf ((char *)xmlGetProp(node, (xmlChar *)"chanId"), "%d", &(channel->chanId)); - sscanf ((char *)xmlGetProp(node, (xmlChar *)"callSign"), "%d", &(channel->callSign)); - - channel->programList = get_Program_List(node->children); - - epg->channelList = g_slist_append(epg->channelList, channel); - } -} - -/** Retrieves the properties from the ProgramGuide - * - * @param nodeTab A pointer to a node inside the XML - * @param epg The struct where is the current epg - * @return The epg from "param" updated - */ -void get_ProgramGuide_Properties (xmlNodePtr nodeTab, GMythEpg* epg) -{ - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"startChanId"), "%d", &(epg->startChanId)); - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"endChanId"), "%d", &(epg->endChanId)); - - epg->version = g_string_new((char *)xmlGetProp(nodeTab, (xmlChar *)"version")); - - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"protoVer"), "%d", &(epg->protoVer)); - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"totalCount"), "%d", &(epg->totalCount)); - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"numOfChannels"), "%d", &(epg->numOfChannels)); - - epg->asOf = gmyth_util_string_to_time_val ((char *)xmlGetProp(nodeTab, (xmlChar *)"asOf")); - epg->startTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(nodeTab, (xmlChar *)"startTime")); - epg->endTime = gmyth_util_string_to_time_val ((char *)xmlGetProp(nodeTab, (xmlChar *)"endTime")); - - sscanf ((char *)xmlGetProp(nodeTab, (xmlChar *)"details"), "%d", &(epg->details)); - - // go to Channel section and retrieve Channels and Programs - get_Channel_List(nodeTab->children->next->children->next, epg); -} - -/** Aux function to retrieve the Eletronic Program Guide - * - * @param doc An XML document (xmlDocPtr) - * @return The epg - */ -void getEpg (xmlDocPtr doc, GMythEpg* epg) -{ - xmlXPathObjectPtr result; - xmlNodeSetPtr nodeset; - xmlChar *keyword; - - int i; - result = getXPath((xmlChar *)"/*", doc); - - if (result) - { - nodeset = result->nodesetval; - for (i=0; i < nodeset->nodeNr; i++) - { - keyword = (xmlChar*)nodeset->nodeTab[i]->name; - if (g_ascii_strcasecmp((char *)keyword, "ProgramGuide") == 0) - get_ProgramGuide_Properties(nodeset->nodeTab[i], epg); - } - xmlXPathFreeObject (result); - } - -} - -/** Retrieves the Eletronic Program Guide from the backend - * - * @param doc An XML document (xmlDocPtr) - * @return The epg - */ -GMythEpg retrieve_epg (GMythBackendInfo *backend_info, int port, \ - GTimeVal* StartTime, GTimeVal* EndTime, \ - gint StartChanId, gint NumOfChannels, \ - gchar* Details) -{ - GMythEpg epg; - MemoryStruct chunk; - - chunk.memory=NULL; /* we expect realloc(NULL, size) to work */ - chunk.size = 0; /* no data at this point */ - - gchar* starttime = (gchar*)g_malloc(sizeof(gchar)*20); - starttime = gmyth_util_time_to_mythformat_from_time_val(StartTime); - - gchar* endtime = (gchar*)g_malloc(sizeof(gchar)*20); - endtime = gmyth_util_time_to_mythformat_from_time_val(EndTime); - - GString* command = g_string_new(""); - g_string_printf(command, "getProgramGuide?StartTime=%s&EndTime=%s&StartChanId=%d" - "&NumOfChannels=%d&Details=%s", starttime, endtime, \ - StartChanId, NumOfChannels, Details); - - chunk = gmyth_http_request(backend_info, command); - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); - getEpg(doc, &epg); - free(chunk.memory); - - return epg; -} - -/* Aux functions got from libcurl */ -void *myrealloc (void *ptr, size_t size) -{ - /* There might be a realloc() out there that doesn't like reallocing - NULL pointers, so we take care of it here */ - if(ptr) - return realloc(ptr, size); - else - return malloc(size); -} - -size_t -WriteMemoryCallback (void *ptr, size_t size, size_t nmemb, void *data) -{ - size_t realsize = size * nmemb; - MemoryStruct *mem = (struct _MemoryStruct *)data; - - mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1); - if (mem->memory) - { - memcpy(&(mem->memory[mem->size]), ptr, realsize); - mem->size += realsize; - mem->memory[mem->size] = 0; - } - - return realsize; -} - -/** Create a String containing the URL with the command - * - * @param command A string with the command - * @param variables Vars to use with their values \ - * MUST FINISH WITH NULL!!! - * @return The response - */ -GString* gmyth_http_create_command (GString *command, ...) -{ - va_list args; - va_start(args, command); - gchar* s = NULL; - - g_string_append(command, "?"); - - /* Sintax: var, value */ - while ( (s = va_arg(args, gchar *)) != NULL ) - { - g_string_append(command, s); - g_string_append(command, "="); - s = va_arg(args, gchar *); - g_string_append(command, s); - g_string_append(command, "&"); - } - - free(s); - va_end(args); - - return command; -} - -/** Send HTTP Command and receives the result of it - * - * @return A string with the response from the server - * NULL if there is no response. - */ -MemoryStruct gmyth_http_request (GMythBackendInfo *backend_info, GString *command) -{ - LIBXML_TEST_VERSION - - size_t size = strlen(backend_info->hostname) + strlen(command->str) + 13; - gchar *URL = (gchar *)g_malloc(sizeof(gchar)*size); - g_snprintf(URL, size+1, "http://%s:6544/%s", backend_info->hostname, command->str); - - CURL *curl_handle; - - MemoryStruct chunk; - - chunk.memory=NULL; /* we expect realloc(NULL, size) to work */ - chunk.size = 0; /* no data at this point */ - - curl_global_init(CURL_GLOBAL_ALL); - - /* init the curl session */ - curl_handle = curl_easy_init(); - - /* specify URL to get */ - curl_easy_setopt(curl_handle, CURLOPT_URL, URL); - - /* send all data to this function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); - - /* we pass our 'chunk' struct to the callback function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); - - /* some servers don't like requests that are made without a user-agent - field, so we provide one */ - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); - - /* get it! */ - curl_easy_perform(curl_handle); - - /* cleanup curl stuff */ - curl_easy_cleanup(curl_handle); - - return chunk; -}