1 2 3 /** 4 * @name CeL file function 5 * @fileoverview 6 * 本檔案包含了 file functions。 7 * @since 8 * @see 9 * <a href="http://dev.w3.org/2006/webapi/FileAPI/" accessdate="2010/6/20 14:49">File API</a> 10 */ 11 12 13 /* 14 15 16 */ 17 18 if (typeof CeL === 'function'){ 19 20 /** 21 * 本 module 之 name(id),<span style="text-decoration:line-through;">不設定時會從呼叫時之 path 取得</span>。 22 * @type String 23 * @constant 24 * @inner 25 * @ignore 26 */ 27 var module_name = 'IO.file'; 28 29 //=================================================== 30 /** 31 * 若欲 include 整個 module 時,需囊括之 code。 32 * @type Function 33 * @param {Function} library_namespace namespace of library 34 * @param load_arguments 呼叫時之 argument(s) 35 * @return 36 * @name CeL.IO.file 37 * @constant 38 * @inner 39 * @ignore 40 */ 41 var code_for_including = function() { 42 43 /** 44 * null module constructor 45 * @class 檔案操作相關之 function。 46 */ 47 CeL.IO.file 48 = function() { 49 // null module constructor 50 }; 51 52 /** 53 * for JSDT: 有 prototype 才會將之當作 Class 54 */ 55 CeL.IO.file 56 .prototype = { 57 }; 58 59 60 61 62 // path處理 ------------------------------------------------------- 63 64 // path,mode=1:去除檔名,只餘目錄,如輸入http://hostname/aaa/bbb/ccc得到http://hostname/aaa/bbb/ 尚未處理:: * ? 65 //reducePath[generateCode.dLK]='dirSp,dirSpR'; 66 function reducePath(p,m){ 67 //alert(typeof p+'\n'+p); 68 if(!(p=''+p))return; 69 var t; 70 if(t=p.match(/^"([^"]*)/))p=t[1]; 71 if(t=p.match(/(.*)\|<>/))p=t[1]; 72 //Windows environment variables在真實path前,尚未測試! 73 if(typeof WinEnvironment=='object'&&(t=p.match(/%(.+)%/g)))for(i in t) 74 if(WinEnvironment[i])p.replace(new RegExp(i,"ig"),WinEnvironment[i]); 75 p=p.replace(new RegExp(dirSp=='/'?'\\\\':'/',"g"),dirSp); 76 if(m&&(t=p.lastIndexOf(dirSp))!=-1&&t+1!=p.length)p=p.slice(0,t+1);//去除檔名:假如輸入sss/ddd,會把ddd除去!需輸入sss/ddd/以標示ddd為目錄 77 //p=p.replace(new RegExp(dirSp+dirSp,'g'),dirSp); // \\→\,未考慮到'\\pictures\scenic\canyon.bmp'的情況 78 return p.replace(new RegExp('^(\\.'+dirSpR+')+'),'') // .\→'' 79 .replace(new RegExp(dirSpR+'(\\.'+dirSpR+')+','g'),dirSp) // \.\→\ 80 .replace(new RegExp('[^.'+dirSpR+']+'+dirSpR+'\\.\\.'+dirSpR,'g'),''); // xx\..\→'' 81 } 82 //alert(reducePath('http://hostname/../aaa/bbb/../ccc/../ddd',1)); 83 84 // 去除hostname等,如輸入http://hostname/aaa/bbb/ccc得到aaa/bbb/ccc/ 85 // 假如輸入的格式不正確,可能得出不預期的回應值! 86 /* 對dirSp.length>1的情形(嚴謹) 87 function getPathOnly(p){ 88 //discard hash & search 89 var i=p.lastIndexOf('?'),j=p.lastIndexOf('#'),dirSpL=dirSp.length; 90 if(i==-1)i=j;else if(j!=-1&&i>j)i=j;if(i!=-1)p=p.slice(0,i); 91 // 去除http://hostname/等 92 if(p.slice(0,5)=='file:///')p=p.substr('file:///'.length); // 對file:///特別處理! 93 else if((i=p.indexOf(':'+dirSp+dirSp))!=-1&&(i=p.indexOf(dirSp,i+(':'+dirSp+dirSp).length))!=-1))p=p.substr(i+dirSpL); // http://hostname/path→path 94 else if(p.slice(0,dirSpL)==dirSp) 95 // /usr/local/→usr/local/ 96 if(p.substr(dirSpL,dirSpL)!=dirSp)p=p.substr(dirSpL); 97 // 去除\\hostname\ 98 else if((i=p.indexOf(dirSp,dirSpL+dirSpL))>dirSpL+dirSpL)p=p.substr(i+dirSpL); 99 // \\\zzzz的情形:不合法的路徑 100 else if(i!=-1)throw new Error(1,'illegal path:'+p); 101 return p; 102 } 103 */ 104 // 對dirSp.length==1的情形簡化 105 //getPathOnly[generateCode.dLK]='dirSp';//,isFile 106 function getPathOnly(p){ 107 //discard hash & search 108 var i=p.lastIndexOf('?'),j=p.lastIndexOf('#'); 109 if(i==-1)i=j;else if(j!=-1&&i>j)i=j;if(i!=-1)p=p.slice(0,i); 110 // 去除http://hostname/等 111 if(p.slice(0,8)=='file:///')p=p.substr(8); // 對file:///(應該是file:)特別處理! 112 else if((i=p.indexOf(':'+dirSp+dirSp))!=-1&&(i=p.indexOf(dirSp,i+3)!=-1))p=p.substr(i+1); // http://hostname/path→path 113 else if(p.charAt(0)==dirSp) 114 // /usr/local/→usr/local/ 115 if(p.charAt(1)!=dirSp)p=p.substr(1); 116 // 去除\\hostname\ 不去除:.replace(/[^\\]+$/,'') 117 else if((i=p.indexOf(dirSp,2))>2)p=p.substr(i+1); 118 // \\\zzzz的情形:不合法的路徑 119 else if(i!=-1)throw new Error(1,'illegal path:'+p); 120 if(typeof isFile=='function'&&isFile(p)) // !isWeb()&&~ 121 p=p.replace(new RegExp(dirSpR+'[^'+dirSpR+']+$'),dirSp); 122 return p; 123 } 124 125 126 127 128 /* 2003/10/1 15:57 129 pn(path now)相對於bp(base path)之path(增加../等) 130 */ 131 //relative_path[generateCode.dLK]='reducePath,is_absolute_path,same_length,dirSp,dirSpR'; 132 //,WScript,WshShell 133 function relative_path(bp,pn){ 134 if(!pn)pn=typeof location=='object'?location.href:typeof WScript=='object'?WScript.ScriptFullName:''; 135 if(!bp)bp=typeof location=='object'?location.href:typeof WshShell=='object'?WshShell.CurrentDirectory:typeof WScript=='object'?WScript.ScriptFullName:''; 136 //alert('relative_path: parse 1\n'+bp+'\n'+pn); 137 var p=reducePath(pn); 138 if(!p)return; 139 var d=reducePath(bp,1); 140 if(!d||!is_absolute_path(d))return p; // bp需要是絕對路徑 141 142 //alert('relative_path: parse 2\n'+d+'\n'+p); 143 if(!is_absolute_path(p)){ // p非絕對路徑時先處理成絕對路徑 144 var q=p.indexOf(dirSp,1); // 預防第一字元為dirSp 145 if(q==-1)q=p;else q=p.slice(0,q); // 取得第一識別用目錄名 146 //alert('relative_path: parse 3\n'+d+'\n'+q); 147 q=d.indexOf(q); 148 if(q==-1)return p; 149 p=d.slice(0,q)+p; 150 151 /* 152 var i=0,q=p.split(dirSp),s=new Array(q.length),a=-1,P,bigPC=0,bigP; 153 // 找出最大連續相同路徑:尚未最佳化 154 for(i=0;i<q.length;i++){ 155 if(a==-1)P=q[i];else P+=dirSp+q[i]; 156 if(d.indexOf(P)==-1){if(a!=-1&&s[a]>bigPC)bigPC=s[a],bigP=P;a=-1;} 157 else{if(a==-1)a=i;++s[a];} 158 } 159 d=d.indexOf(bigP); 160 */ 161 } 162 var s=same_length(p,d); 163 164 //alert('dirSp: '+dirSp+'\npath now:\n '+p+'\nbase path:\n '+d+'\nsame: '+s); 165 //alert(p+'\n'+d+'\n'+s+'\n'+d.substr(s)+'\n'+d.substr(s).match(new RegExp(dirSp,'g')).length); 166 //pLog(d.charAt(s-1)+','+d.slice(0,s)+':'+s+','+d.slice(0,s).lastIndexOf(dirSp)); 167 if(s>0&&d.charAt(s-1)!=dirSp)s=d.slice(0,s).lastIndexOf(dirSp)+1; 168 return s>0?d.substr(s).replace(new RegExp('([^'+dirSpR+']+'+dirSpR+')','g'),'..'+dirSp)+p.substr(s):p; 169 } 170 // 想要保持 Protocol,但卻是不同機器時 http://nedbatchelder.com/blog/200710.html#e20071017T215538 171 //alert(relative_path('//lyrics.meicho.com.tw/game/game.pl?seg=diary21','cgi-bin/game/photo/'));WScript.Quit(); 172 173 174 175 CeL.IO.file 176 . 177 /** 178 * determine base path. 179 * 給定 base path 的結構後,藉由 path_now 推測 base path 的 full path. 180 * cf. 181 * @param {String} base_path_structure base path 的範本結構 182 * @param {String} path_now 183 * @return {String} 推測的 base path full path 184 * @example 185 * alert(determine_base_path('kanashimi/www/cgi-bin/game/')); 186 * @requres reducePath,getPathOnly,dirSp,dirSpR 187 * @memberOf CeL.IO.file 188 */ 189 determine_base_path=function (base_path_structure, path_now) { 190 if (!path_now) 191 path_now = library_namespace.get_base_path(); 192 193 var p = reducePath(path_now, 1); 194 if (!p) 195 return; 196 if (!base_path_structure) 197 return p; 198 199 var i, j, k, t, 200 // or use .split() 201 d = getPathOnly(reducePath(base_path_structure, 1)) 202 .match(new RegExp('([^' + dirSpR + ']+' + dirSpR + ')', 'g')); 203 if (!d) 204 return; 205 206 for (i = 0, t = ''; i < d.length; i++) 207 if (p.lastIndexOf(dirSp + d[i]) !== -1) { 208 t = dirSp; 209 while (d[i] && (k = p.lastIndexOf(t + d[i])) !== -1) 210 j = k, t += d[i++]; 211 while (d[i]) 212 t += d[i++]; 213 break; 214 } 215 if (!t) 216 //alert("Can't find base directory of this file!\n" + path_name + '\n\nTreat base directory as:\n' + p); 217 return p; 218 219 //alert('determine_base_path:\nbp='+bp+'\npn='+pn+'\n\n'+p.slice(0,j)+'\n'+t+'\n'+(t.replace(new RegExp('([^'+dirSpR+']+'+dirSpR+')','g'),' ').length-1)); 220 return p.slice(0, j) + t; 221 }; 222 223 224 CeL.IO.file 225 . 226 /** 227 * cf: getFN() 228 * @param {String} path path name 229 * @return 230 * @memberOf CeL.IO.file 231 */ 232 parse_path=function (path) { 233 if (typeof path !== 'string' || !path) 234 return; 235 236 var path_data = { 237 oInput : path 238 }, m; 239 240 if (m = path.match(/^(([A-Za-z]):\\)(([^\\]+\\)*)([^\\]+)?$/)) 241 path_data.drive = m[2], 242 path_data.path_name = m[3], 243 path_data.file_name = m[5]; 244 else if (m = path 245 .match(/^file:\/\/\/([A-Za-z]):\/(([^\/]+\/)*)([^\/]+)?$/)) 246 path_data.drive = m[1], 247 path_data.path_name = m[2].replace(/\//g, '\\'), 248 path_data.file_name = m[4].replace(/\//g, '\\'); 249 250 path_data.path = path_data.path_name + path_data.file_name; 251 path_data.location = path_data.drive + ':\\' + path_data.path; 252 path_data.directory = path_data.drive + ':\\' + path_data.path_name; 253 254 return path_data; 255 }; 256 257 258 CeL.IO.file 259 . 260 /** 261 * is absolute or relative path, not very good solution 262 * @param {String} path 263 * @return 264 * @requires dirSp,dirSpR 265 * @memberOf CeL.IO.file 266 */ 267 is_absolute_path=function (path) { 268 //alert(typeof path + '\n' + path); 269 return path 270 && (dirSp === '/' && path.charAt(0) === dirSp || new RegExp( 271 '^(\\\\|[A-Za-z]+:)' + dirSpR).test(path)) 272 // ?true:false 273 ; 274 }; 275 276 277 // 轉成path(加'\') 278 function turnToPath(p){return p?p+(p.slice(-1)=='\\'?'':'\\'):'';} 279 // 僅取得path部分(包括 dirSp),不包括檔名。 280 //getFilePath[generateCode.dLK]='dirSp'; 281 function getFilePath(p){ 282 var i=p.lastIndexOf(dirSp); 283 if(i==-1)p+=dirSp; // 相對路徑? 284 else if(i<p.length-1)p=p.slice(0,i+1); // 取得path部分 285 return p; 286 } 287 /* 傳回包括檔名之絕對/相對路徑,假如是資料夾,也會回傳資料夾路徑。可包含'.','..'等 the return value include ? # 288 在Win/DOS下輸入'\'..會加上base driver 289 若只要相對路徑,可用reducePath()。取得如'..\out'的絕對路徑可用getFP('../out',1) 290 */ 291 //getFP[generateCode.dLK]='determine_base_path,reducePath,is_absolute_path,getPathOnly,relative_path'; 292 function getFP(p,m,bp){ // path,mode=0:傳回auto(維持原狀),1:傳回絕對路徑,2:傳回相對路徑,base path 293 //old: return (p.lastIndexOf('\\')==-1&&p.lastIndexOf('/')==-1?getFolder(getScriptFullName()):'')+p;//getF 294 if(!p)return''; 295 if(p.charAt(0)=='\\'&&determine_base_path(bp).match(/^(\\\\|[A-Za-z]+:)/))p=RegExp.$1+p; 296 p=reducePath(p); 297 if(m==1){ 298 if(!is_absolute_path(p))p=reducePath((bp?getPathOnly(bp):determine_base_path())+p); // 當為相對路徑時前置base path 299 }else if(m==2&&is_absolute_path(p))p=relative_path(determine_base_path(bp),p); 300 return p; 301 } 302 // 傳回檔名部分,the return value include ? # 303 //getFN[generateCode.dLK]='getFP,dirSp'; 304 function getFN(p,bp,m){ // path,base path,mode=0:檔名,1:(當輸入為不可信賴的字串時)去除檔名中不允許的字元,割掉? #等 305 p=getFP(p,0,bp); 306 p=p.slice(p.lastIndexOf(dirSp)+1); // 不能用.substr(p.lastIndexOf(dirSp))+dirSp,因為p.lastIndexOf(dirSp)可能==-1 // 比起(m=p.lastIndexOf(dirSp))==-1?p:p.substr(m+1);此法比較直接,不過感覺多一道手續… 307 if(m){ 308 if(p.match(/[#?]/))p=p.substr(0,RegExp.lastIndex-1); 309 p=p.replace(/[\\\/:*?"<>|]/g,'_');//[ \.] // 去除檔名中不允許的字元 310 } 311 return p; 312 } 313 // 傳回檔案/資料夾物件 FileSystemObjectのバグ(制限)で、環境によっては2G以上の領域を認識できません。WSH5.6ではこのバグが修正されています。 314 //getF[generateCode.dLK]='isFile,dealShortcut,getFP,dirSp,getFolder,initWScriptObj'; 315 function getF(p,m,bp){ // path,mode=0:auto(維持原狀),1:絕對路徑,2:相對路徑,base path 316 try{return isFile(p=dealShortcut(getFP(p,m,bp),1))?fso.GetFile(p):fso.GetFolder(p);} 317 catch(e){return p.indexOf(dirSp)==-1?getF(getFolder(WScript.ScriptFullName)+p,m,bp):null;} 318 } 319 //alert(getFP('\program files\\xxx\\xxx.exe',2)); 320 321 322 323 324 325 return ( 326 CeL.IO.file 327 ); 328 }; 329 330 //=================================================== 331 332 CeL.setup_module(module_name, code_for_including); 333 334 }; 335