pax_global_header00006660000000000000000000000064124155247360014523gustar00rootroot0000000000000052 comment=704f6dc54fffdc0fa33aca13dbac8f575a06ab1b node-stringprep-0.6.2/000077500000000000000000000000001241552473600146505ustar00rootroot00000000000000node-stringprep-0.6.2/.gitignore000066400000000000000000000000721241552473600166370ustar00rootroot00000000000000.lock-wscript .DS_Store node_modules build *~ *.log .idea node-stringprep-0.6.2/.jshintrc000066400000000000000000000011741241552473600165000ustar00rootroot00000000000000{ "asi": true, "camelcase": true, "eqeqeq": true, "eqnull": true, "globalstrict": true, "immed": true, "indent": 4, "latedef": "nofunc", "laxcomma": true, "maxparams": 4, "maxdepth": 3, "maxstatements": 20, "maxcomplexity": 14, "maxlen": 120, "newcap": true, "noarg": true, "noempty": true, "nonew": true, "quotmark": "single", "undef": true, "unused": true, "strict": true, "trailing": true, "node": true, "predef": [ "define", "module", "require", "before", "beforeEach", "describe", "it", "after", "window" ] }node-stringprep-0.6.2/.travis.yml000066400000000000000000000006521241552473600167640ustar00rootroot00000000000000language: node_js node_js: - "0.8" - "0.10" - "0.11" before_install: - "sudo apt-get install libicu-dev" # Workaround for a permissions issue with Travis virtual machine images # that breaks Python's multiprocessing: # https://github.com/travis-ci/travis-cookbooks/issues/155 - sudo rm -rf /dev/shm - sudo ln -s /run/shm /dev/shm - npm i -g npm@1.X env: DEBUG=* before_script: - npm install -g grunt-cli node-stringprep-0.6.2/Gruntfile.js000066400000000000000000000013151241552473600171450ustar00rootroot00000000000000'use strict'; module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), jshint: { allFiles: ['Gruntfile.js', 'test/**/*.js', 'index.js'], options: { jshintrc: '.jshintrc', } }, mochacli: { all: ['test/**/*.js', 'index.js'], options: { reporter: 'spec', ui: 'tdd' } } }) // Load the plugins grunt.loadNpmTasks('grunt-contrib-jshint') grunt.loadNpmTasks('grunt-mocha-cli') // Configure tasks grunt.registerTask('default', ['test']) grunt.registerTask('test', ['mochacli', 'jshint']) } node-stringprep-0.6.2/LICENSE000066400000000000000000000020411241552473600156520ustar00rootroot00000000000000Copyright (c) 2010 Stephan Maka Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. node-stringprep-0.6.2/README.markdown000066400000000000000000000010731241552473600173520ustar00rootroot00000000000000# node-stringprep # [![Build Status](https://travis-ci.org/node-xmpp/node-stringprep.png)](https://travis-ci.org/node-xmpp/node-stringprep) [Flattr this!](https://flattr.com/thing/44598/node-stringprep) ## Manual Please see the `node-xmpp` manual for more information, http://node-xmpp.github.io/doc/nodestringprep.html. ## Running Tests ```npm test``` ## Purpose Exposes predefined Unicode normalization functions that are required by many protocols. This is just a binding to [ICU](http://icu-project.org/), which is [said to be fast.](http://ayena.de/node/74) node-stringprep-0.6.2/binding.gyp000066400000000000000000000026061241552473600170070ustar00rootroot00000000000000{ 'targets': [ { 'target_name': 'node_stringprep', 'cflags_cc!': [ '-fno-exceptions', '-fmax-errors=0' ], 'include_dirs': [ ' /dev/null || echo n)"!="n"', { 'sources': [ 'node-stringprep.cc' ], 'cflags!': [ '-fno-exceptions', '-fmax-errors=0', '`icu-config --cppflags`' ], 'libraries': [ '`icu-config --ldflags`' ], 'conditions': [ ['OS=="freebsd"', { 'include_dirs': [ '/usr/local/include' ], }], ['OS=="mac"', { 'include_dirs': [ '/opt/local/include', '/usr/local/include' ], 'xcode_settings': { 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES' } }] ] }] ] }] ] } ] } node-stringprep-0.6.2/index.js000066400000000000000000000056171241552473600163260ustar00rootroot00000000000000'use strict'; var log = require('debug')('node-stringprep') // from unicode/uidna.h var UIDNA_ALLOW_UNASSIGNED = 1 var UIDNA_USE_STD3_RULES = 2 try { var bindings = require('bindings')('node_stringprep.node') } catch (ex) { if (process.title !== 'browser') { console.log( 'Cannot load StringPrep-' + require('./package.json').version + ' bindings (using fallback). You may need to ' + '`npm install node-stringprep`' ) log(ex) } } var toUnicode = function(value, options) { options = options || {} try { return bindings.toUnicode(value, (options.allowUnassigned && UIDNA_ALLOW_UNASSIGNED) | 0) } catch (e) { return value } } var toASCII = function(value, options) { options = options || {} try { return bindings.toASCII(value, (options.allowUnassigned && UIDNA_ALLOW_UNASSIGNED) | (options.useSTD3Rules && UIDNA_USE_STD3_RULES)) } catch (e) { if (options.throwIfError) { throw e } else { return value } } } var StringPrep = function(operation) { this.operation = operation try { this.stringPrep = new bindings.StringPrep(this.operation) } catch (e) { this.stringPrep = null log('Operation does not exist', operation, e) } } StringPrep.prototype.UNKNOWN_PROFILE_TYPE = 'Unknown profile type' StringPrep.prototype.UNHANDLED_FALLBACK = 'Unhandled JS fallback' StringPrep.prototype.LIBICU_NOT_AVAILABLE = 'libicu unavailable' StringPrep.prototype.useJsFallbacks = true StringPrep.prototype.prepare = function(value) { this.value = value try { if (this.stringPrep) { return this.stringPrep.prepare(this.value) } } catch (e) {} if (false === this.useJsFallbacks) { throw new Error(this.LIBICU_NOT_AVAILABLE) } return this.jsFallback() } StringPrep.prototype.isNative = function() { return (null !== this.stringPrep) } StringPrep.prototype.jsFallback = function() { switch (this.operation) { case 'nameprep': case 'nodeprep': return this.value.toLowerCase() case 'resourceprep': return this.value case 'nfs4_cs_prep': case 'nfs4_cis_prep': case 'nfs4_mixed_prep prefix': case 'nfs4_mixed_prep suffix': case 'iscsi': case 'mib': case 'saslprep': case 'trace': case 'ldap': case 'ldapci': throw new Error(this.UNHANDLED_FALLBACK) default: throw new Error(this.UNKNOWN_PROFILE_TYPE) } } StringPrep.prototype.disableJsFallbacks = function() { this.useJsFallbacks = false } StringPrep.prototype.enableJsFallbacks = function() { this.useJsFallbacks = true } module.exports = { toUnicode: toUnicode, toASCII: toASCII, StringPrep: StringPrep } node-stringprep-0.6.2/node-stringprep.cc000066400000000000000000000170051241552473600203020ustar00rootroot00000000000000#include #include #include #include #include #include using namespace v8; using namespace node; /* supports return of just enum */ class UnknownProfileException : public std::exception { }; // protect constructor from GC static Persistent stringprep_constructor; class StringPrep : public ObjectWrap { public: static void Initialize(Handle target) { NanScope(); Local t = NanNew(New); NanAssignPersistent(stringprep_constructor, t); t->InstanceTemplate()->SetInternalFieldCount(1); NODE_SET_PROTOTYPE_METHOD(t, "prepare", Prepare); target->Set(NanNew("StringPrep"), t->GetFunction()); } bool good() const { return U_SUCCESS(error); } const char *errorName() const { return u_errorName(error); } protected: /*** Constructor ***/ static NAN_METHOD(New) { NanScope(); if (args.Length() >= 1 && args[0]->IsString()) { String::Utf8Value arg0(args[0]->ToString()); UStringPrepProfileType profileType; try { profileType = parseProfileType(arg0); } catch (UnknownProfileException &) { NanThrowTypeError("Unknown StringPrep profile"); NanReturnUndefined(); } StringPrep *self = new StringPrep(profileType); if (self->good()) { self->Wrap(args.This()); NanReturnValue(args.This()); } else { const char* err = self->errorName(); delete self; NanThrowError(err); NanReturnUndefined(); } } else { NanThrowTypeError("Bad argument."); NanReturnUndefined(); } } StringPrep(const UStringPrepProfileType profileType) : error(U_ZERO_ERROR) { profile = usprep_openByType(profileType, &error); } /*** Destructor ***/ ~StringPrep() { if (profile) usprep_close(profile); } /*** Prepare ***/ static NAN_METHOD(Prepare) { NanScope(); if (args.Length() >= 1 && args[0]->IsString()) { StringPrep *self = ObjectWrap::Unwrap(args.This()); String::Value arg0(args[0]->ToString()); NanReturnValue(self->prepare(arg0)); } else { NanThrowTypeError("Bad argument."); NanReturnUndefined(); } } Handle prepare(String::Value &str) { size_t destLen = str.length() + 1; UChar *dest = NULL; while(!dest) { error = U_ZERO_ERROR; dest = new UChar[destLen]; size_t w = usprep_prepare(profile, *str, str.length(), dest, destLen, USPREP_DEFAULT, NULL, &error); if (error == U_BUFFER_OVERFLOW_ERROR) { // retry with a dest buffer twice as large destLen *= 2; delete[] dest; dest = NULL; } else if (!good()) { // other error, just bail out delete[] dest; NanThrowError(errorName()); return NanUndefined(); } else destLen = w; } Local result = NanNew(dest, destLen); delete[] dest; return result; } private: UStringPrepProfile *profile; UErrorCode error; static enum UStringPrepProfileType parseProfileType(String::Utf8Value &profile) throw(UnknownProfileException) { if (strcasecmp(*profile, "nameprep") == 0) return USPREP_RFC3491_NAMEPREP; if (strcasecmp(*profile, "nfs4_cs_prep") == 0) return USPREP_RFC3530_NFS4_CS_PREP; if (strcasecmp(*profile, "nfs4_cs_prep") == 0) return USPREP_RFC3530_NFS4_CS_PREP_CI; if (strcasecmp(*profile, "nfs4_cis_prep") == 0) return USPREP_RFC3530_NFS4_CIS_PREP; if (strcasecmp(*profile, "nfs4_mixed_prep prefix") == 0) return USPREP_RFC3530_NFS4_MIXED_PREP_PREFIX; if (strcasecmp(*profile, "nfs4_mixed_prep suffix") == 0) return USPREP_RFC3530_NFS4_MIXED_PREP_SUFFIX; if (strcasecmp(*profile, "iscsi") == 0) return USPREP_RFC3722_ISCSI; if (strcasecmp(*profile, "nodeprep") == 0) return USPREP_RFC3920_NODEPREP; if (strcasecmp(*profile, "resourceprep") == 0) return USPREP_RFC3920_RESOURCEPREP; if (strcasecmp(*profile, "mib") == 0) return USPREP_RFC4011_MIB; if (strcasecmp(*profile, "saslprep") == 0) return USPREP_RFC4013_SASLPREP; if (strcasecmp(*profile, "trace") == 0) return USPREP_RFC4505_TRACE; if (strcasecmp(*profile, "ldap") == 0) return USPREP_RFC4518_LDAP; if (strcasecmp(*profile, "ldapci") == 0) return USPREP_RFC4518_LDAP_CI; throw UnknownProfileException(); } }; /*** IDN support ***/ NAN_METHOD(ToUnicode) { NanScope(); if (args.Length() >= 2 && args[0]->IsString() && args[1]->IsInt32()) { String::Value str(args[0]->ToString()); int32_t options = args[1]->ToInt32()->Value(); // ASCII encoding (xn--*--*) should be longer than Unicode size_t destLen = str.length() + 1; UChar *dest = NULL; while(!dest) { dest = new UChar[destLen]; UErrorCode error = U_ZERO_ERROR; size_t w = uidna_toUnicode(*str, str.length(), dest, destLen, options, NULL, &error); if (error == U_BUFFER_OVERFLOW_ERROR) { // retry with a dest buffer twice as large destLen *= 2; delete[] dest; dest = NULL; } else if (U_FAILURE(error)) { // other error, just bail out delete[] dest; NanThrowError(u_errorName(error)); NanReturnUndefined(); } else destLen = w; } Local result = NanNew(dest, destLen); delete[] dest; NanReturnValue(result); } else { NanThrowTypeError("Bad argument."); NanReturnUndefined(); } } NAN_METHOD(ToASCII) { NanScope(); if (args.Length() >= 2 && args[0]->IsString() && args[1]->IsInt32()) { String::Value str(args[0]->ToString()); int32_t options = args[1]->ToInt32()->Value(); // find out length first UErrorCode error = U_ZERO_ERROR; size_t strLen = str.length(); size_t destLen = uidna_toASCII(*str, strLen, NULL, 0, options, NULL, &error); UChar *dest = NULL; if (error == U_BUFFER_OVERFLOW_ERROR) { // now try with dest buffer error = U_ZERO_ERROR; dest = new UChar[destLen]; uidna_toASCII(*str, strLen, dest, destLen, options, NULL, &error); } if (U_FAILURE(error)) { // other error, just bail out delete[] dest; NanThrowError(u_errorName(error)); NanReturnUndefined(); } Local result = NanNew(dest, destLen); delete[] dest; NanReturnValue(result); } else { NanThrowTypeError("Bad argument."); NanReturnUndefined(); } } /*** Initialization ***/ extern "C" void init(Handle target) { NanScope(); StringPrep::Initialize(target); NODE_SET_METHOD(target, "toUnicode", ToUnicode); NODE_SET_METHOD(target, "toASCII", ToASCII); } NODE_MODULE(node_stringprep, init) node-stringprep-0.6.2/package.json000066400000000000000000000016621241552473600171430ustar00rootroot00000000000000{ "name": "node-stringprep", "version": "0.6.2", "main": "index.js", "description": "ICU StringPrep profiles", "keywords": [ "unicode", "stringprep", "icu" ], "scripts": { "test": "grunt test" }, "dependencies": { "nan": "~1.2.0", "bindings": "~1.1.1", "debug": "~2.0.0" }, "devDependencies": { "proxyquire": "~0.5.2", "grunt-mocha-cli": "~1.3.0", "grunt-contrib-jshint": "~0.7.2", "should": "~2.1.1", "grunt": "~0.4.2" }, "repository": { "type": "git", "path": "git://github.com/node-xmpp/node-stringprep.git" }, "homepage": "http://github.com/node-xmpp/node-stringprep", "bugs": "http://github.com/node-xmpp/node-stringprep/issues", "author": { "name": "Lloyd Watkin", "email": "lloyd@evilprofessor.co.uk", "web": "http://evilprofessor.co.uk" }, "licenses": [ { "type": "MIT" } ], "engines": { "node": ">=0.8" } } node-stringprep-0.6.2/test/000077500000000000000000000000001241552473600156275ustar00rootroot00000000000000node-stringprep-0.6.2/test/fallback.js000066400000000000000000000065011241552473600177260ustar00rootroot00000000000000'use strict'; var proxyquire = require('proxyquire') /* jshint -W030 */ describe('Should use JS fallbacks for StringPrep', function() { var StringPrep = proxyquire('../index', { 'bindings': null }).StringPrep it('Should throw on unknown icu-profile', function(done) { var prep = new StringPrep('cRaZYcASE') try { prep.prepare('UPPERCASE') done('Should have thrown error') } catch (e) { e.message.should.equal(prep.UNKNOWN_PROFILE_TYPE) done() } }) it('Should perform a \'nameprep\'', function(done) { var prep = new StringPrep('nameprep') prep.prepare('UPPERCASE').should.equal('uppercase') done() }) it('Should perform a \'nodeprep\'', function(done) { var prep = new StringPrep('nodeprep') prep.prepare('UPPERCASE').should.equal('uppercase') done() }) it('Should preform a \'resourceprep\'', function(done) { var prep = new StringPrep('resourceprep') prep.prepare('UPPERCASE').should.equal('UPPERCASE') done() }) it('Can\'t handle other profiles', function(done) { var unsupportedFallbackProfiles = [ 'nfs4_cs_prep', 'nfs4_cis_prep', 'nfs4_mixed_prep prefix', 'nfs4_mixed_prep suffix', 'iscsi', 'mib', 'saslprep', 'trace', 'ldap', 'ldapci' ] var isDone = false unsupportedFallbackProfiles.forEach(function(profile) { var prep = new StringPrep(profile) try { prep.prepare('UPPERCASE') isDone = true done('Should have thrown error') } catch (e) { e.message.should.equal(prep.UNHANDLED_FALLBACK) } }) if (false === isDone) done() }) }) describe('Can disable fallbacks', function() { var StringPrep = proxyquire('../index', { 'bindings': null }).StringPrep it('Should allow javascript fallbacks to be disabled', function(done) { var prep = new StringPrep('nameprep') try { prep.disableJsFallbacks() prep.prepare('UPPERCASE') done('Should have thrown exception') } catch (e) { e.message.should.equal(prep.LIBICU_NOT_AVAILABLE) done() } }) it('Should allow javascript fallbacks to be re-enabled', function(done) { var prep = new StringPrep('nameprep') try { prep.disableJsFallbacks() prep.prepare('UPPERCASE') done('Should have thrown exception') } catch (e) { e.message.should.equal(prep.LIBICU_NOT_AVAILABLE) prep.enableJsFallbacks() prep.prepare('UPPERCASE') done() } }) }) describe('\'isNative\' method test', function() { it('Reports true with native', function() { var StringPrep = require('../index').StringPrep var prep = new StringPrep('resourceprep') prep.isNative().should.be.true }) it('Reports false without native', function() { var StringPrep = proxyquire('../index', { 'bindings': null }).StringPrep var prep = new StringPrep('resourceprep') prep.isNative().should.be.false }) }) node-stringprep-0.6.2/test/leakcheck.js000066400000000000000000000004621241552473600201010ustar00rootroot00000000000000'use strict'; require('should') it('Should not leak', function(done) { var SP = require('../index') try { var p = new SP.StringPrep('nameprep') var result = p.prepare('A\u0308ffin') result.should.equal('äffin') done() } catch (e) { done(e) } }) node-stringprep-0.6.2/test/toascii.js000066400000000000000000000013741241552473600176250ustar00rootroot00000000000000'use strict'; require('should') it('Should convert to ASCII', function(done) { var SP = require('../index') var result = SP.toASCII('i\u2665u') result.should.equal('xn--iu-t0x') done() }) it('Should throw on error', function(done) { var SP = require('../index') SP.toASCII.bind(SP, '\ud83d\ude03', { throwIfError: true }).should.throw() done() }) it('Should convert unassigned code point', function(done) { var SP = require('../index') var result = SP.toASCII('\ud83d\ude03', { allowUnassigned : true }) result.should.equal('xn--h28h') done() }) it('Should error on non-STD3 char', function(done) { var SP = require('../index') SP.toASCII.bind(SP, 'abc#def', { throwIfError: true, useSTD3Rules: true }).should.throw() done() })node-stringprep-0.6.2/test/tounicode.js000066400000000000000000000006441241552473600201620ustar00rootroot00000000000000'use strict'; require('should') it('Should convert to Unicode', function(done) { var SP = require('../index') var result = SP.toUnicode('xn--iu-t0x') result.should.equal('i\u2665u') done() }) it('Should convert unassigned code point', function(done) { var SP = require('../index') var result = SP.toUnicode('xn--h28h', { allowUnassigned : true }) result.should.equal('\ud83d\ude03') done() })