| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * @fileoverview | |
| 7 * Module to format IQ messages so they can be displayed in the debug log. | |
| 8 */ | |
| 9 | |
| 10 'use strict'; | |
| 11 | |
| 12 /** @suppress {duplicate} */ | |
| 13 var remoting = remoting || {}; | |
| 14 | |
| 15 /** | |
| 16 * @constructor | |
| 17 * @param {string} clientJid | |
| 18 * @param {string} hostJid | |
| 19 */ | |
| 20 remoting.FormatIq = function(clientJid, hostJid) { | |
| 21 /** @private */ | |
| 22 this.clientJid_ = clientJid; | |
| 23 /** @private */ | |
| 24 this.hostJid_ = hostJid; | |
| 25 }; | |
| 26 | |
| 27 /** | |
| 28 * Verify that the only attributes on the given |node| are those specified | |
| 29 * in the |attrs| string. | |
| 30 * | |
| 31 * @param {Node} node The node to verify. | |
| 32 * @param {string} validAttrs Comma-separated list of valid attributes. | |
| 33 * | |
| 34 * @return {boolean} True if the node contains only valid attributes. | |
| 35 */ | |
| 36 remoting.FormatIq.prototype.verifyAttributes = function(node, validAttrs) { | |
| 37 var attrs = ',' + validAttrs + ','; | |
| 38 var len = node.attributes.length; | |
| 39 for (var i = 0; i < len; i++) { | |
| 40 /** @type {Node} */ | |
| 41 var attrNode = node.attributes[i]; | |
| 42 var attr = attrNode.nodeName; | |
| 43 if (attrs.indexOf(',' + attr + ',') == -1) { | |
| 44 return false; | |
| 45 } | |
| 46 } | |
| 47 return true; | |
| 48 }; | |
| 49 | |
| 50 /** | |
| 51 * Calculate the 'pretty' version of data from the |server| node. | |
| 52 * | |
| 53 * @param {Node} server Xml node with server info. | |
| 54 * | |
| 55 * @return {?string} Formatted server string. Null if error. | |
| 56 */ | |
| 57 remoting.FormatIq.prototype.calcServerString = function(server) { | |
| 58 if (!this.verifyAttributes(server, 'host,udp,tcp,tcpssl')) { | |
| 59 return null; | |
| 60 } | |
| 61 var host = server.getAttribute('host'); | |
| 62 var udp = server.getAttribute('udp'); | |
| 63 var tcp = server.getAttribute('tcp'); | |
| 64 var tcpssl = server.getAttribute('tcpssl'); | |
| 65 | |
| 66 var str = "'" + host + "'"; | |
| 67 if (udp) | |
| 68 str += ' udp:' + udp; | |
| 69 if (tcp) | |
| 70 str += ' tcp:' + tcp; | |
| 71 if (tcpssl) | |
| 72 str += ' tcpssl:' + tcpssl; | |
| 73 | |
| 74 str += '; '; | |
| 75 return str; | |
| 76 }; | |
| 77 | |
| 78 /** | |
| 79 * Calc the 'pretty' version of channel data. | |
| 80 * | |
| 81 * @param {Node} channel Xml node with channel info. | |
| 82 * | |
| 83 * @return {?string} Formatted channel string. Null if error. | |
| 84 */ | |
| 85 remoting.FormatIq.prototype.calcChannelString = function(channel) { | |
| 86 var name = channel.nodeName; | |
| 87 if (!this.verifyAttributes(channel, 'transport,version,codec')) { | |
| 88 return null; | |
| 89 } | |
| 90 var transport = channel.getAttribute('transport'); | |
| 91 var version = channel.getAttribute('version'); | |
| 92 | |
| 93 var str = name + ' ' + transport + ' v' + version; | |
| 94 if (name == 'video') { | |
| 95 str += ' codec=' + channel.getAttribute('codec'); | |
| 96 } | |
| 97 str += '; '; | |
| 98 return str; | |
| 99 }; | |
| 100 | |
| 101 /** | |
| 102 * Pretty print the jingleinfo from the given Xml node. | |
| 103 * | |
| 104 * @param {Node} query Xml query node with jingleinfo in the child nodes. | |
| 105 * | |
| 106 * @return {?string} Pretty version of jingleinfo. Null if error. | |
| 107 */ | |
| 108 remoting.FormatIq.prototype.prettyJingleinfo = function(query) { | |
| 109 var nodes = query.childNodes; | |
| 110 var stun_servers = ''; | |
| 111 var result = ''; | |
| 112 for (var i = 0; i < nodes.length; i++) { | |
| 113 /** @type {Node} */ | |
| 114 var node = nodes[i]; | |
| 115 var name = node.nodeName; | |
| 116 if (name == 'stun') { | |
| 117 var sserver = ''; | |
| 118 var stun_nodes = node.childNodes; | |
| 119 for(var s = 0; s < stun_nodes.length; s++) { | |
| 120 /** @type {Node} */ | |
| 121 var stun_node = stun_nodes[s]; | |
| 122 var sname = stun_node.nodeName; | |
| 123 if (sname == 'server') { | |
| 124 var stun_str = this.calcServerString(stun_node); | |
| 125 if (!stun_str) { | |
| 126 return null; | |
| 127 } | |
| 128 sserver += stun_str; | |
| 129 } | |
| 130 } | |
| 131 result += '\n stun ' + sserver; | |
| 132 } else if (name == 'relay') { | |
| 133 var token = ''; | |
| 134 var rserver = ''; | |
| 135 var relay_nodes = node.childNodes; | |
| 136 for(var r = 0; r < relay_nodes.length; r++) { | |
| 137 /** @type {Node} */ | |
| 138 var relay_node = relay_nodes[r]; | |
| 139 var rname = relay_node.nodeName; | |
| 140 if (rname == 'token') { | |
| 141 token = token + relay_node.textContent; | |
| 142 } | |
| 143 if (rname == 'server') { | |
| 144 var relay_str = this.calcServerString(relay_node); | |
| 145 if (!relay_str) { | |
| 146 return null; | |
| 147 } | |
| 148 rserver += relay_str; | |
| 149 } | |
| 150 } | |
| 151 result += '\n relay ' + rserver + ' token: ' + token; | |
| 152 } else { | |
| 153 return null; | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 return result; | |
| 158 }; | |
| 159 | |
| 160 /** | |
| 161 * Pretty print the session-initiate or session-accept info from the given | |
| 162 * Xml node. | |
| 163 * | |
| 164 * @param {Node} jingle Xml node with jingle session-initiate or session-accept | |
| 165 * info contained in child nodes. | |
| 166 * | |
| 167 * @return {?string} Pretty version of jingle stanza. Null if error. | |
| 168 */ | |
| 169 remoting.FormatIq.prototype.prettySessionInitiateAccept = function(jingle) { | |
| 170 if (jingle.childNodes.length != 1) { | |
| 171 return null; | |
| 172 } | |
| 173 var content = jingle.firstChild; | |
| 174 if (content.nodeName != 'content') { | |
| 175 return null; | |
| 176 } | |
| 177 var content_children = content.childNodes; | |
| 178 var result = ''; | |
| 179 for (var c = 0; c < content_children.length; c++) { | |
| 180 /** @type {Node} */ | |
| 181 var content_child = content_children[c]; | |
| 182 var cname = content_child.nodeName; | |
| 183 if (cname == 'description') { | |
| 184 var channels = ''; | |
| 185 var resolution = ''; | |
| 186 var auth = ''; | |
| 187 var desc_children = content_child.childNodes; | |
| 188 for (var d = 0; d < desc_children.length; d++) { | |
| 189 /** @type {Node} */ | |
| 190 var desc = desc_children[d]; | |
| 191 var dname = desc.nodeName; | |
| 192 if (dname == 'control' || dname == 'event' || dname == 'video') { | |
| 193 var channel_str = this.calcChannelString(desc); | |
| 194 if (!channel_str) { | |
| 195 return null; | |
| 196 } | |
| 197 channels += channel_str; | |
| 198 } else if (dname == 'initial-resolution') { | |
| 199 resolution = desc.getAttribute('width') + 'x' + | |
| 200 desc.getAttribute('height'); | |
| 201 } else if (dname == 'authentication') { | |
| 202 var auth_children = desc.childNodes; | |
| 203 for (var a = 0; a < auth_children.length; a++) { | |
| 204 /** @type {Node} */ | |
| 205 var auth_info = auth_children[a]; | |
| 206 if (auth_info.nodeName == 'auth-token') { | |
| 207 auth = auth + ' (auth-token) ' + auth_info.textContent; | |
| 208 } else if (auth_info.nodeName == 'certificate') { | |
| 209 auth = auth + ' (certificate) ' + auth_info.textContent; | |
| 210 } else if (auth_info.nodeName == 'master-key') { | |
| 211 auth = auth + ' (master-key) ' + auth_info.textContent; | |
| 212 } else { | |
| 213 return null; | |
| 214 } | |
| 215 } | |
| 216 } else { | |
| 217 return null; | |
| 218 } | |
| 219 } | |
| 220 result += '\n channels: ' + channels; | |
| 221 result += '\n auth: ' + auth; | |
| 222 result += '\n initial resolution: ' + resolution; | |
| 223 } else if (cname == 'transport') { | |
| 224 // The 'transport' node is currently empty. | |
| 225 var transport_children = content_child.childNodes; | |
| 226 if (transport_children.length != 0) { | |
| 227 return null; | |
| 228 } | |
| 229 } else { | |
| 230 return null; | |
| 231 } | |
| 232 } | |
| 233 return result; | |
| 234 }; | |
| 235 | |
| 236 /** | |
| 237 * Pretty print the session-terminate info from the given Xml node. | |
| 238 * | |
| 239 * @param {Node} jingle Xml node with jingle session-terminate info contained in | |
| 240 * child nodes. | |
| 241 * | |
| 242 * @return {?string} Pretty version of jingle session-terminate stanza. Null if | |
| 243 * error. | |
| 244 */ | |
| 245 remoting.FormatIq.prototype.prettySessionTerminate = function(jingle) { | |
| 246 if (jingle.childNodes.length != 1) { | |
| 247 return null; | |
| 248 } | |
| 249 var reason = jingle.firstChild; | |
| 250 if (reason.nodeName != 'reason' || reason.childNodes.length != 1) { | |
| 251 return null; | |
| 252 } | |
| 253 var info = reason.firstChild; | |
| 254 if (info.nodeName == 'success' || info.nodeName == 'general-error') { | |
| 255 return '\n reason=' + info.nodeName; | |
| 256 } | |
| 257 return null; | |
| 258 }; | |
| 259 | |
| 260 /** | |
| 261 * Pretty print the transport-info info from the given Xml node. | |
| 262 * | |
| 263 * @param {Node} jingle Xml node with jingle transport info contained in child | |
| 264 * nodes. | |
| 265 * | |
| 266 * @return {?string} Pretty version of jingle transport-info stanza. Null if | |
| 267 * error. | |
| 268 */ | |
| 269 remoting.FormatIq.prototype.prettyTransportInfo = function(jingle) { | |
| 270 if (jingle.childNodes.length != 1) { | |
| 271 return null; | |
| 272 } | |
| 273 var content = jingle.firstChild; | |
| 274 if (content.nodeName != 'content') { | |
| 275 return null; | |
| 276 } | |
| 277 var transport = content.firstChild; | |
| 278 if (transport.nodeName != 'transport') { | |
| 279 return null; | |
| 280 } | |
| 281 var transport_children = transport.childNodes; | |
| 282 var result = ''; | |
| 283 for (var t = 0; t < transport_children.length; t++) { | |
| 284 /** @type {Node} */ | |
| 285 var candidate = transport_children[t]; | |
| 286 if (candidate.nodeName != 'candidate') { | |
| 287 return null; | |
| 288 } | |
| 289 if (!this.verifyAttributes(candidate, 'name,address,port,preference,' + | |
| 290 'username,protocol,generation,password,type,' + | |
| 291 'network')) { | |
| 292 return null; | |
| 293 } | |
| 294 var name = candidate.getAttribute('name'); | |
| 295 var address = candidate.getAttribute('address'); | |
| 296 var port = candidate.getAttribute('port'); | |
| 297 var pref = candidate.getAttribute('preference'); | |
| 298 var username = candidate.getAttribute('username'); | |
| 299 var protocol = candidate.getAttribute('protocol'); | |
| 300 var generation = candidate.getAttribute('generation'); | |
| 301 var password = candidate.getAttribute('password'); | |
| 302 var type = candidate.getAttribute('type'); | |
| 303 var network = candidate.getAttribute('network'); | |
| 304 | |
| 305 var info = name + ': ' + address + ':' + port + ' ' + protocol + | |
| 306 ' name:' + username + ' pwd:' + password + | |
| 307 ' pref:' + pref + | |
| 308 ' ' + type; | |
| 309 if (network) { | |
| 310 info = info + " network:'" + network + "'"; | |
| 311 } | |
| 312 result += '\n ' + info; | |
| 313 } | |
| 314 return result; | |
| 315 }; | |
| 316 | |
| 317 /** | |
| 318 * Pretty print the jingle action contained in the given Xml node. | |
| 319 * | |
| 320 * @param {Node} jingle Xml node with jingle action contained in child nodes. | |
| 321 * @param {string} action String containing the jingle action. | |
| 322 * | |
| 323 * @return {?string} Pretty version of jingle action stanze. Null if error. | |
| 324 */ | |
| 325 remoting.FormatIq.prototype.prettyJingleAction = function(jingle, action) { | |
| 326 if (action == 'session-initiate' || action == 'session-accept') { | |
| 327 return this.prettySessionInitiateAccept(jingle); | |
| 328 } | |
| 329 if (action == 'session-terminate') { | |
| 330 return this.prettySessionTerminate(jingle); | |
| 331 } | |
| 332 if (action == 'transport-info') { | |
| 333 return this.prettyTransportInfo(jingle); | |
| 334 } | |
| 335 return null; | |
| 336 }; | |
| 337 | |
| 338 /** | |
| 339 * Pretty print the jingle error information contained in the given Xml node. | |
| 340 * | |
| 341 * @param {Node} error Xml node containing error information in child nodes. | |
| 342 * | |
| 343 * @return {?string} Pretty version of error stanze. Null if error. | |
| 344 */ | |
| 345 remoting.FormatIq.prototype.prettyError = function(error) { | |
| 346 if (!this.verifyAttributes(error, 'xmlns:err,code,type,err:hostname,' + | |
| 347 'err:bnsname,err:stacktrace')) { | |
| 348 return null; | |
| 349 } | |
| 350 var code = error.getAttribute('code'); | |
| 351 var type = error.getAttribute('type'); | |
| 352 var hostname = error.getAttribute('err:hostname'); | |
| 353 var bnsname = error.getAttribute('err:bnsname'); | |
| 354 var stacktrace = error.getAttribute('err:stacktrace'); | |
| 355 | |
| 356 var result = '\n error ' + code + ' ' + type + " hostname:'" + | |
| 357 hostname + "' bnsname:'" + bnsname + "'"; | |
| 358 var children = error.childNodes; | |
| 359 for (var i = 0; i < children.length; i++) { | |
| 360 /** @type {Node} */ | |
| 361 var child = children[i]; | |
| 362 result += '\n ' + child.nodeName; | |
| 363 } | |
| 364 if (stacktrace) { | |
| 365 var stack = stacktrace.split(' | '); | |
| 366 result += '\n stacktrace:'; | |
| 367 // We use 'length-1' because the stack trace ends with " | " which results | |
| 368 // in an empty string at the end after the split. | |
| 369 for (var s = 0; s < stack.length - 1; s++) { | |
| 370 result += '\n ' + stack[s]; | |
| 371 } | |
| 372 } | |
| 373 return result; | |
| 374 }; | |
| 375 | |
| 376 /** | |
| 377 * Print out the heading line for an iq node. | |
| 378 * | |
| 379 * @param {string} action String describing action (send/receive). | |
| 380 * @param {string} id Packet id. | |
| 381 * @param {string} desc Description of iq action for this node. | |
| 382 * @param {string|null} sid Session id. | |
| 383 * | |
| 384 * @return {string} Pretty version of stanza heading info. | |
| 385 */ | |
| 386 remoting.FormatIq.prototype.prettyIqHeading = function(action, id, desc, | |
| 387 sid) { | |
| 388 var message = 'iq ' + action + ' id=' + id; | |
| 389 if (desc) { | |
| 390 message = message + ' ' + desc; | |
| 391 } | |
| 392 if (sid) { | |
| 393 message = message + ' sid=' + sid; | |
| 394 } | |
| 395 return message; | |
| 396 }; | |
| 397 | |
| 398 /** | |
| 399 * Print out an iq 'result'-type node. | |
| 400 * | |
| 401 * @param {string} action String describing action (send/receive). | |
| 402 * @param {NodeList} iq_list Node list containing the 'result' xml. | |
| 403 * | |
| 404 * @return {?string} Pretty version of Iq result stanza. Null if error. | |
| 405 */ | |
| 406 remoting.FormatIq.prototype.prettyIqResult = function(action, iq_list) { | |
| 407 /** @type {Node} */ | |
| 408 var iq = iq_list[0]; | |
| 409 var id = iq.getAttribute('id'); | |
| 410 var iq_children = iq.childNodes; | |
| 411 | |
| 412 if (iq_children.length == 0) { | |
| 413 return this.prettyIqHeading(action, id, 'result (empty)', null); | |
| 414 } else if (iq_children.length == 1) { | |
| 415 /** @type {Node} */ | |
| 416 var child = iq_children[0]; | |
| 417 if (child.nodeName == 'query') { | |
| 418 if (!this.verifyAttributes(child, 'xmlns')) { | |
| 419 return null; | |
| 420 } | |
| 421 var xmlns = child.getAttribute('xmlns'); | |
| 422 if (xmlns == 'google:jingleinfo') { | |
| 423 var result = this.prettyIqHeading(action, id, 'result ' + xmlns, null); | |
| 424 result += this.prettyJingleinfo(child); | |
| 425 return result; | |
| 426 } | |
| 427 return ''; | |
| 428 } else if (child.nodeName == 'rem:log-result') { | |
| 429 if (!this.verifyAttributes(child, 'xmlns:rem')) { | |
| 430 return null; | |
| 431 } | |
| 432 return this.prettyIqHeading(action, id, 'result (log-result)', null); | |
| 433 } | |
| 434 } | |
| 435 return null; | |
| 436 }; | |
| 437 | |
| 438 /** | |
| 439 * Print out an Iq 'get'-type node. | |
| 440 * | |
| 441 * @param {string} action String describing action (send/receive). | |
| 442 * @param {NodeList} iq_list Node containing the 'get' xml. | |
| 443 * | |
| 444 * @return {?string} Pretty version of Iq get stanza. Null if error. | |
| 445 */ | |
| 446 remoting.FormatIq.prototype.prettyIqGet = function(action, iq_list) { | |
| 447 /** @type {Node} */ | |
| 448 var iq = iq_list[0]; | |
| 449 var id = iq.getAttribute('id'); | |
| 450 var iq_children = iq.childNodes; | |
| 451 | |
| 452 if (iq_children.length != 1) { | |
| 453 return null; | |
| 454 } | |
| 455 | |
| 456 /** @type {Node} */ | |
| 457 var query = iq_children[0]; | |
| 458 if (query.nodeName != 'query') { | |
| 459 return null; | |
| 460 } | |
| 461 if (!this.verifyAttributes(query, 'xmlns')) { | |
| 462 return null; | |
| 463 } | |
| 464 var xmlns = query.getAttribute('xmlns'); | |
| 465 return this.prettyIqHeading(action, id, 'get ' + xmlns, null); | |
| 466 }; | |
| 467 | |
| 468 /** | |
| 469 * Print out an iq 'set'-type node. | |
| 470 * | |
| 471 * @param {string} action String describing action (send/receive). | |
| 472 * @param {NodeList} iq_list Node containing the 'set' xml. | |
| 473 * | |
| 474 * @return {?string} Pretty version of Iq set stanza. Null if error. | |
| 475 */ | |
| 476 remoting.FormatIq.prototype.prettyIqSet = function(action, iq_list) { | |
| 477 /** @type {Node} */ | |
| 478 var iq = iq_list[0]; | |
| 479 var id = iq.getAttribute('id'); | |
| 480 var iq_children = iq.childNodes; | |
| 481 | |
| 482 var children = iq_children.length; | |
| 483 if (children == 1) { | |
| 484 /** @type {Node} */ | |
| 485 var child = iq_children[0]; | |
| 486 if (child.nodeName == 'gr:log') { | |
| 487 var grlog = child; | |
| 488 if (!this.verifyAttributes(grlog, 'xmlns:gr')) { | |
| 489 return null; | |
| 490 } | |
| 491 | |
| 492 if (grlog.childNodes.length != 1) { | |
| 493 return null; | |
| 494 } | |
| 495 var grentry = grlog.firstChild; | |
| 496 if (grentry.nodeName != 'gr:entry') { | |
| 497 return null; | |
| 498 } | |
| 499 if (!this.verifyAttributes(grentry, 'role,event-name,session-state,' + | |
| 500 'os-name,cpu,browser-version,' + | |
| 501 'webapp-version')) { | |
| 502 return null; | |
| 503 } | |
| 504 var role = grentry.getAttribute('role'); | |
| 505 var event_name = grentry.getAttribute('event-name'); | |
| 506 var session_state = grentry.getAttribute('session-state'); | |
| 507 var os_name = grentry.getAttribute('os-name'); | |
| 508 var cpu = grentry.getAttribute('cpu'); | |
| 509 var browser_version = grentry.getAttribute('browser-version'); | |
| 510 var webapp_version = grentry.getAttribute('webapp-version'); | |
| 511 | |
| 512 var result = this.prettyIqHeading(action, id, role + ' ' + event_name + | |
| 513 ' ' + session_state, null); | |
| 514 result += '\n ' + os_name + ' ' + cpu + " browser:" + browser_version + | |
| 515 " webapp:" + webapp_version; | |
| 516 return result; | |
| 517 } | |
| 518 if (child.nodeName == 'jingle') { | |
| 519 var jingle = child; | |
| 520 if (!this.verifyAttributes(jingle, 'xmlns,action,sid,initiator')) { | |
| 521 return null; | |
| 522 } | |
| 523 | |
| 524 var jingle_action = jingle.getAttribute('action'); | |
| 525 var sid = jingle.getAttribute('sid'); | |
| 526 | |
| 527 var result = this.prettyIqHeading(action, id, 'set ' + jingle_action, | |
| 528 sid); | |
| 529 var action_str = this.prettyJingleAction(jingle, jingle_action); | |
| 530 if (!action_str) { | |
| 531 return null; | |
| 532 } | |
| 533 return result + action_str; | |
| 534 } | |
| 535 } | |
| 536 return null; | |
| 537 }; | |
| 538 | |
| 539 /** | |
| 540 * Print out an iq 'error'-type node. | |
| 541 * | |
| 542 * @param {string} action String describing action (send/receive). | |
| 543 * @param {NodeList} iq_list Node containing the 'error' xml. | |
| 544 * | |
| 545 * @return {?string} Pretty version of iq error stanza. Null if error parsing | |
| 546 * this stanza. | |
| 547 */ | |
| 548 remoting.FormatIq.prototype.prettyIqError = function(action, iq_list) { | |
| 549 /** @type {Node} */ | |
| 550 var iq = iq_list[0]; | |
| 551 var id = iq.getAttribute('id'); | |
| 552 var iq_children = iq.childNodes; | |
| 553 | |
| 554 var children = iq_children.length; | |
| 555 if (children != 2) { | |
| 556 return null; | |
| 557 } | |
| 558 | |
| 559 /** @type {Node} */ | |
| 560 var jingle = iq_children[0]; | |
| 561 if (jingle.nodeName != 'jingle') { | |
| 562 return null; | |
| 563 } | |
| 564 if (!this.verifyAttributes(jingle, 'xmlns,action,sid,initiator')) { | |
| 565 return null; | |
| 566 } | |
| 567 var jingle_action = jingle.getAttribute('action'); | |
| 568 var sid = jingle.getAttribute('sid'); | |
| 569 var result = this.prettyIqHeading(action, id, 'error from ' + jingle_action, | |
| 570 sid); | |
| 571 var action_str = this.prettyJingleAction(jingle, jingle_action); | |
| 572 if (!action_str) { | |
| 573 return null; | |
| 574 } | |
| 575 result += action_str; | |
| 576 | |
| 577 /** @type {Node} */ | |
| 578 var error = iq_children[1]; | |
| 579 if (error.nodeName != 'cli:error') { | |
| 580 return null; | |
| 581 } | |
| 582 | |
| 583 var error_str = this.prettyError(error); | |
| 584 if (!error_str) { | |
| 585 return null; | |
| 586 } | |
| 587 result += error_str; | |
| 588 return result; | |
| 589 }; | |
| 590 | |
| 591 /** | |
| 592 * Try to log a pretty-print the given IQ stanza (XML). | |
| 593 * Return true if the stanza was successfully printed. | |
| 594 * | |
| 595 * @param {boolean} send True if we're sending this stanza; false for receiving. | |
| 596 * @param {string} message The XML stanza to add to the log. | |
| 597 * | |
| 598 * @return {?string} Pretty version of the Iq stanza. Null if error. | |
| 599 */ | |
| 600 remoting.FormatIq.prototype.prettyIq = function(send, message) { | |
| 601 var parser = new DOMParser(); | |
| 602 var xml = parser.parseFromString(message, 'text/xml'); | |
| 603 | |
| 604 var iq_list = xml.getElementsByTagName('iq'); | |
| 605 | |
| 606 if (iq_list && iq_list.length > 0) { | |
| 607 /** @type {Node} */ | |
| 608 var iq = iq_list[0]; | |
| 609 if (!this.verifyAttributes(iq, 'xmlns,xmlns:cli,id,to,from,type')) | |
| 610 return null; | |
| 611 | |
| 612 // Verify that the to/from fields match the expected sender/receiver. | |
| 613 var to = iq.getAttribute('to'); | |
| 614 var from = iq.getAttribute('from'); | |
| 615 var action = ''; | |
| 616 var bot = remoting.settings.DIRECTORY_BOT_JID; | |
| 617 if (send) { | |
| 618 if (to && to != this.hostJid_ && to != bot) { | |
| 619 console.warn('FormatIq: bad to: ' + to); | |
| 620 return null; | |
| 621 } | |
| 622 if (from && from != this.clientJid_) { | |
| 623 console.warn('FormatIq: bad from: ' + from); | |
| 624 return null; | |
| 625 } | |
| 626 | |
| 627 action = "send"; | |
| 628 if (to == bot) { | |
| 629 action = action + " (to bot)"; | |
| 630 } | |
| 631 } else { | |
| 632 if (to && to != this.clientJid_) { | |
| 633 console.warn('FormatIq: bad to: ' + to); | |
| 634 return null; | |
| 635 } | |
| 636 if (from && from != this.hostJid_ && from != bot) { | |
| 637 console.warn('FormatIq: bad from: ' + from); | |
| 638 return null; | |
| 639 } | |
| 640 | |
| 641 action = "receive"; | |
| 642 if (from == bot) { | |
| 643 action = action + " (from bot)"; | |
| 644 } | |
| 645 } | |
| 646 | |
| 647 var type = iq.getAttribute('type'); | |
| 648 if (type == 'result') { | |
| 649 return this.prettyIqResult(action, iq_list); | |
| 650 } else if (type == 'get') { | |
| 651 return this.prettyIqGet(action, iq_list); | |
| 652 } else if (type == 'set') { | |
| 653 return this.prettyIqSet(action, iq_list); | |
| 654 } else if (type == 'error') { | |
| 655 return this.prettyIqError(action, iq_list); | |
| 656 } | |
| 657 } | |
| 658 | |
| 659 return null; | |
| 660 }; | |
| 661 | |
| 662 /** | |
| 663 * Return a pretty-formatted string for the IQ stanza being sent. | |
| 664 * If the stanza cannot be made pretty, then a string with a raw dump of the | |
| 665 * stanza will be returned. | |
| 666 * | |
| 667 * @param {string} message The XML stanza to make pretty. | |
| 668 * | |
| 669 * @return {string} Pretty version of XML stanza being sent. A raw dump of the | |
| 670 * stanza is returned if there was a parsing error. | |
| 671 */ | |
| 672 remoting.FormatIq.prototype.prettifySendIq = function(message) { | |
| 673 var result = this.prettyIq(true, message); | |
| 674 if (!result) { | |
| 675 // Fall back to showing the raw stanza. | |
| 676 return 'Sending Iq: ' + message; | |
| 677 } | |
| 678 return result; | |
| 679 }; | |
| 680 | |
| 681 /** | |
| 682 * Return a pretty-formatted string for the IQ stanza that was received. | |
| 683 * If the stanza cannot be made pretty, then a string with a raw dump of the | |
| 684 * stanza will be returned. | |
| 685 * | |
| 686 * @param {string} message The XML stanza to make pretty. | |
| 687 * | |
| 688 * @return {string} Pretty version of XML stanza that was received. A raw dump | |
| 689 * of the stanza is returned if there was a parsing error. | |
| 690 */ | |
| 691 remoting.FormatIq.prototype.prettifyReceiveIq = function(message) { | |
| 692 var result = this.prettyIq(false, message); | |
| 693 if (!result) { | |
| 694 // Fall back to showing the raw stanza. | |
| 695 return 'Receiving Iq: ' + message; | |
| 696 } | |
| 697 return result; | |
| 698 }; | |
| OLD | NEW |