text:
package com.android.simone.github.marvelapp.domain.model;

import java.util.List;

/**
 * @author Simone Bellotti
 */

public class Comic {

    private String id;
    private String title;
    private String description;
    private String pageCount;
    private String thumbnail;
    private String year;
    private String price;
    private List<String> images;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getPageCount() {
        return pageCount;
    }

    public void setPageCount(String pageCount) {
        this.pageCount = pageCount;
    }

    public String getThumbnail() {
        return thumbnail;
    }

    public void setThumbnail(String thumbnail) {
        this.thumbnail = thumbnail;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public List<String> getImages() {
        return images;
    }

    public void setImages(List<String> images) {
        this.images = images;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Comic{" +
                "year='" + year + '\'' +
                ", price='" + price + '\'' +
                ", pageCount='" + pageCount + '\'' +
                ", title='" + title + '\'' +
                ", images=" + images +
                '}';
    }
}


text:
namespace System.Web.Mvc {
    using System;
    using System.Web.Mvc.Resources;

    public class HandleErrorInfo {

        public HandleErrorInfo(Exception exception, string controllerName, string actionName) {
            if (exception == null) {
                throw new ArgumentNullException("exception");
            }
            if (String.IsNullOrEmpty(controllerName)) {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "controllerName");
            }
            if (string.IsNullOrEmpty(actionName)) {
                throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
            }

            Exception = exception;
            ControllerName = controllerName;
            ActionName = actionName;
        }

        public string ActionName {
            get;
            private set;
        }

        public string ControllerName {
            get;
            private set;
        }

        public Exception Exception {
            get;
            private set;
        }

    }
}

redpajama_set_name: RedPajamaGithub


text:
package at.ac.tuwien.dbai.pdfwrap.operator;

import at.ac.tuwien.dbai.pdfwrap.pdfread.PDFObjectExtractor;
import org.apache.pdfbox.cos.COSNumber;
import org.apache.pdfbox.util.PDFOperator;
import org.apache.pdfbox.util.operator.OperatorProcessor;

import java.awt.geom.Point2D;
import java.util.List;

/**
 * Implementation of content stream operator for PDFObjectExtractor.
 *
 * Adapted from PDFBox code
 * @author Ben Litchfield, ben@benlitchfield.com
 * @author Tamir Hassan, pdfanalyser@tamirhassan.com
 * @version PDF Analyser 0.9
 */
public class CurveToReplicateFinalPoint extends OperatorProcessor
{

    /**
     * process : y : Append curved segment to path (final point replicated).
      The operator that is being executed.
      List
     */
    public void process(PDFOperator operator, List arguments)
    {
        PDFObjectExtractor drawer = (PDFObjectExtractor)context;

        COSNumber x1 = (COSNumber)arguments.get( 0 );
        COSNumber y1 = (COSNumber)arguments.get( 1 );
        COSNumber x3 = (COSNumber)arguments.get( 2 );
        COSNumber y3 = (COSNumber)arguments.get( 3 );
        /*float x1f = x1.floatValue();
        float y1f = (float)drawer.fixY( x1f, y1.floatValue() );
        float x3f = x3.floatValue();
        float y3f = (float)drawer.fixY( x3f, y3.floatValue() );
        drawer.getLinePath().curveTo(x1f,y1f,x3f,y3f,x3f,y3f);
        */

        Point2D P1 = drawer.TransformedPoint(x1.doubleValue(), y1.doubleValue());
        Point2D P3 = drawer.TransformedPoint(x3.doubleValue(), y3.doubleValue());

        drawer.getLinePath().curveTo((float)P1.getX(), (float)P1.getY(), (float)P3.getX(), (float)P3.getY(), (float)P3.getX(), (float)P3.getY());
        drawer.simpleCurveTo((float)P1.getX(), (float)P1.getY(), (float)P3.getX(), (float)P3.getY(), (float)P3.getX(), (float)P3.getY());
    }
}


text:
mongoexport --db referandum --collection hours --out temp_hour_data.json
mongo referandum --eval 'db.hours.drop()'
python3 update_hours.py
rm temp_hour_data.json


text:
package main

import "fmt"
import "time"

func main() {
	runGoRoutines()
}

func ProducerActor(itemChannel chan int, doneChannel chan int, items int) {
	for i := 0; i < items; i++ {
		itemChannel <- i
	}
	fmt.Println("Finished production")
	doneChannel <- 0
}

func ConsumerActor(itemChannel chan int, doneChannel chan int, id int) {
	for i := 0; true; i++ {
		if i%100 == 0 {
			fmt.Printf("[consumer %d] consumed %d.\n", id, i)
		}
		time.Sleep(10 * time.Millisecond)
		<-itemChannel
		doneChannel <- 1
	}
}

func runGoRoutines() {
	itemChannel := make(chan int, 100)
	doneChannel := make(chan int)
	const PRODUCERS = 5
	const CONSUMERS = 3
	const N = 1000

	fmt.Printf("Starting. C=%d P=%d, N=%d\n", CONSUMERS, PRODUCERS, N)
	for i := 0; i < PRODUCERS; i++ {
		go ProducerActor(itemChannel, doneChannel, N)
	}

	for i := 0; i < CONSUMERS; i++ {
		go ConsumerActor(itemChannel, doneChannel, i)
	}

	result := 0
	for result < N*PRODUCERS {
		result += <-doneChannel
	}
	fmt.Println("Finished", result)
}


text:
import os, sys

assert sys.version_info[:2] >= ( 2, 4 )

def reverse_complement(s):
    complement_dna = {"A":"T", "T":"A", "C":"G", "G":"C", "a":"t", "t":"a", "c":"g", "g":"c", "N":"N", "n":"n" , ".":"."}
    reversed_s = []
    for i in s:
        reversed_s.append(complement_dna[i])
    reversed_s.reverse()
    return "".join(reversed_s)

def __main__():
    nuc_index = {'a':0,'t':1,'c':2,'g':3,'n':4}
    coverage = {}        # key = (chrom, index)
    invalid_lines = 0
    invalid_chrom = 0
    infile = sys.argv[1]
    outfile = sys.argv[2]

    for i, line in enumerate( open( infile ) ):
        line = line.rstrip('\r\n')
        if not line or line.startswith('#'):
            continue
        fields = line.split()
        if len(fields) < 21:                # standard number of pslx columns
            invalid_lines += 1
            continue
        if not fields[0].isdigit():
            invalid_lines += 1
            continue
        chrom = fields[13]
        if not chrom.startswith( 'chr' ):
            invalid_lines += 1
            invalid_chrom += 1
            continue
        try:
            block_count = int(fields[17])
        except:
            invalid_lines += 1
            continue
        block_size = fields[18].split(',')
        chrom_start = fields[20].split(',')

        for j in range( block_count ):
            try:
                this_block_size = int(block_size[j])
                this_chrom_start = int(chrom_start[j])
            except:
                invalid_lines += 1
                break
            # brut force coverage
            for k in range( this_block_size ):
                cur_index = this_chrom_start + k
                if coverage.has_key( ( chrom, cur_index ) ):
                    coverage[(chrom, cur_index)] += 1
                else:
                    coverage[(chrom, cur_index)] = 1

    # generate a index file
    outputfh = open(outfile, 'w')
    keys = coverage.keys()
    keys.sort()
    previous_chrom = ''
    for i in keys:
        (chrom, location) = i
        sum = coverage[(i)]
        if chrom != previous_chrom:
            outputfh.write( 'variableStep chrom=%s\n' % ( chrom ) )
            previous_chrom = chrom
        outputfh.write( "%s\t%s\n" % ( location, sum ) )
    outputfh.close()

    if invalid_lines:
        invalid_msg = "Skipped %d invalid lines" % invalid_lines
        if invalid_chrom:
            invalid_msg += ", including %d lines with chrom id errors which must begin with 'chr' to map correctly to the UCSC Genome Browser. "

if __name__ == '__main__': __main__()


text:
using System;
using CSJ2K.Icc;

namespace CSJ2K.Icc.Tags
{
    public class ICCDataType : ICCTag
    {
        new public int type;
        public int reserved;
        public int dataFlag;
        //byte[] Data;

        /// <summary> Construct this tag from its constituant parts</summary>
        /// <param name="signature">tag id</param>
        /// <param name="data">array of bytes</param>
        /// <param name="offset">to data in the data array</param>
        /// <param name="length">of data in the data array</param>
        protected internal ICCDataType(int signature, byte[] data, int offset, int length)
            : base(signature, data, offset, offset + 2 * ICCProfile.int_size)
        {
            type = ICCProfile.getInt(data, offset);
            reserved = ICCProfile.getInt(data, offset + ICCProfile.int_size);
            dataFlag = ICCProfile.getInt(data, offset + ICCProfile.int_size);
            //Data = ICCProfile.getString(data, offset + ICCProfile.int_size, length, true);
        }
    }
}


text:
<?php
namespace ErpNET\Tests\Services;

use ErpNET\Tests\TestCase;
use League\FactoryMuffin\Facade as FactoryMuffin;

class ServiceTestCase extends TestCase
{
    public static function setupBeforeClass()
    {
        // note that method chaining is supported
        FactoryMuffin::setCustomSetter(function ($object, $name, $value) {
            $functionName = camel_case("set-".$name);
            if (method_exists($object, $functionName) && is_callable([$object, $functionName]))
                call_user_func([$object, $functionName], $value);
            else {
                dd(get_class($object).' dont have '.camel_case("set-".$name));
            }
        });
    }

    protected function prepareForTests()
    {
        parent::prepareForTests();
        if (!is_null($this->app) && !is_null($this->testClass)){
            $class = $this->app->make($this->testClass);
            if ($class instanceof \Doctrine\ORM\EntityRepository){
                $em = $class->em;
                FactoryMuffin::setCustomSaver(function ($entity) use ($em) {
                    $em->persist($entity);
                    $em->flush();
                    return true;
                });
            }
        }
    }
}


text:
from twisted.trial import unittest

from demosminerva import ljstream

class TestUnescapeXhtml(unittest.TestCase):

	def test_unescapeXhtml(self):
		self.assertEqual(u"", ljstream.unescapeXhtml(u""))
		self.assertEqual(u" ", ljstream.unescapeXhtml(u" "))
		self.assertEqual(u"
", ljstream.unescapeXhtml(u"
"))
		self.assertEqual(u"\"&'\u00a9", ljstream.unescapeXhtml(u""&'©"))


text:
    {{ Form::textarea('file_content', $sampleContent, [
        'class' => 'form-control'
    ]) }}

{!! trans('setup_wizard::steps.env.view.help_text') !!}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

[RequireComponent(typeof(Player))]
[RequireComponent(typeof(PlayerMovement))]
public class PlayerBallInteraction : MonoBehaviour
{
	Player Player;
	PlayerMovement PlayerMovement;

	ClownId ClownId { get { return Player.ClownId; } }

	bool IsHoldingBall = false;
	float DistanceToBall { get { return Vector2.Distance( Ball.Instance.transform.position, transform.position ); } }
	bool IsBallInJuggleRange { get { return DistanceToBall <= BalanceValues.Instance.JuggleDistance; } }

	void Awake() {
		Player = GetComponent<Player>();
		PlayerMovement = GetComponent<PlayerMovement>();
	}

	public void CatchBall() {
		if (!PlayerMovement.IsStunned) {
			IsHoldingBall = true;
			Ball.Instance.Catch( ClownId );
		}
	}

	void Update() {
		if (PlayerMovement.IsStunned) {
			return;
		}

		if (InputManager.Instance.WasThrowPressedThisFrame(ClownId)) {
			Throw();
		}
	}

	void Throw() {
		if (IsHoldingBall) {
			Ball.Instance.Throw( ClownId );
		}
		else if (IsBallInJuggleRange) {
			Ball.Instance.Juggle( ClownId );
		}
		IsHoldingBall = false;
	}
}


text:
namespace blink {

class LayoutFullScreenItem : public LayoutBlockItem {
 public:
  explicit LayoutFullScreenItem(LayoutBlock* layoutBlock)
      : LayoutBlockItem(layoutBlock) {}

  explicit LayoutFullScreenItem(const LayoutBlockItem& item)
      : LayoutBlockItem(item) {
    SECURITY_DCHECK(!item || item.isLayoutFullScreen());
  }

  explicit LayoutFullScreenItem(std::nullptr_t) : LayoutBlockItem(nullptr) {}

  LayoutFullScreenItem() {}

  void unwrapLayoutObject() { return toFullScreen()->unwrapLayoutObject(); }

 private:
  LayoutFullScreen* toFullScreen() {
    return toLayoutFullScreen(layoutObject());
  }
  const LayoutFullScreen* toFullScreen() const {
    return toLayoutFullScreen(layoutObject());
  }
};

}  // namespace blink

#endif  // LayoutFullScreenItem_h


text:
package com.codepath.apps.Tweeter.activities;

import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;

import com.codepath.apps.Tweeter.R;
import com.codepath.apps.Tweeter.fragments.UserTimelineFragment;
import com.codepath.apps.Tweeter.models.User;
import com.codepath.apps.Tweeter.service.TwitterApplication;
import com.codepath.apps.Tweeter.service.TwitterClient;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.squareup.picasso.Picasso;

import org.json.JSONObject;

import cz.msebera.android.httpclient.Header;

public class ProfileActivity extends AppCompatActivity {

    TwitterClient client;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_profile);

        User user = (User) getIntent().getSerializableExtra("user");
        String screenname = user == null ? null : user.getScreenName();
        if (user == null) {
            client = TwitterApplication.getRestClient();
            client.getUserInfo(new JsonHttpResponseHandler() {

                @Override
                public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
                    User user = new User(response);
                    getSupportActionBar().setTitle(user.getScreenName());
                    populateProfileHeader(user);
                }

            });
        } else {
            getSupportActionBar().setTitle(user.getScreenName());
            populateProfileHeader(user);
        }

        if (savedInstanceState == null) {
            UserTimelineFragment fragment = UserTimelineFragment.newInstance(screenname);
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.flContainer, fragment);
            ft.commit();
        }

    }

    private void populateProfileHeader(User user){
        ImageView ivProfileImage = (ImageView) findViewById(R.id.ivProfileImage);
        Picasso.with(this).load(user.getProfileImageUrl()).into(ivProfileImage);
        TextView tvName = (TextView) findViewById(R.id.tvName);
        tvName.setText(user.getName());
        TextView tvTagline = (TextView) findViewById(R.id.tvTagline);
        tvTagline.setText(user.getTagline());

        TextView tvTweets = (TextView) findViewById(R.id.tvTweets);
        tvTweets.setText(String.valueOf(user.getNumTweets()));
        TextView tvFollowing = (TextView) findViewById(R.id.tvFollowing);
        tvFollowing.setText(String.valueOf(user.getNumFollowing()));
        TextView tvFollowers = (TextView) findViewById(R.id.tvFollowers);
        tvFollowers.setText(String.valueOf(user.getNumFollowers()));
    }

}


text:
<?php

namespace PetrKnap\Symfony\MarkdownWeb;

const BUNDLE_NAME = "MarkdownWeb";
const BUNDLE_ALIAS = "markdown_web";
const BUNDLE_CONSOLE = "markdown-web";
const CONFIG = BUNDLE_ALIAS . ".config";
const CONTROLLER_CACHE = BUNDLE_ALIAS . ".controller_cache";
const TWIG_EXTENSION = BUNDLE_ALIAS . ".twig";
const CRAWLER_SERVICE = BUNDLE_ALIAS . ".crawler";
const BUILD_CACHE_COMMAND = BUNDLE_CONSOLE . ":build-cache";


text:
public class ArrayIterator implements Iterator {
	MenuItem[] items;
	int position = 0;

	public ArrayIterator(MenuItem[] items) {
		this.items = items;
	}

	public Object next() {
		MenuItem menuItem = items[position];
		position = position + 1;
		return menuItem;
	}

	public boolean hasNext() {
		if (position >= items.length || items[position] == null) {
			return false;
		} else {
			return true;
		}
	}
}


text:
declare module "gulp-sourcemaps" {
    interface InitOptions {
        loadMaps?: boolean;
        debug?: boolean;
    }

    interface WriteMapper {
        (file: string): string;
    }

    interface CloneOptions {
        contents?: boolean;
        deep?: boolean;
    }

    interface WriteOptions {
        addComment?: boolean;
        includeContent?: boolean;
        sourceRoot?: string | WriteMapper;
        sourceMappingURLPrefix?: string | WriteMapper;
        clone?: boolean | CloneOptions;
    }

    export function init(opts?: InitOptions): NodeJS.ReadWriteStream;
    export function write(path?: string, opts?: WriteOptions): NodeJS.ReadWriteStream;
    export function write(opts?: WriteOptions): NodeJS.ReadWriteStream;
    export function mapSources(mapFn: (sourcePath: string) => string): NodeJS.ReadWriteStream;

}


text:
/**
 *
 */
package gov.nih.nci.calims2.business.administration.unit;

/**
 * Unit conversion exception.
 *
 * @author viseem
 */
public class UnitConversionException extends RuntimeException {
  private static final long serialVersionUID = 4221469573347293535L;

  /**
   * Constructs a new UnitConversionException with null as its detail message.
   */
  public UnitConversionException() {
    super();
  }

  /**
   * Constructs a new UnitConversionException with the specified detail message.
   *
   * @param message the detail message. The detail message is saved for later retrieval by the Throwable.getMessage() method.
   */
  public UnitConversionException(String message) {
    super(message);
  }

  /**
   * Constructs a new UnitConversionException with the specified detail message and cause.
   *
   * @param message the detail message. The detail message is saved for later retrieval by the Throwable.getMessage() method.
   * @param cause the cause (which is saved for later retrieval by the Throwable.getCause() method). (A null value is permitted, and
   *          indicates that the cause is nonexistent or unknown.)
   */
  public UnitConversionException(String message, Throwable cause) {
    super(message, cause);
  }

  /**
   * Constructs a new UnitConversionException with the specified cause and a detail message of (cause==null ? null :
   * cause.toString()) (which typically contains the class and detail message of cause).
   *
   * @param cause the cause (which is saved for later retrieval by the Throwable.getCause() method). (A null value is permitted, and
   *          indicates that the cause is nonexistent or unknown.)
   */
  public UnitConversionException(Throwable cause) {
    super(cause);
  }

}


text:
package org.springframework.security.web;

import org.junit.Test;

import org.springframework.mock.web.MockHttpServletRequest;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;

/**
 * Tests {@link PortResolverImpl}.
 *
 * @author Ben Alex
 */
public class PortResolverImplTests {

	@Test
	public void testDetectsBuggyIeHttpRequest() {
		PortResolverImpl pr = new PortResolverImpl();
		MockHttpServletRequest request = new MockHttpServletRequest();
		request.setServerPort(8443);
		request.setScheme("HTtP"); // proves case insensitive handling
		assertThat(pr.getServerPort(request)).isEqualTo(8080);
	}

	@Test
	public void testDetectsBuggyIeHttpsRequest() {
		PortResolverImpl pr = new PortResolverImpl();
		MockHttpServletRequest request = new MockHttpServletRequest();
		request.setServerPort(8080);
		request.setScheme("HTtPs"); // proves case insensitive handling
		assertThat(pr.getServerPort(request)).isEqualTo(8443);
	}

	@Test
	public void testDetectsEmptyPortMapper() {
		PortResolverImpl pr = new PortResolverImpl();
		assertThatIllegalArgumentException().isThrownBy(() -> pr.setPortMapper(null));
	}

	@Test
	public void testGettersSetters() {
		PortResolverImpl pr = new PortResolverImpl();
		assertThat(pr.getPortMapper() != null).isTrue();
		pr.setPortMapper(new PortMapperImpl());
		assertThat(pr.getPortMapper() != null).isTrue();
	}

	@Test
	public void testNormalOperation() {
		PortResolverImpl pr = new PortResolverImpl();
		MockHttpServletRequest request = new MockHttpServletRequest();
		request.setScheme("http");
		request.setServerPort(1021);
		assertThat(pr.getServerPort(request)).isEqualTo(1021);
	}

}


text:
<?php declare(strict_types=1);

namespace SebastianBergmann\CodeCoverage\StaticAnalysis;

use SebastianBergmann\CodeCoverage\Filter;

final class CacheWarmer
{
    public function warmCache(string $cacheDirectory, bool $useAnnotationsForIgnoringCode, bool $ignoreDeprecatedCode, Filter $filter): void
    {
        $analyser = new CachingFileAnalyser(
            $cacheDirectory,
            new ParsingFileAnalyser(
                $useAnnotationsForIgnoringCode,
                $ignoreDeprecatedCode
            )
        );

        foreach ($filter->files() as $file) {
            $analyser->process($file);
        }
    }
}


text:
'use strict';

var _ = require('underscore');
var dateformat = require('dateformat');
var url = require('url');
var async = require('async');
var Path = require('path');

var utils = require('../../common/utils');
var logger = require('../../common/log-manager');
var authMgr = require('../../common/auth-manager');
var config = require('../../common/conf-manager').conf;

var ClientError = utils.ClientError;
var ServerError = utils.ServerError;

var ntf = null;

// TODO implement 'expireAfterSeconds' feature on Mysql DB

var shortid = require('shortid');
var db = require('../../common/db-manager')('sequence', 'user', 'group', 'client', 'code', 'token', 'tempKey',
    'policy', 'system');
var dao = db.dao;

var emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
var integerPattern = /^[0-9]+$/;
var STATUS = Object.freeze({PENDING: 0, APPROVED: 1, REJECTED: 2, PASSWORDRESET: 3});
var ACTIONS_TO_NOTI = ['fs:*', 'fs:list', 'fs:readFile', 'fs:writeFile', 'fs:getMeta'];

exports.STATUS = STATUS;
exports.start = function (svc, ntfMgr) {
    ntf = ntfMgr;
};

function notifyTopics(policy, trigger, sessionID) {
    var data;
    var msg;
    var topics;

    if (!sessionID) {
        return;
    }

    data = {
        eventType: 'acl.changed',
        trigger: trigger,
        policy: policy,
        sessionID: sessionID
    };
    msg = {
        topic: 'reserved',
        eventType: 'acl.change',
        data: data
    };
    topics = [];
    policy.resource.forEach(function (rsc) {
        var arr = rsc.substr(3).split('/');
        if (rsc.search('fs:') !== 0) {
            return;
        }

        if (!arr[0] || arr[0] === '*' || !arr[1]) {
            return;
        } else {
            topics.push('sys.acl.change:fs:' + arr[0] + '/' + arr[1]);
        }
    });

    if (topics.length === 0) {
        return;
    } else {
        ntf.sysnoti2(_.uniq(topics), msg, function () {
            logger.info('notified topics - ', topics);
            logger.info('notified data - ', msg);
            return;
        });
    }
}

exports.createGuestSequence = function (callback) {
    db.transaction([
        dao.sequence.updateSequence({space: 'guestid'}),
        function (context, next) {
            dao.sequence.getSequence({space: 'guestid'}, function (err, context) {
                if (err) {
                    return next(err);
                } else {
                    var result = context.result();
                    if (result[0].seq > result[0].maxSeq) {
                        return next('guest id sequence reached to limit.');
                    } else {
                        context.data('seq', result[0].seq);
                        return next(null);
                    }
                }
            }, context);
        }
    ], function (err, context) {
        if (err) {
            logger.error(err);
        }
        callback(err, context.data('seq'));
    });
};

function createSubject(type, callback) {
    db.transaction([
        dao.sequence.updateSequence({space: 'uid'}),
        function (context, next) {
            dao.sequence.getSequence({space: 'uid'}, function (err, context) {
                var result = context.result();
                if (err) {
                    return next(err);
                } else {
                    if (result[0].seq > result[0].maxSeq) {
                        return next('User account reached the max limit.');
                    } else {
                        context.data('seq', result[0].seq);
                        return next(null);
                    }
                }
            }, context);
        }, function (context, next) {
            var uid = context.data('seq');
            var subjectId = shortid.generate();
            context.data('subjectId', subjectId);
            dao.user.addSubject({subjectId: subjectId, type: type, uid: uid}, function (err) {
                next(err);
            }, context);
        }
    ], function (err, context) {
        callback(err, {subjectId: context.data('subjectId'), seq: context.data('seq')});
    });
}

exports.addClient = function (client, callback) {
    client.clientId = shortid.generate();

    dao.client.$save(client, function (err) {
        if (err) {
            callback(err);
        } else {
            dao.client.$findOne({clientId: client.clientId}, callback);
        }
    });
};

exports.updateClient = function (client, callback) {
    var updateClient = {
        name: client.clientName,
        oauthClientSecret: client.clientSecret,
        redirectUrl: client.redirectURL
    };
    if (client.isSystemApp !== undefined) {
        updateClient.isSystem = client.isSystemApp ? 1 : 0;
    }
    exports.findClientByClientID(client.clientID, function (err, result) {
        if (err) {
            callback(err);
        } else if (result) {
            dao.client.$update({oauthClientId: client.clientID, $set: updateClient}, callback);
        } else {
            updateClient.oauthClientId = client.clientID;
            exports.addClient(updateClient, callback);
        }
    });
};

exports.findClientByClientID = function (oauthClientId, callback) {
    dao.client.$findOne({oauthClientId: oauthClientId}, function (err, context) {
        callback(err, context.result());
    });
};

exports.addNewCode = function (code, clientID, redirectURI, uid, callback) {
    exports.findUserByUid(uid, function (err, user) {
        var msPeriod = config.services.auth.codeExpireTime * 1000;
        var expireTime = new Date(new Date().getTime() + msPeriod);
        if (err) {
            callback(err);
        } else if (!user) {
            callback('unknown user uid: ' + uid);
        } else {
            dao.code.$save({codeId: shortid.generate(), code: code, oauthClientId: clientID, redirectUrl: redirectURI,
                userId: user.userId, expireTime: expireTime}, function (err) {
                if (err) {
                    callback(err);
                } else {
                    exports.findCode(code, function (err, context) {
                        callback(err, context.result());
                    });
                }
            });
        }
    });
};

exports.findCode = function (code, callback) {
    dao.code.findValidCode({code: code, currentTime: new Date()}, function (err, context) {
        callback(err, context.result());
    });
};

exports.getTokenInfo = function (token, callback) {
    dao.token.findValidToken({token: token, currentTime: new Date()}, function (err, context) {
        var result;
        if (err) {
            callback(err);
        } else {
            result = context.result();
            if (result.length === 0) {
                callback();
            } else {
                callback(null, result[0]);
            }
        }
    });
};

exports.addNewToken = function (uid, clientID, token, callback) {
    exports.findUserByUid(uid, function (err, user) {
        var msPeriod = config.services.auth.tokenExpireTime * 1000;
        var expireTime = new Date(new Date().getTime() + msPeriod);
        if (err) {
            callback(err);
        } else if (!user) {
            callback('unknown user uid: ' + uid);
        } else {
            dao.token.$save({tokenId: shortid.generate(), token: token, oauthClientId: clientID, userId: user.userId,
                    expireTime: expireTime, validityPeriod: config.services.auth.tokenExpireTime},
                function (err) {
                if (err) {
                    callback(err);
                } else {
                    dao.token.$findOne({token: token}, function (err, context) {
                        callback(err, context.result());
                    });
                }
            });
        }
    });
};

exports.addNewPersonalToken = function (uid, token, callback) {
    exports.findUserByUid(uid, function (err, user) {
        if (err) {
            callback(err);
        } else if (!user) {
            callback('unknown user uid: ' + uid);
        } else {
            dao.token.$save({tokenId: shortid.generate(), token: token, oauthClientId: 'any_' + token,
                userId: user.userId, validityPeriod: 0/* 0:INFINITE */}, function (err) {
                    if (err) {
                        callback(err);
                    } else {
                        dao.token.$findOne({token: token}, function (err, context) {
                            callback(err, context.result());
                        });
                    }
                });
        }
    });
};

exports.deletePersonalToken = function (uid, token, callback) {
    dao.token.$findOne({token: token}, function (err, context) {
        var info = context.result();
        if (err) {
            callback(err);
        } else if (!info) {
            callback(new ClientError('Token not exist.'));
        } else {
            dao.user.$findOne({userId: info.userId}, function (err, context) {
                var user = context.result();
                if (err) {
                    callback('Unknown user: ' + info.userId);
                } else {
                    if (user.uid !== uid) {
                        callback(new ClientError(401, 'Unauthorized access.'));
                    } else {
                        dao.token.$remove({tokenId: info.tokenId}, function (err, context) {
                            callback(err, context.result());
                        });
                    }
                }
            });
        }
    });
};

exports.deleteAllPersonalTokens = function (uid, callback) {
    dao.token.deletePersonalTokensByUid({uid: uid}, function (err, context) {
        callback(err, context.result());
    });
    //d.tokens.remove({uid: uid, expireTime: 'INFINITE'}, callback);
};

exports.getPersonalTokens = function (uid, callback, context) {
    dao.token.getPersonalTokensByUid({uid: uid}, function (err, context) {
        var tokens = context.result();
        if (err) {
            return callback(err);
        }
        callback(null, tokens.map(function (token) {
            return {
                issueTime: token.created,
                data: token.token
            };
        }));
    }, context);
};

exports.verifyToken = function (req, res, next) {
    /* jshint camelcase: false */
    var token = req.headers.authorization || url.parse(req.url, true).query.access_token;
    /* jshint camelcase: true */
    if (!token) {
        req.user = null;
        return next();
    }

    logger.info('verifyToken', token);
    exports.getTokenInfo(token, function (err, info) {
        if (err) {
            return res.status(500).send(utils.fail(err));
        } else if (!info) {
            return res.status(419).send(utils.fail('Token is expired.'));
        } else {
            dao.user.$findOne({userId: info.userId}, function (err, context) {
                var user;
                if (err) {
                    return res.status(500).send(utils.fail(err));
                } else if (!context.result()) {
                    return res.status(400).send(utils.fail('user not found: ' + info.userId));
                } else {
                    user = context.result();
                    console.log('login user: ', user);
                    req.user = user;
                    req.user.token = token;
                    return next();
                }
            });
        }
    });
};

exports.createServerConf = function (callback) {
    dao.sequence.$findOne({space: 'uid'}, function (err, context) {
        var sequence = context.result();
        if (err) {
            callback(err);
        } else if (!sequence) {
            dao.sequence.$save({space: 'uid', currentSeq: config.services.auth.baseUID,
                    maxSeq: config.services.auth.maxUID}, callback);
        } else {
            dao.sequence.$update({space: 'uid', $set: {
                currentSeq: config.services.auth.baseUID, maxSeq: config.services.auth.maxUID}}, callback);
        }
    });

    dao.sequence.$findOne({space: 'guestid'}, function (err, context) {
        var sequence = context.result();
        if (err) {
            callback(err);
        } else if (!sequence) {
            dao.sequence.$save({space: 'guestid', currentSeq:0, maxSeq: 4000000000});
        } else {
            dao.sequence.$update({space: 'guestid',
                $set: {space: 'guestid', currentSeq:0, maxSeq: 4000000000}}, callback);
        }
    });
};

exports.checkSystemApp = function (clientID, callback) {
    dao.client.$findOne({oauthClientId: clientID}, function (err, context) {
        var client = context.result();
        if (err || !client) {
            return callback(new Error('Check system app failed(' + clientID + ')'));
        } else {
            return callback(null, (client.isSystem === 1));
        }
    });
};

exports.close = function (/*callback*/) {
    //d.close();
};

exports.addTempKey = function (uid, key, callback) {
    exports.findUserByUid(uid, function (err, user) {
        if (err) {
            callback(err);
        } else if (!user) {
            callback('unknown user uid: ' + uid);
        } else {
            dao.tempKey.upsertTempKey({keyId: shortid.generate(), userId: user.userId, key: key}, callback);
        }
    });
};

exports.findTempKey = function (field, callback) {
    dao.tempKey.$findOne(field, function (err, context) {
        callback(err, context.result());
    });
};

exports.removeTempKey = function (field, callback) {
    dao.tempKey.$remove(field, function (err, context) {
        callback(err, context.result());
    });
};

//==========================================================
// acldb using mysql
exports.createPolicy = function (uid, policy, token, callback, context) {
    async.waterfall([
        function (next) {
            var gid;
            var pid;
            var fsid;
            var prefix;
            var aclInfo;
            // check resource (fs, auth, app, acl, group)
            async.each(policy.resource, function (rsc, cb) {
                prefix = rsc.split(':')[0];
                if (!prefix) {
                    return callback(new ClientError('Service prefix of resource ' + rsc + ' is invalid.'));
                }

                if (prefix === 'fs') { // fs resource check
                    fsid = rsc.substr(3).split('/')[0];
                    authMgr.getFSInfo(fsid, token, function (err/*, info*/) {
                        if (err) {
                            return cb(err);
                        } else {
                            return cb();
                        }
                    });
                } else if (prefix === 'fssvc') { // TODO : fs service resource check
                    return cb();
                } else if (prefix === 'auth') { // TODO : auth resource check
                    return cb();
                } else if (prefix === 'app') { // TODO : app resource check
                    return cb();
                } else if (prefix === 'acl') { // acl resource check
                    pid = rsc.split(':')[1];
                    if (!pid) {
                        return callback(new ClientError('Invalid policy id'));
                    }

                    exports.isPolicyOwner(uid, pid, function (err, result) {
                        if (err) {
                            return callback(err);
                        } else if (result) {
                            return cb();
                        } else {
                            rsc = 'acl:' + pid;
                            aclInfo = {uid: uid, action: 'acl:createPolicy', rsc: rsc};
                            exports.checkAuthorize(aclInfo, function (err, result) {
                                if (err) {
                                    return callback(err);
                                } else if (result) {
                                    return cb();
                                } else {
                                    return callback(401, utils.fail('Not authorized.'));
                                }
                            });
                        }
                    }, context);
                } else if (prefix === 'group') { // group resource check
                    gid = rsc.split(':')[1];
                    if (!gid) {
                        return callback(new ClientError('Invalid group id'));
                    }
                    exports.isGroupOwner(uid, gid, function (err, result) {
                        var rsc;
                        var aclInfo;
                        if (err) {
                            return callback(err);
                        } else if (result) {
                            return cb();
                        } else {
                            rsc = 'group:' + gid;
                            aclInfo = {uid: uid, action: 'group:createGroup', rsc: rsc};
                            exports.checkAuthorize(aclInfo, function (err, result) {
                                if (err) {
                                    return callback(err);
                                } else if (result) {
                                    return cb();
                                } else {
                                    return callback(401, utils.fail('Not authorized.'));
                                }
                            });
                            return cb();
                        }
                    }, context);
                } else {
                    return cb(new ClientError('Unknown service prefix.'));
                }
            }, function (err) {
                if (err) {
                    return callback(err);
                } else {
                    return next();
                }
            });
        }, function (next) {
            var pid = shortid.generate();//cuid();

            if (!policy.hasOwnProperty('effect')) {
                policy.effect = 'allow';
            }

            exports.findUserByUid(uid, function (err, user) {
                if (err) {
                    logger.error('createPolicy error', err);
                    return next(new ServerError('Internal server error while creating policy'));
                } else if (!user) {
                    logger.error('createPolicy error: user not found: ' + uid);
                    return next(new ServerError('Internal server error while creating policy'));
                } else {
                    dao.policy.$save({pid: pid, name: policy.name, effect: policy.effect, ownerId: user.userId,
                        action: JSON.stringify(policy.action), resource: JSON.stringify(policy.resource)},
                        function (err) {
                            if (err) {
                                return next(new ServerError('Internal server error while creating policy'));
                            } else {
                                dao.policy.$findOne({pid: pid}, function (err, context) {
                                    var result = context.result();
                                    if (err) {
                                        return next(err);
                                    } else {
                                        result.action = JSON.parse(result.action);
                                        result.resource = JSON.parse(result.resource);
                                        return next(null, result);
                                    }
                                }, context);
                            }
                        },
                    context);
                }
            }, context);
        }
    ], callback);
};

exports.createPolicies = function (uid, policies, token, callback) {
    var results = [];
    db.transaction([
        function (context, next) {
            logger.info('[acl] createPolicies', policies);
            async.eachSeries(policies, function (policy, cb) {
                exports.createPolicy(uid, policy, token, function (err, result) {
                    if (err) {
                        logger.error('[acl] createPolicies error: ', err);
                        return cb(err);
                    } else {
                        results.push(result);
                        return cb();
                    }
                }, context);
            }, next);
        }
    ], function (err) {
        callback(err, results);
    });
};

exports.deletePolicy = function (pid, callback) {
    //var sql;
    var policy;
    var ids = null;

    logger.info('[acl] deletePolicy', pid);

    db.transaction([
        dao.policy.getUidsByPolicyId({pid: pid}),
        function (context, next) {
            ids = context.result();
            if (ids.length > 0) {
                dao.policy.deleteRelationWithUserByPolicyId({pid: pid}, next, context);
            } else {
                next();
            }
        },   // TODO rsccheck
        dao.policy.$findOne({pid: pid}),
        function (context, next) {
            policy = context.result();
            if (!policy) {
                return next(new ClientError(404, 'No such policy.'));
            } else {
                policy.resource = JSON.parse(policy.resource);
                dao.policy.$remove({pid: pid}, next, context);
            }
        }
    ], callback);
};

exports.updatePolicy = function (pid, fields, sessionID, callback) {
    //var policy;
    var ids = null;
    //var sql;

    var isUpdateNeed = false;
    var isNotiNeed = false;

    if (!fields) {
        return callback(null, null);
    }

    if (fields.hasOwnProperty('action')) {
        if (_.intersection(fields.action, ACTIONS_TO_NOTI).length > 0) {
            isNotiNeed = true;
        }

        fields.action = JSON.stringify(fields.action);
        isUpdateNeed = true;
    }

    if (fields.hasOwnProperty('resource')) {
        fields.resource = JSON.stringify(fields.resource);
        isUpdateNeed = true;
    }

    if (fields.hasOwnProperty('effect')) {
        isUpdateNeed = true;
    }

    db.transaction([
        dao.policy.$findOne({pid: pid}),
        function (context, next) {
            var policy = context.result();
            if (policy) {
                isNotiNeed = _.intersection(JSON.parse(policy.action), ACTIONS_TO_NOTI).length > 0;
                next();
            } else {
                next(new ClientError('Unknown policy id: ' + pid));
            }
        },
        dao.policy.getUidsByPolicyId({pid: pid}),
        function (context, next) {
            var relation = context.result();
            if (relation) {
                ids = relation;
            }
            next();
        },
        function (context, next) {
            if (!isUpdateNeed || !ids) {
                next();
            } else {
                async.each(ids, function (value, cb) {
                    exports.removePolicy({pid: pid, user: value.uid}, cb, context);
                }, function (err) {
                    return next(err);
                });
            }
        },
        dao.policy.$update({pid: pid, $set: fields}),
        function (context, next) {
            if (!isUpdateNeed || !ids) {
                next();
            }
            async.each(ids, function (value, cb) {
                exports.assignPolicy({pid: pid, user: value.uid}, cb, context);
            }, function (err) {
                return next(err);
            });
        }
    ], function (err) {
        if (err) {
            return callback(err);
        }
        dao.policy.$findOne({pid: pid}, function (err, context) {
            var policy = context.result();
            if (err) {
                callback(new ServerError(500, 'Server internal error.'));
            } else {
                if (policy) {
                    policy.action = JSON.parse(policy.action);
                    policy.resource = JSON.parse(policy.resource);

                    if (isNotiNeed) {
                        notifyTopics(policy, 'updatePolicy', sessionID);
                    }
                }
                callback(null, policy);
            }
        });
    });
};

// info:{pid, user, sessionID}
exports.assignPolicy = function (info, callback, context) {
    async.waterfall([
        function (next) {
            dao.policy.getRelation({pid: info.pid, uid: info.user}, function (err, context) {
                var relation = context.result();
                if (err) {
                    next(err);
                } else if (!relation || relation.length === 0) {
                    next();
                } else {
                    next('No need to add relation');
                }
            }, context);
        }, function (next) {
            dao.policy.addRelation({pid: info.pid, uid: info.user}, next, context);
        }, function (result, next) {
            dao.policy.$findOne({pid: info.pid}, function (err, context) {
                var policy = context.result();
                if (err) {
                    next(err);
                } else if (policy && info.sessionID) {
                    policy.resource = JSON.parse(policy.resource);
                    policy.action = JSON.parse(policy.action);
                    notifyTopics(policy, 'assignPolicy', info.sessionID);
                }
                //TODO rsccheck
                next();
            }, context);
        }
    ], function (err) {
        if (err && err !== 'No need to add relation') {
            callback(err);
        } else {
            callback();
        }
    });
};

exports.assignPolicies = function (info, callback) {
    var uidArr;
    var pidArr;
    if (info.user) {
        uidArr = info.user.split(';');
    }
    if (info.pid) {
        pidArr = info.pid.split(';');
    }
    db.transaction([
        function (context, next) {
            logger.info('[acl] assignPolicies', info);
            async.eachSeries(pidArr, function (pid, cb) {
                async.eachSeries(uidArr, function (user, cb2) {
                    exports.assignPolicy({
                        pid: pid,
                        user: user,
                        sessionID: info.sessionID
                    }, function (err) {
                        if (err) {
                            logger.error('[acl] assignPolicy failed for user: ' + user, err);
                            return cb2(new ServerError('[acl] assignPolicy failed for user: ' + user));
                        } else {
                            return cb2(null);
                        }
                    }, context);
                }, cb);
            }, next);
        }
    ], callback);
};

// info:{pid, user, sessionID}
exports.removePolicy = function (info, callback) {
    logger.info('[acl] removePolicy for ', info.pid, info.user);

    db.transaction([
        dao.policy.deleteRelation({pid: info.pid, uid: info.user}),
        dao.policy.$findOne({pid: info.pid}),
        function (context, next) {
            context.data('policy', context.result());
            // TODO caching
            next();
        },
        function (context, next) {
            var policy = context.data('policy');
            if (info.sessionID && policy) {
                policy.action = JSON.parse(policy.action);
                policy.resource = JSON.parse(policy.resource);
                notifyTopics(policy, 'removePolicy', info.sessionID);
            }
            next();
        }
    ], callback);
};

exports.getAssignedUser = function (pid, type, callback) {

    var queryFn = (type === 'u') ? dao.user.getAllUsersByPolicyId : dao.group.getAllGroupsByPolicyId;

    queryFn({pid: pid}, function (err, context) {
        var usersOrGroups = context.result();
        logger.info('getAssigned: ', type, pid, usersOrGroups);
        callback(err, usersOrGroups);
    });
};

exports.getAuthorizedUser = function (action, rsc, type, callback) {
    var index;
    var resourceRegex;
    var actionPrefix;
    var users = [];
    var actionSplited = action.split(':');
    var patterns = [rsc];
    actionPrefix = (actionSplited[1] !== '*') ? actionSplited[0] : undefined;
    while ((index = rsc.lastIndexOf('/')) > -1) {
        rsc = rsc.slice(0, index);
        patterns.push(rsc + '\\\\*');
    }
    resourceRegex = patterns.join('|');

    dao.policy.getPolicyIdsByActionAndResource({action: action, actionPrefix: actionPrefix,
        resourceRegex: resourceRegex}, function (err, context) {
        var pids = context.result();
        if (err) {
            return callback(err);
        }

        async.eachSeries(pids, function (value, cb) {
            exports.getAssignedUser(value.pid, type, function (err, results) {
                if (err) {
                    return cb(err);
                }

                users = users.concat(results);
                return cb();
            });
        }, function (err) {
            var ret = [];
            var i;
            if (err) {
                logger.info('[acl] getAuthorizedUser failed', err);
                return callback(err);
            }

            // filtering as unique value
            for (i = 0; i < users.length; i++) {
                if (ret.indexOf(users[i]) === -1) {
                    ret.push(users[i]);
                }
            }
            return callback(null, ret);
        });
    });

};

exports.getAuthorizedRsc = function (uid, action, callback) {
    var actionSplited = action.split(':');
    var actionPrefix = (actionSplited[1] !== '*') ? actionSplited[0] : undefined;

    logger.info('getAuthorizedRsc', uid, action);

    async.waterfall([
        function (next) {
            var subjectIds = [];
            dao.user.$findOne({uid: uid}, function (err, context) {
                var user = context.result();
                if (err) {
                    next(err);
                } else {
                    subjectIds.push(user.userId);
                    dao.group.getAllGroupIdByUserId({userId: user.userId}, function (err, context) {
                        var groups = context.result();
                        var groupIds;
                        if (err) {
                            next(err);
                        } else {
                            groupIds = groups.map(function (group) {
                                return group.groupId;
                            });
                            subjectIds = subjectIds.concat(groupIds);
                            next(null, subjectIds);
                        }
                    });
                }
            });
        }, function (subjectIds, next) {
            dao.policy.getResourcesByUidAndAction({subjectIds: subjectIds, action: action, actionPrefix: actionPrefix},
                function (err, context) {
                    var resources = context.result();
                    var result = [];
                    if (err) {
                        next(err);
                    } else {
                        _.forEach(resources, function (r) {
                            var resourceArr = JSON.parse(r.resource);
                            result = result.concat(resourceArr);
                        });
                        next(null, result);
                    }
                });
        }
    ], callback);

};

exports.getAssignedPolicy = function (id, callback) {
    logger.info('[acl] getAssignedPolicy', id);
    dao.policy.getPolicyByUid({uid: id}, function (err, context) {
        var result;
        var policies = context.result();
        logger.info('policies', policies);
        if (err) {
            callback(err);
        } else {
            result = policies.map(function (policy) {
                if (policy.hasOwnProperty('action')) {
                    policy.action = JSON.parse(policy.action);
                }
                if (policy.hasOwnProperty('resource')) {
                    policy.resource = JSON.parse(policy.resource);
                }
                return policy;
            });
            callback(null, result);
        }
    });
};

exports.getOwnedPolicy = function (id, callback) {
    logger.info('[acl] getOwnedPolicy', id);

    dao.policy.getPolicyByOwnerUid({uid: id}, function (err, context) {
        callback(err, context.result());
    });
};

exports.getPolicies = function (pidArr, callback) {

    dao.policy.getPolicyByPolicyIds({policyIds: pidArr}, function (err, context) {
        var policies = context.result();
        var result;
        if (err) {
            callback(err);
        } else {
            result = policies.map(function (policy) {
                if (policy.hasOwnProperty('action')) {
                    policy.action = JSON.parse(policy.action);
                }
                if (policy.hasOwnProperty('resource')) {
                    policy.resource = JSON.parse(policy.resource);
                }
                return policy;
            });
            callback(null, result);
        }
    });
};

//==========================================================
// groupdb using mysql
exports.createGroup = function (group, callback) {
    async.waterfall([
        function (next) {
            dao.group.getGroup(group, function (err, context) {
                var result = context.result();
                if (err) {
                    return next(err);
                }
                if (result.length > 0) {
                    return next(new ClientError('The group is already exist.'));
                } else {
                    return next(null);
                }
            });
        }, function (next) {
            createSubject('g', next);
        }, function (result, next) {
            group.groupId = result.subjectId;
            group.gid = result.seq;

            dao.group.addGroup(group, function (err) {
                if (err) {
                    return next(err);
                }
                dao.group.$findOne({groupId: group.groupId}, function (err, context) {
                    return next(err, context.result());
                });
            });
        }
    ], callback);
};

exports.deleteGroup = function (gid, callback) {
    var groupId;
    db.transaction([
        dao.group.$findOne({gid: gid}),
        function (context, next) {
            var group = context.result();
            if (group) {
                groupId = group.groupId;
                next();
            } else {
                next(new ClientError('Unkown group: ' + gid));
            }
        },
        function (context, next) {
            dao.group.deleteRelationWithPolicyByGroupId({groupId: groupId}, next, context);
        },
        function (context, next) {
            dao.group.deleteRelationWithUserByGroupId({groupId: groupId}, next, context);
        },
        function (context, next) {
            dao.group.deleteSubjectByGroupId({groupId: groupId}, next, context);
        },
        function (context, next) {
            dao.group.$remove({groupId: groupId}, next, context);
        }
    ], callback);

};

exports.addUsersToGroup = function (uidArr, gid, callback) {
    if (uidArr.length === 0) {
        return callback(null);
    }

    dao.group.$findOne({gid: gid}, function (err, context) {
        var group = context.result();
        if (err) {
            callback(err);
        } else if (group) {
            dao.group.addUsersToGroup({groupId: group.groupId, userIds: uidArr}, callback);
        } else {
            callback(new ClientError('Unknown group: ' + gid));
        }
    });
};

exports.removeUsersFromGroup = function (uidArr, gid, callback) {
    if (uidArr.length === 0) {
        return callback(true);
    }

    dao.group.$findOne({gid: gid}, function (err, context) {
        var group = context.result();
        if (err) {
            callback(err);
        } else if (group) {
            dao.group.removeUsersFromGroup({groupId: group.groupId, userIds: uidArr}, callback);
        } else {
            callback(new ClientError('Unknown group: ' + gid));
        }
    });
};

exports.getGroups = function (uid, callback) {
    dao.group.getAllGroupByOwnerUid({uid: uid}, function (err, context) {
        callback(err, context.result());
    });
};

exports.getAssignedGroups = function (uid, callback) {
    dao.group.getAllGroupByUid({uid: uid}, function (err, context) {
        callback(err, context.result());
    });
};

exports.getGroupMembers = function (gid, callback) {
    dao.user.getAllUserByGid({gid: gid}, function (err, context) {
        callback(err, context.result());
    });
};

exports.setGroupMembers = function (gid, uidArr, callback) {
    dao.group.$findOne({gid: gid}, function (err, context) {
        var group = context.result();
        if (err) {
            callback(err);
        } else if (group) {
            dao.group.deleteRelationWithUserByGroupId({groupId: group.groupId}, function (err) {
                if (err) {
                    callback(err);
                } else {
                    exports.addUsersToGroup(uidArr, gid, callback);
                }
            });
        } else {
            callback(new ClientError('Unknown group: ' + gid));
        }
    });
};

exports.getAllGroups = function (callback) {
    dao.group.$find({}, function (err, context) {
        callback(err, context.result());
    });
};

exports.UPDATABLE_GROUPINFO = ['name', 'userdata'];
exports.updateGroup = function (gid, groupInfo, callback) {
    db.transaction([
        dao.group.$findOne({gid: gid}),
        function (context, next) {
            var group = context.result();
            if (group) {
                if (groupInfo.hasOwnProperty('name')) {
                    dao.group.$findOne({name: groupInfo.name, ownerId: group.ownerId}, function (err, context) {
                        var result = context.result();
                        if (err) {
                            next(err);
                        } else if (result) {
                            next(new ClientError('The group name is already exist.'));
                        } else {
                            next();
                        }
                    }, context);
                }
            } else {
                next(new ClientError('Group not found'));
            }
        },
        dao.group.$update({gid: gid, $set: groupInfo})
    ], function (err) {
        if (err) {
            callback(err);
        }
        dao.group.$findOne({gid: gid}, function (err, context) {
            callback(err, context.result());
        });
    });
};

//==========================================================
// userdb using mysql

exports.findUserByUid = function (uid, callback, context) {
    dao.user.$findOne({uid: uid}, function (err, context) {
        if (err) {
            callback(err);
        } else {
            callback(null, context.result());
        }
    }, context);
};

exports.findUserByEmail = function (email, callback) {
    dao.user.$findOne({email: email}, function (err, context) {
        if (err) {
            callback(err);
        } else {
            callback(null, context.result());
        }
    });
};

exports.FINDABLE_USERINFO = ['userId', 'uid', 'email', 'name', 'company', 'telephone', 'department', 'url', 'location',
        'gravatar', 'activationKey', 'status', 'isAdmin'];
exports.findUser = function (info, callback, context) {
    var invalidate;
    // check integer fields validity
    ['uid', 'status', 'isAdmin'].every(function (field) {
        if (info[field] !== undefined && !integerPattern.test(info[field])) {
            invalidate = 'Invalid ' + field + ' format';
            return false;
        }
        return true;
    });
    if (invalidate) {
        return callback(new ClientError(400, invalidate));
    }
    info = _.pick(info, exports.FINDABLE_USERINFO);
    dao.user.findUsers(info, function (err, context) {
        callback(err, context.result());
    }, context);
};

// authinfo : {email, password, name, company, telephone, department, activationKey}
// email, password must be exist.
exports.findOrAddUser = function (authinfo, callback, context) {
    logger.info('findOrAddUser authinfo', authinfo);

    if (!config.services.auth.signup.allowSignup) {
        return callback('Signup is forbidden');
    }

    if (!authinfo.email) {
        return callback('Email is required');
    }

    if (!emailPattern.test(authinfo.email)) {
        return callback('Invalid email address format');
    }

    if (!authinfo.password) {
        return callback('Password is required');
    }

    dao.user.$findOne({email: authinfo.email}, function (err, context) {
        var user = context.result();
        if (err) {
            logger.info(err);
            callback(err);
        } else if (user) {
            if (user.status === STATUS.PENDING) {
                logger.info('found a PENDING user. update activation key', authinfo.email);
                exports.updateUserActivationKey(user.uid, authinfo.activationKey, callback, context);
            } else {
                logger.info('Found user', user);
                return callback('Email ' + authinfo.email + ' is already used.');
            }
        } else {
            logger.info('cannot find user. add it', authinfo.email);
            exports.addUser(authinfo, callback, context);
        }
    }, context);
};

exports.updateUserActivationKey = function (uid, activationKey, callback, context) {
    dao.user.$update({uid: uid, $set: {activationKey: activationKey}}, function (err) {
        if (err) {
            callback(err);
        } else {
            exports.findUserByUid(uid, function (err, user) {
                if (err) {
                    return callback(err);
                }
                if (!user) {
                    return callback(new ClientError('User not found'));
                }
                return callback(null, user);
            }, context);
        }
    }, context);
};

// authinfo : {email, password, name, company, telephone, department, activationKey}
exports.addUser = function (authinfo, callback) {
    createSubject('u', function (err, result) {
        if (err) {
            return callback(err);
        } else {
            authinfo.userId = result.subjectId;
            authinfo.passwordDigest = utils.getSha256Digest(authinfo.password);
            authinfo.uid = result.seq;
            authinfo.status = authinfo.status || STATUS.PENDING;
            authinfo.isAdmin = authinfo.isAdmin || 0;

            dao.user.addUser(authinfo, function (err) {
                if (err) {
                    return callback(err);
                }
                logger.debug('added user - now should find by uid ' + result.seq);
                return exports.findUserByUid(result.seq, callback);
            });
        }
    });
};

exports.UPDATABLE_USERINFO = ['password', 'name', 'company', 'telephone', 'department', 'url', 'location',
    'gravatar', 'status', 'isAdmin'];
exports.updateUser = function (field, fields, callback, context) {
    exports.findUser(field, function (err, users) {
        if (err) {
            return callback(err);
        }
        if (users.length === 0) {
            return callback(new ClientError('User not found'));
        }

        fields = _.pick(fields, exports.UPDATABLE_USERINFO);
        if (fields.hasOwnProperty('password')) {
            fields.password = utils.getSha256Digest(fields.password);
            //delete fields.password;

            if (users[0].status === STATUS.PASSWORDRESET) {
                fields.status = STATUS.APPROVED;
            }
        }
        logger.debug('updateUser', users[0].email, fields);

        dao.user.$update({uid: users[0].uid, $set: fields}, function (err) {
            if (err) { return callback(err); }

            exports.findUserByUid(users[0].uid, function (err, user) {
                if (err) {
                    return callback(err);
                }
                if (!user) {
                    return callback(new ClientError('User not found'));
                }
                return callback(null, user);
            }, context);
        }, context);
    }, context);
};

exports.getAllUsers = function (callback) {
    function date(timestamp) {
        return dateformat(new Date(timestamp), 'yyyy-mm-dd HH:MM:ss Z');
    }
    exports.getSessions(function (err, sessions) {
        var sessMap = {};
        if (err) { throw err; }
        sessions.forEach(function (session) {
            var sessObj = JSON.parse(session.session);
            if (sessObj.passport && sessObj.passport.user) {
                sessMap[sessObj.passport.user] = sessObj;
            }
        });

        dao.user.$find({}, function (err, context) {
            var users = context.result();
            var result = {};
            if (users.length <= 0) {
                return callback(null, []);
            }

            users.forEach(function (user) {
                logger.debug('session user: ', user, sessMap[user.email]);
                if (user.lastLoginTimestampUTC) {   // FIXME ???
                    user.lastLoginStr = date(user.lastLoginTimestampUTC);
                }
                result[user.email] = user;
            });
            return callback(err, result);
        });
    });
};

exports.deleteUser = function (uid, callback) {

    dao.user.$findOne({uid: uid}, function (err, context) {
        var user = context.result();
        var userId;

        if (err) {
            callback(err);
        } else if (!user) {
            callback(new ClientError('Unknown user: ' + uid));
        } else {
            userId = user.userId;

            db.transaction([
                dao.policy.deleteRelationByOwnerId({ownerId: userId}),
                dao.policy.deletePolicyByOwnerId({ownerId: userId}),
                dao.policy.deleteRelationWithUserBySubjectId({subjectId: userId}),
                dao.group.deleteRelationWithUserByOwnerId({ownerId: userId}),
                dao.group.deleteGroupByOwnerId({ownerId: userId}),
                dao.group.deleteRelationWithUserByUserId({userId: userId}),
                dao.token.$remove({userId: userId}),
                dao.tempKey.$remove({userId: userId}),
                dao.user.$remove({userId: userId})
                // TODO rsccheck
            ], callback);
        }
    });
};

exports.setLastLogin = function (uid, callback) {
    dao.user.$update({uid: uid, $set: {lastLoginTime: new Date()}}, callback);
};

// aclInfo : {uid:int, action:string, rsc:string}
exports.checkAuthorize = function (aclInfo, callback) {
    // if uid === owner then return true;
    var rscArr;
    var idArr = ['0', '1'];

    function makeRscArr(rsc) {
        var rscArr = [
            '["' + rsc + '"]',
            '["' + rsc + '/*"]',
            '["' + Path.dirname(rsc) + '/+"]'    // FIXME ??
        ];
        var res = rsc.split(':');
        var prefix = res[0];
        var str = res[1];
        var index;
        if (str === '*') {
            return rscArr;
        }

        while (true) {
            index = str.lastIndexOf('/');
            if (index === -1) {
                break;
            }

            str = str.slice(0, index);
            rscArr.push('["' + prefix + ':' + str + '/*"]');
        }
        rscArr.push('["' + prefix + ':*"]');
        return rscArr;
    }

    rscArr = makeRscArr(aclInfo.rsc);

    async.waterfall([
        function (next) {
            if (aclInfo.uid === 0) {
                next(null, 0);
            } else {
                dao.user.$findOne({uid: aclInfo.uid}, function (err, context) {
                    var user = context.result();
                    if (err) {
                        next(new ServerError(500, 'Server error while check authorization.'));
                    } else if (!user) {
                        next(new ClientError(400, 'Unknown User: ' + aclInfo.uid));
                    } else {
                        next(null, user.userId);
                    }
                });
            }
        },
        function (userId, next) {
            if (userId === 0) {
                next();
            } else {
                idArr.push(userId);
                dao.group.getAllGroupIdByUserId({userId: userId}, function (err, context) {
                    var groupIds = context.result();
                    if (err) {
                        next(new ServerError(500, 'Server error while check authorization.'));
                    } else {
                        idArr = idArr.concat(groupIds.map(function (group) {
                            return group.groupId;
                        }));
                        next();
                    }
                });
            }
        }, function (next) {
            var policy;
            var allowed = false;
            var daoRequest = {
                subjectIds : idArr,
                resources : rscArr
            };
            logger.debug('getPolicyBySubjectIdAndResources - policy dao request', daoRequest);
            dao.policy.getPolicyBySubjectIdsAndResources(daoRequest,
                function (err, context) {
                    var i;
                    var result = context.result();
                    if (err) {
                        next(new ServerError(500, 'Server error while check authorization.'));
                    } else {
                        logger.debug('getPolicyBySubjectIdAndResources - result = ', result);
                        for (i = 0; i < result.length; i++) {
                            policy = result[i];
                            if ((policy.action.indexOf(aclInfo.action) > -1) || (policy.action.indexOf('*') > -1)) {
                                if (policy.effect === 'deny') {
                                    logger.info('[acl] checkAuthorize find deny policy, so return 401');
                                    next(new ClientError(401, utils.fail('Not authorized.')));
                                    break;
                                } else {
                                    allowed = true;
                                }
                            }
                        }
                        if (allowed) {
                            return next();
                        } else {
                            return next(new ClientError(401, 'Not authorized.'));
                        }
                    }
                }
            );
        }
    ], function (err) {
        if (err) {
            logger.info('[acl] checkAuthorize denied for ', aclInfo);
            return callback(err);
        } else {
            logger.info('[acl] checkAuthorize allowed for ', aclInfo);
            return callback(null);
        }
    });
};

exports.createSQLTable = function (callback) {
    logger.info('[acl] createSQLTable called.');

    db.transaction([
        dao.system.createUserTable(),
        dao.system.createTempKeyTable(),
        dao.system.createGroupTable(),
        dao.system.createGroupUserTable(),
        dao.system.createSubjectTable(),
        dao.system.createPolicyTable(),
        dao.system.createPolicySubjectTable(),
        dao.system.createSequenceTable(),
        dao.system.createClientTable(),
        dao.system.createCodeTable(),
        dao.system.createTokenTable(),
        function (context, next) {
            dao.user.$findOne({userId: '0'}, function (err, context) {
                var system = context.result();
                if (err) {
                    next(err);
                } else if (!system) {
                    dao.system.addSystemUser({}, function (err) {
                        if (err) {
                            next(err);
                        } else {
                            dao.system.addSystemSubject({}, function (err) {
                                next(err);
                            }, context);
                        }
                    }, context);
                } else {
                    next();
                }
            }, context);
        }
    ], callback);
};

exports.createSystemFSPolicy = function (callback) {
    logger.info('[acl] createSystemFSPolicy called.');
    async.each(config.services.auth.systemFS, function (rsc, cb) {
        //TODO caching
        var pid = shortid.generate();
        var systemPolicy = {
            pid: pid,
            name: 'systemFs',
            ownerId: '0',
            resource: '["' + rsc + '"]',
            action: '["fs:*"]',
            effect: 'allow'
        };

        db.transaction([
            dao.policy.$findOne(systemPolicy),
            function (context, next) {
                var result = context.result();
                if (!result) {
                    dao.policy.$save(systemPolicy, function (err) {
                        if (err) {
                            next(err);
                        } else {
                            dao.policy.addRelationBySubjectId({pid: pid, subjectId: '0'}, next, context);
                        }
                    }, context);
                } else {
                    next();
                }
            }
        ], function (err) {
            logger.info('[acl] createSystemFSPolicy end.', err);
            return cb(err);
        });
    }, function (err) {
        logger.info('[acl] createSystemFSPolicy end.', err);
        return callback(err);
    });
};

exports.updatePolicyRsc = function (src, dst, callback) {
    dao.policy.updatePolicyResource({src: src, dest: dst}, callback);
    // TODO cache update
};

exports.isGroupOwner = function (uid, gid, callback, context) {
    dao.group.getOwnerUidByGid({gid: gid}, function (err, context) {
        var group = context.result();
        if (err) {
            callback(err);
        } else if (!group || group.length === 0) {
            callback(new ClientError('Unknown group: ' + gid));
        } else if (uid === group[0].ownerUid) {
            callback(null, true);
        } else {
            callback(null, false);
        }
    }, context);
};

exports.isGroupOwnerOrMember = function (uid, gid, callback) {
    exports.isGroupOwner(uid, gid, function (err, result) {
        if (err) {
            return callback(err);
        } else if (result) {
            return callback(null, true);
        } else {
            dao.group.countRelationWithUserByGidAndUid({gid: gid, uid: uid}, function (err, context) {
                var count = context.result();
                if (err) {
                    return callback(err);
                } else {
                    return callback(null, (count > 0));
                }
            });
        }
    });
};

exports.isPolicyOwner = function (uid, pid, callback, context) {
    dao.policy.getOwnerUidByPolicyId({pid: pid}, function (err, context) {
        var policy = context.result();
        if (err) {
            callback(err);
        } else if (!policy || policy.length === 0) {
            callback(new ClientError('Unknown policy: ' + pid));
        } else if (uid === policy[0].ownerUid) {
            callback(null, true);
        } else {
            callback(null, false);
        }
    }, context);
};

exports.isPoliciesOwner = function (uid, pidArr, callback) {
    async.eachSeries(pidArr, function (pid, cb) {
        exports.isPolicyOwner(uid, pid, function (err, result) {
            if (err) {
                return callback(err);
            } else if (result) {
                return cb(null);
            } else {
                return callback(null, false);
            }
        });
    }, function () {
        return callback(null, true);
    });
};

exports.signupUser = function (email, key, sendEmail, callback) {
    db.transaction([
        function (context, next) {
            var authinfo = {email: email, password: key, activationKey: key};
            exports.findOrAddUser(authinfo, function (err/*, result*/) {
                return next(err);
            }, context);
        },
        function (context, next) {
            var redirect = config.services.auth.signup.activatingURL + key;
            var emailBody = '<b>Welcome to Webida!!</b>' +
                'This is the sign up validation email to webida.org of ' + email + ',' +
                'Please click belows.<br><br>' +
                '<a href="' + redirect + '">' + redirect + '</a>';

            var mailOptions = {
                from: config.services.auth.signup.emailSender,
                to: email,
                subject: 'Email validation check for webida.org signup',
                html: emailBody
            };

            sendEmail(mailOptions, function (err/*, data*/) {
                if (err) {
                    return next(err);
                }
                return next();
            });
        }
    ], callback);
};

exports.signup2 = function (authInfoArr, callback) {
    db.transaction([
        function (context, next) {
            async.eachSeries(authInfoArr, function (authInfo, cb) {
                if (authInfo.admin) {
                    authInfo.status = exports.STATUS.PASSWORDRESET;
                }

                if (!authInfo.password) {
                    authInfo.password = authInfo.email;
                }

                exports.findOrAddUser(authInfo, function (err, result) {
                    if (err) {
                        return cb('Failed to signup2 ' + err);
                    }

                    exports.createDefaultPolicy(result, function (err) {
                        if (err) {
                            return cb('Failed to signup2. ' + err);
                        }
                        return cb();
                    }, context);
                }, context);
            }, next);
        }
    ], function (err) {
        callback(err);
    });
};

exports.activateAccount = function (password, activationKey, callback) {
    var user;
    if (password.length < 6) {
        return callback('password length must be longer than 5 chareacters.');
    }
    db.transaction([
        dao.user.$findOne({activationKey: activationKey}),
        function (context, next) {
            var passwordDigest;
            user = context.result();
            if (user) {
                passwordDigest = utils.getSha256Digest(password);
                dao.user.$update({userId: user.userId, $set: {password: passwordDigest, status: STATUS.APPROVED}},
                    function (err) {
                    if (err) {
                        next(new ServerError(503, 'Activating failed'));
                    } else {
                        user.status = STATUS.APPROVED;
                        next();
                    }
                }, context);
            } else {
                next('Unknown user activationKey: ' + activationKey);
            }
        },
        function (context, next) {
            exports.createDefaultPolicy(user, function (err) {
                next(err);
            }, context);
        }
    ], function (err) {
        if (err) {
            callback(err);
        } else {
            callback(null, user);
        }
    });
};

exports.createDefaultPolicy = function (user, callback, context) {
    var token;
    async.waterfall([
        function (next) {
            exports.getPersonalTokens(100000, function (err, result) {
                if (err) {
                    return next(err);
                }
                if (result.length === 0) {
                    return next(new ServerError(500, 'Creating default policy failed'));
                }
                token = result[0].data;
                return next(null);
            }, context);
        }, function (next) {
            var userId = (user.isAdmin === 1) ? '*' : user.userId;
            var defaultAuthPolicy = _.clone(config.services.auth.defaultAuthPolicy);
            defaultAuthPolicy.resource = defaultAuthPolicy.resource.map(function (rsc) {
                return _.template(rsc)({userId: userId});
            });
            exports.createPolicy(user.uid, defaultAuthPolicy, token, function (err, policy) {
                if (err) {
                    return next(new ServerError(500, 'Set default auth policy failed'));
                }
                return next(null, policy.pid);
            }, context);
        }, function (pid, next) {
            exports.assignPolicy({pid: pid, user: user.uid}, function (err) {
                if (err) {
                    console.error('Assign default auth policy failed', err);
                    return next(new ServerError(500, 'Assign default auth policy failed'));
                }
                return next(null);
            }, context);
        }, function (next) {
            exports.createPolicy(user.uid, config.services.auth.defaultAppPolicy, token, function (err, policy) {
                if (err) {
                    return next(new ServerError(500, 'Set default app policy failed'));
                }
                return next(null, policy.pid);
            }, context);
        }, function (pid, next) {
            exports.assignPolicy({pid: pid, user: user.uid}, function (err) {
                if (err) {
                    return next(new ServerError(500, 'Assign default app policy failed'));
                }
                return next(null);
            }, context);
        }, function (next) {
            exports.createPolicy(user.uid, config.services.auth.defaultFSSvcPolicy, token, function (err, policy) {
                if (err) {
                    return next(new ServerError(500, 'Set default fssvc policy failed'));
                }
                return next(null, policy.pid);
            }, context);
        }, function (pid, next) {
            exports.assignPolicy({pid: pid, user: user.uid}, function (err) {
                if (err) {
                    return next(new ServerError(500, 'Assign default fssvc policy failed'));
                }
                return next(null);
            }, context);
        }
    ], function (err) {
        return callback(err);
    });
};


text:
package com.halcyon;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import com.halcyon.API.KcoinService;
import com.halcyon.API.Urls;
import com.halcyon.model.request.TradeListRequest;
import com.halcyon.model.response.TradeListResponse;

import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.Response;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btn_post).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RestAdapter adapter = new RestAdapter.Builder().setEndpoint(Urls.BASE_URL).build();
                KcoinService kcoinService = adapter.create(KcoinService.class);
                kcoinService.tradeList(new TradeListRequest(), new Callback<TradeListResponse>() {
                    @Override
                    public void success(TradeListResponse tradeListResponse, Response response) {
                        Log.e("success", tradeListResponse.content.size() + "");
                    }

                    @Override
                    public void failure(RetrofitError error) {
                        Log.e("failure", error.getMessage() + "");
                    }
                });
            }
        });

        findViewById(R.id.btn_post2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
    }

}


text:
/*****************************************************************************/
/* CascPort.h                             Copyright (c) Ladislav Zezula 2014 */
/*---------------------------------------------------------------------------*/
/* Portability module for the CascLib library. Contains a wrapper symbols    */
/* to make the compilation under Linux work                                  */
/*---------------------------------------------------------------------------*/
/*   Date    Ver   Who  Comment                                              */
/* --------  ----  ---  -------                                              */
/* 29.04.14  1.00  Lad  Created                                              */
/*****************************************************************************/

#ifndef __CASCPORT_H__
#define __CASCPORT_H__

#ifndef __cplusplus
    #include <stdbool.h>
#endif

//-----------------------------------------------------------------------------
// Defines for Windows

#if !defined(CASCLIB_PLATFORM_DEFINED) && (defined(_WIN32) || defined(_WIN64))

  // Make sure that headers are only included once in newer SDKs
  #if defined (_MSC_VER) && (_MSC_VER >= 1020)
  #pragma once
  #endif

  // In MSVC 8.0, there are some functions declared as deprecated.
  #define _CRT_SECURE_NO_DEPRECATE
  #define _CRT_NON_CONFORMING_SWPRINTFS

  #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
  #endif

  // Suppress definitions of `min` and `max` macros by <windows.h>:
  #define NOMINMAX 1

  #include <tchar.h>
  #include <assert.h>
  #include <ctype.h>
  #include <io.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <direct.h>
  #include <malloc.h>
  #include <windows.h>
  #include <ws2tcpip.h>
  #include <strsafe.h>

  #define CASCLIB_PLATFORM_LITTLE_ENDIAN

  #pragma intrinsic(memset, memcmp, memcpy)     // Make these functions intrinsic (inline)

  #define URL_SEP_CHAR              '/'
  #define PATH_SEP_CHAR             '\\'
  #define PATH_SEP_STRING           "\\"

  #define CASCLIB_PLATFORM_WINDOWS
  #define CASCLIB_PLATFORM_DEFINED              // The platform is known now

#endif

#ifndef FIELD_OFFSET
#define FIELD_OFFSET(type, field)    ((LONG)(size_t)&(((type *)0)->field))
#endif

//-----------------------------------------------------------------------------
// Defines for Mac

#if !defined(CASCLIB_PLATFORM_DEFINED) && defined(__APPLE__)  // Mac BSD API

  // Macintosh
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/socket.h>
  #include <sys/mman.h>
  #include <fcntl.h>
  #include <dirent.h>
  #include <unistd.h>
  #include <stddef.h>
  #include <stdint.h>
  #include <stdlib.h>
  #include <stdio.h>
  #include <stdarg.h>
  #include <string.h>
  #include <ctype.h>
  #include <wchar.h>
  #include <cassert>
  #include <errno.h>
  #include <pthread.h>
  #include <netdb.h>

  // Support for PowerPC on Max OS X
  #if (__ppc__ == 1) || (__POWERPC__ == 1) || (_ARCH_PPC == 1)
    #include <stdint.h>
    #include <CoreFoundation/CFByteOrder.h>
  #endif

  #define    PKEXPORT

  #ifndef __SYS_ZLIB
    #define    __SYS_ZLIB
  #endif

  #ifndef __BIG_ENDIAN__
    #define CASCLIB_PLATFORM_LITTLE_ENDIAN
  #endif

  #define URL_SEP_CHAR              '/'
  #define PATH_SEP_CHAR             '/'
  #define PATH_SEP_STRING           "/"

  typedef int SOCKET;

  #define CASCLIB_PLATFORM_MAC
  #define CASCLIB_PLATFORM_DEFINED          // The platform is known now

#endif

//-----------------------------------------------------------------------------
// Assumption: we are not on Windows nor Macintosh, so this must be linux *grin*

#if !defined(CASCLIB_PLATFORM_DEFINED)
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/socket.h>
  #include <sys/mman.h>
  #include <fcntl.h>
  #include <dirent.h>
  #include <unistd.h>
  #include <stddef.h>
  #include <stdint.h>
  #include <stdlib.h>
  #include <stdio.h>
  #include <stdarg.h>
  #include <string.h>
  #include <ctype.h>
  #include <wchar.h>
  #include <assert.h>
  #include <errno.h>
  #include <pthread.h>
  #include <netdb.h>

  #define URL_SEP_CHAR              '/'
  #define PATH_SEP_CHAR             '/'
  #define PATH_SEP_STRING           "/"

  typedef int SOCKET;

  #define CASCLIB_PLATFORM_LITTLE_ENDIAN
  #define CASCLIB_PLATFORM_LINUX
  #define CASCLIB_PLATFORM_DEFINED

#endif

//-----------------------------------------------------------------------------
// Definition of Windows-specific types for non-Windows platforms

#ifndef CASCLIB_PLATFORM_WINDOWS

  // Typedefs for ANSI C
  typedef unsigned char  BYTE;
  typedef unsigned short USHORT;
  typedef int            LONG;
  typedef unsigned int   DWORD;
  typedef long long      LONGLONG;
  typedef signed long long LONGLONG;
  typedef signed long long *PLONGLONG;
  typedef unsigned long long ULONGLONG;
  typedef unsigned long long *PULONGLONG;
  typedef void         * HANDLE;
  typedef char           TCHAR;
  typedef unsigned int   LCID;
  typedef LONG         * PLONG;
  typedef DWORD        * PDWORD;
  typedef BYTE         * LPBYTE;
  typedef char         * LPSTR;
  typedef const char   * LPCSTR;
  typedef TCHAR        * LPTSTR;
  typedef const TCHAR  * LPCTSTR;

  #ifndef __LP64__
    #define _LZMA_UINT32_IS_ULONG
  #endif

  // Some Windows-specific defines
  #ifndef MAX_PATH
    #define MAX_PATH 1024
  #endif

  #define WINAPI

  #define FILE_BEGIN    SEEK_SET
  #define FILE_CURRENT  SEEK_CUR
  #define FILE_END      SEEK_END

  #define INVALID_HANDLE_VALUE ((HANDLE)-1)

  #define _T(x)     x
  #define _tcslen   strlen
  #define _tcscat   strcat
  #define _tcschr   strchr
  #define _tcsrchr  strrchr
  #define _tcsstr   strstr
  #define _tcsspn   strspn
  #define _tcsncmp  strncmp
  #define _tprintf  printf
  #define _tremove  remove
  #define _taccess  access
  #define _access   access

  #define _stricmp  strcasecmp
  #define _strnicmp strncasecmp
  #define _tcsicmp  strcasecmp
  #define _tcsnicmp strncasecmp

  #define closesocket close

#endif // !CASCLIB_PLATFORM_WINDOWS

// 64-bit calls are supplied by "normal" calls on Mac
#if defined(CASCLIB_PLATFORM_MAC)
  #define stat64  stat
  #define fstat64 fstat
  #define lseek64 lseek
  #define ftruncate64 ftruncate
  #define off64_t off_t
  #define O_LARGEFILE 0
#endif

// Platform-specific error codes for UNIX-based platforms
#if defined(CASCLIB_PLATFORM_MAC) || defined(CASCLIB_PLATFORM_LINUX)
  #define ERROR_SUCCESS                  0
  #define ERROR_FILE_NOT_FOUND           ENOENT
  #define ERROR_PATH_NOT_FOUND           ENOENT
  #define ERROR_ACCESS_DENIED            EPERM
  #define ERROR_INVALID_HANDLE           EBADF
  #define ERROR_NOT_ENOUGH_MEMORY        ENOMEM
  #define ERROR_NOT_SUPPORTED            ENOTSUP
  #define ERROR_INVALID_PARAMETER        EINVAL
  #define ERROR_DISK_FULL                ENOSPC
  #define ERROR_ALREADY_EXISTS           EEXIST
  #define ERROR_INSUFFICIENT_BUFFER      ENOBUFS
  #define ERROR_BAD_FORMAT               1000       // No such error code under Linux
  #define ERROR_NO_MORE_FILES            1001       // No such error code under Linux
  #define ERROR_HANDLE_EOF               1002       // No such error code under Linux
  #define ERROR_CAN_NOT_COMPLETE         1003       // No such error code under Linux
  #define ERROR_FILE_CORRUPT             1004       // No such error code under Linux
  #define ERROR_FILE_ENCRYPTED           1005       // Returned by encrypted stream when can't find file key
  #define ERROR_FILE_TOO_LARGE           1006       // No such error code under Linux
  #define ERROR_ARITHMETIC_OVERFLOW      1007       // The string value is too large to fit in the given type
  #define ERROR_NETWORK_NOT_AVAILABLE    1008       // Cannot connect to the internet
#endif

#ifndef ERROR_FILE_INCOMPLETE
#define ERROR_FILE_INCOMPLETE            1006       // The required file part is missing
#endif

#ifndef ERROR_FILE_OFFLINE
#define ERROR_FILE_OFFLINE               1007       // The file is not available in the local storage
#endif

#ifndef ERROR_BUFFER_OVERFLOW
#define ERROR_BUFFER_OVERFLOW            1008
#endif

#ifndef ERROR_CANCELLED
#define ERROR_CANCELLED                  1009
#endif

#ifndef ERROR_INDEX_PARSING_DONE
#define ERROR_INDEX_PARSING_DONE         1010
#endif

#ifndef ERROR_REPARSE_ROOT
#define ERROR_REPARSE_ROOT               1011
#endif

#ifndef _countof
#define _countof(x)   (sizeof(x) / sizeof(x[0]))
#endif

//-----------------------------------------------------------------------------
// Swapping functions

#ifdef CASCLIB_PLATFORM_LITTLE_ENDIAN
    #define    BSWAP_INT16_UNSIGNED(a)          (a)
    #define    BSWAP_INT16_SIGNED(a)            (a)
    #define    BSWAP_INT32_UNSIGNED(a)          (a)
    #define    BSWAP_INT32_SIGNED(a)            (a)
    #define    BSWAP_INT64_SIGNED(a)            (a)
    #define    BSWAP_INT64_UNSIGNED(a)          (a)
    #define    BSWAP_ARRAY16_UNSIGNED(a,b)      {}
    #define    BSWAP_ARRAY32_UNSIGNED(a,b)      {}
    #define    BSWAP_ARRAY64_UNSIGNED(a,b)      {}
#else

#ifdef __cplusplus
  extern "C" {
#endif
    int16_t  SwapInt16(uint16_t);
    uint16_t SwapUInt16(uint16_t);
    int32_t  SwapInt32(uint32_t);
    uint32_t SwapUInt32(uint32_t);
    int64_t  SwapInt64(uint64_t);
    uint64_t SwapUInt64(uint64_t);
    void ConvertUInt16Buffer(void * ptr, size_t length);
    void ConvertUInt32Buffer(void * ptr, size_t length);
    void ConvertUInt64Buffer(void * ptr, size_t length);
#ifdef __cplusplus
  }
#endif
    #define    BSWAP_INT16_SIGNED(a)            SwapInt16((a))
    #define    BSWAP_INT16_UNSIGNED(a)          SwapUInt16((a))
    #define    BSWAP_INT32_SIGNED(a)            SwapInt32((a))
    #define    BSWAP_INT32_UNSIGNED(a)          SwapUInt32((a))
    #define    BSWAP_INT64_SIGNED(a)            SwapInt64((a))
    #define    BSWAP_INT64_UNSIGNED(a)          SwapUInt64((a))
    #define    BSWAP_ARRAY16_UNSIGNED(a,b)      ConvertUInt16Buffer((a),(b))
    #define    BSWAP_ARRAY32_UNSIGNED(a,b)      ConvertUInt32Buffer((a),(b))
    #define    BSWAP_ARRAY64_UNSIGNED(a,b)      ConvertUInt64Buffer((a),(b))
#endif

//-----------------------------------------------------------------------------
// Interlocked operations

inline DWORD CascInterlockedIncrement(DWORD * PtrValue)
{
#ifdef CASCLIB_PLATFORM_WINDOWS
    return (DWORD)InterlockedIncrement((LONG *)(PtrValue));
#elif defined(__GNUC__)
    return __sync_add_and_fetch(PtrValue, 1);
#else
    #define INTERLOCKED_NOT_SUPPORTED
    return ++(*PtrValue);
#endif
}

inline DWORD CascInterlockedDecrement(DWORD * PtrValue)
{
#ifdef CASCLIB_PLATFORM_WINDOWS
    return (DWORD)InterlockedDecrement((LONG *)(PtrValue));
#elif defined(__GNUC__)
    return __sync_sub_and_fetch(PtrValue, 1);
#else
    return --(*PtrValue);
#endif
}

//-----------------------------------------------------------------------------
// Lock functions

#ifdef CASCLIB_PLATFORM_WINDOWS

typedef RTL_CRITICAL_SECTION CASC_LOCK;
#define CascInitLock(Lock)      InitializeCriticalSection(&Lock);
#define CascFreeLock(Lock)      DeleteCriticalSection(&Lock);
#define CascLock(Lock)          EnterCriticalSection(&Lock);
#define CascUnlock(Lock)        LeaveCriticalSection(&Lock);

#else

typedef pthread_mutex_t CASC_LOCK;
#define CascInitLock(Lock)      pthread_mutex_init(&Lock, NULL);
#define CascFreeLock(Lock)      pthread_mutex_destroy(&Lock);
#define CascLock(Lock)          pthread_mutex_lock(&Lock);
#define CascUnlock(Lock)        pthread_mutex_unlock(&Lock);

#endif

//-----------------------------------------------------------------------------
// Forbidden functions, do not use

#ifdef __CASCLIB_SELF__
#define strcpy  UNSAFE_DO_NOT_USE_STRCPY
#define strcat  UNSAFE_DO_NOT_USE_STRCAT
#define sprintf UNSAFE_DO_NOT_USE_SPRINTF
#endif

#endif // __CASCPORT_H__