| 1 | /* |
| 2 | * Copyright (c) 2014-2015 Sylvain Peyrefitte |
| 3 | * |
| 4 | * This file is part of node-rdpjs. |
| 5 | * |
| 6 | * node-rdpjs is free software: you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation, either version 3 of the License, or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | */ |
| 19 | |
| 20 | var type = require('../../core').type; |
| 21 | var error = require('../../core').error; |
| 22 | |
| 23 | /** |
| 24 | * @param s {type.Stream} read value from stream |
| 25 | * @returns read length from per format |
| 26 | */ |
| 27 | function readLength(s) { |
| 28 | var byte = new type.UInt8().read(s).value; |
| 29 | var size = 0; |
| 30 | if(byte & 0x80) { |
| 31 | byte &= ~0x80; |
| 32 | size = byte << 8; |
| 33 | size += new type.UInt8().read(s).value; |
| 34 | } |
| 35 | else { |
| 36 | size = byte; |
| 37 | } |
| 38 | return size; |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * @param value {raw} value to convert to per format |
| 43 | * @returns type objects per encoding value |
| 44 | */ |
| 45 | function writeLength(value) { |
| 46 | if(value > 0x7f) { |
| 47 | return new type.UInt16Be(value | 0x8000); |
| 48 | } |
| 49 | else { |
| 50 | return new type.UInt8(value); |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | /** |
| 55 | * @param s {type.Stream} |
| 56 | * @returns {integer} choice decoding from per encoding |
| 57 | */ |
| 58 | function readChoice(s) { |
| 59 | return new type.UInt8().read(s).value; |
| 60 | } |
| 61 | |
| 62 | /** |
| 63 | * @param choice {integer} |
| 64 | * @returns {type.UInt8} choice per encoded |
| 65 | */ |
| 66 | function writeChoice(choice) { |
| 67 | return new type.UInt8(choice); |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * @param s {type.Stream} |
| 72 | * @returns {integer} number represent selection |
| 73 | */ |
| 74 | function readSelection(s) { |
| 75 | return new type.UInt8().read(s).value; |
| 76 | } |
| 77 | |
| 78 | /** |
| 79 | * @param selection {integer} |
| 80 | * @returns {type.UInt8} per encoded selection |
| 81 | */ |
| 82 | function writeSelection(selection) { |
| 83 | return new type.UInt8(selection); |
| 84 | } |
| 85 | |
| 86 | /** |
| 87 | * @param s {type.Stream} |
| 88 | * @returns {integer} number of sets |
| 89 | */ |
| 90 | function readNumberOfSet(s) { |
| 91 | return new type.UInt8().read(s).value; |
| 92 | } |
| 93 | |
| 94 | /** |
| 95 | * @param numberOfSet {integer} |
| 96 | * @returns {type.UInt8} per encoded nuimber of sets |
| 97 | */ |
| 98 | function writeNumberOfSet(numberOfSet) { |
| 99 | return new type.UInt8(numberOfSet); |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * @param s {type.Stream} |
| 104 | * @returns {integer} enumerates number |
| 105 | */ |
| 106 | function readEnumerates(s) { |
| 107 | return new type.UInt8().read(s).value; |
| 108 | } |
| 109 | |
| 110 | /** |
| 111 | * @param enumerate {integer} |
| 112 | * @returns {type.UInt8} per encoded enumerate |
| 113 | */ |
| 114 | function writeEnumerates(enumerate) { |
| 115 | return new type.UInt8(enumerate); |
| 116 | } |
| 117 | |
| 118 | /** |
| 119 | * @param s {type.Stream} |
| 120 | * @returns {integer} integer per decoded |
| 121 | */ |
| 122 | function readInteger(s) { |
| 123 | var result; |
| 124 | var size = readLength(s); |
| 125 | switch(size) { |
| 126 | case 1: |
| 127 | result = new type.UInt8(); |
| 128 | break; |
| 129 | case 2: |
| 130 | result = new type.UInt16Be(); |
| 131 | break; |
| 132 | case 4: |
| 133 | result = new type.UInt32Be(); |
| 134 | break; |
| 135 | default: |
| 136 | throw new error.UnexpectedFatalError('NODE_RDP_PROTOCOL_T125_PER_BAD_INTEGER_LENGTH'); |
| 137 | } |
| 138 | return result.read(s).value; |
| 139 | } |
| 140 | |
| 141 | /** |
| 142 | * @param value {integer} |
| 143 | * @returns {type.Component} per encoded integer |
| 144 | */ |
| 145 | function writeInteger(value) { |
| 146 | if(value <= 0xff) { |
| 147 | return new type.Component([writeLength(1), new type.UInt8(value)]); |
| 148 | } |
| 149 | else if(value < 0xffff) { |
| 150 | return new type.Component([writeLength(2), new type.UInt16Be(value)]); |
| 151 | } |
| 152 | else { |
| 153 | return new type.Component([writeLength(4), new type.UInt32Be(value)]); |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | /** |
| 158 | * @param s {type.Stream} |
| 159 | * @param minimum {integer} increment (default 0) |
| 160 | * @returns {integer} per decoded integer 16 bits |
| 161 | */ |
| 162 | function readInteger16(s, minimum) { |
| 163 | return new type.UInt16Be().read(s).value + (minimum || 0); |
| 164 | } |
| 165 | |
| 166 | /** |
| 167 | * @param value {integer} |
| 168 | * @param minimum {integer} decrement (default 0) |
| 169 | * @returns {type.UInt16Be} per encoded integer 16 bits |
| 170 | */ |
| 171 | function writeInteger16(value, minimum) { |
| 172 | return new type.UInt16Be(value - (minimum || 0)); |
| 173 | } |
| 174 | |
| 175 | /** |
| 176 | * Check object identifier |
| 177 | * @param s {type.Stream} |
| 178 | * @param oid {array} object identifier to check |
| 179 | */ |
| 180 | function readObjectIdentifier(s, oid) { |
| 181 | var size = readLength(s); |
| 182 | if(size !== 5) { |
| 183 | return false; |
| 184 | } |
| 185 | |
| 186 | var a_oid = [0, 0, 0, 0, 0, 0]; |
| 187 | var t12 = new type.UInt8().read(s).value; |
| 188 | a_oid[0] = t12 >> 4; |
| 189 | a_oid[1] = t12 & 0x0f; |
| 190 | a_oid[2] = new type.UInt8().read(s).value; |
| 191 | a_oid[3] = new type.UInt8().read(s).value; |
| 192 | a_oid[4] = new type.UInt8().read(s).value; |
| 193 | a_oid[5] = new type.UInt8().read(s).value; |
| 194 | |
| 195 | for(var i in oid) { |
| 196 | if(oid[i] !== a_oid[i]) return false; |
| 197 | } |
| 198 | |
| 199 | return true; |
| 200 | } |
| 201 | |
| 202 | /** |
| 203 | * @param oid {array} oid to write |
| 204 | * @returns {type.Component} per encoded object identifier |
| 205 | */ |
| 206 | function writeObjectIdentifier(oid) { |
| 207 | return new type.Component([new type.UInt8(5), new type.UInt8((oid[0] << 4) & (oid[1] & 0x0f)), new type.UInt8(oid[2]), new type.UInt8(oid[3]), new type.UInt8(oid[4]), new type.UInt8(oid[5])]); |
| 208 | } |
| 209 | |
| 210 | /** |
| 211 | * Read as padding... |
| 212 | * @param s {type.Stream} |
| 213 | * @param minValue |
| 214 | */ |
| 215 | function readNumericString(s, minValue) { |
| 216 | var length = readLength(s); |
| 217 | length = (length + minValue + 1) / 2; |
| 218 | s.readPadding(length); |
| 219 | } |
| 220 | |
| 221 | /** |
| 222 | * @param nStr {String} |
| 223 | * @param minValue {integer} |
| 224 | * @returns {type.Component} per encoded numeric string |
| 225 | */ |
| 226 | function writeNumericString(nStr, minValue) { |
| 227 | var length = nStr.length; |
| 228 | var mlength = minValue; |
| 229 | if(length - minValue >= 0) { |
| 230 | mlength = length - minValue; |
| 231 | } |
| 232 | |
| 233 | var result = []; |
| 234 | |
| 235 | for(var i = 0; i < length; i += 2) { |
| 236 | var c1 = nStr.charCodeAt(i); |
| 237 | var c2 = 0; |
| 238 | if(i + 1 < length) { |
| 239 | c2 = nStr.charCodeAt(i + 1); |
| 240 | } |
| 241 | else { |
| 242 | c2 = 0x30; |
| 243 | } |
| 244 | c1 = (c1 - 0x30) % 10; |
| 245 | c2 = (c2 - 0x30) % 10; |
| 246 | |
| 247 | result[result.length] = new type.UInt8((c1 << 4) | c2); |
| 248 | } |
| 249 | |
| 250 | return new type.Component([writeLength(mlength), new type.Component(result)]); |
| 251 | } |
| 252 | |
| 253 | /** |
| 254 | * @param s {type.Stream} |
| 255 | * @param length {integer} length of padding |
| 256 | */ |
| 257 | function readPadding(s, length) { |
| 258 | s.readPadding(length); |
| 259 | } |
| 260 | |
| 261 | /** |
| 262 | * @param length {integer} length of padding |
| 263 | * @returns {type.BinaryString} per encoded padding |
| 264 | */ |
| 265 | function writePadding(length) { |
| 266 | return new type.BinaryString(Buffer.from(Array(length + 1).join("\x00"))); |
| 267 | } |
| 268 | |
| 269 | /** |
| 270 | * @param s {type.Stream} |
| 271 | * @param octetStream {String} |
| 272 | * @param minValue {integer} default 0 |
| 273 | * @returns {Boolean} true if read octectStream is equal to octetStream |
| 274 | */ |
| 275 | function readOctetStream(s, octetStream, minValue) { |
| 276 | var size = readLength(s) + (minValue || 0); |
| 277 | if(size !== octetStream.length) { |
| 278 | return false; |
| 279 | } |
| 280 | for(var i = 0; i < size; i++) { |
| 281 | var c = new type.UInt8().read(s); |
| 282 | if(octetStream.charCodeAt(i) !== c.value) { |
| 283 | return false; |
| 284 | } |
| 285 | } |
| 286 | |
| 287 | return true; |
| 288 | } |
| 289 | |
| 290 | /** |
| 291 | * @param oStr {String} |
| 292 | * @param minValue {integer} default 0 |
| 293 | * @returns {type.Component} per encoded octet stream |
| 294 | */ |
| 295 | function writeOctetStream(oStr, minValue) { |
| 296 | minValue = minValue || 0; |
| 297 | var length = oStr.length; |
| 298 | var mlength = minValue; |
| 299 | |
| 300 | if(length - minValue >= 0) { |
| 301 | mlength = length - minValue; |
| 302 | } |
| 303 | |
| 304 | result = []; |
| 305 | for(var i = 0; i < length; i++) { |
| 306 | result[result.length] = new type.UInt8(oStr[i]); |
| 307 | } |
| 308 | |
| 309 | return new type.Component([writeLength(mlength), new type.Component(result)]); |
| 310 | } |
| 311 | |
| 312 | /** |
| 313 | * Module exports |
| 314 | */ |
| 315 | module.exports = { |
| 316 | readLength : readLength, |
| 317 | writeLength : writeLength, |
| 318 | readChoice : readChoice, |
| 319 | writeChoice : writeChoice, |
| 320 | readSelection : readSelection, |
| 321 | writeSelection : writeSelection, |
| 322 | readNumberOfSet : readNumberOfSet, |
| 323 | writeNumberOfSet : writeNumberOfSet, |
| 324 | readEnumerates : readEnumerates, |
| 325 | writeEnumerates : writeEnumerates, |
| 326 | readInteger : readInteger, |
| 327 | writeInteger : writeInteger, |
| 328 | readInteger16 : readInteger16, |
| 329 | writeInteger16 : writeInteger16, |
| 330 | readObjectIdentifier : readObjectIdentifier, |
| 331 | writeObjectIdentifier : writeObjectIdentifier, |
| 332 | readNumericString : readNumericString, |
| 333 | writeNumericString : writeNumericString, |
| 334 | readPadding : readPadding, |
| 335 | writePadding : writePadding, |
| 336 | readOctetStream : readOctetStream, |
| 337 | writeOctetStream : writeOctetStream |
| 338 | }; |