Thursday, April 30, 2015

Change the ios application display name in home screen

The following steps can be used to change the application name under the app icon in home screen:
1. open the project info.plist
2. add a new item
3. select the item key from the list as Bundle display name
4. set the new name for the application

Monday, April 13, 2015

Swift optional variable ? ! as?

var v : UIView?
   the variable v may be nil or may be a valid UIView Object

var uv = v!
   although v is optional, but when the above line is executed, developer promises the v points to a valid uiView object, otherwise, the app will crash

var m = v?.backgroundColor
   if v is nil, the express return nil. Otherwise, returning the UIView's background color

if let t = v {
   var h = t.backgroundColor
}
else{
}
  combine if check with optional variable. t is not optional

var k : UIView!
var bc =  k.backgroundColor
  k, as an implicitly unwrapped optional type, is similar to option type, so we do no need to set an initial value when declaring and defining the variable, also we do no need to explicitly unwrap the variable with ! when assigning it to a non optional variable. 
However, when defining implicitly unwrapped option type, developer promised that whenever the variable is used, it will always have a valid value assign to it. so the variable will be set before its value is used. This type is mostly used for IBOutlet.

let a : UIView?= v as? UIView
 case v to UIView and assign to a. The result may be nil or an option variable points to a valid object

let m: UIView = v as UIView
  Developer guarantees the v points to a valid object

option chain
When accessing an optional variable's property or method, the variable must be unwrapped with either ? or !, so that if the variable is nil, the express can return nil gracefully. If the variable definitely has a value, then ! can also be used to unwrapped the variable.
var mainStoryBoard = window?.rootViewController?.storyboard


Thursday, March 26, 2015

Two bugs in comparison operation in objective c

Two kinds of bug may happen in ios comparison operation:

1. compare NSNumber to integer
NSNumber cannot be used to compare with an integer directly using == operator, as

NSNumber num=...;
if (num == 0){
}
will fail, as == in objective c will compare two objects are refer to the same one, instead [NSNumber isEquelToNumber:] should be used to compare NSNumber. However, the below code still does not work

NSNumber* num =...;
if ([num isEqualToNumber: 0]){
...
}
as isEqualToNumber requires the input parameter also a NSNumber object, passing a integer will throw exception.

So the correct comparison with integer should be
if (num.intValue ==0){
}
assume num is not nil.


2. condition operation
NSString a = "a";
NSString b= "";
NSString c="c";
NSString d="d";
NSString c= a+b?c:d;

The expected result is "ad", however, the actual result is "ac", as + has priority over :, so the above expression is equal to (a+b)?c:d, as a+b is always true, so c is used instead of d.
The fix is explicitly set the priority as a+ (b?c:d), which will generate the result of "ad";

Monday, March 23, 2015

Symbolize ios crash report based on app bundle and dSYM file with Xcode 8

If you archive the ios build from one box and need to symbolize the ios crash report from another box, then you need to do it with the following command
1. First copy application dSYM file,  and device crash report (.crash) file into the same folder on mac

2. open terminal app into the above folder

3 run the below command from terminal
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer

4.run the below command from terminal to generate the symbolized crash log

/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash ./devicecrashreport.crash > symbolized.crash

If there are spaces on the above file name, then add single quotation mark around the file name

5. after the new symbolized crash report file (symbolized.crash) is generated on the same folder, double click it from Finder to show the symbolized file in console app




If the symbolization failed, then likely the crash report does not match the binary build, using the below steps to verify it:
1.from crash report, get the build uuid immediately after 'Binary Images" within <>.

2.from the bundle file, run the below command from terminal
xcrun dwarfdump --uuid <PATH_TO_APP_EXECUTABLE>

The file at PATH_TO_APP_EXECUTABLE must be an executable file, not an .app bundle or .ipa file.

3. The two UUID must match.


Saturday, January 31, 2015

Steps to install shibboleth idp on windows with tomcat


1. download zip file for shibboleth-idp installation from
http://shibboleth.net/downloads/identity-provider, do not use the latest 3.0, which is not yet stable as well as well documented. Use 2.4. and unzip it to a folder

2. check java -version to be sure it is 1.7.0 or above

3. execute install.bat, and enable https connection with 9443. Set the identity of your idp, for example
https://torn00461340a.amer.global.corp.sap/idp/shibboleth

4. download tomcat 7 (port 9080 and 9443 are used), and add the server into eclipse

5. add idp.xml as mentioned in https://wiki.shibboleth.net/confluence/display/SHIB2/IdPApacheTomcatPrepare
Set unpackwar to true to avoid an error in eclipse server start.

6. start tomcat from eclipse , and be sure the below query works
http://localhost:9080/idp/status
http://localhost:9080/idp/profile/Metadata/SAML


7 backup and update relying-party.xml MetadataProvider section as below

     <metadata:MetadataProvider id="ShibbolethMetadata" xsi:type="metadata:ChainingMetadataProvider">
         <metadata:MetadataProvider id="IdPMD" xsi:type="metadata:FilesystemMetadataProvider"
                                   metadataFile="C:\opt\shibboleth-idp/metadata/idp-metadata.xml"
                                   maxRefreshDelay="P1D" />
              <metadata:MetadataProvider id="URLMD" xsi:type="metadata:FilesystemMetadataProvider"
                                   metadataFile="C:\opt\shibboleth-idp/metadata/testshib.xml"
                                    />
    </metadata:MetadataProvider>

8 open IDP_HOME/conf/handler.xml, comment out LoginHandler RemoteUser element, and uncomment LoginHandler UsernamePassword element.

9 Open the file IDP_HOME/conf/login.config and uncomment Example LDAP authentication element. Pay attention to the "file:///" part.
   <!-- Login Handlers
    <ph:LoginHandler xsi:type="ph:RemoteUser">
        <ph:AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</ph:AuthenticationMethod>
    </ph:LoginHandler>
 -->
    <!--  Username/password login handler -->
 
    <ph:LoginHandler xsi:type="ph:UsernamePassword"
                  jaasConfigurationLocation="file:///C:\opt\shibboleth-idp/conf/login.config">
        <ph:AuthenticationMethod>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</ph:AuthenticationMethod>
    </ph:LoginHandler>

10 download Windows AD LDS and install it on Windows 7. Use the below online help to to install it - "Office 365 Single Sign-On with Shibboleth 2 whitepaper"
http://www.microsoft.com/en-ca/download/details.aspx?id=35464


11. update login.config with the below info based on AD LDS installation
      edu.vt.middleware.ldap.jaas.LdapLoginModule required
      ldapUrl="ldap://localhost:389"
      baseDn="CN=torn00461340a,DC=SAP"
 userFilter="cn={0}"
 subtreeSearch="true"
          ssl="false"
 tls="false"
 bindDn="cn=ShibbolethServiceAccount,cn=torn00461340a,dc=SAP"
 bindCredential="password";

12 open attribute.resolver.xml, and update LDAP connector element as below
    <!-- Example LDAP Connector -->
 
    <resolver:DataConnector id="myLDAP" xsi:type="dc:LDAPDirectory"
        ldapURL="ldap://localhost:389"
        baseDN="CN=torn00461340a,DC=SAP"
        principal="cn=ShibbolethServiceAccount,cn=torn00461340a,dc=SAP"
        principalCredential="password">
        <dc:FilterTemplate>
            <![CDATA[
                (uid=$requestContext.principalName)
            ]]>
        </dc:FilterTemplate>
    </resolver:DataConnector>
 

13. update attribute-resolver.xml to include assertion required by SP.
for example, the mail attribute
<resolver:AttributeDefinition id="email" xsi:type="Simple" xmlns="urn:mace:shibboleth:2.0:resolver:ad"
        sourceAttributeID="mail">
  <resolver:Dependency ref="ADLDS" />

  <resolver:AttributeEncoder xsi:type="SAML1String" xmlns="urn:mace:shibboleth:2.0:attribute:encoder"
        name="urn:mace:dir:attribute-def:mail" />

  <resolver:AttributeEncoder xsi:type="SAML2String" xmlns="urn:mace:shibboleth:2.0:attribute:encoder"
        name="urn:oid:0.9.2342.19200300.100.1.3" friendlyName="mail" />
</resolver:AttributeDefinition>


14.update attribute-filter.xml with below segment to allow idp to  release the attribute of givenName to service provider
   <afp:AttributeFilterPolicy id="releaseAttriToTestSP">
        <afp:PolicyRequirementRule xsi:type="basic:ANY" />

        <afp:AttributeRule attributeID="givenName">
            <afp:PermitValueRule xsi:type="basic:ANY" />
        </afp:AttributeRule>
    </afp:AttributeFilterPolicy>


15. Update relying-party.xml to test with testshib to verify the SP can redirect to your IDP and prompt you to input username and password.

              <metadata:MetadataProvider id="URLMD" xsi:type="metadata:FilesystemMetadataProvider"
                                   metadataFile="C:\opt\shibboleth-idp/metadata/testshib.xml"
                                    />

After inputting user name and password, it shows a screen says "Shibboleth-protected TestShib Content. You can also verify the givenName is sent to SP by IDP by using Firefox saml tracer plugin.

Sunday, January 18, 2015

Receive native side notification by javascript using cordova plugin

Usually, the cordova plugin is used to invoke native api from javascript. However, it can also be used by javascript to listen for native side notification. This feature is already used in several cordova build in plugins, such as device motion plugin at https://github.com/apache/cordova-plugin-device-motion.

The basic idea is when calling the cordova plugin's callback method, it also an option to keep the callback alive, so after the cordova plugin API is initially called from javascritp to native side, the native code can keep the callback method in its data member. Whenever the native code needs to send a notification to javascript, it can just call this saved callback method with the notification data, also specify the callback method should be kept alive on javascirpt side in order to get following notification, otherwise, the javascript will delete the callback after it receives the first callback method from native side.

A sample callback made from Android native code are as below

   PluginResult result = new PluginResult(PluginResult.Status.OK, "This is notification data");
   result.setKeepCallback(true);

   _callbackContext.sendPluginResult(result);

Serve static web content by tomcat

The following steps can be used to server static web content by tomcat server, the static web content includes html, image, and js, jsp files.

1. create a subfolder under tomcat's webapps folder, for example, mytestfolder
2. copy html file and js file into the folder, for example, index.html
3. visit localhost:8080/mytestfolder/index.hmtl to visit the html file

In addition, jsp files can also be put in the folder and serve the client request without any servlet configuration change.

Sometimes when debugging tomcat, an error of ""Several ports (8080, 8009) required by Tomcaat v8.0 Server at localhost are already in use", to solve the issue, going to tomcat bin folder and run the below commend to close the running tomcat instance.


bash shutdown.sh