Tuesday, March 29, 2016

Check which services failed to start on boot on CentOS 7

Check which services failed to start on boot on CentOS 7

# systemctl --failed

0 loaded units listed. Pass --all to see loaded but inactive units, too.

Cross-Site Request Forgery (CSRF)

Cross-Site Request Forgery (CSRF)

Preventing Cross-Site Request Forgery in Go
https://elithrar.github.io/article/preventing-csrf-attacks-in-go/

Why refresh CSRF token per form request?
http://security.stackexchange.com/questions/22903/why-refresh-csrf-token-per-form-request

Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#Double_Submit_Cookies

Monday, March 28, 2016

HTTP Cookies: What's the difference between Max-age and Expires?

HTTP Cookies: What's the difference between Max-age and Expires?

Quick Answer:

Expires sets an expiry date for when a cookie gets deleted
Max-age sets the time in seconds for when a cookie will be deleted
Internet Explorer (ie6, ie7, and ie8) does not support “max-age”, while (mostly) all browsers support expires

Reference:

http://mrcoles.com/blog/cookies-max-age-vs-expires/

convert array to csv string

Solution 1:

<?php
$out = fopen('php://output', 'w');
fputcsv($out, array('this','is some', 'csv "stuff", you know.'));
fclose($out);
?>

Solution 2:

$csv = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
fputcsv($csv, array('blah','blah'));
rewind($csv);

// put it all in a variable
$output = stream_get_contents($csv);
fclose($csv);

Solution 3:

function outputCSV($data) {
  $outstream = fopen("php://output", 'w');
  function __outputCSV(&$vals, $key, $filehandler) {
    fputcsv($filehandler, $vals, ';', '"');
  }
  array_walk($data, '__outputCSV', $outstream);
  fclose($outstream);
}

Reference:

http://stackoverflow.com/questions/4692709/how-to-make-fputcsv-echo-the-data

http://php.net/manual/en/wrappers.php.php

Sunday, March 27, 2016

gorilla csrf - Forbidden - CSRF token invalid

gorilla csrf - Forbidden - CSRF token invalid

If you're developing locally over plain HTTP (without HTTPS), you'll need to turn off the Secure flag on the CSRF cookie else you'll get an error (because the cookie won't be sent back to the server).

    http.ListenAndServe(":8000",
        csrf.Protect([]byte("32-byte-long-auth-key"), csrf.Secure(false))(r))

gorilla/csrf defaults to 'true' for the Secure and HttpOnly flags on the cookie for security reasons.

Note: remember to set it to true csrf.Secure(true) (or remove the option enitrely) in production.

Reference:

https://github.com/gorilla/csrf/issues/13

https://github.com/gorilla/csrf

Convert struct to json. Then, output to the browser

Convert struct to json. Then, output to the browser

test.go:

package main

import (
  "fmt"
  "io"
  "net/http"
  "log"
  "encoding/json"
)

type Item struct {
  ItemName string
  ItemPrice int
}

type MyOrder struct {
  Status bool
  CustomerName string
  ItemArr []Item
}

func getOrder() (MyOrder) {
  item0 := Item {
    ItemName: "Computer",
    ItemPrice: 90,
  }

  order1 := MyOrder {
    Status: true,
    ItemArr: []Item{item0, Item {ItemName: "Pen", ItemPrice: 91}}, // initialize with two items.
  }

  return order1
}

func handler(w http.ResponseWriter, r *http.Request) {
  // we will demonstrate the different ways of outputing string to the browser in the code below.
  // So, we set the content type to text/plan.
  //w.Header().Set("Content-Type", "application/json; charset=UTF-8")
  w.Header().Set("Content-Type", "text/plain; charset=UTF-8")

  // I am not sure what this line does. Leave it here for now.
  //w.WriteHeader(http.StatusOK)

  myorder := getOrder()
  //json.NewEncoder(w).Encode(myorder) // this line will actually output the json string to the browser. However, we wrap it in if for checking error.

  if err := json.NewEncoder(w).Encode(myorder); err == nil {
    // demonstrate the different ways of outputing string to the browser.
    str := "test"

    fmt.Fprintf(w, "This is the first method %v\n", str)

    io.WriteString(w, "This is the second method\n")

    w.Write([]byte("This is the third method\n"))
  } else {
    fmt.Printf("Here: %v\n", err) // this line will output the string to the console screen instead of the browser.
  }
}

func main() {
  http.HandleFunc("/", handler)

  err := http.ListenAndServe(":80", nil)

  if err != nil {
    fmt.Printf("main(): %s\n", err)
    log.Fatal("ListenAndServe: ", err)
  }
}

The output in Browser:

{"Status":true,"CustomerName":"","ItemArr":[{"ItemName":"Computer","ItemPrice":90},{"ItemName":"Pen","ItemPrice":91}]}

This is the first method test
This is the second method
This is the third method

Reference:

http://blog.ijun.org/2016/03/initialize-data-structure-and-convert.html

initialize data structure and convert it to a JSON string

initialize data structure and convert it to a JSON string

package main

import (
  "fmt"
  "os"
  "encoding/json"
)

type Item struct {
  ItemName string
  ItemPrice int
}

type MyOrder struct {
  Status bool
  CustomerName string
  ItemArr []Item
}

func main() {
  item0 := Item {
    ItemName: "Computer",
    ItemPrice: 90,
  }
  item2 := Item { ItemName: "Motherboard", ItemPrice: 92, }
  item3 := Item { ItemName: "Hard drive", ItemPrice: 93, }
  item4 := Item { ItemName: "Mouse", ItemPrice: 94, }
  item5 := Item { ItemName: "Monitor", ItemPrice: 95, }
  item6 := Item { ItemName: "Book", ItemPrice: 96, }
  item7 := Item { ItemName: "Desk", ItemPrice: 97, }
  item8 := Item { ItemName: "Door", ItemPrice: 98, }
  item9 := Item { ItemName: "Car", ItemPrice: 99, }

  order1 := MyOrder {
    Status: true,
    ItemArr: []Item{item0, Item {ItemName: "Pen", ItemPrice: 91}}, // initialize with two items.
  }

  order1.CustomerName = "Jun"

  // first way of appending the items to the ItemArr slice.
  order1.ItemArr = append(order1.ItemArr, item2, item3)

  // second way of appending the items to the ItemArr slice.
  // The three dots is called variadic parameter / Ellipsis meaning unpack this slice into a set of variadic arguments.
  order1.ItemArr = append(order1.ItemArr, []Item{item4, item5}...)

  // third way of appending the items to the ItemArr slice.
  itemArr := []Item{item6, item7}
  order1.ItemArr = append(order1.ItemArr, itemArr...)

  // fourth way of appending the items to the ItemArr slice.
  order1.ItemArr = append(order1.ItemArr, item8)
  order1.ItemArr = append(order1.ItemArr, item9)

  encoder := json.NewEncoder(os.Stdout) //output to screen

  if err := encoder.Encode(order1); err != nil {
    fmt.Println(err)
  }
}

When should you use JSON Web Tokens?

When should you use JSON Web Tokens?

These are some scenarios where JSON Web Tokens are useful:

- Authentication: This is the typical scenario for using JWT, once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single Sign On is a feature that widely uses JWT nowadays, because of its small overhead and its ability to be easily used among systems of different domains.

- Information Exchange: JWTs are a good way of securely transmitting information between parties, because as they can be signed, for example using a public/private key pair, you can be sure that the sender is who he says he is. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn’t changed.

How do JSON Web Tokens work?

In authentication, when the user successfully logs in using his credentials, a JSON Web Token will be returned and must be saved locally (typically in local storage, but cookies can be also used), instead of the traditional approach of creating a session in the server and returning a cookie.

Reference:

https://auth0.com/learn/json-web-tokens/

http://jwt.io/introduction/

http://thenewstack.io/make-a-restful-json-api-go/

https://gist.github.com/cryptix/45c33ecf0ae54828e63b

Some interesting articles regarding Go and Node.js

Some interesting articles regarding Go and Node.js

TJ leaving node.js
https://bjouhier.wordpress.com/2014/07/05/tj-leaving-node-js/

Farewell Node.js Leaving node.js land to Go
https://medium.com/@tjholowaychuk/farewell-node-js-4ba9e7f3e52b#.3ivxpejvm

To Node.js Or Not To Node.js
http://www.haneycodes.net/to-node-js-or-not-to-node-js/

How We Went from 30 Servers to 2: Go
https://www.iron.io/how-we-went-from-30-servers-to-2-go/

Go After 2 Years in Production
https://www.iron.io/go-after-2-years-in-production/

Why Go Is Not Good
http://yager.io/programming/go.html

Go Is Unapologetically Flawed, Here’s Why We Use It
http://bravenewgeek.com/go-is-unapologetically-flawed-heres-why-we-use-it/

Making a RESTful JSON API in Go
http://thenewstack.io/make-a-restful-json-api-go/

A Djangonaut Building a Webapp in Go with Gorilla
https://lincolnloop.com/blog/djangonaut-building-webapp-go-gorilla/

complacency 自信自滿 - a feeling of smug or uncritical satisfaction with oneself or one's achievements.

complacency 自信自滿 - a feeling of smug or uncritical satisfaction with oneself or one's achievements.

There is always room for improvement. There is never room for complacency.

Reference:

http://bravenewgeek.com/go-is-unapologetically-flawed-heres-why-we-use-it/

Saturday, March 26, 2016

cannot convert data (type interface {}) to type string: need type assertion

According to the Go specification:

   For an expression x of interface type and a type T, the primary expression x.(T) asserts that x is not nil and that the value stored in x is of type T.

A "type assertion" allows you to declare an interface value contains a certain concrete type or that its concrete type satisfies another interface.

In your example, you were asserting data (type interface{}) has the concrete type string. If you are wrong, the program will panic at runtime. You do not need to worry about efficiency, checking just requires comparing two pointer values.

If you were unsure if it was a string or not, you could test using the two return syntax.

str, ok := data.(string)

If data is not a string, ok will be false. It is then common to wrap such a statement into an if statement like so:

if str, ok := data.(string); ok {
    /* act on str */
} else {
    /* not string */
}

Reference:

http://stackoverflow.com/questions/14289256/cannot-convert-data-type-interface-to-type-string-need-type-assertion

Encode Decode arbitrary map and JSON in Go golang

Encode Decode arbitrary map and JSON in Go golang

package main

import (
    "fmt"
    "reflect"
    "encoding/json"
)

func main() {
    /*
     * Encode Decode arbitrary map and JSON
     */
    orderMap := map[string]interface{}{
      "status": true,
      "name": "bot",
      "age": 18,
      //"itemArr": []map[string]interface{}{},
      "itemArr": []interface{}{},
    }

    orderMap["email"] = "bot@example.com"

    item0 := map[string]interface{}{
      "lineNum": 0,
      "itemNum": "A0",
      "itemPrice": 90,
    }
    item1 := map[string]interface{}{
      "lineNum": 1,
      "itemNum": "A1",
      "itemPrice": 91,
      "accessoryArr": []interface{}{},
    }

    item1["accessoryArr"] = append(item1["accessoryArr"].([]interface{}), map[string]interface{}{"name": "bag", "price": 10})
    item1["accessoryArr"] = append(item1["accessoryArr"].([]interface{}), map[string]interface{}{"name": "tray", "price": 12})

    // To access the element we can use a type assertion to access the underlying map of the orderMap["itemArr"].
    orderMap["itemArr"] = append(orderMap["itemArr"].([]interface{}), item0)
    orderMap["itemArr"] = append(orderMap["itemArr"].([]interface{}), item1)

    orderJson, err := json.Marshal(orderMap)

    if err == nil {
      itemArrType := reflect.TypeOf(orderMap["itemArr"])
      itemArrTypeKind := reflect.TypeOf(orderMap["itemArr"]).Kind()
      itemArrElemType := reflect.TypeOf(orderMap["itemArr"]).Elem()

      fmt.Printf("itemArr: %v\n", itemArrType)
      fmt.Printf("itemArrTypeKind: %v\n", itemArrTypeKind)
      fmt.Printf("itemElement: %v\n", itemArrElemType)
      fmt.Printf("\n")

      fmt.Println("=== Showing the original orderMap:")

      fmt.Printf("%v\n\n", orderMap)

      fmt.Println("=== Showing the encoded orderJson:")

      fmt.Printf("%v\n\n", string(orderJson))

      fmt.Println("=== Showing the decoded orderJson:")

      // As we're un-marshalling into an interface, we need to inform go what data type each key is before we can perform operations on it.
      // This is what the .(map[string]interface{}) does
      var orderMapTmp map[string]interface{}
      json.Unmarshal([]byte(orderJson), &orderMapTmp)
      fmt.Printf("%v\n\n", orderMapTmp)

      fmt.Println("=== Showing how to access individual element in the decoded orderJson:")

      // The data type here was the key. [0] was not actually a map, but an interface{}, which could be anything - a map, a string, an int. You need to "type assertion" it to a map first, or do the awkward case switch outlined in JSON and Go.
      // Otherwise, you will get "invalid operation: type interface {} does not support indexing)".
      fmt.Printf("itemNum: %v\n", orderMapTmp["itemArr"].([]interface{})[0].(map[string]interface{})["itemNum"])
      fmt.Printf("itemPrice: %v\n", orderMapTmp["itemArr"].([]interface{})[0].(map[string]interface{})["itemPrice"])
    }
}

Output:

itemArr: []interface {}
itemArrTypeKind: slice
itemElement: interface {}

=== Showing the original orderMap:
map[status:true name:bot age:18 itemArr:[map[lineNum:0 itemNum:A0 itemPrice:90] map[itemPrice:91 accessoryArr:[map[name:bag price:10] map[price:12 name:tray]] lineNum:1 itemNum:A1]] email:bot@example.com]

=== Showing the encoded orderJson:
{"age":18,"email":"bot@example.com","itemArr":[{"itemNum":"A0","itemPrice":90,"lineNum":0},{"accessoryArr":[{"name":"bag","price":10},{"name":"tray","price":12}],"itemNum":"A1","itemPrice":91,"lineNum":1}],"name":"bot","status":true}

=== Showing the decoded orderJson:
map[status:true age:18 email:bot@example.com itemArr:[map[itemNum:A0 itemPrice:90 lineNum:0] map[accessoryArr:[map[name:bag price:10] map[name:tray price:12]] itemNum:A1 itemPrice:91 lineNum:1]] name:bot]

=== Showing how to access individual element in the decoded orderJson:
itemNum: A0
itemPrice: 90

Reference:

https://michaelheap.com/golang-encodedecode-arbitrary-json/

http://stackoverflow.com/questions/25214036/getting-invalid-operation-mymaptitle-type-interface-does-not-support-in

Serving static content files in Go Gorilla

package main

import (
  "fmt"
  "net/http"
  "log"
  "github.com/gorilla/mux"
)

const (
  PORT       = ":80"
  STATIC_DIR = "/static/"
)

func main() {
  mx := mux.NewRouter()
  mx.PathPrefix(STATIC_DIR).Handler(http.StripPrefix(STATIC_DIR, http.FileServer(http.Dir("." + STATIC_DIR))))

  err := http.ListenAndServe(PORT, mx)

  if err != nil {
    fmt.Printf("main(): %s\n", err)
    log.Fatal("ListenAndServe: ", err)
  }
}

Reference:

http://stackoverflow.com/questions/15834278/serving-static-content-with-a-root-url-with-the-gorilla-toolkit

Set HTTP header content type to HTML in Go Gorilla

package main

import (
    "fmt"
    "net/http"
    "log"
    "github.com/gorilla/mux"
)

const (
    PORT       = ":80"
)

func SayHelloWorld(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/html; charset=utf-8")
    w.Write([]byte("<span style=\"color: red;\">Hello, World!</span>"))
}

func main() {
    mx := mux.NewRouter()
    mx.HandleFunc("/", SayHelloWorld)

    err := http.ListenAndServe(PORT, mx)

    if err != nil {
        fmt.Printf("main(): %s\n", err)
        log.Fatal("ListenAndServe: ", err)
    }
}

Reference:

http://stackoverflow.com/questions/12830095/setting-http-headers-in-golang

create a temporary file storage

The go build tool uses /tmp when compiling and testing, this can cause heavy wear and tear if /tmp lives on your SD card. To minimise this effect, either export TMPDIR to somewhere that lives on another filesystem. Alternatively if you have lots of physical memory you can mount a swap backed tmpfs filesystem on /tmp by adding this line to /etc/fstab

# tmpfs /tmp tmpfs nodev,nosuid,mode=1777 0 0

Reference:

https://github.com/golang/go/wiki/GoArm

Thursday, March 24, 2016

asynchronous web server in .NET

asynchronous web server in .NET

/// <summary>
/// A simple program to show off an OWIN self-hosted web app.
/// </summary>
public class Program
{
    /// <summary>
    /// The entry point for the console application.
    /// </summary>
    /// <param name="args">The arguments to the execution of the console application. Ignored.</param>
    static void Main(string[] args)
    {
        // Start OWIN host
        using (WebApp.Start<Startup>(url: "http://localhost:8000"))
        {
            // Runs until a key is pressed
            Console.ReadKey();
        }
    }
 
    /// <summary>
    /// This code configures the OWIN web app. The Startup class is specified as a type parameter in the WebApp.Start method.
    /// </summary>
    private class Startup
    {
        /// <summary>
        /// Configures the web app.
        /// </summary>
        /// <param name="app">The app builder.</param>
        public void Configuration( IAppBuilder app )
        {
            // We ignore any rules here and just return the same response for any request
            app.Run( context =>
            {
                context.Response.ContentType = "text/plain";
                return context.Response.WriteAsync( "Hello World\n" );
            } );
        }
    }
}

Reference:

http://www.haneycodes.net/to-node-js-or-not-to-node-js/

How to Log Messages in Drupal 8

How to Log Messages in Drupal 8

<?php
// Logs a notice
\Drupal::logger('my_module')->notice('@type: deleted %title.', [
  '@type' => $this->entity->bundle(),
  '%title' => $this->entity->label(),
]);

// Logs an error
\Drupal::logger('my_module')->error('@type: deleted %title.', [
  '@type' => $this->entity->bundle(),
  '%title' => $this->entity->label(),
]);
?>

<?php
try {
  // some code
}
catch (\Exception $e) {
  watchdog_exception('test', $e);
}
?>

Then, go to http://mydomain.com/admin/reports/dblog

Placeholder types

@variable — Use this style of placeholder for most use-cases. Special characters in the text will be converted to HTML entities.

%variable — Use this style of placeholder to pass text through drupal_placeholder() which will result in HTML escaped text, then wrapped with <em> tags.

:variable — Use this style of placeholder when substituting the value of an href attribute. Values will be HTML escaped, and filtered for dangerous protocols.

Reference:

https://drupalize.me/blog/201510/how-log-messages-drupal-8

Wednesday, March 23, 2016

veteran - 老將、老兵、有經驗的人

veteran - 老將、老兵、有經驗的人

seasoned - 老練的

Tuesday, March 22, 2016

Send email in Drupal 8

Send email in Drupal 8

<?php
/**
* Implements hook_mail().
*/
function mymodule_mail($key, &$message, $params) {
  $options = [
    'langcode' => $message['langcode'],
  ];

  switch ($key) {
    case 'order_confirmation':
      $message['from'] = \Drupal::config('system.site')->get('mail');
      $message['subject'] = t('test: @subject', [
        '@subject' => $params['subject'],
      ], $options);
      $message['body'][] = $params['body'];
      break;
  }
}

function mymodule_sendOrderConfirmation($toEmail, $params) {
  \Drupal::service('plugin.manager.mail')->mail(
    'mymodule',
    'order_confirmation',
    $toEmail,
    \Drupal::languageManager()->getDefaultLanguage()->getId(),
    $params,
    NULL, // Optional email address to be used to answer.
    TRUE
  );
}

mymodule_sendOrderConfirmation('test@example.com', [
  'subject' => 'test subject',
  'body' => 'test body',
]);
?>

Monday, March 21, 2016

use EDGE.JS to integrate .NET framework into Node.js

We use EDGE.JS to integrate .NET framework into Node.js.

To install edge.js on client side:

# npm install edge

Server side index.php - http://my.cent-dev.local:

<html>
  <head>
    <script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
    <script>
    $( document ).ready(function() {
      $('#uploadBtn').on('click', function(event){
        $.get( 'http://127.0.0.1:1337/', function( data ) {
          console.log(data);
        });
      });
    });
    </script>
  </head>
  <body>

    <p id="uploadBtn">Hit me to Upload</p>
  </bodY>
</html>

Server side - upload.php:

<?php
file_put_contents('/tmp/debug1', print_r($_FILES, TRUE) . PHP_EOL, FILE_APPEND);

if (!empty($_FILES)) {
  $dir = '/www/my/javascript/tmp/upload_dir/';

  ### Warning: remember to sanitize the filename because it could be forged.
  move_uploaded_file($_FILES['file1']['tmp_name'], $dir . $_FILES['file1']['name']);
}
?>

Client side - running a Node.js web server that will upload the local files to the remote server:

const http = require('http');

const hostname = '127.0.0.1';
const port = 1337;

var url = require('url');
var edge = require('edge');

var uploadFile = edge.func(
    {
        source: function() {/*
            using System;
            using System.IO;
            using System.Threading.Tasks;
            using System.Drawing;
            using System.Drawing.Printing;
            using System.Net.Http;

            public class Startup
            {
                public async Task<object> Invoke(dynamic input)
                {
                    int a = (int)input.a;
                    int b = (int)input.b;

                    //MathHelper.printToPrinter(input.myMsg);
                    MathHelper.Upload(input.uploadURL, input.filePath);

                    return MathHelper.Add(a, b);
                }

            }

            static class MathHelper
            {
                public static int Add(int a, int b)
                {
                    return a + b;
                }

                public static System.IO.Stream Upload(string url, string filename)
                {

                    Stream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
                    HttpContent fileStreamContent = new StreamContent(fileStream);

                    // Submit the form using HttpClient and 
                    // create form data as Multipart (enctype="multipart/form-data")

                    using (var client = new HttpClient())
                    using (var formData = new MultipartFormDataContent())
                    {
                        formData.Add(fileStreamContent, "file1", filename);

                        // equivalent to (action="{url}" method="post")
                        var response = client.PostAsync(url, formData).Result;

                        // equivalent of pressing the submit button on the form
                        if (!response.IsSuccessStatusCode)
                        {
                            return null;
                        }
                        return response.Content.ReadAsStreamAsync().Result;
                    }
                }

                public static void printToPrinter(string s) {
                  //string s = "string to print2";

                  PrintDocument p = new PrintDocument();
                  p.PrintPage += delegate (object sender1, PrintPageEventArgs e1)
                  {
                      e1.Graphics.DrawString(s, new Font("Times New Roman", 12), new SolidBrush(Color.Black), new RectangleF(0, 0, p.DefaultPageSettings.PrintableArea.Width, p.DefaultPageSettings.PrintableArea.Height));
                  };
                  try
                  {
                      p.Print();
                  }
                  catch (Exception ex)
                  {
                      throw new Exception("Exception Occured While Printing", ex);
                  }
                }
            }
        */},
        references: ["System.dll", "System.Drawing.dll", "System.Net.Http.dll"]
    });

var myTxt = "Hello World";
var remoteURL = 'http://my.cent-dev.local';
var uploadURL = remoteURL + "/javascript/tmp/upload.php";

var filePath = "C:/Users/bot/Downloads/tmp/node.js/asdf2.pdf";

http.createServer((req, res) => {
  var queryData = url.parse(req.url, true).query;

  console.log(queryData);

  uploadFile({ a: 5, b: 10, myMsg: myTxt, uploadURL: uploadURL, filePath: filePath}, function (error, result) {
      console.log(result);
  });

  res.writeHead(200, {
    'Content-Type': 'text/plain',
    'Access-Control-Allow-Origin': remoteURL,
  });

  res.end('Hello World123\n');

}).listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});


Reference:

http://tjanczuk.github.io/edge/#/

http://stackoverflow.com/questions/566462/upload-files-with-httpwebrequest-multipart-form-data

Sunday, March 20, 2016

intrigue 激起 .. 的好奇心 To engage in secret or underhand schemes; plot.

intrigue 激起 .. 的好奇心 To engage in secret or underhand schemes; plot.

where node.js meets .net in-process and the intrigue begins

Reference:

http://tjanczuk.github.io/edge/

prologue 序幕/開場白 An introduction or introductory chapter

prologue 序幕/開場白 An introduction or introductory chapter

1. An introduction or preface, especially a poem recited to introduce a play.
2. An introduction or introductory chapter, as to a novel.
3. An introductory act, event, or period.

where node.js meets .net in-process and the intrigue begins

Reference:

http://tjanczuk.github.io/edge/#/1

sway 搖擺/撼動 - To exert influence or control over: His speech swayed the voters.

sway 搖擺/撼動 - To exert influence or control over: His speech swayed the voters.

1. To cause to swing back and forth or to and fro: The breeze swayed the wheat.
2. To cause to incline or bend: The wind swayed the trees toward the house.
3. To exert influence or control over: His speech swayed the voters.

There are many factors to consider when choosing a platform for your enterprise applications or customers. When AnyPresence debated the adoption of Java, .Net, or Node.js for our enterprise development platform, the decision wasn’t obvious or made overnight. In the end, the scalability, speed, enterprise readiness, and community support of Node.js swayed our engineers.

Reference:

http://www.infoworld.com/article/2975233/javascript/why-node-js-beats-java-net-for-web-mobile-iot-apps.html

How to create an empty object

Object.create(null) is similar to { }, but without the delegation to Object.prototype, so it's "more empty" than just { }

var emptyObj = Object.create( null );

Reference:

https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/ch2.md

Saturday, March 19, 2016

eccentricities 怪異、超呼尋常 - unconventional or irregular behaviour

eccentricities 怪異、超呼尋常 - unconventional or irregular behaviour

1. unconventional or irregular behaviour
2. (Mathematics) deviation from a circular path or orbit
3. (Astronomy) a measure of the noncircularity of an elliptical orbit, the distance between the foci divided by the length of the major axis
4. (Mathematics) geometry a number that expresses the shape of a conic section: the ratio of the distance of a point on the curve from a fixed point (the focus) to the distance of the point from a fixed line (the directrix)
5. (Mechanical Engineering) the degree of displacement of the geometric centre of a rotating part from the true centre, esp of the axis of rotation of a wheel or shaft

While JavaScript is perhaps one of the easiest languages to get up and running with, its eccentricities make solid mastery of the language a vastly less common occurrence than in many other languages.

Reference:

https://github.com/getify/You-Dont-Know-JS/blob/master/preface.md

seasoned 老練 - To render competent through trial and experience

seasoned 老練 - To render competent through trial and experience

1. To improve or enhance the flavor of (food) by adding salt, spices, herbs, or other flavorings.
2. To add zest, piquancy, or interest to: seasoned the lecture with jokes.
3. To treat or dry (lumber, for example) until ready for use; cure.
4. To render competent through trial and experience: a lawyer who had been seasoned by years in the trial courts.
5. To accustom or inure; harden: troops who had been seasoned in combat. See Synonyms at harden.
6. To moderate; temper.

It is simultaneously a simple, easy-to-use language that has broad appeal, and a complex and nuanced collection of language mechanics which without careful study will elude true understanding even for the most seasoned of JavaScript developers.

Reference:

https://github.com/getify/You-Dont-Know-JS/blob/master/preface.md

idioms 慣用語法 - A specialized vocabulary used by a group of people

idioms 慣用語法 - A specialized vocabulary used by a group of people

1. A speech form or an expression of a given language that is peculiar to itself grammatically or cannot be understood from the individual meanings of its elements, as in keep tabs on.
2. The specific grammatical, syntactic, and structural character of a given language.
3. Regional speech or dialect.
4. A specialized vocabulary used by a group of people; jargon: legal idiom.
5. A style of artistic expression characteristic of a particular individual, school, period, or medium: the idiom of the French impressionists; the punk rock idiom.

Because JavaScript borrows concepts and syntax idioms from several languages, including proud C-style procedural roots as well as subtle, less obvious Scheme/Lisp-style functional roots, it is exceedingly approachable to a broad audience of developers, even those with just little to no programming experience.

Reference:

https://github.com/getify/You-Dont-Know-JS/blob/master/preface.md

vastly 極大地 - Very great in size

vastly 極大地 - Very great in size

1. Very great in size, extent, or quantity. See Synonyms at enormous.
2. Very great in scope or import: a vast improvement.

The two languages are vastly different in many important ways. "JavaScript" is as related to "Java" as "Carnival" is to "Car".

Reference:

https://github.com/getify/You-Dont-Know-JS/blob/master/preface.md

perpetually 永久性地 - Lasting forever; never-ending

perpetually 永久性地 - Lasting forever; never-ending

1. Lasting forever; never-ending: conceived heaven as a state of perpetual bliss.
2. Continuing or being so for an indefinitely long time: found themselves in perpetual debt; felt like a perpetual outsider. See Synonyms at continual.
3. Flowering throughout the growing season.

But as a language, it has perpetually been a target for a great deal of criticism, owing partly to its heritage but even more to its design philosophy.

Reference:

https://github.com/getify/You-Dont-Know-JS/blob/master/preface.md

Friday, March 18, 2016

Focus state bug on text field AJAX calls

Focus state bug on text field AJAX calls. It will refocus to the same field after the AJAX calls.

$element['#ajax']['disable-refocus'] = TRUE;

Reference:

https://www.drupal.org/node/2627788

https://www.drupal.org/node/2124397#comment-9159611

CSS Background Image Opacity

CSS Background Image Opacity

<style>
article {
  position: relative;
  z-index: 1;
  background: transparent url('/path/to/your/image') no-repeat center center;
}

article::after{
  content: "";
  position: absolute;
  top: 0; 
  left: 0;
  width: 100%; 
  height: 100%;  
  opacity: 0.4; 
  z-index: -1;
  background: #000000;
}
</style>

<article>
  Text.
</article>

Note: ::before would work, too.

Reference:

http://stackoverflow.com/questions/10422949/css-background-opacity

Display word one by one

To display word one by one.

Shorter delay, and a longer animation, so the animations overlap a little:

var str = "Happy New Year 2011";

var spans = '<span>' + str.split(/\s+/).join(' </span><span>') + '</span>';

$(spans).hide().appendTo('body').each(function(i) {
    $(this).delay(400 * i).fadeIn(1000);
});

Another example:

var str = "Happy New Year 2011";

var spans = '<span>' + str.split(/\s+/).join(' </span><span>') + '</span>';

$(spans).hide().appendTo('body').each(function(i) {
    $(this).delay(1000 * i).fadeIn();
});

Another example that deals with tag:

<style>
strong {
    font-weight: bold;
}
</style>

<div id="greeting">
    <h1>here is a test text. <strong>We believe this is better</strong> than ever.</h1>
</div>

<script>
$(document).ready(function() {
    var h1 = $('div#greeting h1');

    h1.hide().contents().each(function() {
        var words;
        if (this.nodeType === 3) {
            words = '<span> ' + this.data.split(/\s+/).join(' </span><span> ') + ' </span>';
            $(this).replaceWith(words);
        } else if (this.nodeType === 1) {
            this.innerHTML = '<span> ' + this.innerHTML.split(/\s+/).join(' </span><span> ') + ' </span>';
        }
    });

    h1.find('span').hide().each(function() {
        if (!$.trim(this.innerHTML)) {
            $(this).remove();
        }
    });

    h1.show().find('span').each(function(i) {
        $(this).delay(400 * i).fadeIn(600);
    });
});
</script>

Reference:

http://stackoverflow.com/questions/4607613/jquery-text-effect-where-words-appear-one-by-one

jQuery display character text one by one

<div id="mydiv"></div>
<button>Go</button>

<script>
var mystr = 'How are you doing?';

$(document).ready(function() {
    $('button').click(function() {
        var dv = $('#mydiv');
        dv.text("");

        jQuery({
            count: 0
        }).animate({
            count: mystr.length
        }, {
            duration: 4500,
            step: function() {
                dv.text(mystr.substring(0, Math.round(this.count)));
            },
        });
    });
});
</script>

Wednesday, March 16, 2016

Install PHP 7 on CentOS through IUS Repository

Install PHP 7 on CentOS through IUS Repository

# cd ~ ; curl 'https://setup.ius.io/' -o setup-ius.sh

# bash setup-ius.sh

# yum install httpd24u mod24u_ssl

# yum install php70u-bcmath php70u-cli php70u-common php70u-dba php70u-dbg php70u-devel php70u-fpm php70u-fpm-httpd php70u-gd php70u-gmp php70u-intl php70u-json php70u-mbstring php70u-mcrypt php70u-mysqlnd php70u-opcache php70u-pdo php70u-pear php70u-xml php70u-xmlrpc

Edit mpm.conf:

# vim /etc/httpd/conf.modules.d/00-mpm.conf

Comment out the following line:

LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

Uncomment the following line:

LoadModule mpm_event_module modules/mod_mpm_event.so

Change the following line:

# vim /etc/httpd/conf/httpd.conf

<Directory "/var/www/html">
  AllowOverride All

  # New directive needed in Apache 2.4.3: 
  Require all granted
</Directory>

Enable and restart services:

# systemctl enable httpd.service

# systemctl restart httpd.service

# systemctl enable php-fpm.service

# systemctl restart php-fpm.service

Tuesday, March 15, 2016

How can I process the results of find in a bash script?

How can I process the results of find in a bash script?

find . -name '*.txt' | while read line; do
    echo "Processing file '$line'"
done

Reference:

http://stackoverflow.com/questions/2087001/how-can-i-process-the-results-of-find-in-a-bash-script

Set up SSH for Git on GitHub

Step 1: Check for SSH keys:

First, we need to check for existing SSH keys on your computer. Open up your Git Bash and type:

# ls -al ~/.ssh

Check the directory listing to see if you already have a public SSH key. The default public key file names are:

id_dsa.pub
id_ecdsa.pub
id_ed25519.pub
id_rsa.pub

Step 2: Generate a new SSH key:

To generate a new SSH key, copy and paste the text below, making sure to substitute in your email address. The default settings are preferred, so when you're prompted to "Enter a file in which to save the key", just press Enter to continue.

# ssh-keygen -t rsa -C "username@example.com"

Note: we strongly recommend a very good, secure passphrase. For more information, see Working with SSH key passphrases.

Next, you'll be asked to enter a passphrase. Type a passphrase.

Step 3: Run ssh-agent - a passphrase manager:

ssh-agent can securely save your passphrase, so you don't have to re-enter it every time you use the key.

On FreeBSD, start the ssh-agent in the background. The following command will generate C-shell commands on stdout:
# eval `ssh-agent -c`

On Linux, start the ssh-agent in the background. The following command will generate Bourne shell commands on stdout:
# eval `ssh-agent -s`

Agent pid 5989

Note: Why do we need to use eval instead of just ssh-agent? It is because ssh-add and ssh (assuming you are using the openssh implementations) require an environment variable to know how to talk to the ssh agent. If you started the agent in a different command prompt window to the one you're using now, or if you started it incorrectly, neither ssh-add nor ssh will see that environment variable set (because the environment variable is set locally to the command prompt it's set in).

This will start an agent automatically for each new command prompt window that you open (which is suboptimal if you open multiple command prompts in one session, but at least it should work):

# cat ~/.bashrc

######
# start up ssh-agent automatically when a new bash session starts.
# Note: the reason why I added -n "$SSH_TTY" is because without it, sftp and/or scp may fail at connection time if you have shell initialization (.profile, .bashrc, .cshrc, etc) which produces output for non-interactive sessions. This output confuses the sftp/scp client.
# Note: the other way: if [ -z "$SSH_AUTH_SOCK" -a -x "$SSHAGENT" ]; then
######
SSHAGENT=/usr/bin/ssh-agent
SSHAGENTARGS="-s"

if [[ -z "$SSH_AUTH_SOCK" && -n "$SSH_TTY" && -a "$SSHAGENT" && -x "$SSHAGENT" ]]; then
  eval `$SSHAGENT $SSHAGENTARGS`
  trap "kill $SSH_AGENT_PID" 0
fi

With a little bit of if-then and a flat file, you can do this once and have all other consoles use the same one, instead of starting one per console, and (if you use key auth) having to ssh-add each time.

Just pipe the output of ssh-agent to a file, then run the file (e.g. with ‘source’ command), check the $SSH_AGENT_PID with ps, and if it’s not running, then run ssh-agent (again, piping its output to the file and then sourcing the file). Put your ssh-adds in there too so it will ask you on start.

For example here’s what I did:

if [[ -e $HOME/.sshagent.conf ]]; then
  . $HOME/.sshagent.conf
fi

if `ps -p ${SSH_AGENT_PID}>/dev/null`; then
  true;
else
  ssh-agent >| $HOME/.sshagent.conf
  . $HOME/.sshagent.conf
  ssh-add ~/.ssh/id_dsa
fi

This will run the SSH agent and authenticate only the first time you need it, not every time you open your Bash terminal. It can be used for any program using SSH in general, including ssh itself and scp. Just add this to /etc/profile.d/ssh-helper.sh:

ssh-auth() {
    # Start the SSH agent only if not running
    [[ -z $(ps | grep ssh-agent) ]] && echo $(ssh-agent) > /tmp/ssh-agent-data.sh

    # Identify the running SSH agent
    [[ -z $SSH_AGENT_PID ]] && source /tmp/ssh-agent-data.sh > /dev/null

    # Authenticate (change key path or make a symlink if needed)
    [[ -z $(ssh-add -l | grep "/home/$(whoami)/.ssh/id_rsa") ]] && ssh-add
}

# You can repeat this for other commands using SSH
git() { ssh-auth; command git "$@"; }

Note: ssh-agent is a tool that provides a secure way of storing and using your SSH keys.

Make sure ssh-agent is running:

# ps auxww | grep ssh-agent

If you want ssh-agent to forget your key after some time, you can configure it to do so by running:

# ssh-add -t 3600

You can change the passphrase for an existing private key without regenerating the keypair. Just type the following command:

# ssh-keygen -p

Start the SSH key creation process
Enter file in which the key is (/Users/you/.ssh/id_rsa): [Hit enter]
Key has comment '/Users/you/.ssh/id_rsa'
Enter new passphrase (empty for no passphrase): [Type new passphrase]
Enter same passphrase again: [One more time for luck]
Your identification has been saved with the new passphrase.

Step 4: Add your new key to the ssh-agent:

# ssh-add ~/.ssh/id_rsa

Note: if you see, Could not open a connection to your authentication agent, try running the ssh-agent by using the following command before you run ssh-add:

On FreeBSD:
# eval `ssh-agent -c`

On Linux:
# eval `ssh-agent -s`

Step 5: Add your SSH key to your GitHub account, copy the text:

# cat ~/.ssh/id_rsa.pub

Note: paste the text you copied above to your GitHub account.

Step 6: go to https://github.com/:

In the top right corner of any page, click on the "settings" icon.

In the user settings sidebar, click on "SSH keys".

Click on "Add SSH key".

In the "Title" field, add a descriptive label for the new key. For example, if you're using a personal Mac, you might call this key "Personal MacBook Air".

Paste your key into the "Key" field.

Click on "Add key".

Confirm the action by entering your GitHub password.

Step 7: Test everything out:

To make sure everything is working, you'll now try SSHing to GitHub. When you do this, you will be asked to authenticate this action using your password, which was the passphrase you created earlier.

# ssh -T git@github.com

Note: if you're switching from HTTPS to SSH, you'll now need to update your remote repository URLs (see below).

Note: if you receive a message about "access denied," you can read these instructions for diagnosing the issue.

Step 8: start pulling data from the repository stored on GitHub:

Clone the repository:

# git clone git@github.com:USERNAME/REPOSITORY_NAME.git

Switching remote URLs from HTTPS to SSH:

# git remote -v

origin https://github.com/USERNAME/REPOSITORY_NAME.git (fetch)
origin https://github.com/USERNAME/REPOSITORY_NAME.git (push)

# git remote set-url origin git@github.com:USERNAME/REPOSITORY_NAME.git

Verify new remote URL:

# git remote -v

origin git@github.com:USERNAME/REPOSITORY_NAME.git (fetch)
origin git@github.com:USERNAME/REPOSITORY_NAME.git (push)

Switching remote URLs from SSH to HTTPS:

# git remote -v

origin git@github.com:USERNAME/REPOSITORY_NAME.git (fetch)
origin git@github.com:USERNAME/REPOSITORY_NAME.git (push)

# git remote set-url origin https://github.com/USERNAME/REPOSITORY_NAME.git

Verify new remote URL:

# git remote -v

origin https://github.com/USERNAME/REPOSITORY_NAME.git (fetch)
origin https://github.com/USERNAME/REPOSITORY_NAME.git (push)

If you set the remote URLs to HTTPS instead of SSH, the next time you git fetch, git pull, or git push to the remote repository, you'll be asked for your GitHub username and password:

https://help.github.com/articles/generating-ssh-keys/
https://help.github.com/articles/working-with-ssh-key-passphrases/
https://help.github.com/articles/changing-a-remote-s-url/
http://stackoverflow.com/questions/17846529/could-not-open-a-connection-to-your-authentication-agent/4086756#4086756
http://blog.killtheradio.net/how-tos/ssh-agent-on-cygwin/

Monday, March 14, 2016

endeavour 努力 - try hard to do or achieve something.

endeavour 努力 - try hard to do or achieve something.

Amazon provide VPN access with their Virtual Private Cloud (VPC)

AWS allow you to create your own private network 'in the cloud'. They call this VPC and it's fairly east to setup.

You can connect to your VPC in a number of ways, two examples:

VPN
You can connect to instances in your VPC via VPN (over an Internet Connection).

Direct Connect
You could also use Direct Connect to connect to instances in your VPC via a private network (ie NOT over the Internet).

Faster
Better ping/response times (more reliable)
More secure (as it bypasses any and all Internet traffic)
More costly (there are setup/ongoing charges with Direct Connect)

More Info

VPC & Peering
http://aws.amazon.com/vpc/

Also have a look at peering for communication between VPCs.

Connect privately to other VPCs- Peer VPCs together to share resources across multiple virtual networks owned by your or other AWS accounts.

Direct Connect
http://aws.amazon.com/directconnect/

Direct Connect & VPN
Setting Up AWS Direct Connect with VPN http://docs.aws.amazon.com/govcloud-us/latest/UserGuide/setting-up-direct-connect-with-vpn.html

Reference:

http://serverfault.com/questions/616805/join-ec2-instance-to-my-local-area-network

Sunday, March 13, 2016

temptation 誘惑誤導 - a desire to do something, especially something wrong or unwise

temptation 誘惑誤導 - a desire to do something, especially something wrong or unwise

There is a temptation to think that all of the code you see in JavaScript program is interpreted line-by-line, top-down in order, as the program executes. While that is substantially true, there is one part of that assumption that can lead to incorrect thinking about your program.

subtle 微妙難捉摸的 - (especially of a change or distinction) so delicate or precise as to be difficult to analyze or describe.

subtle 微妙難捉摸的 - (especially of a change or distinction) so delicate or precise as to be difficult to analyze or describe.

But there is a subtle detail of how scope attachment works with declarations that appear in various locations within a scope, and that detail is what we will examine here.

parallax scrolling

parallax scrolling

- flat design vs realism design (realistic design or called skeuomorph design) http://www.flatvsrealism.com/
- slideshow
- storyboard
- mood boards

- ScrollMagic https://github.com/janpaepke/ScrollMagic
- http://alfredservice.com/
- https://ihatetomatoes.net/scrollmagic-tutorial-fullscreen-slideshow/
- https://ihatetomatoes.net/simple-scrollmagic-tutorial/

- Stellar.js http://markdalgleish.com/projects/stellar.js/
- Jarallax http://www.jarallax.com/
- Skrollr.js https://github.com/Prinzhorn/skrollr

- GSAP (GreenSock Animation Platform) https://greensock.com/
- https://ihatetomatoes.net/how-i-created-my-first-svg/
- https://ihatetomatoes.net/how-to-animate-svg-with-greensock/
- http://greensock.com/forums/topic/7537-timelinemax-staggerto-simple-onoff-image-cycle/

- sticky navigation bar (fixed header)
- SMINT (Sticky Menu Including Navigation Thingy) http://www.outyear.co.uk/smint/
- fullPage.js https://github.com/alvarotrigo/fullPage.js
- waypoints.js http://imakewebthings.com/waypoints/
- http://codepen.io/jakob-e/pen/mhCyx
- http://jsfiddle.net/senff/4D3bH/3/

https://ihatetomatoes.net/how-to-create-a-parallax-scrolling-website/
http://www.flatvsrealism.com/
http://alfredservice.com/

creep 潛入 - (of a thing) move very slowly at an inexorably steady pace.

creep 潛入 - (of a thing) move very slowly at an inexorably steady pace.

So I hope that you enjoy this book, but moreso, that Kyle's way of critically thinking about how every tiny bit of the language works will creep into your mindset and general workflow. Instead of just using the antenna, figure out how and why it works.

Reference:

You Don't Know JS: Scope & Closures By Kyle Simpson

tackle 決心做某事 - make determined efforts to deal with (a problem or difficult task)

tackle 決心做某事 - make determined efforts to deal with (a problem or difficult task)

An aspiring software developer looking for their first job in the industry must be well-prepared to tackle the ubiquitous coding challenge, a common feature of the interview process.

Reference:

https://www.codementor.io/learn-programming/9-essential-tips-tackle-coding-challenge

Saturday, March 12, 2016

Why does this CSS margin-top style not work?

Solutions:

1. Set padding-top: 1px; to #outer

2. Set border-top: 1px solid transparent; to #outer

3. Set float: left; to either #outer or #inner

4. Set display: inline-block; to either #outer or #inner

5. Set overflow: auto; (or any value other than visible) to #outer.

Why does this CSS margin-top style not work?

You're actually seeing the top margin of the #inner element collapse into the top edge of the #outer element, leaving only the #outer margin intact (albeit not shown in your images). The top edges of both boxes are flush against each other because their margins are equal.

Here are the relevant points from the W3C spec:

8.3.1 Collapsing margins
In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.

Adjoining vertical margins collapse [...]

Two margins are adjoining if and only if:

- both belong to in-flow block-level boxes that participate in the same block formatting context
- no line boxes, no clearance, no padding and no border separate them
- both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
-- top margin of a box and top margin of its first in-flow child

The reason why doing any of the following prevents the margin from collapsing:

- Floating either of your div elements
- Making either of your div elements inline blocks
- Setting overflow of #outer to auto (or any value other than visible)

Is because:

- Margins between a floated box and any other box do not collapse (not even between a float and its in-flow children).
- Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.
- Margins of inline-block boxes do not collapse (not even with their in-flow children).

The left and right margins behave as you expect because:

Horizontal margins never collapse.

Reference:

http://www.w3.org/TR/CSS21/box.html#collapsing-margins

http://stackoverflow.com/questions/9519841/why-does-this-css-margin-top-style-not-work

Friday, March 11, 2016

hone - refine or perfect (something) over a period of time.

Developers spend many years honing their craft. Some have languages thrust upon them, but those who reach Ninja level usually make their own choice based on a host of factors.

hone:

1. sharpen (a blade)
2. refine or perfect (something) over a period of time.

craft:

1. an activity involving skill in making things by hand.

Reference:

http://www.sitepoint.com/sitepoint-smackdown-php-vs-node-js/

Thursday, March 10, 2016

jQuery animate fired the callback twice

Animate would fire the callback twice because it calls its callback once for each element in the set you call animate on.

Because the animation works on body on some browsers but on html on other browsers. We can solve this issue by using .promise().then:

    $('html, body').animate({
      scrollTop: $('#test').offset().top,
    }, 400, function(){
      console.log('this will be fired twice');
    })
    .promise().then(function() {
      // Called when the animation in total is complete
      console.log('this will be fired once');
    });

Wednesday, March 9, 2016

Display a video from a Blob Javascript

<video autoplay controls poster="../images/poster.jpg" preload="metadata">Your browser does not support the video element</video>
<script src="js/main.js"></script>

js/main.js:

'use strict';

/* globals FileError */

// get video file via XHR
// store with File API
// read Blob from File API and set as video src using createObjectUrl()
// play video

var video = document.querySelector('video');

function getVideo(fileEntry) {
  get('../video/chrome.webm', function(uInt8Array) {
    var blob = new Blob([uInt8Array], {
      type: 'video/webm'
    });
    writeToFile(fileEntry, blob);
  });
}

function get(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'arraybuffer';
  xhr.send();

  xhr.onload = function() {
    if (xhr.status !== 200) {
      alert('Unexpected status code ' + xhr.status + ' for ' + url);
      return false;
    }
    callback(new Uint8Array(xhr.response));
  };
}

// code adapted from HTML5 Rocks article by Eric Bidelman
// http://www.html5rocks.com/en/tutorials/file/filesystem/

// init a FileSystem
// create a file
// write to the file
// read from the file

window.requestFileSystem =
window.requestFileSystem || window.webkitRequestFileSystem;

window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, // 5MB
  handleInitSuccess, handleError);

function handleInitSuccess(fileSystem) {
  window.fileSystem = fileSystem;
  log('Initiated FileSystem: ' + fileSystem.name);
  createFile('video.webm');
}

function createFile(fullPath) {
  window.fileSystem.root.getFile(fullPath, {
    create: true
    /* exclusive: true */
  },
  function(fileEntry) {
    log('Created file: ' + fileEntry.fullPath);
    getVideo(fileEntry);
  }, handleError);
}

function writeToFile(fileEntry, blob) {
  // Create a FileWriter object for fileEntry
  fileEntry.createWriter(function(fileWriter) {
    fileWriter.onwriteend = function() {
      // read from file
      log('Wrote to file ' + fileEntry.fullPath);
      readFromFile(fileEntry.fullPath);
    };
    fileWriter.onerror = function(e) {
      log('Write failed: ' + e.toString());
    };
    // Create a new Blob and write it to file
    fileWriter.write(blob);
  }, handleError);
}

function readFromFile(fullPath) {
  window.fileSystem.root.getFile(fullPath, {}, function(fileEntry) {
    // Get a File object representing the file
    // then use FileReader to read its contents
    fileEntry.file(function(file) {
      var reader = new FileReader();
      reader.onloadend = function() {
        // video.src = this.result;
        video.src = URL.createObjectURL(new Blob([this.result]));
      };
      // reader.readAsDataURL(file);
      reader.readAsArrayBuffer(file);
    }, handleError);
  }, handleError);
}

function handleError(e) {
  switch (e.code) {
  case FileError.QUOTA_EXCEEDED_ERR:
    log('QUOTA_EXCEEDED_ERR');
    break;
  case FileError.NOT_FOUND_ERR:
    log('NOT_FOUND_ERR');
    break;
  case FileError.SECURITY_ERR:
    log('SECURITY_ERR');
    break;
  case FileError.INVALID_MODIFICATION_ERR:
    log('INVALID_MODIFICATION_ERR');
    break;
  case FileError.INVALID_STATE_ERR:
    log('INVALID_STATE_ERR');
    break;
  default:
    log('Unknown error');
    break;
  }
}

var data = document.getElementById('data');

function log(text) {
  data.innerHTML += text + '<br />';
}

document.querySelector('video').addEventListener('loadedmetadata', function() {
  var fileName = this.currentSrc.replace(/^.*[\\\/]/, '');
  document.querySelector('#videoSrc').innerHTML = 'currentSrc: ' + fileName +
  '<br /> videoWidth: ' + this.videoWidth + 'px<br /> videoHeight: ' + this
  .videoHeight + 'px';
});

Reference:

http://stackoverflow.com/questions/14317179/display-a-video-from-a-blob-javascript

http://simpl.info/video/offline/

https://github.com/samdutton/simpl/blob/gh-pages/video/offline/index.html

Monday, March 7, 2016

use Unicode in AutoHotKey

To use Unicode in AutoHotKey, save your script file to UTF-8 + Bom (UTF-8 won't work).

Wednesday, March 2, 2016

special permission setuid setgid sticky bit

Linux offers three types of special permission bits that may be set on executable files or directories to allow them to respond differently for certain operations:

setuid (set user identifier) bit:

When setuid bit is set on executable file at the file owner level, the file is executed by other regular users with the same privileges as that of the file owner.

# chmod 4755 test.sh

Or

# chmod u+s test.sh

# ls -l test.sh

-rwsr-xr-x. 1 root root 0 Jan 23 16:37 test.sh

# find . -perm -4000

./test.sh

setgid (set group identifier) bit:

When setgid attribute is set on executable files at the group level, the file is executed by non-owners with the exact same privileges that the group members have. The setgid bit can also be set on group-shared directories to allow files and sub-directories created in that directory to automatically inherit the directory's owning group.

# chmod 2555 test

Or

# chmod g+s test

# ls -ld test

dr-xr-sr-x. 2 root root 6 Jan 23 16:40 test

# find . -perm -2000

./test

sticky bit:

The sticky bit is set on public writable directories (or other directories with rw permission for everyone) to protect files and sub-directories owned by regular users from being deleted or moved by other regular users.

# chmod 1755 test

or

# chmod o+t test

# ls -ld test

drwxr-x--T. 2 root root 6 Jan 23 16:46 test

# find . -perm -1000

./test

Reference:

RHCSA & RHCE Red Hat Enterprise Linux 7: Training and Exam Preparation Guide (EX200 and EX300), Third Edition
http://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Dstripbooks&field-keywords=rhcsa+rhce+red+hat+