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.Ace is already defined, we have a namespace clash!
 22 if (nl.sara.webdav.Ace !== undefined) {
 23   throw new nl.sara.webdav.Exception('Namespace nl.sara.webdav.Ace already taken, could not load JavaScript library for WebDAV connectivity.', nl.sara.webdav.Exception.NAMESPACE_TAKEN);
 24 }
 25 
 26 /**
 27  * @class WebDAV property
 28  *
 29  * @param  {Node}  [xmlNode]  Optional; the xmlNode describing the ace object (should be compliant with RFC 3744)
 30  * @property  {mixed}    principal        The principal. Is one of the class constants ALL, AUTHENTICATED, UNAUTHENTICATED or SELF or a String with the path to the principal or a property. See RFC 3744 for more information on this.
 31  * @property  {Boolean}  invertprincipal  Whether to invert the principal; true means 'all principals except the one specified'. Default is false.
 32  * @property  {Boolean}  isprotected      Whether this ACE is protected. Default is false.
 33  * @property  {Number}   grantdeny        Grant or deny ACE? Is one of the class constants GRANT or DENY.
 34  * @property  {mixed}    inherited        False if the ACE is not inherited, else a String with the path to the parent collection from which this ACE is inherited.
 35  */
 36 nl.sara.webdav.Ace = function(xmlNode) {
 37   // First define private attributes
 38   Object.defineProperty(this, '_namespaces', {
 39     'value': {},
 40     'enumerable': false,
 41     'configurable': false,
 42     'writable': true
 43   });
 44   Object.defineProperty(this, '_principal', {
 45     'value': null,
 46     'enumerable': false,
 47     'configurable': false,
 48     'writable': true
 49   });
 50   Object.defineProperty(this, '_invertprincipal', {
 51     'value': false,
 52     'enumerable': false,
 53     'configurable': false,
 54     'writable': true
 55   });
 56   Object.defineProperty(this, '_grantdeny', {
 57     'value': null,
 58     'enumerable': false,
 59     'configurable': false,
 60     'writable': true
 61   });
 62   Object.defineProperty(this, '_isprotected', {
 63     'value': false,
 64     'enumerable': false,
 65     'configurable': false,
 66     'writable': true
 67   });
 68   Object.defineProperty(this, '_inherited', {
 69     'value': false,
 70     'enumerable': false,
 71     'configurable': false,
 72     'writable': true
 73   });
 74 
 75   // Constructor logic
 76   function parsePrincipal(object, child) {
 77     if (!nl.sara.webdav.Ie.isIE && !(child instanceof Node)) {
 78       throw new nl.sara.webdav.Exception('Principal XML node not recognized!', nl.sara.webdav.Exception.WRONG_XML);
 79     }
 80     for (var j = 0; j < child.childNodes.length; j++) {
 81       var principal = child.childNodes.item(j);
 82       if ((principal.nodeType !== 1) || (principal.namespaceURI === null) || (principal.namespaceURI !== 'DAV:')) { // Skip if not from the right namespace
 83         continue;
 84       }
 85       switch (nl.sara.webdav.Ie.getLocalName(principal)) {
 86         case 'href':
 87           object.principal = principal.childNodes.item(0).nodeValue;
 88           break;
 89         case 'all':
 90           object.principal = nl.sara.webdav.Ace.ALL;
 91           break;
 92         case 'authenticated':
 93           object.principal = nl.sara.webdav.Ace.AUTHENTICATED;
 94           break;
 95         case 'unauthenticated':
 96           object.principal = nl.sara.webdav.Ace.UNAUTHENTICATED;
 97           break;
 98         case 'property':
 99           for (var k = 0; k < principal.childNodes.length; k++) {
100             var element = principal.childNodes.item(k);
101             if (element.nodeType !== 1) {
102               continue;
103             }
104             var prop = new nl.sara.webdav.Property(element);
105             object.principal = prop;
106             break;
107           }
108           break;
109         case 'self':
110           object.principal = nl.sara.webdav.Ace.SELF;
111           break;
112         default:
113           throw new nl.sara.webdav.Exception('Principal XML Node contains illegal child node: ' + nl.sara.webdav.Ie.getLocalName(principal), nl.sara.webdav.Exception.WRONG_XML);
114         break;
115       }
116     }
117   }
118 
119   function parsePrivileges(object, privilegeList) {
120     for (var i = 0; i < privilegeList.length; i++) {
121       var privilege = privilegeList.item(i);
122       if ( ( privilege.nodeType === 1 ) &&
123            ( privilege.namespaceURI === 'DAV:' ) &&
124            ( nl.sara.webdav.Ie.getLocalName( privilege ) === 'privilege' ) ) {
125         object.addPrivilege( new nl.sara.webdav.Privilege( privilege.childNodes[0] ) );
126       }
127     }
128   }
129 
130   // Parse the XML
131   if (typeof xmlNode !== 'undefined') {
132     if ((xmlNode.namespaceURI !== 'DAV:') || (nl.sara.webdav.Ie.getLocalName(xmlNode) !== 'ace')) {
133       throw new nl.sara.webdav.Exception('Node is not of type DAV:ace', nl.sara.webdav.Exception.WRONG_XML);
134     }
135     var data = xmlNode.childNodes;
136     for (var i = 0; i < data.length; i++) {
137       var child = data.item(i);
138       if ((child.namespaceURI === null) || (child.namespaceURI !== 'DAV:')) { // Skip if not from the right namespace
139         continue;
140       }
141       switch (nl.sara.webdav.Ie.getLocalName(child)) {
142         case 'principal':
143           this.invertprincipal = false;
144           parsePrincipal(this, child);
145           break;
146         case 'invert':
147           this.invertprincipal = true;
148           for (var j = 0; j < child.childNodes.length; j++) {
149             var element = child.childNodes.item(j);
150             if ((element.namespaceURI !== 'DAV:') || (nl.sara.webdav.Ie.getLocalName(element) !== 'principal')) {
151               continue;
152             }
153             parsePrincipal(this, element);
154           }
155           break;
156         case 'grant':
157           this.grantdeny = nl.sara.webdav.Ace.GRANT;
158           parsePrivileges(this, child.childNodes);
159           break;
160         case 'deny':
161           this.grantdeny = nl.sara.webdav.Ace.DENY;
162           parsePrivileges(this, child.childNodes);
163           break;
164         case 'protected':
165           this.isprotected = true;
166           break;
167         case 'inherited':
168           for (var j = 0; j < child.childNodes.length; j++) {
169             var element = child.childNodes.item(j);
170             if ((element.namespaceURI !== 'DAV:') || (nl.sara.webdav.Ie.getLocalName(element) !== 'href')) {
171               continue;
172             }
173             this.inherited = child.childNodes.item(j).childNodes.item(0).nodeValue;
174           }
175         break;
176       }
177     }
178   }
179 };
180 
181 /**#@+
182  * Class constant
183  */
184 nl.sara.webdav.Ace.GRANT = 1;
185 nl.sara.webdav.Ace.DENY = 2;
186 nl.sara.webdav.Ace.ALL = 3;
187 nl.sara.webdav.Ace.AUTHENTICATED = 4;
188 nl.sara.webdav.Ace.UNAUTHENTICATED = 5;
189 nl.sara.webdav.Ace.SELF = 6;
190 /**#@-*/
191 
192 //######################### DEFINE PUBLIC ATTRIBUTES ###########################
193 Object.defineProperty(nl.sara.webdav.Ace.prototype, 'principal', {
194   'set': function(value) {
195     switch (value) {
196       case nl.sara.webdav.Ace.ALL:
197       case nl.sara.webdav.Ace.AUTHENTICATED:
198       case nl.sara.webdav.Ace.UNAUTHENTICATED:
199       case nl.sara.webdav.Ace.SELF:
200         break;
201       default: // If it isn't one of the constants, it should be either a Property object or a string/URL
202         if (!nl.sara.webdav.Ie.isIE && !(value instanceof nl.sara.webdav.Property)) {
203           value = String(value);
204         }
205       break;
206     }
207     this._principal = value;
208   },
209   'get': function() {
210     return this._principal;
211   }
212 });
213 
214 Object.defineProperty(nl.sara.webdav.Ace.prototype, 'invertprincipal', {
215   'set': function(value) {
216     this._invertprincipal = Boolean(value);
217   },
218   'get': function() {
219     return this._invertprincipal;
220   }
221 });
222 
223 Object.defineProperty(nl.sara.webdav.Ace.prototype, 'isprotected', {
224   'set': function(value) {
225     this._isprotected = Boolean(value);
226   },
227   'get': function() {
228     return this._isprotected;
229   }
230 });
231 
232 Object.defineProperty(nl.sara.webdav.Ace.prototype, 'grantdeny', {
233   'set': function(value) {
234     if ((value !== nl.sara.webdav.Ace.GRANT) && (value !== nl.sara.webdav.Ace.DENY)) {
235       throw new nl.sara.webdav.Exception('grantdeny must be either nl.sara.webdav.Ace.GRANT or nl.sara.webdav.Ace.DENY', nl.sara.webdav.Exception.WRONG_VALUE);
236     }
237     this._grantdeny = value;
238   },
239   'get': function() {
240     return this._grantdeny;
241   }
242 });
243 
244 Object.defineProperty(nl.sara.webdav.Ace.prototype, 'inherited', {
245   'set': function(value) {
246     if (Boolean(value)) {
247       this._inherited = String(value);
248     }else{
249       this._inherited = false;
250     }
251   },
252   'get': function() {
253     return this._inherited;
254   }
255 });
256 
257 //########################## DEFINE PUBLIC METHODS #############################
258 /**
259  * Adds a WebDAV privilege
260  *
261  * @param    {nl.sara.webdav.Privilege}  privilege  The privilege to add
262  * @returns  {nl.sara.webdav.Ace}                   The ace itself for chaining methods
263  */
264 nl.sara.webdav.Ace.prototype.addPrivilege = function(privilege) {
265   if (!nl.sara.webdav.Ie.isIE && !(privilege instanceof nl.sara.webdav.Privilege)) {
266     throw new nl.sara.webdav.Exception('Privilege should be instance of Privilege', nl.sara.webdav.Exception.WRONG_TYPE);
267   }
268   var namespace = privilege.namespace;
269   if (namespace) {
270     if (this._namespaces[namespace] === undefined) {
271       this._namespaces[namespace] = {};
272     }
273   }else{
274     throw new nl.sara.webdav.Exception('Privilege should have a namespace', nl.sara.webdav.Exception.WRONG_TYPE);
275   }
276 
277   this._namespaces[namespace][privilege.tagname] = privilege;
278   return this;
279 };
280 
281 /**
282  * Gets a WebDAV privilege
283  *
284  * @param    {String}                    namespace  The namespace of the privilege
285  * @param    {String}                    privilege  The privilege to get
286  * @returns  {nl.sara.webdav.Privilege}             The value of the privilege or undefined if the privilege doesn't exist
287  */
288 nl.sara.webdav.Ace.prototype.getPrivilege = function(namespace, privilege) {
289   if ((this._namespaces[namespace] === undefined) || (this._namespaces[namespace][privilege] === undefined)) {
290     return undefined;
291   }
292   return this._namespaces[namespace][privilege];
293 };
294 
295 /**
296  * Gets the namespace names
297  *
298  * @returns  {String[]}  The names of the different namespaces
299  */
300 nl.sara.webdav.Ace.prototype.getNamespaceNames = function() {
301   return Object.keys(this._namespaces);
302 };
303 
304 /**
305  * Gets the privilege names of a namespace
306  *
307  * @param    {String}    namespace  The namespace of the privilege
308  * @returns  {String[]}             The names of the different privilege of a namespace
309  */
310 nl.sara.webdav.Ace.prototype.getPrivilegeNames = function(namespace) {
311   if (this._namespaces[namespace] === undefined) {
312     return new Array();
313   }
314   return Object.keys(this._namespaces[namespace]);
315 };
316 
317 // End of library
318