COMPUTER SCIENCE, TECHNOLOGY, Uncategorized

iOS – Sharing file path between a share extension and iOS app

Here’s an app store accepted way to share file path between an extension and an app.

  1. Share extension
#import "ShareViewController.h"
#import <MobileCoreServices/UTCoreTypes.h>
//Macro to hide post dialog or not, if defined, will be hidden, comment during debugging
#define HIDE_POST_DIALOG

@interface ShareViewController ()

@end

@implementation ShareViewController

NSUInteger m_inputItemCount = 0; // Keeps track of the number of attachments we have opened asynchronously.
NSString * m_invokeArgs = NULL; // A string to be passed to your AIR app with information about the attachments.
NSString * APP_SHARE_GROUP = @"group.com.schemename.nameofyourshareappgroup";
const NSString * APP_SHARE_URL_SCHEME = @"schemename";
CGFloat m_oldAlpha = 1.0; // Keeps the original transparency of the Post dialog for when we want to hide it.

- (BOOL)isContentValid {
// Do validation of contentText and/or NSExtensionContext attachments here
return YES;
}

- ( void ) didSelectPost
{
#ifdef HIDE_POST_DIALOG
return;
#endif

[ self passSelectedItemsToApp ];
// Note: This call is expected to be made here. Ignore it. We'll tell the host we are done after we've invoked the app.
// [ self.extensionContext completeRequestReturningItems: @[] completionHandler: nil ];
}
- ( void ) addImagePathToArgumentList: ( NSString * ) imagePath
{
assert( NULL != imagePath );

// The list of arguments we will pass to the AIR app when we invoke it.
// It will be a comma-separated list of file paths: /path/to/image1.jpg,/path/to/image2.jpg
if ( NULL == m_invokeArgs )
{
m_invokeArgs = imagePath;
}
else
{
m_invokeArgs = [ NSString stringWithFormat: @"%@,%@", m_invokeArgs, imagePath ];
}
}

- ( NSString * ) saveImageToAppGroupFolder: ( UIImage * ) image
imageIndex: ( int ) imageIndex
{
assert( NULL != image );

NSData * jpegData = UIImageJPEGRepresentation( image, 1.0 );

NSURL * containerURL = [ [ NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier: APP_SHARE_GROUP ];
NSString * documentsPath = containerURL.path;

// Note that we aren't using massively unique names for the files in this example:
NSString * fileName = [ NSString stringWithFormat: @"image%d.jpg", imageIndex ];

NSString * filePath = [ documentsPath stringByAppendingPathComponent: fileName ];
[ jpegData writeToFile: filePath atomically: YES ];

//Mahantesh -- Store image url to NSUserDefaults

NSUserDefaults *defaults=[[NSUserDefaults alloc] initWithSuiteName:@"group.com.schemename.nameofyourshareappgroup"];
[defaults setObject:filePath forKey:@"url"];
[defaults synchronize];

return filePath;
}

- ( void ) passSelectedItemsToApp
{
NSExtensionItem * item = self.extensionContext.inputItems.firstObject;

// Reset the counter and the argument list for invoking the app:
m_invokeArgs = NULL;
m_inputItemCount = item.attachments.count;

// Iterate through the attached files
for ( NSItemProvider * itemProvider in item.attachments )
{
// Check if we are sharing a Image
if ( [ itemProvider hasItemConformingToTypeIdentifier: ( NSString * ) kUTTypeImage ] )
{
// Load it, so we can get the path to it
[ itemProvider loadItemForTypeIdentifier: ( NSString * ) kUTTypeImage
options: NULL
completionHandler: ^ ( UIImage * image, NSError * error )
{
static int itemIdx = 0;

if ( NULL != error )
{
NSLog( @"There was an error retrieving the attachments: %@", error );
return;
}

// The app won't be able to access the images by path directly in the Camera Roll folder,
// so we temporary copy them to a folder which both the extension and the app can access:
NSString * filePath = [ self saveImageToAppGroupFolder: image imageIndex: itemIdx ];

// Now add the path to the list of arguments we'll pass to the app:
[ self addImagePathToArgumentList: filePath ];

// If we have reached the last attachment, it's time to hand control to the app:
if ( ++itemIdx >= m_inputItemCount )
{
[ self invokeApp: m_invokeArgs ];
}
} ];
}
}
}
- ( void ) invokeApp: ( NSString * ) invokeArgs
{
// Prepare the URL request
// this will use the custom url scheme of your app
// and the paths to the photos you want to share:
NSString * urlString = [ NSString stringWithFormat: @"%@://%@", APP_SHARE_URL_SCHEME, ( NULL == invokeArgs ? @"" : invokeArgs ) ];
NSURL * url = [ NSURL URLWithString: urlString ];

NSString *className = @"UIApplication";
if ( NSClassFromString( className ) )
{
id object = [ NSClassFromString( className ) performSelector: @selector( sharedApplication ) ];
[ object performSelector: @selector( openURL: ) withObject: url ];
}

// Now let the host app know we are done, so that it unblocks its UI:
[ super didSelectPost ];
}

#ifdef HIDE_POST_DIALOG
- ( NSArray * ) configurationItems
{
// Comment out this whole function if you want the Post dialog to show.
[ self passSelectedItemsToApp ];

// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
return @[];
}
#endif

#ifdef HIDE_POST_DIALOG
- ( void ) willMoveToParentViewController: ( UIViewController * ) parent
{
// This is called at the point where the Post dialog is about to be shown.
// Make it transparent, so we don't see it, but first remember how transparent it was originally:

m_oldAlpha = [ self.view alpha ];
[ self.view setAlpha: 0.0 ];
}
#endif

#ifdef HIDE_POST_DIALOG
- ( void ) didMoveToParentViewController: ( UIViewController * ) parent
{
// Restore the original transparency:
[ self.view setAlpha: m_oldAlpha ];
}
#endif
#ifdef HIDE_POST_DIALOG
- ( id ) init
{
if ( self = [ super init ] )
{
// Subscribe to the notification which will tell us when the keyboard is about to pop up:
[ [ NSNotificationCenter defaultCenter ] addObserver: self selector: @selector( keyboardWillShow: ) name: UIKeyboardWillShowNotification object: nil ];
}

return self;
}
#endif
#ifdef HIDE_POST_DIALOG
- ( void ) keyboardWillShow: ( NSNotification * ) note
{
// Dismiss the keyboard before it has had a chance to show up:
[ self.view endEditing: true ];
}
#endif
@end

 

2. In the openURL method of your application delegate

  //Slartibartfast -- For the case where we are opening app from an extension
         NSString *STATIC_FILE_HANDLE = @"file://";
        //If app is opened from share extension, do the following
        /*
         1.) Get path of shared file from NSUserDefaults
         2.) Get data from file and store in some variable
         3.) Create a new accesible unique file path
         4.) Dump data created into this file.
         */

        NSUserDefaults *defaults=[[NSUserDefaults alloc] initWithSuiteName:YOURAPP_STATIC_APP_GROUP_NAME];
        NSString *path=nil;
        if(defaults)
        {
            [defaults synchronize];
            path = [defaults stringForKey:@"url"];
        }

        if(path.length != 0)
        {
            NSData *data;
            //Get file path from url shared
            NSString * newFilePathConverted = [STATIC_FILE_HANDLE stringByAppendingString:path];
            url = [ NSURL URLWithString: newFilePathConverted ];
            data = [NSData dataWithContentsOfURL:url];
            //Create a regular access path because this app cant preview a shared app group path
            NSString *regularAccessPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
            NSString *uuid = [[NSUUID UUID] UUIDString];
            //Copy file to a jpg image(ignore extension, will convert from png)
            NSString *uniqueFilePath= [ NSString stringWithFormat: @"/image%@.jpg", uuid];
            regularAccessPath = [regularAccessPath stringByAppendingString:uniqueFilePath];
            NSString * newFilePathConverted1 = [STATIC_FILE_HANDLE stringByAppendingString:regularAccessPath];
            url = [ NSURL URLWithString: newFilePathConverted1 ];
            //Dump existing shared file path data into newly created file.
            [data writeToURL:url atomically:YES];
            //Reset NSUserDefaults to Nil once file is copied.
            [defaults setObject:nil forKey:@"url"];

        }
    //Do what you want
    }

You’re welcome 🙂
Original: https://stackoverflow.com/questions/32228182/code-to-share-file-path-file-between-a-share-extension-and-ios-app/33795269#33795269

Advertisements
Uncategorized

Cantonese Proverbs in One Picture

廣府話小研究Cantonese Resources

阿塗(Ah To), a graphic designer and part-time cartoonist who concerns about the survival of Cantonese in Canton and Hong Kong, has just published a comic called ” The Great Canton and Hong Kong Proverbs” on Hong Kong independent media “Passion Times“. The cartoon contains illustrations of 81 Cantonese proverbs.
comic58

“The Great Canton and Hong Kong Proverbs”
In 1559, Dutch artist Pieter Bruegel created the oil painting “Netherlandish Proverbs” which illustrates many Dutch proverbs to praise the Dutch culture. In 2014, Ah To imitated the idea and created “Great Canton and Hong Kong proverbs” illustrating 81 Cantonese proverbs to propagate the Cantonese culture and defend Cantonese.

81 Cantonese Proverbs 

answer0226

(The 2 extra proverbs are the bonus given by the author. And audio clips only work on PC.)

1. cantoneseproverb67 上山捉蟹 [séuhng sāan jūk háaih]

(To catch crabs on a hill)
Harder than hard, almost impossible

2. cantoneseproverb1 鬼揞眼 [gwái ám…

View original post 2,297 more words

Uncategorized

Medieval Selfies

Really fun article on medieval selfies

medievalbooks

Self-portraits of medieval book artisans are as exciting as they are rare. In the age before the modern camera there were limited means to show others what you looked like. In the very late medieval period, when the Renaissance spirit was already felt in the air, some painters made self-portraits or included themselves in paintings commissioned by others. Stunningly, the medieval painter Jan van Eyck showed himself in the portrait of Giovanni Arnolfini and his fiance: he is staring at you from the mirror that is hanging behind the couple. For those who still didn’t get it, he painted above it Johannes de eyck fuit hic, Jan van Eyck was here” (Fig. 1, more here). He added the date 1434 to the picture, making it a particularly early selfie.

Jan van Eyck, Giovanni Arnolfini and his fiance, 1434 (right) and mirror detail (left) Fig. 1 – Jan van Eyck, Giovanni Arnolfini and fiance (right)  and mirror detail (left)

As far as producers of books is concerned, there were only two kinds…

View original post 1,052 more words

Uncategorized

Sequoia::Hackathon 2014 – Analysis

Just came back from Sequoia Hack 2014 at the ITC Gardenia in Bangalore. We were team Slartibartfast (Jainendra Kumar) and I. My original teammate couldn’t come, and Jai decided to join up for a fun 24 hour hackathon(his first). As it is the norm in bangalore, a great crowd of some of the smartest hackers in Bangalore had showed up .  A lot of Sequoia backed indian companies were releasing API’s like JustDial, Freecharge, HealthKart, Practo, Appier etc, But we were focused on working and seeing the OLA cabs API. We were quite excited because we both are excited about the potential Ola cabs has to disrupt the transportation space in India. There were 12 tracks one could be in- i.e Payments, ML, Transport, Open Source, Gaming, Social,Virtual Goods, Search, Analytics, Infra, healthcare and (one more that I cant remember anymore, will update).

Our original idea was to build Poola – Carpooling with Ola. But when the OLA API’s were released, they just weren’t enough to build what we wanted to, and we didn’t want to download and fudge data and show something fake and even though Ola worked really hard on releasing the API’s they couldnt expose more data. We tried to build a pseudo hack till 10PM with dummy data without a lot of API use on Saturday but then realized it would be futile to continue, plus we later discovered a lot of teams were doing Carpooling with Ola . This is when we made the switch from Transportation to Gaming. We ended up building a small game on Android.

The premise for building the game:

  1. Very easy game play but should be difficult to master
  2. Addictive
  3. Can be built in 10 hours and Put onto play store by 10 am
  4. Learn about game building on Android for work purposes, try to use concepts like OPENGL etc., to build it

Presenting Wiley Runner. (Removed for now off the store, will be back after a few image tweaks)

feature

Help Wile E. Coyote – the hero in our game(Yes!) escape a barrage of roadrunners and kill as many as you can with ACME missiles Instructions:

  1.  Move the coyote from left to right to escape roadrunners
  2.  Swipe up to shoot ACME missiles
  3. Try to achieve high scores and compete with your friends .

Next steps for the app will include

  1. Google play integration
  2. Ads
  3. Infinite scroll levels

And Maybe gaze tracking integration (Anand chandrashekaran from MadStreetDen will be thrilled) Lets see if it can become the next flappy bird – everyone I sent the game to are still playing it 😀 All in all a great event.

Met a few investors of Sequoia who I will certainly want to be talking to again 😉

Feedback to the event organizers:

  1. Wifi – Very hit/miss . Maybe try handing out one day dongles to every one next time?
  2. Segregate teams doing 24 hours hacks vs . I know this is difficult but this would be great.
  3. Organized better – we weren’t in any of the track lists, we didn’t receive a google link to register our track and we literally had 1 minute with the judges towards the end because quite literally time was up.

But then its only the second sequoia hack and hope it gets better next year- so all in all good fun! The food and the continuous supply of paper boat/tzinga was brilliant

Congratulations to all the winners and great work!

Follow the #seqhack tag on twitter to find all the winners and winning ideas.

Uncategorized

Why we don’t want SHA-1 anymore.

Wondering why Google wants to kill SHA-1.?

Been meaning to write in great depth about SHA-1 , what it is, and why we don’t want it anymore, but hey someone’s already done it very very well here–  in fact he’s even written a live web checker.

So I’m just going to summarize the core of this issue

  • Any web site that is HTTPS, when connected to ,will present a certificate to the browser claiming to be authentic, secure and real.
  • The certificate has been issued to the website by a regulatory body called a Certificate Authority (Examples – Verisign, Comodo)
  • The certificate has two parts – key for encrypted connection and SHA-1 hash to ensure that the website you have connected really is the website it claims to be. For e.g. when you go to https://www.facebook.com , the facebook certificate has been signed with a private key that only the CA knows, and the browser will maintain an encrypted connection throughout the session.
  • But the browser will only show you a green lock if it can verify that the website really is what it claims to be. For this firstly the CA signs the certificate and runs it through an algorithm which in most cases is SHA-1 . This is where the problem lies.
  • One-way hash algorithms like SHA-1 are designed to produce unique, irreversible so that the browser can identify the authenticity of the site
  • When your browser sees a certificate, it can calculate the SHA-1 for that certificate’s information itself, and then compare it to the signed SHA-1 that the certificate offered as proof. Because SHA-1 promises unique information, the browser trusts that if they match, the certificate on offer is the same one the Certificate Authority signed.
  • If you could engineer a certificate that “collides” with a target certificate, and coax a Certificate Authority to issue you that certificate, then you would successfully forge a certificate that a browser would find indistinguishable from the target.
  • In 2005, cryptographers proved that SHA-1 could be cracked 2,000 times faster than predicted. It would still be hard and expensive — but since computers always get faster and cheaper, it was time for the internet to stop using SHA-1.
  • Then the internet just kept using SHA-1. In 2012, Jesse Walker wrote an estimate, reprinted by Bruce Schneier, of the cost to forge a SHA-1 certificate. The estimate uses Amazon Web Services pricing and Moore’s Law as a baseline.Walker’s estimate suggested then that a SHA-1 collision would cost $2M in 2012, $700K in 2015, $173K in 2018, and $43K in 2021. Based on these numbers, Schneier suggested that an “organized crime syndicate” would be able to forge a certificate in 2018, and that a university could do it in 2021.Walker’s estimates and Schneier’s characterization have become widely cited in the planning and debate over transitioning from SHA-1. A group of leading Certificate Authorities, the CA Security Council, cited them recently to complain about Google’s schedule. In that complaint, the CAs use those estimates to suggest “the lack of a practical attack until 2018”.

 

So there you go, you don’t need more proof do you? , Go ahead, change to SHA-2 today

 

Courtesy – https://konklone.com/post/why-google-is-hurrying-the-web-to-kill-sha-1  – Eric Mills site