Drizzled Public API Documentation

http_functions.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2011 Stewart Smith
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <drizzled/plugin/function.h>
00023 #include <drizzled/function/str/strfunc.h>
00024 #include <drizzled/charset.h>
00025 #include <drizzled/error.h>
00026 
00027 #include <curl/curl.h>
00028 
00029 using namespace drizzled;
00030 
00031 class HttpGetFunction :public Item_str_func
00032 {
00033   String result;
00034 public:
00035   HttpGetFunction() :Item_str_func() {}
00036   String *val_str(String *);
00037   void fix_length_and_dec();
00038   const char *func_name() const { return "http_get"; }
00039 
00040   bool check_argument_count(int n)
00041   {
00042     return n == 1;
00043   }
00044 };
00045 
00046 extern "C" size_t
00047 http_get_result_cb(void *ptr, size_t size, size_t nmemb, void *data);
00048 
00049 extern "C" size_t
00050 http_get_result_cb(void *ptr, size_t size, size_t nmemb, void *data)
00051 {
00052   size_t realsize= size * nmemb;
00053   String *result= (String *)data;
00054 
00055   result->reserve(realsize + 1);
00056   result->append((const char*)ptr, realsize);
00057 
00058   return realsize;
00059 }
00060 
00061 
00062 String *HttpGetFunction::val_str(String *str)
00063 {
00064   assert(fixed == 1);
00065   String *url = args[0]->val_str(str);
00066   CURL *curl;
00067   CURLcode retref;
00068 
00069   if ((null_value=args[0]->null_value))
00070     return NULL;
00071 
00072   curl= curl_easy_init();
00073   curl_easy_setopt(curl, CURLOPT_URL, url->c_str());
00074   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_cb);
00075   curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&result);
00076   curl_easy_setopt(curl, CURLOPT_USERAGENT, "drizzle-http-functions/1.0");
00077   retref= curl_easy_perform(curl);
00078   curl_easy_cleanup(curl);
00079 
00080   if (retref != 0)
00081     my_error(ER_GET_ERRMSG, MYF(0), retref, curl_easy_strerror(retref),
00082              "http_get");
00083 
00084   return &result;
00085 }
00086 
00087 void HttpGetFunction::fix_length_and_dec()
00088 {
00089   collation.set(args[0]->collation);
00090   max_length = ~0;
00091 }
00092 
00093 class HttpPostFunction :public Item_str_func
00094 {
00095   String result;
00096 public:
00097   HttpPostFunction() :Item_str_func() {}
00098   String *val_str(String *);
00099   void fix_length_and_dec();
00100   const char *func_name() const { return "http_post"; }
00101 
00102   bool check_argument_count(int n)
00103   {
00104     return n == 2;
00105   }
00106 };
00107 
00108 class HttpPostData
00109 {
00110 private:
00111   String *data;
00112   size_t progress;
00113 
00114 public:
00115   HttpPostData(String* d) : data(d), progress(0) {}
00116 
00117   size_t length() { return data->length(); }
00118 
00119   size_t write(void* dest, size_t size)
00120   {
00121     size_t to_write= size;
00122 
00123     if ((data->length() - progress) < to_write)
00124       to_write= data->length() - progress;
00125 
00126     memcpy(dest, data->ptr() + progress, to_write);
00127 
00128     progress+= to_write;
00129 
00130     return to_write;
00131   }
00132 };
00133 
00134 extern "C" size_t
00135 http_post_readfunc(void *ptr, size_t size, size_t nmemb, void *data);
00136 
00137 extern "C" size_t
00138 http_post_readfunc(void *ptr, size_t size, size_t nmemb, void *data)
00139 {
00140   size_t realsize= size * nmemb;
00141   HttpPostData *post_data= (HttpPostData *)data;
00142 
00143   return post_data->write(ptr, realsize);
00144 }
00145 
00146 String *HttpPostFunction::val_str(String *str)
00147 {
00148   assert(fixed == 1);
00149   String *url = args[0]->val_str(str);
00150   CURL *curl;
00151   String post_storage;
00152   HttpPostData post_data(args[1]->val_str(&post_storage));
00153 
00154   if ((null_value=args[0]->null_value))
00155     return NULL;
00156 
00157   curl= curl_easy_init();
00158   curl_easy_setopt(curl, CURLOPT_URL, url->c_str());
00159   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_cb);
00160   curl_easy_setopt(curl, CURLOPT_POST, 1L);
00161   curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, post_data.length());
00162   curl_easy_setopt(curl, CURLOPT_READDATA, &post_data);
00163   curl_easy_setopt(curl, CURLOPT_READFUNCTION, http_post_readfunc);
00164   curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&result);
00165   curl_easy_setopt(curl, CURLOPT_USERAGENT, "drizzle-http-functions/1.0");
00166   /*CURLcode retref=*/ curl_easy_perform(curl);
00167   curl_easy_cleanup(curl);
00168 
00169   return &result;
00170 }
00171 
00172 void HttpPostFunction::fix_length_and_dec()
00173 {
00174   collation.set(args[0]->collation);
00175   max_length = ~0;
00176 }
00177 
00178 static int initialize(drizzled::module::Context &context)
00179 {
00180   curl_global_init(CURL_GLOBAL_ALL);
00181   context.add(new plugin::Create_function<HttpGetFunction>("http_get"));
00182   context.add(new plugin::Create_function<HttpPostFunction>("http_post"));
00183   return 0;
00184 }
00185 
00186 DRIZZLE_DECLARE_PLUGIN
00187 {
00188   DRIZZLE_VERSION_ID,
00189   "http_functions",
00190   "1.0",
00191   "Stewart Smith",
00192   "HTTP functions",
00193   PLUGIN_LICENSE_GPL,
00194   initialize, /* Plugin Init */
00195   NULL,   /* depends */
00196   NULL    /* config options */
00197 }
00198 DRIZZLE_DECLARE_PLUGIN_END;