00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "autoconfig.h"
00034 #endif
00035
00036 #ifdef HAVE_CURL
00037
00038 #include "server.h"
00039 #include "common.h"
00040 #include "storage.h"
00041 #include "ixml.h"
00042 #include "buffered_io_handler.h"
00043 #include "dictionary.h"
00044 #include "url_request_handler.h"
00045 #include "cds_objects.h"
00046 #include "play_hook.h"
00047
00048 #ifdef ONLINE_SERVICES
00049 #include "online_service_helper.h"
00050 #endif
00051 #include "url.h"
00052 #include "curl_io_handler.h"
00053 #ifdef EXTERNAL_TRANSCODING
00054 #include "transcoding/transcode_dispatcher.h"
00055 #endif
00056
00057 using namespace zmm;
00058 using namespace mxml;
00059
00060 URLRequestHandler::URLRequestHandler() : RequestHandler()
00061 {
00062 }
00063
00064 void URLRequestHandler::get_info(IN const char *filename, OUT struct File_Info *info)
00065 {
00066 log_debug("start\n");
00067
00068 String header;
00069 String mimeType;
00070 int objectID;
00071 #ifdef EXTERNAL_TRANSCODING
00072 String tr_profile;
00073 #endif
00074
00075 String url, parameters;
00076 parameters = (filename + strlen(LINK_URL_REQUEST_HANDLER));
00077
00078 Ref<Dictionary> dict(new Dictionary());
00079 dict->decodeSimple(parameters);
00080
00081 log_debug("full url (filename): %s, parameters: %s\n",
00082 filename, parameters.c_str());
00083
00084 String objID = dict->get(_("object_id"));
00085 if (objID == nil)
00086 {
00087
00088 throw _Exception(_("get_info: object_id not found"));
00089 }
00090 else
00091 objectID = objID.toInt();
00092
00093
00094
00095 Ref<Storage> storage = Storage::getInstance();
00096
00097 Ref<CdsObject> obj = storage->loadObject(objectID);
00098
00099 int objectType = obj->getObjectType();
00100
00101 if (!IS_CDS_ITEM_EXTERNAL_URL(objectType))
00102 {
00103 throw _Exception(_("get_info: object is not an external url item"));
00104 }
00105
00106 #ifdef EXTERNAL_TRANSCODING
00107 tr_profile = dict->get(_(URL_PARAM_TRANSCODE_PROFILE_NAME));
00108
00109 if (string_ok(tr_profile))
00110 {
00111 Ref<TranscodingProfile> tp = ConfigManager::getInstance()->getTranscodingProfileListOption(CFG_TRANSCODING_PROFILE_LIST)->getByName(tr_profile);
00112
00113 if (tp == nil)
00114 throw _Exception(_("Transcoding requested but no profile "
00115 "matching the name ") + tr_profile + " found");
00116
00117 mimeType = tp->getTargetMimeType();
00118 info->file_length = -1;
00119 }
00120 else
00121 #endif
00122 {
00123 Ref<CdsItemExternalURL> item = RefCast(obj, CdsItemExternalURL);
00124
00125 #ifdef ONLINE_SERVICES
00126 if (item->getFlag(OBJECT_FLAG_ONLINE_SERVICE))
00127 {
00130 Ref<OnlineServiceHelper> helper (new OnlineServiceHelper());
00131 url = helper->resolveURL(item);
00132 }
00133 else
00134 #endif
00135 {
00136 url = item->getLocation();
00137 }
00138
00139 log_debug("Online content url: %s\n", url.c_str());
00140 Ref<URL> u(new URL(1024));
00141 Ref<URL::Stat> st;
00142 try
00143 {
00144 st = u->getInfo(url);
00145 info->file_length = st->getSize();
00146 header = _("Accept-Ranges: bytes");
00147 log_debug("URL used for request: %s\n", st->getURL().c_str());
00148 }
00149 catch (Exception ex)
00150 {
00151 log_warning("%s\n", ex.getMessage().c_str());
00152 info->file_length = -1;
00153 }
00154
00155 mimeType = item->getMimeType();
00156 }
00157
00158 info->is_readable = 1;
00159 info->last_modified = 0;
00160 info->is_directory = 0;
00161
00162 if (string_ok(header))
00163 info->http_header = ixmlCloneDOMString(header.c_str());
00164 else
00165 info->http_header = NULL;
00166
00167 info->content_type = ixmlCloneDOMString(mimeType.c_str());
00168 log_debug("web_get_info(): end\n");
00169
00171 }
00172
00173 Ref<IOHandler> URLRequestHandler::open(IN const char *filename, OUT struct File_Info *info, IN enum UpnpOpenFileMode mode)
00174 {
00175 int objectID;
00176 String mimeType;
00177 String header;
00178 #ifdef EXTERNAL_TRANSCODING
00179 String tr_profile;
00180 #endif
00181
00182 log_debug("start\n");
00183
00184
00185
00186 if (mode != UPNP_READ)
00187 throw _Exception(_("UPNP_WRITE unsupported"));
00188
00189 String url, parameters;
00190 parameters = (filename + strlen(LINK_URL_REQUEST_HANDLER));
00191
00192 Ref<Dictionary> dict(new Dictionary());
00193 dict->decodeSimple(parameters);
00194 log_debug("full url (filename): %s, parameters: %s\n",
00195 filename, parameters.c_str());
00196
00197 String objID = dict->get(_("object_id"));
00198 if (objID == nil)
00199 {
00200 throw _Exception(_("object_id not found"));
00201 }
00202 else
00203 objectID = objID.toInt();
00204
00205 Ref<Storage> storage = Storage::getInstance();
00206
00207 Ref<CdsObject> obj = storage->loadObject(objectID);
00208
00209 int objectType = obj->getObjectType();
00210
00211 if (!IS_CDS_ITEM_EXTERNAL_URL(objectType))
00212 {
00213 throw _Exception(_("object is not an external url item"));
00214 }
00215
00216 Ref<CdsItemExternalURL> item = RefCast(obj, CdsItemExternalURL);
00217
00218 #ifdef ONLINE_SERVICES
00219 if (item->getFlag(OBJECT_FLAG_ONLINE_SERVICE))
00220 {
00221 Ref<OnlineServiceHelper> helper (new OnlineServiceHelper());
00222 url = helper->resolveURL(item);
00223 }
00224 else
00225 #endif
00226 {
00227 url = item->getLocation();
00228 }
00229
00230
00231 log_debug("Online content url: %s\n", url.c_str());
00232
00233 info->is_readable = 1;
00234 info->last_modified = 0;
00235 info->is_directory = 0;
00236 info->http_header = NULL;
00237
00238 #ifdef EXTERNAL_TRANSCODING
00239 tr_profile = dict->get(_(URL_PARAM_TRANSCODE_PROFILE_NAME));
00240
00241 if (string_ok(tr_profile))
00242 {
00243 Ref<TranscodingProfile> tp = ConfigManager::getInstance()->getTranscodingProfileListOption(CFG_TRANSCODING_PROFILE_LIST)->getByName(tr_profile);
00244
00245 if (tp == nil)
00246 throw _Exception(_("Transcoding of file ") + url +
00247 " but no profile matching the name " +
00248 tr_profile + " found");
00249
00250 Ref<TranscodeDispatcher> tr_d(new TranscodeDispatcher());
00251 return tr_d->open(tp, url, RefCast(item, CdsObject), info);
00252 }
00253 else
00254 #endif
00255 {
00256 Ref<URL> u(new URL(1024));
00257 Ref<URL::Stat> st;
00258 try
00259 {
00260 st = u->getInfo(url);
00261 info->file_length = st->getSize();
00262 header = _("Accept-Ranges: bytes");
00263 log_debug("URL used for request: %s\n", st->getURL().c_str());
00264 }
00265 catch (Exception ex)
00266 {
00267 log_warning("%s\n", ex.getMessage().c_str());
00268 info->file_length = -1;
00269 }
00270 mimeType = item->getMimeType();
00271 info->content_type = ixmlCloneDOMString(mimeType.c_str());
00272 }
00273
00274 if (string_ok(header))
00275 info->http_header = ixmlCloneDOMString(header.c_str());
00276
00278 Ref<IOHandler> io_handler(new CurlIOHandler(url, NULL, 1024*1024, 0));
00279
00280 io_handler->open(mode);
00281
00282 PlayHook::getInstance()->trigger(obj);
00283 return io_handler;
00284 }
00285
00286 #endif // HAVE_CURL