does NSMetadataQueryDidUpdateNotification can work with NSFileManager setUbiquitous - icloud

i am trying to track my icloud upload progress using NSMetadataQueryDidUpdateNotification..but it can't work... i don't know what the problem is..
here is my code for upload to icloud
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[fileCoordinator coordinateReadingItemAtURL:backupUrl options:NSFileCoordinatorReadingWithoutChanges error:nil byAccessor:^(NSURL *newURL) {
NSFileManager* fm = [NSFileManager defaultManager];
NSError *theError = nil;
BOOL success =[fm setUbiquitous:YES itemAtURL:backupUrl destinationURL:[[ubiq URLByAppendingPathComponent:#"Documents" isDirectory:true] URLByAppendingPathComponent:bName] error:&theError];
if (!(success)) {
[progView dismiss];
UIAlertView* alertFail=[[UIAlertView alloc]initWithTitle:#"Backup Error" message:#"Could not backup to iCloud." delegate:Nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertFail show];
NSLog(#"iCloud error: %#", [theError localizedDescription]);
}
else{
[self loadNotes:bName];
}
}];
});
and this code for tracing my upload progress
- (void)loadNotes:(NSString *)bname {
self.alertQuery = [[NSMetadataQuery alloc] init];
[self.alertQuery setPredicate:[NSPredicate predicateWithFormat:#"%K LIKE %#", NSMetadataItemFSNameKey, bname]];
[self.alertQuery setSearchScopes:#[NSMetadataQueryUbiquitousDataScope]];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(liveupdate:) name:NSMetadataQueryDidUpdateNotification object:self.alertQuery];
[self.alertQuery startQuery];
}
-(void)liveupdate:(NSNotification *)note {
NSMetadataQuery* query=[note object];
if ([query resultCount]==0){
return;
}
NSMetadataItem* item=[query resultAtIndex:0];
float progress=[[item valueForAttribute:NSMetadataUbiquitousItemPercentUploadedKey]floatValue];
[progView.progBar setProgress:progress animated:NO];
if ([[item valueForAttribute:NSMetadataUbiquitousItemIsUploadedKey] boolValue]){
[query stopQuery];
[query disableUpdates];
_alertQuery=nil;
[progView dismiss];
}
}
what is the wrong with code...
can somebody tell me what is the best way to track icloud upload progress in NSFileManager setUbiquitous....
thank you...

You will probably want to observe the NSMetadataQueryDidFinishGatheringNotification notification, which fires first, with the initial set of results.
But even then, you may not get what you want, because the update notification will only fire if the set of results changes. You are searching for a particular file, and since that file is not being deleted or anything like that, your set of results will remain the same, even if the file uploads or downloads.
In my experience, NSMetadataQuery is not very effective for monitoring upload and download progress. You can hack it to almost work, but it is never exactly what you want.
Probably the best you can do is fire the metadata query, observe the finished-gathering notification, stop the query, and start the query again. Do this at regular intervals of a second or so, and you should be able to track the progress.
You should also consider whether you really want to track progress of an individual file. It will depend how large your files are. In many cases, you may be better to track the number of files to upload/download, or the total bytes remaining.
If this is the case, you can try to setup a metadata that includes a predicate with the uploaded/downloaded status included. This will continually fire notifications when a file finishes uploading/downloading. You can find an example of this here. Look for the method startMonitoringMetadata.

Related

Flutter/Dart - Suggestions for how to Troubleshoot a Future?

Though it was working previously, for some reason my code has now stopped working. Though it fetches the required json data, the build doesn't render. The error on my app page which is supposed to display a page view was;
type String is not a subtype of 'Map<String,dynamic>'
But after some tweaks, now the error is;
invalid arguments(s)
I think I may have narrowed it down to the Future;
FutureBuilder<List<SpeakContent>> futureStage() {
return new FutureBuilder<List<SpeakContent>>(
future: downloadJSON(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print("Snapshot has data.");
List<SpeakContent> speakcrafts = snapshot.data;
return new CustomPageView(speakcrafts);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return new CircularProgressIndicator();
},
);
}
Future<List<SpeakContent>> downloadJSON() async {
final jsonEndpoint =
"http://example.com/getContent.php?";
final response = await get(jsonEndpoint);
if (response.statusCode == 200) {
List speakcrafts = json.decode(response.body);
debugPrint(speakcrafts.toString());
return speakcrafts
.map((speakcraft) => new SpeakContent.fromJson(speakcraft))
.toList();
} else
throw Exception('We were not able to successfully download the json data.');
}
Although it doesn't throw an error, I've noticed that it doesn't print my test statement after the "if (snapshot.hasData)" line.
Shouldn't I see "Snapshot has data." appear in my Android Studio console?
Based on what you provided, this
type String is not a subtype of 'Map<String,dynamic>'
must be this:
return Text('${snapshot.error}');
which means that your downloadJSON() threw an exception. In that case, print('Snapshot has data.'); never executes and the next case that I quoted above is executed.
Please put a breakpoint in the body of downloadJSON(), run it line by line and see what's thrown where.
ALSO, you are making an irrelevant but big mistake here. Do not call downloadJSON() like this. This function is executed at every re-render, which can be many times. You are initiating a JSON download at every redraw of your widget. This may stack up your backend bills... I explain it in this talk in more detail: https://youtu.be/vPHxckiSmKY?t=4771
After performing the troubleshooting tips as suggested by Gazihan Alankus and scrimau, I've found the culprit which was a single null entry in the MYSQL Database. Scary... gotta find out how to prevent that problem in the future.

iOS query update not working

Can someone point me in the right direction to find out how to correctly monitor when files change in the app iCloud container? I've based my code on Apple and other iCloud tutorials I've reviewed, but none of them deal with updates to the iCloud container, just using initial queries. I've been working on this for three weeks now with no success. I use UIDocument in an app saving to the app iCloud container. Since UIDocument sends no notice when a document is added, I can't update the app on another iOS device when the app is running on multiple devices. Changing and deleting a document works fine by monitoring the UIDocument UIDocumentStateChangedNotification.
I use a query to initially check the iCloud container when the app starts or resumes from the background which works fine to get all files in the iCloud container on the device, including any documents added while the app was not active. I disable updates to process the query results when NSMetadataQueryDidFinishGatheringNotification is posted, then enable updates on the query. Sometimes I get one or two update notices shortly after enabling updates from NSMetadataQueryDidUpdateNotification being posted, but that is all. Never any further update notices and never from a document being added to the iCloud container.
I understand the code for iCloud use is somewhat complex, I don't expect anyone to examine my code (I've provided an excerpt for reference) to correct it. I'd appreciate it if someone can point me to more information on the specifics of tracking iCloud container changes during app execution.
Thanks,
Fred
Code excerpt for starting query:
-(void)loadDocument {
// set iCloud URL to nil for local storage to start
NSURL *ubiq = nil;
// if iCloud is selected get the iCloud container URL
if ([_useiCloud isEqualToString:#"YES"]) {
// get the app iCloud container URL
ubiq = DefaultMemoDataController.iCloudContainerURL;
}
// if iCloud URL is available and user chooses to use iCloud, set the query for app memo file names
if (ubiq) {
// adding to see if not creating another query prevents crash resuming from background
if (!self.query) {
self.query = [[NSMetadataQuery alloc] init];
}
// set the scope of the query to look in iCloud documents
[self.query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
// set search to look for a group of file names by setting up a predicate
// use the note file name format for the app
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K like 'FOLMemo_*'", NSMetadataItemFSNameKey];
// set the query to search with the predicate.
[self.query setPredicate:pred];
// set up a notification when the query is complete because the query is an asynchronous call (off the main queue)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(queryDidFinishGathering:)
name:NSMetadataQueryDidFinishGatheringNotification
object:self.query];
// start the query.
[self.query startQuery];
// not sure this is needed, but want to make sure same query is started again for updates.
DefaultMemoDataController.query = self.query;
}
}
code when query completes
-(void)queryDidFinishGathering:(NSNotification *)notification {
// stop the query while processing the query results to prevent changes while processing
NSMetadataQuery *query = [notification object];
[query disableUpdates];
// not sure is needed but want to make sure resume updates on same query
DefaultMemoDataController.query = query;
// stop looking for query did finish notifications since the query was completed.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSMetadataQueryDidFinishGatheringNotification
object:query];
// start looking for query updates
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(processQueryUpdate:)
name:NSMetadataQueryDidUpdateNotification
object:query];
// load the data from the query
[self loadData:query];
}
code to process query:
-(void)loadData:(NSMetadataQuery *)query {
// add all the memos from the query results to the app memos dictionary
for (NSMetadataItem *item in [query results]) {
// get the URL for the memo
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
// load the memo text from the url
FOLMemoDoc *doc = [[FOLMemoDoc alloc] initWithFileURL:url];
// open the note
[doc openWithCompletionHandler:^(BOOL success) {
if (success) {
// add the memo UIDocument object to the memo dictionary
// need temp dictionary since can't change a property dictionary for some reason
NSMutableDictionary * tempDict = [NSMutableDictionary dictionaryWithDictionary:DefaultMemoDataController.masterMemoDictionary];
[tempDict setObject:doc forKey:doc.memoDictionaryKey];
DefaultMemoDataController.masterMemoDictionary = [NSMutableDictionary dictionaryWithDictionary:tempDict];
NSNotification *notice = [NSNotification notificationWithName:kFlashofLightUpdateMemoNotice
object:doc];
[[NSNotificationCenter defaultCenter] postNotification:notice];
} else {
// failed to open document, should probably alert the user
}
}];
}
// enable query updates
[query enableUpdates];
}
After another week's experimentation I got query updates for the iCloud container working by adding a property to my persistent dataController object for the query object. By replacing each query reference in my previous code with the persistent dataController property, keeping the observer for the finished query (NSMetadataQueryDidFinishGatheringNotification) and never stopping the query, query updates now works (NSMetadataQueryDidUpdateNotification). The app receives a NSMetadataQueryDidUpdateNotification notification for every change to the app iCloud container. Multiple notices are received at times, but I have not come across a time when a notice is not posted, so I can now catch all real time updates on all devices running the app.
Here are the revised code extracts from above. This code requires other methods and set-up that is not included, so it will not run stand alone, but shows the changes I had to make to get NSMetadataQueryDidUpdateNotification notifications working in my app.
Code excerpt for starting query:
-(void)loadDocument {
// set iCloud URL to nil for local storage to start
NSURL *ubiq = nil;
// if iCloud is selected get the iCloud container URL
if ([_useiCloud isEqualToString:#"YES"]) {
// get the app iCloud container URL
ubiq = DefaultMemoDataController.iCloudContainerURL;
}
// if iCloud URL is available and user chooses to use iCloud, set the query for app memo file names
if (ubiq) {
// adding to see if not creating another query prevents crash resuming from background
if (!DefaultMemoDataController.query) {
DefaultMemoDataController.query = [[NSMetadataQuery alloc] init];
}
// set the scope of the query to look in iCloud documents
[DefaultMemoDataController.query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
// set search to look for a group of file names by setting up a predicate
// use the note file name format for the app
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K like 'FOLMemo_*'", NSMetadataItemFSNameKey];
// set the query to search with the predicate.
[DefaultMemoDataController.query setPredicate:pred];
//remove observer to make sure no duplicate observers
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSMetadataQueryDidFinishGatheringNotification
object:DefaultMemoDataController.query];
// set up a notification when the query is complete because the query is an asynchronous call (off the main queue)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(queryDidFinishGathering:)
name:NSMetadataQueryDidFinishGatheringNotification
object:DefaultMemoDataController.query];
// remove observer to make sure no duplicate observers
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSMetadataQueryDidUpdateNotification
object:DefaultMemoDataController.query];
// set observer for query update
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(processQueryUpdate:)
name:NSMetadataQueryDidUpdateNotification
object:DefaultMemoDataController.query];
// start the query.
[DefaultMemoDataController.query startQuery];
}
code when query initially completes:
-(void)queryDidFinishGathering:(NSNotification *)notification {
// disable the query while processing the query results to prevent changes while processing
DefaultMemoDataController.query
NSMetadataQuery *query = [notification object];
[DefaultMemoDataController.query disableUpdates];
// call loadData with the query results
[self loadData:DefaultMemoDataController.query];
}
code to process query
-(void)loadData:(NSMetadataQuery *)query {
// add all the memos from the query results to the app memos dictionary
for (NSMetadataItem *item in [query results]) {
// get the URL for the memo
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
// load the memo text from the url
FOLMemoDoc *doc = [[FOLMemoDoc alloc] initWithFileURL:url];
// open the memo
[doc openWithCompletionHandler:^(BOOL success) {
if (success) {
// add the memo UIDocument object to the memo dictionary
// need temp dictionary since can't change a property dictionary for some reason
NSMutableDictionary * tempDict = [NSMutableDictionary dictionaryWithDictionary:DefaultMemoDataController.masterMemoDictionary];
[tempDict setObject:doc forKey:doc.memoDictionaryKey];
DefaultMemoDataController.masterMemoDictionary = [NSMutableDictionary dictionaryWithDictionary:tempDict];
// save the memo dictionary
[DefaultMemoDataController saveMemoDictionary];
NSNotification *notice = [NSNotification notificationWithName:kFlashofLightUpdateMemoNotice
object:doc];
[[NSNotificationCenter defaultCenter] postNotification:notice];
} else {
// failed to open document
// if there is a memo dictionary key available, delete the memo from master memo dictionary
if (doc.memoDictionaryKey) {
// delete memo from master memo dictionary
[DefaultMemoDataController.masterMemoDictionary removeObjectForKey:doc.memoDictionaryKey];
}
// get the dictionary key from the file name and try to delete it that way
else {
NSString * filename = [doc.fileURL lastPathComponent];
if (filename) {
[DefaultMemoDataController.masterMemoDictionary removeObjectForKey:filename];
}
}
}
}];
}
// enable query updates
[DefaultMemoDataController.query enableUpdates];
}
I hope this helps someone else.
Fred

percent escapes removed in NSData writeToURL

I am trying to cache an image retrieved from Flickr. In order to create a unique filename for the cached image, I use CFURLCreateStringByAddingPercentEscapes to percent escape the URL. Appending that to the cache directory, I get a URL with the embedded Flickr URL properly percent escaped; but when I try to cache the image using NSData writeToURL:options:error: I get "The operation couldn’t be completed. No such file or directory" - and it shows the file URL with the original, unescaped Flickr URL where the file name should be.
For example, I NSLog the URL as:
file://localhost/Users/rick/Library/Application%20Support/iPhone%20Simulator/6.1/Applications/77C4A7AA-C386-4575-AD21-B4027D080408/Library/Caches/http%3A%2F%2Ffarm3.static.flickr.com%2F2887%2F9391679341_26643bcafa_b.jpg
but the error message shows
NSFilePath=/Users/rick/Library/Application Support/iPhone Simulator/6.1/Applications/77C4A7AA-C386-4575-AD21-B4027D080408/Library/Caches/http://farm3.static.flickr.com/2887/9391679341_26643bcafa_b.jpg
It's as if in the process of converting the URL to a file path, writeToURL is removing the percent escapes.
Is there a way to prevent this from happening, or do I just need to come up with another way to generate unique names based on the url?
Here's the relevant code:
NSURL *cacheDirectoryURL=[[fileManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
NSString *photoURLString= (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,
(__bridge CFStringRef)([self.photoURL absoluteString]),
NULL,
(CFStringRef) #"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8));
if (photoURLString)
{
NSURL *cachedPhotoURL=[NSURL URLWithString:[[cacheDirectoryURL absoluteString] stringByAppendingString:photoURLString]];
NSData *photoData=[NSData dataWithContentsOfURL:cachedPhotoURL];
if (photoData)
{
UIImage *image=[UIImage imageWithData:photoData];
self.imageView.image=image;
[self setupScrollView]; // new image, need to adjust scroll view
} else {
dispatch_queue_t fetchQueue=dispatch_queue_create("photo downloader", NULL);
dispatch_async(fetchQueue, ^{
NSData *photoData=[NSData dataWithContentsOfURL:self.photoURL];
NSError *error;
if ([photoData writeToURL:cachedPhotoURL options:NSDataWritingAtomic error:&error])
{
NSLog(#"Cached photo");
} else {
NSLog(#"Failed to cache photo");
NSLog(#"%#",error);
}
});
}
}
Thanks in advance for your help!
The problem is that [NSURL URLWithString:...] parses the given string and interprets the
percent escapes. Generally, to create a URL for a file system path, fileURLWithPath:
should be used.
In your case, the following simple code should work:
NSURL *cachedPhotoURL = [cacheDirectoryURL URLByAppendingPathComponent:photoURLString]

Testing HTTP using Kiwi/Nocilla

I just started developing an app that connects to this URL and retrieves the rate exchange for a given pair of currencies.
I need to test the HTTP request and I ended up learning about Kiwi and Nocilla. However, I'm completely new to any kind of testing and there's not a lot of information about Nocilla that can help me to get started.
I added all the NSURLConnectionDataDelegate and NSURLConnectionDelegate methods to the ViewController of my single view application, and the data retrieved from the URL is stored in #property (strong, nonatomic) NSMutableData *receivedData;. When I run the program everything works as expected but I haven't been able to pass the test I wrote:
SPEC_BEGIN(URLConnectionSpec)
__block URLConnectionAppDelegate *app_delegate;
__block URLConnectionViewController *view_controller;
describe(#"URLConnection", ^{
beforeAll(^{
[[LSNocilla sharedInstance] start];
app_delegate = [[UIApplication sharedApplication] delegate];
[[app_delegate shouldNot] beNil];
view_controller = app_delegate.viewController;
});
afterAll(^{
[[LSNocilla sharedInstance] stop];
});
afterEach(^{
[[LSNocilla sharedInstance] clearStubs];
});
context(#"When testing", ^{
it(#"should do something", ^{
stubRequest(#"GET", #"http://rate-exchange.appspot.com/currency?from=USD&to=EUR&q=1");
[view_controller beginCommunication];
[[expectFutureValue([NSString stringWithUTF8String:[view_controller.receivedData bytes]]) shouldEventuallyBeforeTimingOutAfter(2)] equal:#"{\"to\": \"EUR\", \"rate\": 0.76610740799999999, \"from\": \"USD\", \"v\": 0.76610740799999999}"];
});
});
});
SPEC_END
I'm sorry for the long snippet of code.
The test always failed with this message
URLConnection_WhenTesting_ShouldDoSomething] : 'URLConnection, When testing, should do something' [FAILED], expected subject to equal "{"to": "EUR", "rate": 0.76610740799999999, "from": "USD", "v": 0.76610740799999999}", got ""
I tried changing the time to even 10 seconds hoping that the test finished too early but I got the same results. I don't know why 'receivedData' is empty.
I would really appreciate any help
See discussion in comments: the overall structure of the Kiwi test looks good, the Nocilla stubRequest function call doesn't seem to result in the response that the test is expecting.
Perhaps you could use andReturnRawResponse to set up the expected response data. Something like this (assuming I got the Nocilla syntax correct):
NSData *rawData = ...
stubRequest(...).andReturnRawResponse(rawData);
[view_controller beginCommunication];
[expectFutureValue([view_controller.receivedData bytes])
shouldEventuallyBeforeTimingOutAfter(2)] equal:rawData.bytes];

How to get large photo URL in one API call?

I want to display large photos in my Facebook app's feed view immediately. Is it possible to get the large photo src URL from a stream/feed using one API call? The photo id is returned in the stream/feed and one can of course then supply this photo id in an additional FQL or graph API call to retrieve all the information about that photo. However, is there a way using multi-query or batch calls to get a larger photo src url using one API roundtrip?
I haven't tried this with stream/feed photos, but the generally accepted way of doing this is:
http://graph.facebook.com/{ID of object}/picture
If you want the "large" version, you would do:
http://graph.facebook.com/{ID of object}/picture?type=large
I'm not 100% sure if this would work for an actual photo (instead of a user profile picture or page profile pic), but I have a hunch it will - the only caveat is that you obviously must have a logged in user that is authorized to view the photo (unless it's public).
If anybody is looking to this and type large is not enough, I found other solutions.
Type large is kind of small anyway (close to 200px). You can get larger image by adding i.e. ?width=1000 or ?height=1000. Facebook will return picture closest to given dimension and preserve aspect ratio. When passing both dimenstions like ?width=1000&height=1000, facebook will cut image to given dimensions (in this case square).
Use Facebook UserId (Oject ID) to get the picture.
https://graph.facebook.com/173xxxx8635/picture?type=large&redirect=false
which returns JSON data with picture URL.
{
"data": {
"is_silhouette": false,
"url": "https://fbcdn-profile-a.akamaihd.net/xxx/xyz/1cc066a2cae3f301d"
}
}
A good trick with the new api is to get the pic_cover field from the event table and to process it according to the size you want to use
I found when I was having this trouble that it turned out to be the picture I was downloading rather than the size I was setting it.
If for example I downloaded all my photos with a request of
[FBRequestConnection startWithGraphPath:#"/me/photos?fields=created_time,name,picture&type=tagged" parameters:nil HTTPMethod:#"GET" completionHandler:^(FBRequestConnection * connection, id result, NSError *error) {
NSDictionary * userData = (NSDictionary *)result;
NSMutableArray * array = [[NSMutableArray alloc] initWithArray:userData[#"data"]];
for (NSDictionary * dict in eventsToAdd) {
UIImage * image = dict[#"picture"]
}
}];
I am using the dictionary key search "picture" as I want the picture.
This though will get me a lower quality picture than if I searched for "source" in this search:
[FBRequestConnection startWithGraphPath:#"/me/photos?fields=created_time,name,source&type=tagged" parameters:nil HTTPMethod:#"GET" completionHandler:^(FBRequestConnection * connection, id result, NSError *error) {
NSDictionary * userData = (NSDictionary *)result;
NSMutableArray * array = [[NSMutableArray alloc] initWithArray:userData[#"data"]];
for (NSDictionary * dict in eventsToAdd) {
UIImage * image = dict[#"source"]
}
}];
If you go on the Facebook API explorer and search for photos and then click on the picture and source jpg links you can see the difference in size and quality.
Since changing this method I have managed to get rid of using the type parameters as it doesn't seem to make a different.
Note: I am using iPhone and not iPad or a larger screen so I don't know how this affects bigger screens.
The answer by #streetlogics works fine but only on pictures that have {object_id}.
http://graph.facebook.com/{object_id}/picture
But I also wanted large pictures for the feed's shared links, which sometimes don't have {object_id}. I finally realized that the {picture} thumbnail URL contains the encoded URL for the original site's large image:
https://external.xx.fbcdn.net/safe_image.php?d=AQBe9UvGd0vPbAHP&w=130&h=130&url=http%3A%2F%2Fskift.com%2Fwp-content%2Fuploads%2F2015%2F12%2Fpollution.jpg&cfs=1
--> contains -->
http://skift.com/wp-content/uploads/2015/12/pollution.jpg
So I made a loop that checks for {object_id} and if not present then extracts the URL from {picture}:
if(isset($post['object_id'])) {
echo "http://graph.facebook.com/".$post['object_id']."/picture";
}
elseif(isset($post['picture'])) {
echo urldecode(preg_replace('/&cfs.*/', '', preg_replace('/.*url=/', '', $post['picture'])));
}
else {
echo "no_large_image";
}