Skip to content

Instantly share code, notes, and snippets.

@tim-smart
Created July 10, 2012 10:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tim-smart/3082573 to your computer and use it in GitHub Desktop.
Save tim-smart/3082573 to your computer and use it in GitHub Desktop.
// The MIT License
//
// Copyright (c) 2012 Tim Smart
//
// 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.
var uuid = require('node-uuid').v4
var hash = require('crypto').createHash
/**
* Parse a comma seperated list header
*
* @param {String} header
* @return {Object}
*/
function parseListHeader (header) {
var char = ''
var buf = []
var s = {}
var out = {}
for (var i = 0, il = header.length; i < il; i++) {
char = header[i]
if (!s.gotval) {
buf.push(char)
}
if (!s.gotkey && '=' === char) {
buf.pop()
s.gotkey = buf.join('').trim()
buf = []
} else if (s.gotkey) {
if (!s.gotdelim && buf.length === 1 && ('"' === char || "'" === char)) {
s.gotdelim = char
} else if (!s.gotdelim && ',' === char) {
buf.pop()
out[s.gotkey] = buf.join('')
buf = []
s = {}
} else if (s.gotdelim) {
if ('\\' === char && s.gotdelim === header[i + 1]) {
buf.pop()
if ("'" === s.gotdelim) {
buf.push('"')
} else {
buf.push('"')
}
;++i
} else if (s.gotdelim === char) {
if ("'" === char) {
buf.pop()
buf.push('"')
}
out[s.gotkey] = JSON.parse(buf.join(''))
buf = []
s.gotval = true
} else if (s.gotval && ',' === char) {
s = {}
}
}
}
}
return out
}
/**
* Stringify a object into a list header
*
* @param {Object} obj
* @return {String}
*/
function stringifyListHeader (obj) {
var keys = Object.keys(obj)
var key = ''
var buf = []
for (var i = 0, il = keys.length; i < il; i++) {
key = keys[i]
buf.push(
[ key
, JSON.stringify(obj[key])
]
.join('=')
)
}
return buf.join(', ')
}
var nccount = 0
// Export
exports.createHeader =
function createHeader (uri, header, username, password) {
var details = parseListHeader(header.slice(7)) // Remove 'Digest '
if (!details) return null
;++nccount
var cnonce = uuid().replace(/-/g, '')
var digest =
{ username : username
, realm : details.realm
, opaque : details.opaque
, nonce : details.nonce
, cnonce : cnonce
, nc : nccount
, uri : uri
, qop : 'auth'
}
var ha1 = hash('md5')
.update(
[ digest.username
, digest.realm
, password
]
.join(':')
)
.digest('hex')
var ha2 = hash('md5')
.update(
[ 'GET'
, digest.uri
]
.join(':')
)
.digest('hex')
digest.response = hash('md5')
.update(
[ ha1
, digest.nonce
, digest.nc
, digest.cnonce
, 'auth'
, ha2
]
.join(':')
)
.digest('hex')
return 'Digest ' + stringifyListHeader(digest)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment