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 #include "cds_objects.h"
00037 #include "tools.h"
00038 #include "storage.h"
00039 #include "mxml/mxml.h"
00040
00041 using namespace zmm;
00042 using namespace mxml;
00043
00044 CdsObject::CdsObject() : Object()
00045 {
00046 metadata = Ref<Dictionary>(new Dictionary());
00047 auxdata = Ref<Dictionary>(new Dictionary());
00048 resources = Ref<Array<CdsResource> >(new Array<CdsResource>);
00049 id = INVALID_OBJECT_ID;
00050 parentID = INVALID_OBJECT_ID;
00051 refID = INVALID_OBJECT_ID;
00052 virt = 0;
00053 sortPriority = 0;
00054 objectFlags = OBJECT_FLAG_RESTRICTED;
00055 }
00056
00057 void CdsObject::copyTo(Ref<CdsObject> obj)
00058 {
00059 obj->setID(id);
00060 obj->setRefID(refID);
00061 obj->setParentID(parentID);
00062 obj->setTitle(title);
00063 obj->setClass(upnpClass);
00064 obj->setLocation(location);
00065 obj->setVirtual(virt);
00066 obj->setMetadata(metadata->clone());
00067 obj->setAuxData(auxdata->clone());
00068 obj->setFlags(objectFlags);
00069 obj->setSortPriority(sortPriority);
00070 for (int i = 0; i < resources->size(); i++)
00071 obj->addResource(resources->get(i)->clone());
00072 }
00073 int CdsObject::equals(Ref<CdsObject> obj, bool exactly)
00074 {
00075 if (!(
00076 id == obj->getID() &&
00077 parentID == obj->getParentID() &&
00078 isRestricted() == obj->isRestricted() &&
00079 title == obj->getTitle() &&
00080 upnpClass == obj->getClass() &&
00081 sortPriority == obj->getSortPriority()
00082 ))
00083 return 0;
00084
00085 if (! resourcesEqual(obj))
00086 return 0;
00087
00088 if (! metadata->equals(obj->getMetadata()))
00089 return 0;
00090
00091 if (exactly && !
00092 (location == obj->getLocation() &&
00093 virt == obj->isVirtual() &&
00094 auxdata->equals(obj->auxdata) &&
00095 objectFlags == obj->getFlags()
00096 ))
00097 return 0;
00098 return 1;
00099 }
00100
00101 int CdsObject::resourcesEqual(Ref<CdsObject> obj)
00102 {
00103 if (resources->size() != obj->resources->size())
00104 return 0;
00105
00106
00107 for (int i = 0; i < resources->size(); i++)
00108 {
00109 if (! resources->get(i)->equals(obj->resources->get(i)))
00110 return 0;
00111 }
00112 return 1;
00113 }
00114
00115 void CdsObject::validate()
00116 {
00117 if (!string_ok(this->title))
00118 throw _Exception(_("Object validation failed: missing title!\n"));
00119
00120 if (!string_ok(this->upnpClass))
00121 throw _Exception(_("Object validation failed: missing upnp class\n"));
00122
00123 }
00124
00125 Ref<CdsObject> CdsObject::createObject(unsigned int objectType)
00126 {
00127 CdsObject *pobj;
00128
00129 if(IS_CDS_CONTAINER(objectType))
00130 {
00131 pobj = new CdsContainer();
00132 }
00133 else if(IS_CDS_ITEM_INTERNAL_URL(objectType))
00134 {
00135 pobj = new CdsItemInternalURL();
00136 }
00137 else if(IS_CDS_ITEM_EXTERNAL_URL(objectType))
00138 {
00139 pobj = new CdsItemExternalURL();
00140 }
00141 else if(IS_CDS_ACTIVE_ITEM(objectType))
00142 {
00143 pobj = new CdsActiveItem();
00144 }
00145 else if(IS_CDS_ITEM(objectType))
00146 {
00147 pobj = new CdsItem();
00148 }
00149 else
00150 {
00151 throw _Exception(_("invalid object type: ") + objectType);
00152 }
00153 return Ref<CdsObject>(pobj);
00154 }
00155
00156
00157
00158
00159 CdsItem::CdsItem() : CdsObject()
00160 {
00161 objectType = OBJECT_TYPE_ITEM;
00162 upnpClass = _("object.item");
00163 mimeType = _(MIMETYPE_DEFAULT);
00164 trackNumber = 0;
00165 serviceID = nil;
00166 }
00167
00168 void CdsItem::copyTo(Ref<CdsObject> obj)
00169 {
00170 CdsObject::copyTo(obj);
00171 if (! IS_CDS_ITEM(obj->getObjectType()))
00172 return;
00173 Ref<CdsItem> item = RefCast(obj, CdsItem);
00174
00175 item->setMimeType(mimeType);
00176 item->setTrackNumber(trackNumber);
00177 item->setServiceID(serviceID);
00178 }
00179 int CdsItem::equals(Ref<CdsObject> obj, bool exactly)
00180 {
00181 Ref<CdsItem> item = RefCast(obj, CdsItem);
00182 if (! CdsObject::equals(obj, exactly))
00183 return 0;
00184 return (mimeType == item->getMimeType() &&
00185 trackNumber == item->getTrackNumber() &&
00186 serviceID == item->getServiceID());
00187 }
00188
00189 void CdsItem::validate()
00190 {
00191 CdsObject::validate();
00192
00193 if (!string_ok(this->mimeType))
00194 throw _Exception(_("Item validation failed: missing mimetype"));
00195
00196 if (!string_ok(this->location))
00197 throw _Exception(_("Item validation failed: missing location"));
00198
00199 if (!check_path(this->location))
00200 throw _Exception(_("Item validation failed: file ") +
00201 this->location + " not found");
00202 }
00203
00204 CdsActiveItem::CdsActiveItem() : CdsItem()
00205 {
00206 objectType |= OBJECT_TYPE_ACTIVE_ITEM;
00207
00208 upnpClass = _(UPNP_DEFAULT_CLASS_ACTIVE_ITEM);
00209 mimeType = _(MIMETYPE_DEFAULT);
00210 }
00211
00212 void CdsActiveItem::copyTo(Ref<CdsObject> obj)
00213 {
00214 CdsItem::copyTo(obj);
00215 if (! IS_CDS_ACTIVE_ITEM(obj->getObjectType()))
00216 return;
00217 Ref<CdsActiveItem> item = RefCast(obj, CdsActiveItem);
00218 item->setAction(action);
00219 item->setState(state);
00220 }
00221 int CdsActiveItem::equals(Ref<CdsObject> obj, bool exactly)
00222 {
00223 Ref<CdsActiveItem> item = RefCast(obj, CdsActiveItem);
00224 if (! CdsItem::equals(obj, exactly))
00225 return 0;
00226 if (exactly &&
00227 (action != item->getAction() ||
00228 state != item->getState())
00229 )
00230 return 0;
00231 return 1;
00232 }
00233
00234 void CdsActiveItem::validate()
00235 {
00236 CdsItem::validate();
00237 if (!string_ok(this->action))
00238 throw _Exception(_("Active Item validation failed: missing action\n"));
00239
00240 if (!check_path(this->action))
00241 throw _Exception(_("ctive Item validation failed: action script ") +
00242 this->action + " not found\n");
00243 }
00244
00245
00246 CdsItemExternalURL::CdsItemExternalURL() : CdsItem()
00247 {
00248 objectType |= OBJECT_TYPE_ITEM_EXTERNAL_URL;
00249
00250 upnpClass = _(UPNP_DEFAULT_CLASS_ITEM);
00251 mimeType = _(MIMETYPE_DEFAULT);
00252 }
00253
00254 void CdsItemExternalURL::validate()
00255 {
00256 CdsObject::validate();
00257 if (!string_ok(this->mimeType))
00258 throw _Exception(_("URL Item validation failed: missing mimetype\n"));
00259
00260 if (!string_ok(this->location))
00261 throw _Exception(_("URL Item validation failed: missing URL\n"));
00262 }
00263
00264
00265 CdsItemInternalURL::CdsItemInternalURL() : CdsItemExternalURL()
00266 {
00267 objectType |= OBJECT_TYPE_ITEM_INTERNAL_URL;
00268
00269 upnpClass = _("object.item");
00270 mimeType = _(MIMETYPE_DEFAULT);
00271 }
00272
00273 void CdsItemInternalURL::validate()
00274 {
00275 CdsItemExternalURL::validate();
00276
00277 if (this->location.startsWith(_("http://")))
00278 throw _Exception(_("Internal URL item validation failed: only realative URLs allowd\n"));
00279 }
00280
00281 CdsContainer::CdsContainer() : CdsObject()
00282 {
00283 objectType = OBJECT_TYPE_CONTAINER;
00284 updateID = 0;
00285
00286 childCount = -1;
00287 upnpClass = _(UPNP_DEFAULT_CLASS_CONTAINER);
00288 autoscanType = OBJECT_AUTOSCAN_NONE;
00289 }
00290
00291 void CdsContainer::copyTo(Ref<CdsObject> obj)
00292 {
00293 CdsObject::copyTo(obj);
00294 if (! IS_CDS_CONTAINER(obj->getObjectType()))
00295 return;
00296 Ref<CdsContainer> cont = RefCast(obj, CdsContainer);
00297 cont->setUpdateID(updateID);
00298 }
00299 int CdsContainer::equals(Ref<CdsObject> obj, bool exactly)
00300 {
00301 Ref<CdsContainer> cont = RefCast(obj, CdsContainer);
00302 return (
00303 CdsObject::equals(obj, exactly) &&
00304 isSearchable() == cont->isSearchable()
00305 );
00306 }
00307
00308 void CdsContainer::validate()
00309 {
00310 CdsObject::validate();
00312
00313
00314 }
00315 void CdsObject::optimize()
00316 {
00317 metadata->optimize();
00318 auxdata->optimize();
00319 resources->optimize();
00320 }
00321
00322 int CdsObjectTitleComparator(void *arg1, void *arg2)
00323 {
00325 return strcmp(((CdsObject *)arg1)->title.c_str(),
00326 ((CdsObject *)arg2)->title.c_str());
00327 }
00328
00329 String CdsContainer::getVirtualPath()
00330 {
00331 String location;
00332 if (getID() == CDS_ID_ROOT)
00333 {
00334 location = _("/");
00335 }
00336 else if (getID() == CDS_ID_FS_ROOT)
00337 {
00338 Ref<Storage> storage = Storage::getInstance();
00339 location = _("/") + storage->getFsRootName();
00340 }
00341 else if (string_ok(getLocation()))
00342 {
00343 location = getLocation();
00344 if (! isVirtual())
00345 {
00346 Ref<Storage> storage = Storage::getInstance();
00347 location = _("/") + storage->getFsRootName() + location;
00348 }
00349 }
00350
00351 if (!string_ok(location))
00352 throw _Exception(_("virtual location not available"));
00353
00354 return location;
00355 }
00356
00357 String CdsItem::getVirtualPath()
00358 {
00359 Ref<Storage> storage = Storage::getInstance();
00360 Ref<CdsObject> cont = storage->loadObject(getParentID());
00361 String location = cont->getVirtualPath();
00362 location = location + '/' + getTitle();
00363
00364 if (!string_ok(location))
00365 throw _Exception(_("virtual location not available"));
00366
00367 return location;
00368 }
00369
00370 String CdsObject::mapObjectType(int type)
00371 {
00372 if (IS_CDS_CONTAINER(type))
00373 return _(STRING_OBJECT_TYPE_CONTAINER);
00374 if (IS_CDS_PURE_ITEM(type))
00375 return _(STRING_OBJECT_TYPE_ITEM);
00376 if (IS_CDS_ACTIVE_ITEM(type))
00377 return _(STRING_OBJECT_TYPE_ACTIVE_ITEM);
00378 if (IS_CDS_ITEM_EXTERNAL_URL(type))
00379 return _(STRING_OBJECT_TYPE_EXTERNAL_URL);
00380 if (IS_CDS_ITEM_INTERNAL_URL(type))
00381 return _(STRING_OBJECT_TYPE_INTERNAL_URL);
00382 throw Exception(_("illegal objectType: ") + type);
00383 }
00384
00385 int CdsObject::remapObjectType(String objectType)
00386 {
00387 if (objectType == STRING_OBJECT_TYPE_CONTAINER)
00388 return OBJECT_TYPE_CONTAINER;
00389 if (objectType == STRING_OBJECT_TYPE_ITEM)
00390 return OBJECT_TYPE_ITEM;
00391 if (objectType == STRING_OBJECT_TYPE_ACTIVE_ITEM)
00392 return OBJECT_TYPE_ITEM | OBJECT_TYPE_ACTIVE_ITEM;
00393 if (objectType == STRING_OBJECT_TYPE_EXTERNAL_URL)
00394 return OBJECT_TYPE_ITEM | OBJECT_TYPE_ITEM_EXTERNAL_URL;
00395 if (objectType == STRING_OBJECT_TYPE_INTERNAL_URL)
00396 return OBJECT_TYPE_ITEM | OBJECT_TYPE_ITEM_EXTERNAL_URL | OBJECT_TYPE_ITEM_INTERNAL_URL;
00397 throw Exception(_("illegal objectType: ") + objectType);
00398 }