NS_IMETHODIMP sbRemoteSiteLibraryResource::GetProperty( const nsAString &aID, nsAString &_retval ) { LOG_RES(( "sbRemoteSiteLibraryResource::GetProperty(%s)", NS_LossyConvertUTF16toASCII(aID).get() )); // First call the base class impl and see what it says. contentURL will get // denied as it is not remoteReadable by default, we special case for site // objects nsresult rv = sbRemoteLibraryResource::GetProperty( aID, _retval ); if ( NS_SUCCEEDED(rv) || !aID.EqualsLiteral(SB_PROPERTY_CONTENTURL) ) { return rv; } // Do some special checking for contentURL properties. Sites should be able // to access the contentURLs for tracks that aren't on the hard drive. nsString contentURL; rv = mMediaItem->GetProperty( aID, contentURL ); NS_ENSURE_SUCCESS( rv, rv ); if ( StringBeginsWith( contentURL, NS_LITERAL_STRING("file:") ) ) { LOG_RES(( "sbRemoteSiteLibraryResource::GetProperty() - " "Disallowing access to 'file:' URI from contentURL property" )); _retval.AssignLiteral("__BLOCKED__"); return NS_ERROR_FAILURE; } LOG_RES(( "sbRemoteSiteLibraryResource::GetProperty() - " "Allowing access to non-file contentURL to site item/list/lib: %s", NS_LossyConvertUTF16toASCII(contentURL).get() )); _retval.Assign(contentURL); return NS_OK; }
// ---------------------------------------------------------------------------- // // sbILibraryResource // // ---------------------------------------------------------------------------- NS_IMETHODIMP sbRemoteLibraryResource::GetProperty( const nsAString &aID, nsAString &_retval ) { NS_ENSURE_TRUE( mMediaItem, NS_ERROR_NULL_POINTER ); LOG_RES(( "sbRemoteLibraryResource::GetProperty(%s)", NS_LossyConvertUTF16toASCII(aID).get() )); nsresult rv; // get the property manager service nsCOMPtr<sbIPropertyManager> propertyManager = do_GetService( "@songbirdnest.com/Songbird/Properties/PropertyManager;1", &rv ); NS_ENSURE_SUCCESS( rv, rv ); // get the property info for the property being requested nsCOMPtr<sbIPropertyInfo> propertyInfo; rv = propertyManager->GetPropertyInfo( aID, getter_AddRefs(propertyInfo) ); NS_ENSURE_SUCCESS( rv, rv ); // ask if this property is remotely readable bool readable; rv = propertyInfo->GetRemoteReadable(&readable); NS_ENSURE_SUCCESS( rv, rv ); // well, is it readable? if (!readable) { LOG_RES(( "Attempting to get a property's (%s) value that is not allowed " "to be read from the remote API!", NS_LossyConvertUTF16toASCII(aID).get() )); // if not return an error return NS_ERROR_FAILURE; } // readable property nsString propVal; rv = mMediaItem->GetProperty( aID, propVal ); NS_ENSURE_SUCCESS( rv, rv ); // Protect against exposing file:// uris to the world. if ( !aID.EqualsLiteral(SB_PROPERTY_ORIGINURL) || !aID.EqualsLiteral(SB_PROPERTY_COPYRIGHTURL) || !aID.EqualsLiteral(SB_PROPERTY_PRIMARYIMAGEURL) ) { if ( StringBeginsWith( propVal, NS_LITERAL_STRING("file:") ) ) { LOG_RES(( "sbRemoteLibraryResource::GetProperty() - " "Disallowing access to 'file:' URI." )); // Assign a dummy signal value propVal.AssignLiteral("__BLOCKED__"); } else { LOG_RES(( "sbRemoteLibraryResource::GetProperty() - " "Allowing access to non-file value: %s", NS_LossyConvertUTF16toASCII(propVal).get() )); } } _retval.Assign(propVal); return NS_OK; }
sbRemoteSiteLibraryResource::sbRemoteSiteLibraryResource( sbRemotePlayer *aRemotePlayer, sbIMediaItem *aMediaItem ) : sbRemoteLibraryResource( aRemotePlayer, aMediaItem ) { NS_ASSERTION( aRemotePlayer, "Null remote player!" ); NS_ASSERTION( aMediaItem, "Null media item!" ); LOG_RES(("sbRemoteSiteLibraryResource::sbRemoteSiteLibraryResource()")); }
sbRemoteLibraryResource::sbRemoteLibraryResource( sbRemotePlayer *aRemotePlayer, sbIMediaItem *aMediaItem ) : mRemotePlayer(aRemotePlayer), mMediaItem(aMediaItem) { NS_ASSERTION( aRemotePlayer, "Null remote player!" ); NS_ASSERTION( aMediaItem, "Null media item!" ); #ifdef PR_LOGGING if (!gRemoteLibResLog) { gRemoteLibResLog = PR_NewLogModule("sbRemoteLibraryResource"); } LOG_RES(("sbRemoteLibraryResource::sbRemoteLibraryResource()")); #endif }
NS_IMETHODIMP sbRemoteLibraryResource::SetProperties( sbIPropertyArray *aProperties ) { LOG_RES(("sbRemoteLibraryResource::SetProperties()")); NS_ENSURE_ARG_POINTER( aProperties ); NS_ASSERTION( mMediaItem, "SetProperties called before Initialization" ); nsresult rv = mMediaItem->SetProperties(aProperties); NS_ENSURE_SUCCESS( rv, rv ); nsCOMPtr<sbILibrary> library; rv = mMediaItem->GetLibrary( getter_AddRefs(library) ); NS_ENSURE_SUCCESS( rv, rv ); mRemotePlayer->GetNotificationManager()->Action( sbRemoteNotificationManager::eEditedItems, library ); return NS_OK; }
sbRemoteLibraryResource::~sbRemoteLibraryResource() { LOG_RES(("sbRemoteLibraryResource::~sbRemoteLibraryResource()")); }
NS_IMETHODIMP sbRemoteLibraryResource::SetProperty( const nsAString &aID, const nsAString &aValue ) { LOG_RES(( "sbRemoteLibraryResource::SetProperty( %s, %s )", NS_LossyConvertUTF16toASCII(aID).get(), NS_LossyConvertUTF16toASCII(aValue).get() )); NS_ASSERTION( mMediaItem, "SetProperty called before Initialization" ); nsresult rv = NS_OK; // get the property manager service nsCOMPtr<sbIPropertyManager> propertyManager = do_GetService( "@songbirdnest.com/Songbird/Properties/PropertyManager;1", &rv ); NS_ENSURE_SUCCESS( rv, rv ); // Check to see if we have the property first, if not we must create it with // the right settings so websites can modify it. bool hasProp; rv = propertyManager->HasProperty( aID, &hasProp ); // get the property info for the property being requested - this will create // it if it didn't already exist. nsCOMPtr<sbIPropertyInfo> propertyInfo; rv = propertyManager->GetPropertyInfo( aID, getter_AddRefs(propertyInfo) ); NS_ENSURE_SUCCESS( rv, rv ); // check to see if the prop already existed or if we created it if (hasProp) { // ask if this property is remotely writable bool writable = PR_FALSE; rv = propertyInfo->GetRemoteWritable(&writable); NS_ENSURE_SUCCESS( rv, rv ); // well, is it writeable? if (!writable) { // if not return an error LOG_RES(( "Attempting to set a property's (%s) value that is not allowed " "to be set from the remote API!", NS_LossyConvertUTF16toASCII(aID).get() )); return NS_ERROR_FAILURE; } } else { // we created a new property in the system so enable remote write/read rv = propertyInfo->SetRemoteWritable(PR_TRUE); NS_ENSURE_SUCCESS( rv, rv ); rv = propertyInfo->SetRemoteReadable(PR_TRUE); NS_ENSURE_SUCCESS( rv, rv ); } // it all looks ok, pass this request on to the real media item rv = mMediaItem->SetProperty( aID, aValue ); NS_ENSURE_SUCCESS( rv, rv ); nsCOMPtr<sbILibrary> library; rv = mMediaItem->GetLibrary( getter_AddRefs(library) ); NS_ENSURE_SUCCESS( rv, rv ); mRemotePlayer->GetNotificationManager()->Action( sbRemoteNotificationManager::eEditedItems, library ); return NS_OK; }
/* * Loads all resources from the stream, except images, binaries and sprites. */ bool Syscall::loadResources(Stream& file, const char* aFilename) { bool hasResources = true; if(!file.isOpen()) hasResources = false; else { int len, pos; TEST(file.length(len)); TEST(file.tell(pos)); if(len == pos) hasResources = false; } if(!hasResources/* && aFilename != NULL*/) { resources.init(0); return true; } #define MATCH_BYTE(c) { DAR_UBYTE(b); if(b != c) { FAIL; } } MATCH_BYTE('M'); MATCH_BYTE('A'); MATCH_BYTE('R'); MATCH_BYTE('S'); DAR_UVINT(nResources); DAR_UVINT(rSize); resources.init(nResources); resourcesCount = nResources; resourceOffset = new int[nResources]; resourceSize = new int[nResources]; resourceType = new int[nResources]; resourcesFilename = new char[strlen(aFilename) + 1]; strcpy(resourcesFilename, aFilename); // rI is the resource index. int rI = 1; while(true) { DAR_UBYTE(type); if(type == 0) break; //dispose flag DAR_UVINT(size); LOG_RES("Type %i, size %i\n", type, size); int index = rI - 1; TEST(file.tell(resourceOffset[index])); resourceSize[index] = size; resourceType[index] = type; switch(type) { case RT_UBIN: { int pos; MYASSERT(aFilename, ERR_RES_LOAD_UBIN); TEST(file.tell(pos)); #ifndef _android ROOM(resources.dadd_RT_BINARY(rI, new LimitedFileStream(aFilename, pos, size))); #else // Android loads ubins by using JNI. loadUBinary(rI, pos, size); ROOM(resources.dadd_RT_BINARY(rI, new LimitedFileStream( aFilename, pos, size, getJNIEnvironment(), getJNIThis()))); #endif TEST(file.seek(Seek::Current, size)); } break; case RT_PLACEHOLDER: ROOM(resources.dadd_RT_PLACEHOLDER(rI, NULL)); break; case RT_LABEL: { MemStream b(size); TEST(file.readFully(b)); ROOM(resources.dadd_RT_LABEL(rI, new Label((const char*)b.ptr(), rI))); } break; #ifdef LOGGING_ENABLED case 99: //testtype #define DUMP_UVI { DAR_UVINT(u); LOG_RES("u %i\n", u); } #define DUMP_SVI { DAR_SVINT(s); LOG_RES("s %i\n", s); } DUMP_UVI; DUMP_UVI; DUMP_UVI; DUMP_SVI; DUMP_SVI; DUMP_SVI; DUMP_SVI; DUMP_SVI; DUMP_SVI; break; #endif default: TEST(file.seek(Seek::Current, size)); } rI++; } if(rI != nResources + 1) { LOG("rI %i, nR %i\n", rI, nResources); BIG_PHAT_ERROR(ERR_RES_FILE_INCONSISTENT); } LOG_RES("ResLoad complete\n"); return true; }
/* * Loads all resources from the given buffer. */ bool Syscall::loadResourcesFromBuffer(Stream& file, const char* aFilename) { bool hasResources = true; if(!file.isOpen()) hasResources = false; else { int len, pos; TEST(file.length(len)); TEST(file.tell(pos)); if(len == pos) hasResources = false; } if(!hasResources/* && aFilename != NULL*/) { resources.init(0); return true; } #define MATCH_BYTE(c) { DAR_UBYTE(b); if(b != c) { FAIL; } } MATCH_BYTE('M'); MATCH_BYTE('A'); MATCH_BYTE('R'); MATCH_BYTE('S'); DAR_UVINT(nResources); DAR_UVINT(rSize); resources.init(nResources); // rI is the resource index. int rI = 1; while(true) { DAR_UBYTE(type); if(type == 0) break; //dispose flag DAR_UVINT(size); LOG_RES("Type %i, size %i\n", type, size); switch(type) { case RT_BINARY: { #ifndef _android MemStream* ms = new MemStream(size); #else char* b = loadBinary(rI, size); MemStream* ms = new MemStream(b, size); #endif TEST(file.readFully(*ms)); ROOM(resources.dadd_RT_BINARY(rI, ms)); #ifdef _android checkAndStoreAudioResource(rI); #endif } break; case RT_UBIN: { int pos; MYASSERT(aFilename, ERR_RES_LOAD_UBIN); TEST(file.tell(pos)); #ifndef _android ROOM(resources.dadd_RT_BINARY(rI, new LimitedFileStream(aFilename, pos, size))); #else // Android loads ubins by using JNI. loadUBinary(rI, pos, size); ROOM(resources.dadd_RT_BINARY(rI, new LimitedFileStream( aFilename, pos, size, getJNIEnvironment(), getJNIThis()))); #endif TEST(file.seek(Seek::Current, size)); } break; case RT_PLACEHOLDER: ROOM(resources.dadd_RT_PLACEHOLDER(rI, NULL)); break; case RT_IMAGE: { MemStream b(size); TEST(file.readFully(b)); #ifndef _android // On all platforms except Android, we load and add // the image data. "dadd" means "delete and add", // and is defined in runtimes\cpp\base\ResourceArray.h RT_IMAGE_Type* image = loadImage(b); if(!image) BIG_PHAT_ERROR(ERR_IMAGE_LOAD_FAILED); ROOM(resources.dadd_RT_IMAGE(rI, image)); #else // On Android images are stored on the Java side. // Here we allocate a dummy array (real image is // in a table in Java) so that the resource handling, // like deleting resources, will work also on Android. // The actual image will be garbage collected on // Android when a resource is replaced in the Java table. ROOM(resources.dadd_RT_IMAGE(rI, new int[1])); int pos; file.tell(pos); loadImage( rI, pos - size, size, Base::gSyscall->getReloadHandle()); #endif } break; case RT_SPRITE: { DAR_USHORT(indexSource); DAR_USHORT(left); DAR_USHORT(top); DAR_USHORT(width); DAR_USHORT(height); DAR_SHORT(cx); DAR_SHORT(cy); #ifndef _android ROOM(resources.dadd_RT_IMAGE(rI, loadSprite(resources.get_RT_IMAGE(indexSource), left, top, width, height, cx, cy))); #endif } break; case RT_LABEL: { MemStream b(size); TEST(file.readFully(b)); ROOM(resources.dadd_RT_LABEL(rI, new Label((const char*)b.ptr(), rI))); } break; #ifdef LOGGING_ENABLED case 99: //testtype #define DUMP_UVI { DAR_UVINT(u); LOG_RES("u %i\n", u); } #define DUMP_SVI { DAR_SVINT(s); LOG_RES("s %i\n", s); } DUMP_UVI; DUMP_UVI; DUMP_UVI; DUMP_SVI; DUMP_SVI; DUMP_SVI; DUMP_SVI; DUMP_SVI; DUMP_SVI; break; #endif default: TEST(file.seek(Seek::Current, size)); } rI++; } if(rI != nResources + 1) { LOG("rI %i, nR %i\n", rI, nResources); BIG_PHAT_ERROR(ERR_RES_FILE_INCONSISTENT); } LOG_RES("ResLoad complete\n"); return true; }