Wednesday, June 22, 2016

How to build Node.js REST APIs in Raspberry Pi 3

This project is based on the "Build a REST API with node.js" video tutorial from Udemy


The project file can be downloaded here : https://mega.nz/#!z9oFlTgJ!geCPHjoXJ3rpm1OdldU8s5RBSJxLKiAxh_axvTbODB4

The node.js ARMv7 version is v4.4.3 and npm 2.15.1
which (ARMv7) can be downloaded from https://nodejs.org/en/download/
The project also use packages like bcryptjs, body-parser, express, jsonwebtoken and mongoose and integrate with mongodb. - No-SQL db.

To install mongodb in Raspberrry Pi, use sudo apt-get install mongodb

The following enhancements were made to the original project code

1. add shell scripts and use curl for API testing (test1.sh ... test6.sh), as POSTMAN is only available in google chrome
2. add js code to avoid creating of duplicated user (test using test2.sh)
3. add test to user login and obtain Authorization sessionToken (test using test3.sh)
4. add js code to check Authorization before CRUD (create, read, update and delete definition record)
5. add js code to check existence of definition id before update and delete record (test using test5.sh)
6. shell script to get sessionToken in each test for instruction to further test on update and delete definition (test using test5.sh)
7. add js code to create log when create, update and delete definition record (test using test4.sh / test5.sh and then test6.sh)

To use mongo to admin user
mongo
> use workouts
> db.addUser({ user: "test", pwd: "test", roles:["readWrite", "dbAdmin"]});

To use mongo to display mongodb info
mongo
> use workouts
> show collections
> db.users.find()
> db.definitions.find().pretty()
> db.logs.find().pretty()

To use mongo to remove object
> db.definitions.remove({_id:ObjectId("573c29c0f11288dc9997d0")})

Instructions to use
-----------------------
1. First install node.js and mongodb and check that if mongod is running successfully in background. (If you use windows / OSX version of mongodb, please make sure the required data path is created before running mongod.exe / mongod)
2. use mongo to create admin user as above
3. Download the project file and unzip and install packages and start
bash    Select all
unzip nodeapi.zip cd nodeapi npm install npm start & # test ./test1.sh ./test2.sh ./test3.sh ... ./test6.sh # kill background job kill $!



Tuesday, June 21, 2016

How to run Docker for macOS

1) Download from here -> https://docs.docker.com/docker-for-mac/

2) Drag to Application Folder and double click to start and then check version in Terminal
docker --version

3) Search and Pull Docker image
E.g.
docker search kitura
docker pull ibmcom/kitura-ubuntu:latest


4) Run image with port forwarding <local port : container port>
E.g.
docker run -p 8095:8095 -t -i ibmcom/kitura-ubuntu:latest /bin/bash

5) Run / Download (if none) additional images and run as daemon
docker run -d -p 8080:8080 --name nodejs node
docker run -d -p 80:80 --name webserver nginx


6) List all downloaded or committed images
docker images

Download old images from
http://mirror.yandex.ru/mirrors/download.openvz.org/template/precreated/
and using import
cat ~/Downloads/ubuntu-10.04-x86.tar.gz | docker import - ubuntu-x86:10.04
docker run -t -i ubuntu-x86:10.04 bash


7) Run image with port forwarding <local port : container port> and bash shell
docker run -p 8095:8095 -t -i ibmcom/kitura-ubuntu:latest bash
docker run -p 80:80 -t -i nginx:latest bash
docker run -p 3000:3000 -t -i node:latest bash
docker run -t -i lballabio/quantlib-python:latest bash


8) List all containers with <CONTAINER ID>
docker ps -a
#export container
docker export <CONTAINER ID> > ubuntu.tar


Execute container with bash shell
docker exec -t -i <CONTAINER ID> bash

9) Commit changes to image with <newname:newtag>
docker commit <CONTAINER ID> kitura-ubuntu:v2

10) copy docker file to local docker start <CONTAINER ID>
docker cp <CONTAINER ID>:/root/myfile.tgz .






To test the kitura docker image for Swift web app
shell script    Select all
mkdir $HOME/play cd $HOME/play swift build --init cat > $HOME/play/Package.swift <<EOF import PackageDescription let package = Package( name: "play", dependencies: [ .Package(url: "https://github.com/IBM-Swift/Kitura.git", majorVersion:0, minor:15), .Package(url: "https://github.com/OpenKitten/MongoKitten.git", majorVersion: 1, minor: 1) ] ) EOF cat > $HOME/play/Sources/main.swift <<EOF import Foundation import Kitura import KituraSys import KituraNet import MongoKitten // All Web apps need a Router instance to define routes let router = Router() // Simple Mongodb instance let dbserver: MongoKitten.Server! do { dbserver = try Server("mongodb://test:test@localhost:27017", automatically: true) let database = dbserver["workouts"] print("MongoDB is available at port 27017") } catch { // Unable to connect print("MongoDB is not available on the given host and port") } // Simple JSON Wrapper Support func JSON<KeyType, ValueType>(_ dictionary: [KeyType: ValueType]) -> String? { let bridgeValue = dictionary.bridge() do { let jsonData = try NSJSONSerialization.data(withJSONObject:bridgeValue, options: NSJSONWritingOptions.PrettyPrinted) let str = String(data:jsonData, encoding: NSUTF8StringEncoding) return(str) } catch let error as NSError{ print(error.description) return(nil) } } // Basic GET request router.get("/hello") { _, response, next in response.headers["Content-Type"] = "text/plain; charset=utf-8" do { try response.status(.OK).send("Hello World").end() } catch { print("ERROR: Failed to send response to client: \(error)") } } router.get("/today") { _, response, next in let now = NSDate() let dayTimePeriodFormatter = NSDateFormatter() dayTimePeriodFormatter.dateFormat = "E, d MMM yyyy" let dateString = dayTimePeriodFormatter.string(from:now) dayTimePeriodFormatter.dateFormat = "HH:mm:ss Z" let timeString = dayTimePeriodFormatter.string(from:now) response.headers["Content-Type"] = "text/plain; charset=utf-8" do { let payload = ["Message": "Hello World", "Date": dateString, "Time": timeString] if let json = JSON(payload) { try response.status(.OK).send(json).end() } else { try response.status(.OK).send("Does anybody really know what time it is ?").end() } } catch { print("ERROR: Failed to send response to client: \(error)") } } // Start server let port = 8095 let server = HTTPServer.listen(port:port, delegate: router) print("starting server on port \(port)") Server.run() EOF #there are 3 errors in Packages/Strand-1.4.1/Sources/Strand.swift and need to be changed before build #Strand.swift let pointer = UnsafeMutablePointer<Void>(holder.toOpaque()) #change to let pointer = UnsafeMutablePointer<Void>(OpaquePointer(bitPattern: holder)) let unmanaged = Unmanaged<StrandClosure>.fromOpaque(arg)] #change to let unmanaged = Unmanaged<StrandClosure>.fromOpaque(OpaquePointer(arg)) private func runner(arg: UnsafeMutablePointer<Void>?) -> UnsafeMutablePointer<Void>? { #change to private func runner(arg: UnsafeMutablePointer<Void>!) -> UnsafeMutablePointer<Void>! { and 1 error in Packages/MongoKitten-1.1.0/Sources/Server.swift let port: UInt16 = UInt16(url.port?.int16Value ?? 27017) # change to let port: UInt16 = UInt16(url.port?.shortValue ?? 27017) #build app cd $HOME/play swift build -Xcc -fblocks -Xlinker -rpath -Xlinker .build/debug #install and start mongodb server apt-get update apt-get install mongodb -y apt-get install lsb-release -y service mongodb start #create user in mongodb using mongo client mongo > use workouts > db.createUser( {user: "test", pwd: "test", roles: [ "readWrite", "dbAdmin" ]} ); > show users > exit #run app and use mac browser to localhost:8095/hello .build/debug/play






To test the node docker image for node.js web app
shell script    Select all
#install mongodb apt-get update apt-get install mongodb mongodb-server mongodb-clients -y #start mongdb service if not automatically service mongodb start #mongo shell script create user and to display info mongo > use workouts > db.addUser( {user: "test", pwd: "test", roles: [ "readWrite", "dbAdmin" ]} ); > show users > exit #download project file and copy to the container #the project file can be downloaded from here https://mega.nz/#!z9oFlTgJ!geCPHjoXJ3rpm1OdldU8s5RBSJxLKiAxh_axvTbODB4 docker cp ~/Download/nodeapi.zip 6d8baf06826e:/root #unzip and install apt-get install zip unzip -y cd $HOME unzip nodeapi.zip cd nodeapi npm install npm start #use docker to start another shell access to test docker exec -it 6d8baf06826e bash cd $HOME/nodeapi ./test1.sh ./test2.sh ./test3.sh ./test4.sh ./test5.sh ./test6.sh ...






To test the quantlib-python docker image
shell script    Select all
apt-get update apt-get install python-pip pip install --upgrade pip pip install numpy cd $HOME cat > $HOME/qlversion.cpp <<EOF #include <iostream> #include <ql/version.hpp> int main() { std::cout << "Current QL Version:" << QL_LIB_VERSION << std::endl; return 0; } EOF g++ qlversion.cpp -o qlversion ./qlversion cat > $HOME/swap.py <<EOF import numpy as np import QuantLib as ql # Set Evaluation Date today = ql.Date(31,3,2015) ql.Settings.instance().setEvaluationDate(today) # Setup the yield termstructure rate = ql.SimpleQuote(0.03) rate_handle = ql.QuoteHandle(rate) dc = ql.Actual365Fixed() disc_curve = ql.FlatForward(today, rate_handle, dc) disc_curve.enableExtrapolation() hyts = ql.YieldTermStructureHandle(disc_curve) discount = np.vectorize(hyts.discount) start = ql.TARGET().advance(today, ql.Period('2D')) end = ql.TARGET().advance(start, ql.Period('10Y')) nominal = 1e7 typ = ql.VanillaSwap.Payer fixRate = 0.03 fixedLegTenor = ql.Period('1y') fixedLegBDC = ql.ModifiedFollowing fixedLegDC = ql.Thirty360(ql.Thirty360.BondBasis) index = ql.Euribor6M(ql.YieldTermStructureHandle(disc_curve)) spread = 0.0 fixedSchedule = ql.Schedule(start, end, fixedLegTenor, index.fixingCalendar(), fixedLegBDC, fixedLegBDC, ql.DateGeneration.Backward, False) floatSchedule = ql.Schedule(start, end, index.tenor(), index.fixingCalendar(), index.businessDayConvention(), index.businessDayConvention(), ql.DateGeneration.Backward, False) swap = ql.VanillaSwap(typ, nominal, fixedSchedule, fixRate, fixedLegDC, floatSchedule, index, spread, index.dayCounter()) engine = ql.DiscountingSwapEngine(ql.YieldTermStructureHandle(disc_curve)) swap.setPricingEngine(engine) print(swap.NPV()) print(swap.fairRate()) EOF python swap.py git clone git://github.com/mmport80/QuantLib-with-Python-Blog-Examples.git cd QuantLib-with-Python-Blog-Examples/ python blog_frn_example.py



Sunday, May 1, 2016

Android NDK old versions

See here https://github.com/taka-no-me/android-cmake/blob/master/ndk_links.md
and

http://stackoverflow.com/questions/6849981/where-do-i-find-old-versions-of-android-ndk

To extract .bin file under Linux or Mac OSX, chmod +x to make it executable and run for extraction.


Wednesday, April 20, 2016

Android Studio 2.0 Release

http://android-developers.blogspot.com/2016/04/android-studio-2-0.html
Java SE download -> http://www.oracle.com/technetwork/java/javase/downloads/index.html

Update on the new build.gradle dependencies classes com.android.tools.build:gradle:2.0.0 and the experimental com.android.tools.build:gradle-experimental:0.7.0-beta1 in Android Studio 2.0
for the C++ ndk static library build (native_app_glue) with multiple target cpu architectures

The original HelloDroid project file for Android 1.3 is here
or from https://mega.nz/#!iwoHjDiC!dJ45TLYAmCoUYnSOE9H1faYYOSyt5FxfBnmlXeqIRgU

Modifications to the following files are needed for Android Studio 2.0

app/build.gradle    Select all
apply plugin: 'com.android.model.application' Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) def ndkFolder = properties.getProperty('ndk.dir') def projectFolder = file(project.projectDir).absolutePath model { android { compileSdkVersion = 23 buildToolsVersion = '23.0.2' defaultConfig.with { applicationId 'com.beginndkgamecode.hellodroid' minSdkVersion.apiLevel = 9 targetSdkVersion.apiLevel = 23 versionCode = 1 versionName = '1.0' archivesBaseName = 'HELLODRIOD_' + versionName } } /* * native build settings */ android.ndk { moduleName = 'hellodroid' abiFilters.addAll(['armeabi-v7a','x86_64', 'x86']) // cppFlags.addAll(["-I${file("${ndkFolder}/sources/android/native_app_glue")}".toString()]) ldLibs.addAll(['EGL', 'GLESv2', 'android', 'log']) } /* * dependency library */ repositories { libs(PrebuiltLibraries) { native_app_glue { headers.srcDir ndkFolder+"/sources/android/native_app_glue" binaries.withType(StaticLibraryBinary) { staticLibraryFile = file("libs/local/${targetPlatform.getName()}/libandroid_native_app_glue.a") } } } } // jni is the default dir; config this if yours is in different directory android.sources { main { jni { source { srcDirs 'src/main/jni' } dependencies { library 'native_app_glue' linkage 'static' } } } } android.buildTypes { debug { minifyEnabled = false zipAlignEnabled = true ndk.with { debuggable = true } useProguard = false } release { minifyEnabled = false zipAlignEnabled = true useProguard = true proguardFiles.add(file('proguard-rules.txt')) } } android.productFlavors { // for detailed abiFilter descriptions, refer to "Supported ABIs" @ // https://developer.android.com/ndk/guides/abis.html#sa create('armeabi-v7a') { ndk.abiFilters.add('armeabi-v7a') } create('x86_64') { ndk.abiFilters.add('x86_64') } create('x86') { ndk.abiFilters.add('x86') } // To include all cpu architectures, leaves abiFilters empty create('all') } } /* * task to build static library files using ndk-build.cmd (for windows OS), ndk-build (for Mac) */ task staticLibBuild(type: Exec, description: 'Build Static Library files') { commandLine ndkFolder + '/ndk-build.cmd', 'APP_BUILD_SCRIPT='+ndkFolder+'/sources/android/native_app_glue/Android.mk', 'NDK_APPLICATION_MK='+file(projectDir).absolutePath+'/src/main/jni/Application.mk', 'NDK_PROJECT_PATH='+ndkFolder, 'NDK_OUT='+file(projectDir).absolutePath+'/libs' } tasks.withType(CppCompile) { compileTask -> compileTask.dependsOn staticLibBuild } task cleanLibDir(type: Delete) { delete 'libs' } clean.dependsOn cleanLibDir

app/src/main/jni/Application.mk    Select all
APP_PLATFORM := android-9 APP_ABI := armeabi-v7a x86 x86_64

Project:HelloDroid/build.gradle    Select all
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle-experimental:0.7.0-beta1' classpath 'com.android.tools.build:gradle:2.0.0' } } allprojects { repositories { jcenter() } }






HelloBoost, demo of using boost c++ libraries in Android Studio 2.0
a) Download the Android project from https://github.com/donbright/android_hello_boost
b) Download the prebuilt boost libraries for Android from https://github.com/emileb/Boost-for-Android-Prebuilt/ and extract to folder under sdkFolder (see local.properties)
c) Use Android Studio 2.0 menu function to Import Project... from android_hello_boost project and will create new project structure for Android Studio 2.0
d) Modify the app/build.gradle as below
app/build.gradle    Select all
apply plugin: 'com.android.model.application' Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) def sdkFolder = properties.getProperty('sdk.dir') model { android { compileSdkVersion = 23 buildToolsVersion = '23.0.3' defaultConfig { applicationId = 'com.example.helloboost' minSdkVersion.apiLevel = 4 targetSdkVersion.apiLevel = 23 versionCode = 1 versionName = '1.0' archivesBaseName = 'HELLOBOOST_' + versionName } /* * native build settings */ ndk { moduleName = 'hello-boost' abiFilters.addAll(['armeabi','armeabi-v7a', 'x86']) cppFlags.addAll(['-Wall', '-fexceptions', '-frtti']) stl = 'gnustl_static' } buildTypes { debug { minifyEnabled = false zipAlignEnabled = true ndk.with { debuggable = true } useProguard = false } release { minifyEnabled = false zipAlignEnabled = true useProguard = true proguardFiles.add(file('proguard-rules.txt')) } } productFlavors { // for detailed abiFilter descriptions, refer to "Supported ABIs" @ // https://developer.android.com/ndk/guides/abis.html#sa create("arm") { ndk.abiFilters.add("armeabi") } create("arm7") { ndk.abiFilters.add("armeabi-v7a") } create("x86") { ndk.abiFilters.add("x86") } // To include all cpu architectures, leaves abiFilters empty create("all") } } // jni is the default dir; config this if yours is in different directory android.sources { main { jni { source { srcDirs 'src/main/jni' } dependencies { library 'boost_program_options' linkage 'static' library 'boost_thread' linkage 'static' } } } } // PrebuiltLibraries repositories { libs(PrebuiltLibraries) { boost_program_options { headers.srcDir sdkFolder+'/Boost-for-Android-Prebuilt-master/boost_1_53_0/include' binaries.withType(StaticLibraryBinary) { staticLibraryFile = file("${sdkFolder}/Boost-for-Android-Prebuilt-master/boost_1_53_0/${targetPlatform.getName()}/lib/libboost_program_options-gcc-mt-1_53.a") } } boost_thread { headers.srcDir sdkFolder+'/Boost-for-Android-Prebuilt-master/boost_1_53_0/include' binaries.withType(StaticLibraryBinary) { staticLibraryFile = file("${sdkFolder}/Boost-for-Android-Prebuilt-master/boost_1_53_0/${targetPlatform.getName()}/lib/libboost_thread-gcc-mt-1_53.a") } } } } }

Project:android_hello_boost-master/build.gradle    Select all
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle-experimental:0.7.0-beta1' } } allprojects { repositories { jcenter() } }



ATTENTION: Android Studio 2.2 supports NDK build



Tuesday, March 15, 2016

Personal Installation Guide for Raspberry Pi 3 with Swift

Hardware List from RS:
Raspberry Pi 3 Model B SBC
Heatsink BGA 12x12 27K/W black
Official Pi 3 Power Supply Black
Official Pi 3 Black/Grey Case

Accessories:
MicroSDHC Card (with Adapter) 32G Class 10
USB SSD Harddisk 240G
USB Keyboard and Mouse

SD Card images for multiboot
1. NOOBS(easy to install but hard to reconfigure or add custom image for multiboot)
#Download NOOBS using Mac Terminal and write to MicroSDHC Card (with Adapter and mounted in Mac)
cd ~/Downloads
wget http://vx2-downloads.raspberrypi.org/NOOBS/images/NOOBS-2016-02-29/NOOBS_v1_8_0.zip
unzip NOOBS_v1_8_0.zip -d /Volumes/NO\ NAME/

#insert the SD card and power on the machine
#after boot into NOOBS and choose install Rasbian and OSMC (that is kodi)
#Rasbian username and password are pi and raspberry respectively
#OSMC username and password are all osmc


2. BerryBoot(very flexible and allow to add custom image for multiboot)
wget http://downloads.sourceforge.net/project/berryboot/berryboot-20160313-pi2-pi3.zip
unzip berryboot-20160313-pi2-pi3.zip -d /Volumes/NO\ NAME/

#insert the SD card and power on the machine
#after boot into BerryBoot and choose install Debian Rasbian, OpenELEC (that is kodi) or others
#OpenELEC username and password are root and openelec respectively.
#hold down mouse button on AddOS button of BerryBoot Menu and choose Copy OS from USB stick

#To install Ubuntu-trusty image for berryboot downloaded here below
https://mega.nz/#!PwYl1QBJ!Fu7A87qrAL4jTmv0RhlnksprhVCm4gsHi1xhQBELJGk
# login to Ubuntu-trusty, username and password are all ubuntu

#BerryBoot additional images are here below and can be downloaded in USB drive for offline installation
https://sourceforge.net/projects/berryboot/files/os_images/


It is possible to shrink the Linux partition of berryboot in order to create a third partition for the dphys-swapfile with about 2G size. The SD card for berryboot should be mounted as USB and Use  sudo umount /dev/sda2; sudo e2fsck -f /dev/sda2; sudo resize2fs /dev/sda2 27G;  to check and shrink and use  sudo fdisk /dev/sda;  to delete the second partition, recreate the second partition with +27G and then create the third partition with remaining space for swap (about 2.5G if for 32G SD card). And then  sudo mkfs.ext4 /dev/sda3;  to format as ext4 and run  sudo fsck.ext4 /dev/sda1; sudo fsck.ext4 /dev/sda2;  to check.
After booting into the berryboot SD card, add this in /etc/fstab
/dev/mmcblk0p3 /swap ext4 defaults,noatime 0 0
and then edit swap location to /swap/swap and mount the partition using  sudo mkdir -p /swap; sudo mount -t ext4 /dev/mmcblk0p3 /swap;  and then setup dphys-swapfile using  sudo vi /etc/dphys-swapfile;  and run  sudo dphys-swapfile setup; sudo dphys-swapfile swapon; 

shell script    Select all
# change password passwd # su sudo su sudo apt-get update sudo apt-get upgrade sudo apt-get install vim zip unzip openssl-server #Login to Ubuntu-trusty, username and password are ubuntu and ubuntu respectively # install clang and swift for Ubuntu-trusty only (but no swift package manager) sudo apt-get install libicu-dev clang-3.6 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.6 100 sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100 #install swift-2.2_1%3a2.2-0ubuntu11~trusty1_armhf.deb (Ubuntu-trusty only) or just download from here without adding source repo #https://mega.nz/#!fpYxzBgY!MLGiW8HAV6MllAD0gkzrSFlQ6TdubwBfFYGyezNVAXg wget -qO- http://dev.iachieved.it/iachievedit.gpg.key | sudo apt-key add - echo "deb [arch=armhf] http://iachievedit-repos.s3.amazonaws.com/ trusty main" | sudo tee --append /etc/apt/sources.list sudo apt-get update sudo apt-get install swift-2.2 swift --version #test simple swift compile cat > hello.swift <<EOF let device = "Raspberry Pi 3!" print("Hello from Swift on \(device)") EOF swiftc hello.swift ./hello #Login to Rasbian, username and password are pi and raspberry respectively #change password (recomended) passwd #Rasbian config to set locale and timezone sudo raspi-config #vi ~/.bashrc and add export LC_ALL="en_US.UTF-8" #add COLORS=$LS_COLORS:'di=1;44:' ; export LS_COLORS # dir white on blue background sudo locale-gen en_US.UTF-8 #command line reset timezone sudo dpkg-reconfigure tzdata apt-get update apt-get upgrade apt-get install vim openssl-server #install nginx (lightweght webserver) sudo apt-get install nginx cd; ln -s /usr/share/nginx/html . #check ip adress and use browser connect to test web server hostname -I ifconfig eth0 ip addr | grep -Po '(?!(inet 127.\d.\d.1))(inet \K(\d{1,3}\.){3}\d{1,3})' #install php in nginx sudo apt-get install php5-fpm php-apc # link the html folder to home cd ln -s /usr/share/nginx/html . # create testing php page cat > ~/html/info.php <<EOF <?php phpinfo(); ?> EOF # enable php in nginx sudo vi /etc/nginx/sites-enabled/default #see instructions here https://www.raspberrypi.org/documentation/remote-access/web-server/nginx.md #reload web server and test sudo service nginx reload #install samba as a file server sudo apt-get install samba samba-common-bin #edit /etc/samba/smb.conf and add the followings # assume USB drive is mounted on /media/pi/USBDRIVE #manual mount external drive sudo mkdir -p /media/pi/USBDRIVE sudo mount -o uid=pi,gid=pi,rw /dev/sda1 /media/pi/USBDRIVE [public_USBDRIVE] comment = Public USBDRIVE browseable = yes read only = no force user = "pi" guest ok = yes public = yes writable = yes path = /media/pi/USBDRIVE create mask = 0755 directory mask = 0755 # reload samba sudo service samba reload #install google app engine for development wget --no-check-certificate https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.34.zip unzip google_appengine_1.9.34.zip export PATH=$PATH:~/google_appengine/ #test GAE web page from localhost web browser dev_appserver.py ~/google_appengine/demos/python/guestbook #test GAE web app from other machine dev_appserver.py --host $(ip addr | grep -Po '(?!(inet 127.\d.\d.1))(inet \K(\d{1,3}\.){3}\d{1,3})') --port 8080 ~/google_appengine/demos/python/guestbook/ dev_appserver.py --host $(hostname -I) --port 8080 ~/google_appengine/demos/python/guestbook/ #install squid + unblock cn sudo apt-get install squid3 node.js npm git npm install Unblocker/Unblock-Youku #install phantomjs for testing git clone --depth 1 https://github.com/gautamMalu/PhantomJs-armhf.git #optionally install casper tag 1.1.1, PhantomJs+Casper for web scraping git clone --branch '1.1.1' --single-branch --depth 1 https://github.com/casperjs/casperjs.git sudo apt-get install libfontconfig1 libjpeg8 libicu-dev cd PhantomJs-armhf/bin; sudo mv phantomjs /usr/local/bin/ cd ~/node_modules/ub.uku.js/ npm install npm test #cp ~/node_modules/ub.uku.js/shared/urls.js ~/node_modules/ub.uku.js/youku.rules #cat ~/node_modules/ub.uku.js/shared/urls.js | grep "^[ ']*http" | sed "s/^[ ']*/\^/;s/[,'][ ]*\/\/.*$//;s/\*'$//;s/\*',$//;s/',//;s/[*?]$//;s/\*/\.\*/g;s/\?/\\\?/g;" > ~/node_modules/ub.uku.js/youku.rules vi ~/node_modules/ub.uku.js/youku.rules curl -o ~/node_modules/ub.uku.js/youku.rules http://pac.uku.im/regex sudo vi /etc/squid3/squid.conf acl localnet src 10.0.0.0/8 # RFC1918 possible internal network acl localnet src 192.168.0.0/16 # RFC1918 possible internal network http_access allow localnet # add acl rules acl uyouku url_regex -i "/home/pi/node_modules/ub.uku.js/youku.rules" never_direct allow uyouku cache_peer 127.0.0.1 parent 8888 0 no-query default cache_peer_access 127.0.0.1 allow uyouku cache_peer_access 127.0.0.1 deny all # enable cache_dir say 2048 (The default is 100 MB) cache_dir ufs /var/spool/squid3 2048 16 256 # 2016/03/09 https://github.com/Unblocker/Unblock-Youku/issues/618 # dns_nameservers 158.69.209.100 45.32.72.192 45.63.69.42 #restart squid3 sudo service squid3 reload #edit /home/pi/node_modules/ub.uku.js/server/server.js (near line 257) to change listening ip and port say 127.0.0.1 8888 # ubuku_server.listen('8888','127.0.0.1')... # auto run unblockcn and use http://ipservice.163.com/isFromMainland to test # sudo vi /etc/rc.local and add su pi -c '/usr/bin/nodejs /home/pi/node_modules/ub.uku.js/server/server.js --nolog --proxy=https://secure.uku.im:993 --bak_proxy=http://proxy.uku.im:443 --pac_proxy=http://proxy.uku.im:443 > /dev/null &' # test terminal run with external proxy sudo node /home/pi/node_modules/ub.uku.js/server/server.js --proxy=https://secure.uku.im:993 --bak_proxy=http://proxy.uku.im:443 --pac_proxy=http://proxy.uku.im:443 #support Chinese font 文鼎 PL 上海宋 Un and input method sudo apt-get install ttf-arphic-uming scim-tables-zh im-switch #support Chinese font 文泉驛微米黑體、文泉驛正黑體、文泉驛點陣宋體 sudo apt-get install ttf-wqy-microhei ttf-wqy-zenhei xfonts-wqy #ext4 TRIM command support using the discard mount option in fstab (or with tune2fs -o discard /dev/sdaX). sudo tune2fs -o discard /dev/sdb1 #bitcoind #sudo apt-get install bitcoind # bitcoind deb package in Debian is obsolete and needs upgrade #build from source as below or download the precompiled version from here and use sudo dpkg -i to install https://mega.nz/#!KtJWTZ7A!RN4IOGtvflSc0lXuJB1__lYTkdYvsnoegk_JJ0JGtA8 #Build requirements sudo apt-get install build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils git sudo apt-get install libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libminiupnpc-dev libminiupnpc-dev libzmq3-dev libcrypto++9 minissdpd git clone -b 0.12 --depth 1 https://github.com/bitcoin/bitcoin.git #see here to build bitcoind with Berkeley DB script https://github.com/bitcoin/bitcoin/blob/master/doc/build-unix.md cd bitcoin mkdir -p db4 wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz' tar -xzvf db-4.8.30.NC.tar.gz cd db-4.8.30.NC/build_unix/ BDB_PREFIX=$(cd $(dirname "../../db4") && pwd -P)/$(basename "../../db4"); ../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX make install cd ../.. ./autogen.sh BDB_PREFIX="$(pwd)/db4"; ./configure LDFLAGS="-L${BDB_PREFIX}/lib/" CPPFLAGS="-I${BDB_PREFIX}/include/" CXXFLAGS="--param ggc-min-expand=1 --param ggc-min-heapsize=32768" --without-gui --with-miniupnpc --enable-upnp-default --disable-tests #Rasbian config to set boot option to CLI mode sudo raspi-config #compiling bitcoind is cpu-intensive and memory-hungry, better to reboot to CLI mode and kill unnecessary services then make -j2 sudo make install #setup bitcoind and let it create bitcoin.conf bitcoind -daemon bitcoin-cli stop #create data directory in USB SSD drive mkdir -p /media/pi/SSDDRIVE/bitcoin cp ~/.bitcoin/bitcoin.conf /media/pi/SSDDRIVE/bitcoin/ cp ~/wallet.dat /media/pi/SSDDRIVE/bitcoin/ # if have old bitcoin wallet.dat #start bitcoind as daemon in SSD Drive bitcoind -datadir=/media/pi/SSDDRIVE/bitcoin -daemon bitcoind --help #while bitcoind is running as daemon, get new address and check other status # bitcoin-cli help bitcoin-cli getinfo bitcoin-cli listaccounts bitcoin-cli getnewaddress "worker1" # check tx history say https://blockchain.info/address/14uUbzJSi2t5MGgYH72PdTonD22V8drBVN bitcoin-cli getaccountaddress "worker1" bitcoin-cli getbalance #daemon will download the entire block chain data and can take over several days and total size > 60G bitcoin-cli getblockcount # the current blockcount should be over 1M https://blockchain.info/latestblock bitcoin-cli getconnectioncount #cpuminer sudo apt-get install libcurl4-openssl-dev git make git clone --depth 1 git://github.com/pooler/cpuminer.git cd cpuminer ./autogen.sh ./configure CFLAGS="-O3" make sudo make install minerd --help minerd --url http://api.bitcoin.cz:8332 -a sha256d --userpass=yourid.worker1:pass1 #cgminer (but not working in Raspberry Pi 3 #OpenCL...............: Detection overrided. GPU mining support DISABLED git clone -b 3.7 https://github.com/ckolivas/cgminer.git cd cgminer ./autogen.sh ./configure --enable-opencl --enable-scrypt # configure failed due to absence of GPU and opencl in Raspberry Pi 3 #libquantlib0-dev 1.4.2 is available in package repo #QuantLib 1.7.1 #or download the updated package from here https://mega.nz/#!PkYWBDLC!dC8klXxcouc1RrNQ2Bct_tSweaO6A3UwTNkGeXvGldo #Download QuantLib source and extract wget http://jaist.dl.sourceforge.net/project/quantlib/QuantLib/1.7.1/QuantLib-1.7.1.tar.gz tar -xzvf QuantLib-1.7.1.tar.gz #Build requirement sudo apt-get install build-essential libtool libboost-all-dev cd QuantLib-1.7.1 ./configure CXXFLAGS="--param ggc-min-expand=1 --param ggc-min-heapsize=32768" --disable-shared #Rasbian config to set boot option to CLI mode sudo raspi-config #compiling QuantLib is cpu-intensive and memory-hungry, better to reboot to CLI mode and kill unnecessary services then make -j2 # or just make if failed sudo make install #test compile QuantLib example cd ~/QuantLib-1.7.1/Examples/Bonds g++ Bonds.cpp -o bin/Bonds -lQuantLib # run example Bonds ./bin/Bonds #compiling litecoind is similar to bitcoind but it would conflict with bitcoind git clone --depth 1 https://github.com/litecoin-project/litecoin.git #build from source or download the precompiled version from here https://mega.nz/#!Ptwl0KZD!XVyO7DHugtoK2iEib2nj2jdyMRSkadlIMa1oPp3QSak #setup litecoind in raspberry pi litecoind #create data directory in USB SSD drive mkdir -p /media/pi/SSDDRIVE/litecoin cp ~/.litecoin/litecoin.conf /media/pi/SSDDRIVE/litecoin/ #start litecoind as daemon in SSD Drive litecoind -datadir=/media/pi/SSDDRIVE/litecoin -daemon litecoind --help #reindex litecoin database if corrupted litecoind -reindex -datadir=/media/pi/SSDDRIVE/litecoin #while litecoind is running as daemon, get new address and check other status # litecoin-cli help litecoin-cli getinfo litecoin-cli listaccounts litecoin-cli getnewaddress "worker2" # check tx history say https://block-explorer.com/address/LRwz2mJpoMz2FPkqE7hxKvcLnUyUHESW4Q litecoin-cli getaccountaddress "worker2" litecoin-cli getbalance litecoin-cli getblockcount # the current blockcount should be over 900000 see http://explorer.litecoin.net/ #setup local repo sudo apt-get install dpkg-dev sudo mkdir -p /usr/local/mydebs sudo cp -s /var/cache/apt/archives/*.deb /usr/local/mydebs/ cd /usr/local/mydebs sudo sh -c 'dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz' echo "deb file:/usr/local/mydebs ./" | sudo tee --append /etc/apt/sources.list sudo apt-get update #setup swapfile in Rasbian sudo vi /etc/dphys-swapfile #edit the swapfile location and size (suggest min 2048) then save the file #for berryboot the swapfile should be in external USB drive sudo dphys-swapfile setup sudo dphys-swapfile swapon #check memory and swap free -h #turn off swap sudo dphys-swapfile swapoff #configure and make again for the projects #shutdown the machine sudo halt #restart the machine sudo reboot



Swift 2.2 for Linux package requires clang-3.6 and Ubuntu-trusty for Pi
This image https://wiki.ubuntu.com/ARM/RaspberryPi (2015-04-06-ubuntu-trusty.img) is for Raspberry Pi 2 and does not work on Raspberry Pi 3, the FAT32 partition content in the layout folder and the start*.elf, bcm2710-rpi-3-b.dtb should be upgraded/added for the new hardware for booting.
config.txt add these settings
disable_overscan=1
start=1
gpu_mem=64
max_usb_current=1
initramfs initrd7.img
kernel=kernel7.img


It is possible to install the Swift 2.2 in Rasbian other than Ubuntu-trusty for Pi
1. Install clang-3.7 and libicu-dev in Rasbian
sudo apt-get install libicu-dev clang-3.7
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.7 100
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.7 100

2. download the package from here without adding source repo
#https://mega.nz/#!fpYxzBgY!MLGiW8HAV6MllAD0gkzrSFlQ6TdubwBfFYGyezNVAXg

3. download a fake clang-3.6 package that install nothing but to meet dependency as a hack
https://mega.nz/#!voZ0yA6T!10lqNIhEKLfNpptmy-rlsEdRn15gIl14Fd0ibjmI_x8

4. install these deb files together
sudo dkpg -i clang-3.6-fake.deb swift-2.2_1%3a2.2-0ubuntu11~trusty1_armhf.deb

Swift 2.2 for Linux without Swift Package Manager. Here are the alternative ways:
shell script    Select all
#Method 1 : compile everything on build cd ${HOME} mkdir -p SwiftProjects cd ${HOME}/SwiftProjects # get dependency package git clone --depth 1 https://github.com/erica/SwiftString.git git clone --depth 1 https://github.com/haginile/SwiftDate.git #fix some errors in SwiftDate/SwiftDate/DateHelpers.swift and SwiftDate/SwiftDate/Term.swift simlar to previous post "What you need for Swift on Linux" vi SwiftDate/SwiftDate/DateHelpers.swift extension String { /* comment out these 2 func subscript (i: Int) -> String { return String(Array(self.characters)[i]) } subscript (r: Range<int>) -> String { get { let subStart = self.startIndex.advancedBy(r.startIndex, limit: self.endIndex) let subEnd = subStart.advancedBy(r.endIndex - r.startIndex, limit: self.endIndex) return self.substringWithRange(Range(start: subStart, end: subEnd)) } } */ vi +195 SwiftDate/SwiftDate/Term.swift #change from switch timeUnit { #to switch timeUnit! { // unwrapped optional cd ${HOME}/SwiftProjects mkdir -p Sources/Test1 cat > Sources/Test1/main.swift <<EOF #if os(Linux) import Glibc import Foundation #endif //import SwiftString //import SwiftDate import XCTest class SwiftDateTesting: XCTestCase { var allTests : [(String, () -> Void)] { return [ ("testCalendar", testCalendar), ("testDayCounter", testDayCounter), ] } func testCalendar() { var cal = USSettlementCalendar() XCTAssert(cal.isBizDay(Date(string: "2014-05-15")) == true, "Pass") XCTAssert(cal.isBizDay(Date(string: "2014-05-17")) == false, "Pass") XCTAssertEqual(cal.nextBizDay(Date(string: "2014-05-16")).serialNumber, Date(string: "2014-05-19").serialNumber, "Pass") XCTAssertEqual(cal.bizDaysBetween(Date(string: "2014-05-15"), toDate: Date(string : "2014-05-20")), 3, "Pass") } func testDayCounter() { var start_date = Date(string: "2000-01-15") var end_date = Date(string: "2000-05-31") var actual_365 = Actual365Fixed() XCTAssertEqual(actual_365.dayCountFraction(start_date, date2: end_date), 137.0 / 365, "Pass") var nl_365 = NL365() XCTAssertEqual(nl_365.dayCountFraction(start_date, date2: end_date), 136.0 / 365, "Pass") var act_360 = Actual360() XCTAssertEqual(act_360.dayCountFraction(start_date, date2: end_date), 137.0 / 360.0, "Pass") var thirty_360 = Thirty360() XCTAssertEqual(thirty_360.dayCountFraction(start_date, date2: end_date), 136.0 / 360.0, "Pass") var thirty_360e = Thirty360(convention: Thirty360.Convention.EurobondBasis) } } XCTMain([SwiftDateTesting()]) EOF cd Sources/Test1 swiftc -emit-executable ../../SwiftString/Sources/*.swift ../../SwiftDate/SwiftDate/*.swift main.swift -o test1 ./test1 #Method 2 : dynamic library link #build module and library for dynamic linking cd ${HOME}/SwiftProjects mkdir -p Sources/Test2 cat > Sources/Test2/main.swift <<EOF #if os(Linux) import Glibc import Foundation #endif import SwiftDateString let start_date = Date(string: "2000-01-15") var end_date = Date(string: "2000-05-31") var actual_365 = Actual365Fixed() print(actual_365.dayCountFraction(start_date, date2: end_date)) EOF cd Sources/Test2 #build module and dynamic library swiftc -emit-library ../../SwiftString/Sources/*.swift ../../SwiftDate/SwiftDate/*.swift -module-name SwiftDateString -emit-module-path SwiftDateString.swiftmodule -module-name SwiftDateString -module-link-name SwiftDateString #compile and link with dynamic library at current directory swiftc -emit-executable main.swift -o test2 -I. -L. -Xlinker -rpath -Xlinker "." -lSwiftDateString ./test2 #alternative way is to copy the shared library to /usr/lib then link sudo cp libSwiftDateString.so /usr/lib/ swiftc -emit-executable -I. -lSwiftDateString main.swift -o test2a ./test2a #Method 3: static library link #build module and static library for linking cd ${HOME}/SwiftProjects mkdir -p Sources/Test3 cat > Sources/Test3/main.swift <<EOF #if os(Linux) import Glibc import Foundation #endif import SwiftDateString public func timetest(block: () -> Void) { let date = NSDate() block() let timeInterval = NSDate().timeIntervalSinceDate(date) print("Elasped time: \(timeInterval)") } public func testit() { let start_date = Date(string: "2000-01-15") let end_date = Date(string: "2000-05-31") let actual_365 = Actual365Fixed() print("Function: \(__FUNCTION__), File: \(__FILE__)") print("2000-01-15 to 2000-05-31 dayCountFraction is ", terminator:"") print(actual_365.dayCountFraction(start_date, date2: end_date)) } timetest(testit) EOF #compile cd Sources/Test3 swiftc -module-name SwiftDateString -c ../../SwiftString/Sources/*.swift ../../SwiftDate/SwiftDate/*.swift -emit-module-path SwiftDateString.swiftmodule -module-link-name SwiftDateString PROJECT_PREFIX=$(cd $(dirname "../../") && pwd -P)/$(basename "../../"); mkdir -p obj; cd obj; swiftc -parse-as-library -module-name SwiftDateString -emit-object ${PROJECT_PREFIX}/SwiftString/Sources/*.swift ${PROJECT_PREFIX}/SwiftDate/SwiftDate/*.swift; cd .. #build static library ar -rcs libSwiftDateString.a obj/*.o #link with static library swiftc -emit-executable main.swift -o test3 -I. -L. -Xlinker libSwiftDateString.a #Method 4: Use makefile for static library link #makefile to build module and static library for linking cd ${HOME}/SwiftProjects mkdir -p Sources/tidyjson cd Sources/tidyjson git clone --depth 1 https://github.com/benloong/TidyJSON.git # edit TidyJSON/Sources/TidyJSON.swift #find dataUsingEncoding #//if let data = string.dataUsingEncoding(NSUTF8StringEncoding) { #and change it to if let data = NSString(string:string).dataUsingEncoding(NSUTF8StringEncoding) { # edit TidyJSON/Tests/Test.swift #add #if os(Linux) import Glibc #endif # find all lines with # var allTests : [(String, () throws -> ())] { # and change them to var allTests : [(String, () -> Void)] { # find all lines with let content = try String(contentsOfFile: "./Tests/TestCases/\(path).json", encoding: NSUTF8StringEncoding) # and change them to block code as below if let content = try? NSString(contentsOfFile: "./TidyJSON/Tests/TestCases/\(path).json", encoding: NSUTF8StringEncoding).bridge() { // no change here if let _ = try? JSON.parse(content) { ... //(no change here) } else { ... //(no change here) } } #create this Makefile cat <<'EOF' > Makefile APP=tidyjsonTest PROJECT_PREFIX=$(PWD) MODULENAME=TidyJSON OBJ_DIR=obj DEP_LIB_SRC_FOLDER1 = TidyJSON/Sources SWIFT_FILES = $(wildcard $(PROJECT_PREFIX)/$(DEP_LIB_SRC_FOLDER1)/*.swift) OBJ_FILES=$(addprefix, ./obj/, $(notdir $(SWIFT_FILES:.swift=.o))) testfile= $(PROJECT_PREFIX)/TidyJSON/Tests/Test.swift mainfile=$(PROJECT_PREFIX)/TidyJSON/Tests/main.swift all: $(APP) $(APP): $(testfile) $(mainfile) lib$(MODULENAME).a $(MODULENAME).swiftmodule ; \ swiftc -emit-executable $(testfile) $(mainfile) -o $(APP) -I. -L. -Xlinker lib$(MODULENAME).a ; lib$(MODULENAME).a: $(SWIFT_FILES) ; \ $(shell mkdir -p $(OBJ_DIR); cd $(OBJ_DIR); swiftc -parse-as-library -module-name $(MODULENAME) -emit-object $(SWIFT_FILES)) \ rm -f lib$(MODULENAME).* ; \ ar -rcs lib$(MODULENAME).a $(OBJ_DIR)/*.o ; $(MODULENAME).swiftmodule: $(SWIFT_FILES) ; \ rm -f $(MODULENAME).swiftmodule $(MODULENAME).swiftdoc ; \ swiftc -emit-module -module-name $(MODULENAME) -c $(SWIFT_FILES) -emit-module-path $(MODULENAME).swiftmodule -module-link-name $(MODULENAME) ; clean: ; rm -rf obj $(MODULENAME).swift* lib$(MODULENAME).* $(APP) .PHONY: all clean EOF # make then run to test make ./tidyjsonTest

To install docker, see this http://blog.hypriot.com/post/run-docker-rpi3-with-wifi/
The latest Kali Linux image for pentesting is here https://www.offensive-security.com/kali-linux-arm-images/



Swift 3.0 is out for Ubuntu 16 (Xenial Xerus)
see Raspberry Pi image for Ubuntu 16 here https://wiki.ubuntu.com/ARM/RaspberryPi


installation shell script    Select all
cd $HOME wget http://swift-arm.ddns.net/job/Swift-3.0-Pi3-ARM-Incremental/lastSuccessfulBuild/artifact/swift-3.0.tgz mkdir $HOME/swift-3.0 cd $HOME/swift-3.0 && tar -xzf ../swift-3.0.tgz export PATH=$HOME/swift-3.0/usr/bin:$PATH sudo apt-get update sudo apt-get install -y libicu-dev clang-3.6 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.6 100 sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100 mkdir $HOME/hello; cd $HOME/hello swift package init --type executable swift build .build/debug/hello




Wednesday, January 6, 2016

What you need for Swift on Linux

What you need

(1) ubuntu-14.04.3-desktop-amd64.iso
http://releases.ubuntu.com/14.04/

(2) Virtual Box 5.0 from https://www.virtualbox.org/wiki/Downloads
Virtual Harddisk of 20G or above is recommended.

(3) Install clang in ubuntu 14
sudo apt-get update
sudo apt-get --assume-yes install clang-3.4 libicu-dev git vim

(4) download swift in ubuntu 14
curl -O https://swift.org/builds/ubuntu1404/swift-2.2-SNAPSHOT-2015-12-31-a/swift-2.2-SNAPSHOT-2015-12-31-a-ubuntu14.04.tar.gz
tar xzvf swift-2.2-SNAPSHOT-2015-12-31-a-ubuntu14.04.tar.gz
export PATH=$HOME/swift-2.2-SNAPSHOT-2015-12-31-a-ubuntu14.04/usr/bin:$PATH

(5) test compile
swift --version
echo 'print("Hello World")' > helloworld.swift
swiftc helloworld.swift
./helloworld

(6) remember to Insert Guest additions CD-image and reboot the virtual host.

(7) Test build
cd ${HOME}
git clone https://github.com/apple/example-package-dealer.git
cd example-package-dealer
swift build
.build/debug/Dealer

(8) Test build by adding swift package
shell script    Select all
cd ${HOME} mkdir -p teststring cd teststring cat > Package.swift <<EOF import PackageDescription let package = Package( name: "teststring", dependencies: [ .Package(url: "https://github.com/erica/SwiftString.git", majorVersion: 1), ] ) EOF cat > main.swift <<EOF import SwiftString let line = "apple,peach,kiwi" let parts = line.componentsSeparatedByString(",") print(parts) EOF swift build (cd Packages/SwiftString-1.0.5; git pull) swift build .build/debug/teststring


(9) Test build by adding C module
sudo apt-get install -y libcurl4-gnutls-dev libjson-c-dev
cd ${HOME}
git clone https://github.com/iachievedit/moreswift
cd moreswift/translator_swiftpm
swift build
.build/debug/translator "Hello" from "en" to "zh-cn"


(10) Test build by adding and modifying swift package
shell script    Select all
cd ${HOME} mkdir -p testdatestring/Sources/Test1 cd testdatestring cat > Package.swift <<EOF import PackageDescription let package = Package( name: "testdatestring", dependencies: [ .Package(url: "https://github.com/erica/SwiftString.git", majorVersion: 1), .Package(url: "https://github.com/haginile/SwiftDate.git", majorVersion: 1), ] ) EOF cat > Sources/Test1/main.swift <<EOF #if os(Linux) import Glibc import Foundation #endif import SwiftString import SwiftDate let start_date = Date(string: "2000-01-15") var end_date = Date(string: "2000-05-31") var actual_365 = Actual365Fixed() print(actual_365.dayCountFraction(start_date, date2: end_date)) EOF swift build (cd Packages/SwiftDate; ln -s SwiftDate Sources; echo "import PackageDescription;let package = Package(name: \"SwiftDate\")" > Package.swift) (cd Packages; mv SwiftDate SwiftDate-1.0.0) swift build (cd Packages/SwiftString-1.0.5; git pull) swift build


(10.1) Fix some errors in DateHelpers.swift
vim Packages/SwiftDate-1.0.0/SwiftDate/DateHelpers.swift    Select all
import Foundation import SwiftString ... extension String { //subscript (i: Int) -> String { // return String(Array(self.characters)[i]) //} subscript (r: Range) -> String { get { let subStart = self.startIndex.advancedBy(r.startIndex, limit: self.endIndex) let subEnd = subStart.advancedBy(r.endIndex - r.startIndex, limit: self.endIndex) return self[Range(start: startIndex, end: endIndex)] //return self.substringWithRange(Range(start: subStart, end: subEnd)) } }


(10.2) Fix error in Term.swift at line 195
vim +195 Packages/SwiftDate-1.0.0/SwiftDate/Term.swift    Select all
class func parseOneTerm(string : String) -> Term { let str = string.uppercaseString let len = str.characters.count let length = Int(str[0..<(len - 1)]) let timeUnit = str[len-1] switch timeUnit! { // unwrapped optional case "D": return Term(length: length!, timeUnit: TimeUnit.Day) case "W": return Term(length: length!, timeUnit: TimeUnit.Week) case "M": return Term(length: length!, timeUnit: TimeUnit.Month) case "Y": return Term(length: length!, timeUnit: TimeUnit.Year) default: return Term() } }


(10.3) Build target Test1
shell script    Select all
swift build .build/debug/Test1


(10.4) Add XCTest for target Test2
shell script    Select all
cd ${HOME}/testdatestring mkdir -p Sources/Test2 cat > Sources/Test2/main.swift <<EOF #if os(Linux) import Glibc import Foundation #endif import SwiftString import SwiftDate import XCTest class SwiftDateTesting: XCTestCase { var allTests : [(String, () -> Void)] { return [ ("testCalendar", testCalendar), ("testDayCounter", testDayCounter), ] } func testCalendar() { var cal = USSettlementCalendar() XCTAssert(cal.isBizDay(Date(string: "2014-05-15")) == true, "Pass") XCTAssert(cal.isBizDay(Date(string: "2014-05-17")) == false, "Pass") XCTAssertEqual(cal.nextBizDay(Date(string: "2014-05-16")).serialNumber, Date(string: "2014-05-19").serialNumber, "Pass") XCTAssertEqual(cal.bizDaysBetween(Date(string: "2014-05-15"), toDate: Date(string : "2014-05-20")), 3, "Pass") } func testDayCounter() { var start_date = Date(string: "2000-01-15") var end_date = Date(string: "2000-05-31") var actual_365 = Actual365Fixed() XCTAssertEqual(actual_365.dayCountFraction(start_date, date2: end_date), 137.0 / 365, "Pass") var nl_365 = NL365() XCTAssertEqual(nl_365.dayCountFraction(start_date, date2: end_date), 136.0 / 365, "Pass") var act_360 = Actual360() XCTAssertEqual(act_360.dayCountFraction(start_date, date2: end_date), 137.0 / 360.0, "Pass") var thirty_360 = Thirty360() XCTAssertEqual(thirty_360.dayCountFraction(start_date, date2: end_date), 136.0 / 360.0, "Pass") var thirty_360e = Thirty360(convention: Thirty360.Convention.EurobondBasis) } } XCTMain([SwiftDateTesting()]) EOF swift build .build/debug/Test2


Friday, October 16, 2015

The hello world web app of OAuth 2.0 client for Google App Engine

The sample project is here.

However, the missing installation and setup instructions for development server are:
(1) download the above project sample and say put it in project folder called helloworld
(2) install google-api-python-client in the project folder helloworld
(2a) Create a file appengine_config.py in the project folder with the following contents
from google.appengine.ext import vendor

# Add any libraries installed in the "lib" folder.
vendor.add('lib')

(2b) Download google-api-python-client and related libraries into the lib sub-folder of the project folder
cd helloworld
mkdir lib
# if your Mac doesn't have pip do this -> sudo easy_install -U pip
pip install -t lib google-api-python-client

(3) Follow the instructions in here to setup OAuth 2.0 in the developer console for web app in Google App Engine Developer Console

(4) Make sure to enable Google+ API in the console or else you will get KeyError: 'id' when testing


(5) Fill in Authorised Javascript origins and Authorised redirect URIs in the developer console and click create or save


(6) copy the created Client ID and Client secret from the developer console and fill in the file client_secrets.json, like below


(7) Wait a few minutes and start the development server and test



Here is how to add other OAuth 2.0 apps such as Windows Live or facebook.
(1) Setup and revoke websites are :
# Google+ APIs
# Manage Application - https://console.developers.google.com
# Revoke Consent - https://www.google.com/accounts/b/0/IssuedAuthSubTokens
# OAuth 2.0 info https://developers.google.com/api-client-library/python/auth/web-app

# Windows Live API
# Manage Application - https://account.live.com/developers/applications
# Revoke Consent - https://account.live.com/consent/Manage
# OAuth 2.0 info https://msdn.microsoft.com/en-us/library/hh243647.aspx

# Facebook auth apis
# Manage Application - https://developers.facebook.com/apps/
# Revoke Consent Procedure
# Log on to Facebook.
# Click the drop-down arrow in the upper right, then select "Settings"
# Select "Apps" on the left sidebar.
# Scan the list and click the "x" on the right of any app you want to clear.

(2.1) The client_secrets_windows_live.json file is like this
{
  "web": {
    "client_id": "0000000012345678",
    "client_secret": "abcdefg1lHiJK5HCnlZb-aaaaaXX",
    "redirect_uris": ["http://localhost:8080/windows_live_callback"],
    "auth_uri": "https://login.live.com/oauth20_authorize.srf",
    "token_uri": "https://login.live.com/oauth20_token.srf"
  }
}


(2.2) The client_secrets_facebook.json files is like this
{
  "web": {
    "client_id": "123456789012345",
    "client_secret": "a1234567e123456bc4b123456ab6543g",
    "redirect_uris": ["http://localhost:8080/facebook_callback"],
    "auth_uri": "https://www.facebook.com/dialog/oauth",
    "token_uri": "https://graph.facebook.com/oauth/access_token"
  }
}


(3.1) The decorator_windows_live is like these
# Scopes are space-separated, e.g. 'wl.signin wl.basic'.
decorator_windows_live = appengine.oauth2decorator_from_clientsecrets( os.path.join(os.path.dirname(__file__), 'client_secrets_windows_live.json'), scope='wl.signin wl.basic', message=MISSING_CLIENT_SECRETS_MESSAGE)


(3.2) The decorator_facebook is like this
# Multiple Scopes should be comma-separated, e.g. 'user_about_me,email'.
decorator_facebook = appengine.oauth2decorator_from_clientsecrets( os.path.join(os.path.dirname(__file__), 'client_secrets_facebook.json'), scope='user_about_me,email', message=MISSING_CLIENT_SECRETS_MESSAGE)