1 /* 2 * Copyright ©2012 SARA bv, The Netherlands 3 * 4 * This file is part of js-webdav-client. 5 * 6 * js-webdav-client is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as published 8 * by the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * js-webdav-client 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 Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public License 17 * along with js-webdav-client. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 "use strict"; 20 21 // If nl.sara.webdav.Privilege is already defined, we have a namespace clash! 22 if (nl.sara.webdav.Privilege !== undefined) { 23 throw new nl.sara.webdav.Exception('Namespace nl.sara.webdav.Privilege already taken, could not load JavaScript library for WebDAV connectivity.', nl.sara.webdav.Exception.NAMESPACE_TAKEN); 24 } 25 26 /** 27 * @class WebDAV ACL privilege 28 * 29 * @param {Node} [xmlNode] Optional; the xmlNode describing the privilege object 30 * @property {String} namespace The namespace 31 * @property {String} tagname The tag name 32 * @property {NodeList} xmlvalue A NodeList with the value of this privilege 33 */ 34 nl.sara.webdav.Privilege = function(xmlNode) { 35 // First define private attributes 36 Object.defineProperty(this, '_xmlvalue', { 37 'value': null, 38 'enumerable': false, 39 'configurable': false, 40 'writable': true 41 }); 42 // Second define public attributes 43 Object.defineProperty(this, 'namespace', { 44 'value': null, 45 'enumerable': true, 46 'configurable': false, 47 'writable': true 48 }); 49 Object.defineProperty(this, 'tagname', { 50 'value': null, 51 'enumerable': true, 52 'configurable': false, 53 'writable': true 54 }); 55 56 // Constructor logic 57 if (typeof xmlNode !== 'undefined') { 58 this.namespace = xmlNode.namespaceURI; 59 this.tagname = nl.sara.webdav.Ie.getLocalName(xmlNode); 60 this.xmlvalue = xmlNode.childNodes; 61 } 62 }; 63 64 //######################### DEFINE PUBLIC ATTRIBUTES ########################### 65 (function() { 66 // This creates a (private) static variable. It will contain all codecs 67 var codecNamespaces = {}; 68 69 Object.defineProperty(nl.sara.webdav.Privilege.prototype, 'xmlvalue', { 70 'set': function(value) { 71 if (value === null) { 72 this._xmlvalue = null; 73 return; 74 } 75 if (!nl.sara.webdav.Ie.isIE && !(value instanceof NodeList)) { 76 throw new nl.sara.webdav.Exception('xmlvalue must be an instance of NodeList', nl.sara.webdav.Exception.WRONG_TYPE); 77 } 78 this._xmlvalue = value; 79 }, 80 'get': function() { 81 return this._xmlvalue; 82 } 83 }); 84 85 //########################## DEFINE PUBLIC METHODS ############################# 86 /** 87 * Adds functions to encode or decode properties 88 * 89 * This allows exact control in how Privilege.xmlvalue is parsed when 90 * getParsedValue() is called and how XML is rebuild when 91 * setValueAndRebuildXml() is called. You can specify two functions: 'fromXML 92 * and 'toXML'. These should be complementary. That is, toXML should be able 93 * to create a NodeList based on the output of fromXML. For example: 94 * A == toXML(fromXML(A)) && 95 * B == fromXML(toXML(B)) 96 * 97 * @param {nl.sara.webdav.Codec} codec The codec to add 98 * @returns {void} 99 */ 100 nl.sara.webdav.Privilege.addCodec = function(codec) { 101 if (typeof codec.namespace !== 'string') { 102 throw new nl.sara.webdav.Exception('addCodec: codec.namespace must be a String', nl.sara.webdav.Exception.WRONG_TYPE); 103 } 104 if (typeof codec.tagname !== 'string') { 105 throw new nl.sara.webdav.Exception('addCodec: codec.tagname must be a String', nl.sara.webdav.Exception.WRONG_TYPE); 106 } 107 if (codecNamespaces[codec.namespace] === undefined) { 108 codecNamespaces[codec.namespace] = {}; 109 } 110 codecNamespaces[codec.namespace][codec.tagname] = { 111 'fromXML': (codec.fromXML ? codec.fromXML : undefined), 112 'toXML': (codec.toXML ? codec.toXML : undefined) 113 }; 114 }; 115 116 /** 117 * Sets a new value and rebuilds xmlvalue 118 * 119 * If a codec for this privilege is specified, it will use this codec to 120 * rebuild xmlvallue. Else it will attempt to create one CDATA element with 121 * the string value of whatever was fiven as parameter. 122 * 123 * @param {mixed} value The object to base the xmlvalue on 124 * @return {void} 125 */ 126 nl.sara.webdav.Privilege.prototype.setValueAndRebuildXml = function(value) { 127 // Call codec to automatically create correct 'xmlvalue' 128 var xmlDoc = document.implementation.createDocument(this.namespace, this.tagname, null); 129 if ((codecNamespaces[this.namespace] === undefined) || 130 (codecNamespaces[this.namespace][this.tagname] === undefined) || 131 (codecNamespaces[this.namespace][this.tagname]['toXML'] === undefined)) { 132 // No 'toXML' function set, so create a NodeList with just one CDATA node 133 if (value !== null) { // If the value is NULL, then we should add anything to the NodeList 134 var cdata = xmlDoc.createCDATASection(value); 135 xmlDoc.documentElement.appendChild(cdata); 136 } 137 this._xmlvalue = xmlDoc.documentElement.childNodes; 138 }else{ 139 this._xmlvalue = codecNamespaces[this.namespace][this.tagname]['toXML'](value, xmlDoc).documentElement.childNodes; 140 } 141 }; 142 143 /** 144 * Parses the xmlvalue 145 * 146 * If a codec for this privilege is specified, it will use this codec to parse 147 * the XML nodes. Else it will attempt to parse it as text or CDATA elements. 148 * 149 * @return {mixed} If a codec is specified, the return type depends on that 150 * codec. If no codec is specified and at least one node in xmlvalue is not a 151 * text or CDATA node, it will return undefined. If xmlvalue is empty, it will 152 * return null. 153 */ 154 nl.sara.webdav.Privilege.prototype.getParsedValue = function() { 155 // Call codec to automatically create correct 'value' 156 if (this._xmlvalue.length > 0) { 157 if ((codecNamespaces[this.namespace] === undefined) || 158 (codecNamespaces[this.namespace][this.tagname] === undefined) || 159 (codecNamespaces[this.namespace][this.tagname]['fromXML'] === undefined)) { 160 // No 'fromXML' function set, so try to create a text value based on TextNodes and CDATA nodes. If other nodes are present, set 'value' to null 161 var parsedValue = ''; 162 for (var i = 0; i < this._xmlvalue.length; i++) { 163 var node = this._xmlvalue.item(i); 164 if ((node.nodeType === 3) || (node.nodeType === 4)) { // Make sure text and CDATA content is stored 165 parsedValue += node.nodeValue; 166 }else{ // If even one of the nodes is not text or CDATA, then we don't parse a text value at all 167 parsedValue = undefined; 168 break; 169 } 170 } 171 return parsedValue; 172 }else{ 173 return codecNamespaces[this.namespace][this.tagname]['fromXML'](this._xmlvalue); 174 } 175 } 176 return null; 177 }; 178 })(); // Ends the static scope 179 180 /** 181 * Overloads the default toString() method so it returns the value of this privilege 182 * 183 * @returns {String} A string representation of this privilege 184 */ 185 nl.sara.webdav.Privilege.prototype.toString = function() { 186 return this.getParsedValue(); 187 }; 188 189 // End of library 190