Ein Projekt das es ermöglicht Beerpong über das Internet von zwei unabhängigen positionen aus zu spielen. Entstehung im Rahmen einer Praktikumsaufgabe im Fach Interaktion.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*!
  2. * media-typer
  3. * Copyright(c) 2014 Douglas Christopher Wilson
  4. * MIT Licensed
  5. */
  6. /**
  7. * RegExp to match *( ";" parameter ) in RFC 2616 sec 3.7
  8. *
  9. * parameter = token "=" ( token | quoted-string )
  10. * token = 1*<any CHAR except CTLs or separators>
  11. * separators = "(" | ")" | "<" | ">" | "@"
  12. * | "," | ";" | ":" | "\" | <">
  13. * | "/" | "[" | "]" | "?" | "="
  14. * | "{" | "}" | SP | HT
  15. * quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
  16. * qdtext = <any TEXT except <">>
  17. * quoted-pair = "\" CHAR
  18. * CHAR = <any US-ASCII character (octets 0 - 127)>
  19. * TEXT = <any OCTET except CTLs, but including LWS>
  20. * LWS = [CRLF] 1*( SP | HT )
  21. * CRLF = CR LF
  22. * CR = <US-ASCII CR, carriage return (13)>
  23. * LF = <US-ASCII LF, linefeed (10)>
  24. * SP = <US-ASCII SP, space (32)>
  25. * SHT = <US-ASCII HT, horizontal-tab (9)>
  26. * CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
  27. * OCTET = <any 8-bit sequence of data>
  28. */
  29. var paramRegExp = /; *([!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) *= *("(?:[ !\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u0020-\u007e])*"|[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+) */g;
  30. var textRegExp = /^[\u0020-\u007e\u0080-\u00ff]+$/
  31. var tokenRegExp = /^[!#$%&'\*\+\-\.0-9A-Z\^_`a-z\|~]+$/
  32. /**
  33. * RegExp to match quoted-pair in RFC 2616
  34. *
  35. * quoted-pair = "\" CHAR
  36. * CHAR = <any US-ASCII character (octets 0 - 127)>
  37. */
  38. var qescRegExp = /\\([\u0000-\u007f])/g;
  39. /**
  40. * RegExp to match chars that must be quoted-pair in RFC 2616
  41. */
  42. var quoteRegExp = /([\\"])/g;
  43. /**
  44. * RegExp to match type in RFC 6838
  45. *
  46. * type-name = restricted-name
  47. * subtype-name = restricted-name
  48. * restricted-name = restricted-name-first *126restricted-name-chars
  49. * restricted-name-first = ALPHA / DIGIT
  50. * restricted-name-chars = ALPHA / DIGIT / "!" / "#" /
  51. * "$" / "&" / "-" / "^" / "_"
  52. * restricted-name-chars =/ "." ; Characters before first dot always
  53. * ; specify a facet name
  54. * restricted-name-chars =/ "+" ; Characters after last plus always
  55. * ; specify a structured syntax suffix
  56. * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
  57. * DIGIT = %x30-39 ; 0-9
  58. */
  59. var subtypeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_.-]{0,126}$/
  60. var typeNameRegExp = /^[A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126}$/
  61. var typeRegExp = /^ *([A-Za-z0-9][A-Za-z0-9!#$&^_-]{0,126})\/([A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}) *$/;
  62. /**
  63. * Module exports.
  64. */
  65. exports.format = format
  66. exports.parse = parse
  67. /**
  68. * Format object to media type.
  69. *
  70. * @param {object} obj
  71. * @return {string}
  72. * @api public
  73. */
  74. function format(obj) {
  75. if (!obj || typeof obj !== 'object') {
  76. throw new TypeError('argument obj is required')
  77. }
  78. var parameters = obj.parameters
  79. var subtype = obj.subtype
  80. var suffix = obj.suffix
  81. var type = obj.type
  82. if (!type || !typeNameRegExp.test(type)) {
  83. throw new TypeError('invalid type')
  84. }
  85. if (!subtype || !subtypeNameRegExp.test(subtype)) {
  86. throw new TypeError('invalid subtype')
  87. }
  88. // format as type/subtype
  89. var string = type + '/' + subtype
  90. // append +suffix
  91. if (suffix) {
  92. if (!typeNameRegExp.test(suffix)) {
  93. throw new TypeError('invalid suffix')
  94. }
  95. string += '+' + suffix
  96. }
  97. // append parameters
  98. if (parameters && typeof parameters === 'object') {
  99. var param
  100. var params = Object.keys(parameters).sort()
  101. for (var i = 0; i < params.length; i++) {
  102. param = params[i]
  103. if (!tokenRegExp.test(param)) {
  104. throw new TypeError('invalid parameter name')
  105. }
  106. string += '; ' + param + '=' + qstring(parameters[param])
  107. }
  108. }
  109. return string
  110. }
  111. /**
  112. * Parse media type to object.
  113. *
  114. * @param {string|object} string
  115. * @return {Object}
  116. * @api public
  117. */
  118. function parse(string) {
  119. if (!string) {
  120. throw new TypeError('argument string is required')
  121. }
  122. // support req/res-like objects as argument
  123. if (typeof string === 'object') {
  124. string = getcontenttype(string)
  125. }
  126. if (typeof string !== 'string') {
  127. throw new TypeError('argument string is required to be a string')
  128. }
  129. var index = string.indexOf(';')
  130. var type = index !== -1
  131. ? string.substr(0, index)
  132. : string
  133. var key
  134. var match
  135. var obj = splitType(type)
  136. var params = {}
  137. var value
  138. paramRegExp.lastIndex = index
  139. while (match = paramRegExp.exec(string)) {
  140. if (match.index !== index) {
  141. throw new TypeError('invalid parameter format')
  142. }
  143. index += match[0].length
  144. key = match[1].toLowerCase()
  145. value = match[2]
  146. if (value[0] === '"') {
  147. // remove quotes and escapes
  148. value = value
  149. .substr(1, value.length - 2)
  150. .replace(qescRegExp, '$1')
  151. }
  152. params[key] = value
  153. }
  154. if (index !== -1 && index !== string.length) {
  155. throw new TypeError('invalid parameter format')
  156. }
  157. obj.parameters = params
  158. return obj
  159. }
  160. /**
  161. * Get content-type from req/res objects.
  162. *
  163. * @param {object}
  164. * @return {Object}
  165. * @api private
  166. */
  167. function getcontenttype(obj) {
  168. if (typeof obj.getHeader === 'function') {
  169. // res-like
  170. return obj.getHeader('content-type')
  171. }
  172. if (typeof obj.headers === 'object') {
  173. // req-like
  174. return obj.headers && obj.headers['content-type']
  175. }
  176. }
  177. /**
  178. * Quote a string if necessary.
  179. *
  180. * @param {string} val
  181. * @return {string}
  182. * @api private
  183. */
  184. function qstring(val) {
  185. var str = String(val)
  186. // no need to quote tokens
  187. if (tokenRegExp.test(str)) {
  188. return str
  189. }
  190. if (str.length > 0 && !textRegExp.test(str)) {
  191. throw new TypeError('invalid parameter value')
  192. }
  193. return '"' + str.replace(quoteRegExp, '\\$1') + '"'
  194. }
  195. /**
  196. * Simply "type/subtype+siffx" into parts.
  197. *
  198. * @param {string} string
  199. * @return {Object}
  200. * @api private
  201. */
  202. function splitType(string) {
  203. var match = typeRegExp.exec(string.toLowerCase())
  204. if (!match) {
  205. throw new TypeError('invalid media type')
  206. }
  207. var type = match[1]
  208. var subtype = match[2]
  209. var suffix
  210. // suffix after last +
  211. var index = subtype.lastIndexOf('+')
  212. if (index !== -1) {
  213. suffix = subtype.substr(index + 1)
  214. subtype = subtype.substr(0, index)
  215. }
  216. var obj = {
  217. type: type,
  218. subtype: subtype,
  219. suffix: suffix
  220. }
  221. return obj
  222. }