1 // 2 // The Antville Project 3 // http://code.google.com/p/antville 4 // 5 // Copyright 2001-2007 by The Antville People 6 // 7 // Licensed under the Apache License, Version 2.0 (the ``License''); 8 // you may not use this file except in compliance with the License. 9 // You may obtain a copy of the License at 10 // 11 // http://www.apache.org/licenses/LICENSE-2.0 12 // 13 // Unless required by applicable law or agreed to in writing, software 14 // distributed under the License is distributed on an ``AS IS'' BASIS, 15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 // See the License for the specific language governing permissions and 17 // limitations under the License. 18 // 19 // $Revision$ 20 // $LastChangedBy$ 21 // $LastChangedDate$ 22 // $URL$ 23 // 24 25 /** 26 * @fileOverview Defines the Comment prototype. 27 */ 28 29 markgettext("File"); 30 markgettext("file"); 31 32 this.handleMetadata("url"); 33 this.handleMetadata("description"); 34 this.handleMetadata("contentType"); 35 this.handleMetadata("contentLength"); 36 this.handleMetadata("fileName"); 37 38 /** 39 * 40 */ 41 File.remove = function() { 42 if (this.constructor === File) { 43 this.getFile().remove(); 44 this.remove(); 45 } 46 return; 47 } 48 49 /** 50 * 51 * @param {String} name 52 */ 53 File.getName = function(name) { 54 if (name) { 55 //return name.replace(/[^\w\d\s._-]/g, String.EMPTY); 56 return String(name).trim().replace(/[\/\\:;?+\[\]{}|#"`<>^]/g, String.EMPTY); 57 } 58 return null; 59 } 60 61 /** 62 * @name File 63 * @constructor 64 * @property {Date} created 65 * @property {User} creator 66 * @property {Metadata} metadata 67 * @property {Date} modified 68 * @property {User} modifier 69 * @property {String} name 70 * @property {Number} parent_id 71 * @property {String} parent_type 72 * @property {String} prototype 73 * @property {Number} requests 74 * @property {Site} site 75 * @extends HopObject 76 */ 77 File.prototype.constructor = function() { 78 this.creator = this.modifier = session.user; 79 this.created = this.modified = new Date; 80 this.requests = 0; 81 return this; 82 } 83 84 /** 85 * 86 * @param {String} action 87 * @return {Boolean} 88 */ 89 File.prototype.getPermission = function(action) { 90 switch (action) { 91 case ".": 92 case "main": 93 return true; 94 case "delete": 95 case "edit": 96 return this._parent.getPermission("main") && 97 this.creator === session.user || 98 Membership.require(Membership.MANAGER) || 99 User.require(User.PRIVILEGED); 100 } 101 return false; 102 } 103 104 File.prototype.main_action = function() { 105 if (Membership.require(Membership.SUBSCRIBER) && 106 User.require(User.REGULAR)) { 107 this.requests += 1; 108 } 109 return res.redirect(this.getUrl()); 110 } 111 112 File.prototype.edit_action = function() { 113 if (req.postParams.save) { 114 try { 115 this.update(req.postParams); 116 res.message = gettext("The changes were saved successfully."); 117 res.redirect(this._parent.href()); 118 } catch (ex) { 119 res.message = ex; 120 app.log(ex); 121 } 122 } 123 124 res.data.action = this.href(req.action); 125 res.data.title = gettext("Edit File"); 126 res.data.body = this.renderSkinAsString("$File#edit"); 127 return this.site.renderSkin("Site#page"); 128 } 129 130 /** 131 * 132 * @param {String} name 133 * @returns {Object} 134 */ 135 File.prototype.getFormValue = function(name) { 136 var self = this; 137 138 var getOrigin = function(str) { 139 var origin = req.postParams.file_origin || self.origin; 140 if (origin && origin.contains("://")) { 141 return origin; 142 } 143 return null; 144 } 145 146 if (req.isPost()) { 147 if (name === "file") { 148 return getOrigin(); 149 } 150 return req.postParams[name]; 151 } 152 switch (name) { 153 case "file": 154 return getOrigin(); 155 } 156 return this[name]; 157 } 158 159 /** 160 * 161 * @param {Object} data 162 */ 163 File.prototype.update = function(data) { 164 if (data.uploadError) { 165 app.log(data.uploadError); 166 // Looks like the file uploaded has exceeded the upload limit ... 167 throw Error(gettext("File size is exceeding the upload limit.")); 168 } 169 170 if (!data.file_origin) { 171 if (this.isTransient()) { 172 throw Error(gettext("There was nothing to upload. Please be sure to choose a file.")); 173 } 174 } else if (data.file_origin !== this.origin) { 175 var mime = data.file; 176 if (mime.contentLength < 1) { 177 mime = getURL(data.file_origin); 178 if (!mime) { 179 throw Error(gettext("Could not fetch the file from the given URL.")); 180 } 181 } 182 183 this.origin = data.file_origin; 184 var mimeName = mime.normalizeFilename(mime.name); 185 this.contentLength = mime.contentLength; 186 this.contentType = mime.contentType; 187 188 if (!this.name) { 189 var name = File.getName(data.name) || mimeName.split(".")[0]; 190 this.name = this.site.files.getAccessName(name); 191 } 192 193 // Make the file persistent before proceeding with writing 194 // it to disk (also see Helma bug #607) 195 this.isTransient() && this.persist(); 196 197 var extension = mimeName.substr(mimeName.lastIndexOf(".")) || String.EMPTY; 198 var fileName = this.name + extension; 199 if (fileName !== this.fileName) { 200 // Remove existing file if the file name has changed 201 this.getFile().remove(); 202 } 203 this.fileName = fileName; 204 var file = this.getFile(); 205 mime.writeToFile(file.getParent(), file.getName()); 206 } 207 208 // FIXME: one day? 209 //this.setTags(data.tags || data.tag_array); 210 this.description = data.description; 211 this.touch(); 212 return; 213 } 214 215 /** 216 * 217 */ 218 File.prototype.url_macro = function() { 219 return res.write(this.url || this.getUrl()); 220 } 221 222 /** 223 * 224 * @param {Object} param 225 */ 226 File.prototype.contentLength_macro = function(param) { 227 return res.write((this.contentLength / 1024).format("###,###") + " KB"); 228 } 229 230 /** 231 * 232 */ 233 File.prototype.getFile = function() { 234 var site = this.site || res.handlers.site; 235 return site.getStaticFile("files/" + this.fileName); 236 } 237 238 /** 239 * 240 */ 241 File.prototype.getUrl = function() { 242 var site = this.site || res.handlers.site; 243 return site.getStaticUrl("files/" + this.fileName); 244 } 245 246 /** 247 * @returns {String} 248 */ 249 File.prototype.getConfirmText = function() { 250 return gettext("You are about to delete the file {0}.", this.name); 251 } 252