00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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 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,
00195 NULL,
00196 NULL
00197 }
00198 DRIZZLE_DECLARE_PLUGIN_END;