<% /* $Revision$ $Id$ File: FlexFiles.inc.asp Description: Parameters: Context: Note: pModule, pKey en pSubpath worden genormaliseerd tot simpele/veilige padnamen pickfile heeft als bijeffect dat je een bijlage uit de lijst kunt kiezen */ var fso = Server.CreateObject("Scripting.FileSystemObject"); // Die hebben we hier *zo* vaak nog. function bepaalNiveau(pModule, pNiveau) { if (pModule == "MLD") { if ("MO".indexOf(pNiveau) >=0) return pNiveau; else INTERNAL_ERROR_PNIVEAU; } if (pModule == "PRS") { if ("ABCP".indexOf(pNiveau) >=0) return pNiveau; else INTERNAL_ERROR_PNIVEAU; } // return pModule.substr(0,1) zou waarschijnlijk ook voldoen switch (pModule) { case "ALG": pNiveau = "A"; break; case "BES": case "BEZ": pNiveau = "B"; break; case "CNT": pNiveau = "C"; break; case "FIN": pNiveau = "F"; break; case "INS": pNiveau = (pNiveau ? pNiveau : "I"); // S voor sleutel (en toekomst: C voor controle/inspectie) break; case "MRK": pNiveau = "M"; break; case "RES": pNiveau = "R"; break; case "FAQ": pNiveau = "F"; break; } return pNiveau; } var cache_bepaalKenmerkGegevens = []; // vanuit API2 mogelijk voor heel veel records aangeroepen function bepaalKenmerkGegevens(pModule, pKenmerkkey) { if (pKenmerkkey == null) return {kenmerk_omschrijving: null, kenmerk_type: null}; var cache_code = pModule + "_" + pKenmerkkey; if (cache_code in cache_bepaalKenmerkGegevens) return cache_bepaalKenmerkGegevens[cache_code]; var table; var srttable; switch (pModule) { case "ALG": table = "alg_kenmerk"; break; case "BES": table = "bes_kenmerk"; srttable = "bes_srtkenmerk"; break; case "BEZ": table = "bez_kenmerk"; break; case "CNT": table = "cnt_kenmerk"; srttable = "cnt_srtkenmerk"; break; case "FIN": table = "fin_kenmerk"; break; case "INS": table = "ins_kenmerk"; srttable = "ins_srtkenmerk"; break; case "MLD": table = "mld_kenmerk"; srttable = "mld_srtkenmerk"; break; case "PRS": table = "prs_kenmerk"; break; case "RES": table = "res_kenmerk"; srttable = "res_srtkenmerk"; break; case "FAQ": table = "faq_kenmerk"; break; } var sql = "SELECT " + lcl.xsql((srttable? "sk." + srttable : "k." + table) + "_omschrijving", (srttable? "sk." + srttable : "k." + table) + "_key") + " kenmerk_omschrijving" + " , " + (srttable? srttable : table) + "_kenmerktype kenmerk_type" + " FROM " + table + " k" + (srttable ? " , " + srttable + " sk" : "") + " WHERE k." + table + "_key = " + pKenmerkkey + (srttable ? " AND k." + srttable + "_key = sk." + srttable + "_key" : "") var oRs = Oracle.Execute(sql); var kenmerk_omschrijving = oRs("kenmerk_omschrijving").Value; var kenmerk_type = oRs("kenmerk_type").Value; oRs.close(); cache_bepaalKenmerkGegevens[cache_code] = {kenmerk_omschrijving: kenmerk_omschrijving, kenmerk_type: kenmerk_type} return cache_bepaalKenmerkGegevens[cache_code]; } function subfolderNew(pNiveau, pId) { return pNiveau + "__NEW__" + pId; } function subfolderKey(pNiveau, pKey) { var keyStr = "0000000" + pKey; var subfolder = pNiveau + keyStr.substr(keyStr.length-7,4) + "___/" + pNiveau + pKey; return subfolder; } // Codering: M=MLD:K=12345:S=587:N=M:R=R400x400,F=AMSG0-01-A047.JPG function flexProps2(flexcode) { var Module, Key, Subpath, Niveau, getparams; var getparams = { getFiles: true }; var codes = flexcode.split(":"); for (var i = 0; i < codes.length; i++) { var code = codes[i].substr(0,1); var data = codes[i].substr(2); switch (codes[i].substr(0,1)) { case "M": Module = data; break; case "K": Key = data; break; case "S": Subpath = data; // Doorgaans kenmerk key break; case "N": Niveau = data; break; case "F": getparams.getFile = data; break; case "R": getparams.resizeCode = data; break; } } var params = flexProps(Module, Key, Subpath, Niveau, getparams); return params; } function flexProps(pModule, pKey, pSubpath, pNiveau, params) { params = params || {}; var result = { directlink: false, files: [] }; switch (pModule) { case "FGII": // Facilitor Graphics result.AttachRootPath = S("fg_dwf_path_concept"); result.AttachPath = result.AttachRootPath; result.searchfile = true; result.multi = true; result.extFilter = "dwf"; break; case "FGIIV": // Vluchtplannen result.AttachRootPath = S("fg_vlucht_path"); result.AttachPath = result.AttachRootPath + "V" + pKey + "/"; result.pickfile = true; result.multi = true; result.extFilter = "dwf"; break; case "FGIIS": // Facilitor Graphics symbolen result.AttachRootPath = S("fg_symbols_path"); result.AttachPath = result.AttachRootPath; result.pickfile = true; result.multi = true; result.extFilter = "dwf"; break; case "FGIIP": result.AttachRootPath = S("fg_dwf_path_prj"); result.AttachPath = result.AttachRootPath + pKey + "/"; result.pickfile = true; result.multi = true; result.extFilter = "dwf"; break; case "BESPH": // Bestanden zijn te vinden op prs_bedrijf.prs_bedrijf_image_loc of ...cust/xxxx/photos/bes/[disc_key]/ // Wij kunnen alleen bestanden naar ...cust/xxxx/photos/bes/[disc_key]/ uploaden. result.AttachRootPath = Server.MapPath(S("bes_image_path")); result.AttachPath = result.AttachRootPath + "/" + pKey + "/"; result.extFilter = "jpg|png"; result.pickfile = true; result.multi = true; result.regexp = S("bes_photo_size"); result.directlink = true; break; case "INSPH": // Bestanden zijn te vinden op ...cust/x/photos/ins result.AttachRootPath = Server.MapPath(S("ins_image_path")); result.AttachPath = result.AttachRootPath + "/"; result.extFilter = "jpg|png"; result.pickfile = true; result.multi = true; result.regexp = S("ins_photo_size"); result.directlink = true; break; case "MLDS": // Stdmelding symbolen result.AttachRootPath = Server.MapPath(S("mlds_image_path")); result.AttachPath = result.AttachRootPath + "/"; result.pickfile = true; result.multi = true; result.extFilter = "jpg|png"; result.regexp = S("mld_photo_size"); result.directlink = true; break; case "ALG": case "BES": case "BEZ": case "CNT": case "FIN": case "INS": case "MLD": case "PRS": case "RES": case "FAQ": // Bestanden zijn nu te vinden on ...cust/x/flexfiles/[module]/[subfolder]/[key]/[kenmerk_key] result.AttachRootPath = S("flexFilesPath"); result.AttachPath = result.AttachRootPath + "/" + pModule + "/"; result.AttachPath += (pKey > 0? subfolderKey(bepaalNiveau(pModule, pNiveau), pKey) : subfolderNew(bepaalNiveau(pModule, pNiveau), user_key + "_" + getQParam("tmpfolder"))); result.AttachPath += "/" + pSubpath + "/"; // de volgende twee wil ik liever met de kenmerk-key opzoeken in de database // maar dat is even te veel werk hier. De url is toch hmac-protected result.extFilter = getQParam("extFilter", S("flexExtensionFilter")); result.encrypt = getQParamInt("encrypt", 0) == 1; result.regexp = getQParam("pregexp", ""); //P800x600 cropt/resized naar 800x600 if (pModule == "ALG" && params) { result.trackcode = pModule + params.alglevel + "UP"; var kenmerk_geg = bepaalKenmerkGegevens(pModule, pSubpath); result.kenmerkoms = kenmerk_geg.kenmerk_omschrijving; result.kenmerktype = kenmerk_geg.kenmerk_type; } else if (pModule != "FAQ") { if (pModule == "MLD" && pNiveau == "O") result.trackcode = "ORD" + "UPD"; else result.trackcode = pModule + "UPD"; var kenmerk_geg = bepaalKenmerkGegevens(pModule, pSubpath); result.kenmerkoms = kenmerk_geg.kenmerk_omschrijving; result.kenmerktype = kenmerk_geg.kenmerk_type; } break; case "RESPH": case "RESPHA": case "RESPHD": // Bestanden zijn te vinden op ...cust/x/photos result.AttachRootPath = Server.MapPath(S("res_image_path")); if (pModule == "RESPHA") result.AttachRootPath += '/artikel'; if (pModule == "RESPHD") result.AttachRootPath += '/deel'; result.AttachPath = result.AttachRootPath + "/"; result.extFilter = "jpg"; result.searchfile = true; result.multi = true; result.regexp = S("res_photo_size"); result.directlink = true; if (typeof pKey == "string") params.filter = pKey; break; case "MRK": result.AttachRootPath = Server.MapPath(S("mrk_image_path")); result.AttachPath = result.AttachRootPath + "/"; result.AttachPath += (pKey > 0? subfolderKey("M", pKey) : subfolderNew("M", Session.SessionId)); result.AttachPath += "/1/"; result.multi = false; // vooralsnog maar eentje result.extFilter = "jpg|png"; result.regexp = S("mrk_photo_size"); result.directlink = true; break; case "SML": result.AttachRootPath = Server.MapPath(S("prs_image_path")); result.AttachPath = result.AttachRootPath + "/"; result.AttachPath += subfolderKey("P", pKey); result.AttachPath += "/SML/"; result.multi = false; // vooralsnog maar eentje result.forcesingle = true; // verwijder eventuele anderen result.extFilter = "jpg"; result.regexp = S("sml_photo_size"); // "r200x150", Resized naar binnen 200x150 (zonder crop, met behoud aspect ratio) result.directlink = true; break; case "MENU": result.AttachRootPath = Server.MapPath(S("menu_image_path")); result.AttachPath = result.AttachRootPath + "/"; result.multi = true; result.extFilter = S("flexExtensionFilter"); // was "jpg|png"; maar tegenwoordig ook andere bestanden result.regexp = S("menu_photo_size"); result.directlink = true; break; case "BDRADR": result.AttachRootPath = S("bdradrfiles_path"); result.AttachPath = result.AttachRootPath + "/"; result.pickfile = true; result.multi = true; result.extFilter = S("flexExtensionFilter"); // Mag in principe alles zijn break; default: INTERNAL_ERROR_MODULE; } if (result.AttachRootPath.indexOf("..") > -1 || // paranoia mode, should never happen result.AttachPath.indexOf("..") > -1) { __DoLog("Bad attach path with '..'\nAttachRootPath: {0}\nAttachPath: {1}".format(result.AttachRootPath, result.AttachPath), '#F00'); INTERNAL_ERROR_BAD_ATTACHPATH; } result.AttachRootPath = result.AttachRootPath.replace("..", "_"); result.AttachPath = result.AttachPath.replace("..", "_"); if (params.getFile) { if (fso.FileExists(result.AttachPath + params.getFile)) { var fsoFile = fso.GetFile(result.AttachPath + params.getFile); var filedata = oneFileInfo(fsoFile, result, pModule, pKey, pSubpath, pNiveau, params); result.files.push(filedata); } } else if (params.getFiles) // Haal alle bijlagen er bij. { if (fso.FolderExists(result.AttachPath)) { __Log("Scanning {0} for files".format(result.AttachPath)); var f = fso.GetFolder(result.AttachPath); var fc = new Enumerator(f.files); var totalfiles = 0; for (; !fc.atEnd(); fc.moveNext()) { totalfiles ++; var fsoFile = fc.item(); var fName = fsoFile.Name; // function escapeRegExp(str) // { // return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); // } if (params.filter && !(new RegExp(params.filter, "i").test(fName))) continue; var filedata = oneFileInfo(fsoFile, result, pModule, pKey, pSubpath, pNiveau, params); result.files.push(filedata); } __Log("Found {0}/{1} files".format(result.files.length, totalfiles)); } } result.isAllowedName = function _isAllowedName(FileName) { if (result.extFilter) { var regFilter = result.extFilter; regFilter = regFilter.replace(/( |,|;)/g,"|"); // Altijd | karakter regFilter = ".*\\." + "(" + regFilter + ")$"; // er moet een punt voor en extensie is aan het einde } else regFilter = ".*"; return (new RegExp(S("flexAllowedExt"), "ig").test(FileName) && new RegExp(regFilter, "ig").test(FileName)); } return result; } function oneFileInfo(fsoFile, result, pModule, pKey, pSubpath, pNiveau, params) { var fName = fsoFile.Name; var oCrypto = new ActiveXObject("SLNKDWF.Crypto"); var filedata = { name: fName, date: new Date(fsoFile.DateLastModified), size: fsoFile.Size, digest: oCrypto.hex_sha1_file(result.AttachPath + fName) } if (params.getFileEncoded == "base64" || params.getFileEncoded == "hex") { // Verleidelijk om new ActiveXObject("SLNKDWF.Crypto").base64 in te zetten // Die kan echter alleen text-input aan, niet binary data var oStream = Server.CreateObject("ADODB.Stream"); oStream.Open; oStream.Type = 1; // adTypeBinary oStream.LoadFromFile(result.AttachPath + fName); var oXML = new ActiveXObject("Msxml2.DOMDocument.6.0"); var oNode = oXML.createElement("encodeddata"); oNode.dataType = params.getFileEncoded == "base64"?"bin.base64":"bin.hex"; // Zeer snelle oplossing oNode.nodeTypedValue = oStream.read(oStream.Size); filedata.data = oNode.text.replace(/\n/g, ""); // Ik wil de newlines er niet in hebben oStream.Close(); } // IIS 7+ geeft 404.11 op een plus-teken in een url. Historisch hebben we daar // vele bestanden mee en die hernoemen we hier on-the-fly. Er kan nu een // afwijking ontstaan bij 'F' kenmerken. die in de database zijn opgeslagen // maar dat nemen we voor lief. In de praktijk is dat nooit probleem. // Als we *niet* hernoemen hebben we grotere problemen if (fName.toLowerCase() != safe.filename(fName).toLowerCase()) { filedata.name = safe.filename(fName); __DoLog("Auto renaming {0} to safer {1}".format(result.AttachPath + fName, result.AttachPath + filedata.name), "#FFFF00"); fso.MoveFile(result.AttachPath + fName, result.AttachPath + filedata.name); } // Resize een plaatje eventueel if (params.resizeCode && filedata.name.match(/\.(png|jpg|jpeg)$/i)) { var file = result.AttachPath + filedata.name; var Format = params.resizeCode.match(/^([RrCc])(\d*)x(\d*)$/i); // R800x600 if (Format && Format.length == 4) { var oIMG = new ActiveXObject("SLNKDWF.ImageConvert"); try { oIMG.Open(result.AttachPath + filedata.name); } catch(e) { __Log("Kan plaatje {0} niet laden {1}".format(result.AttachPath + filedata.name, e.description)); // Gewoon negeren return; } var RrCc = Format[1]; var h0 = h = parseInt(Format[2], 10); var w0 = w = parseInt(Format[3], 10); if (RrCc == "R" || RrCc == "r") // Dan niet croppen maar aspect ratio behouden { if (oIMG.Width * h > w * oIMG.Height) h = oIMG.Height / oIMG.Width * w; else w = oIMG.Width / oIMG.Height * h; } if (oIMG.Height < h || oIMG.Width < w) // Zou er iets vergroot gaan worden. { if (RrCc == "R" || RrCc == "C") // Dan zijn we streng en eisen we minimale afmeting { result.message = L("lcl_shared_photo_small").format(h0, w0, oIMG.Height, oIMG.Width); // DeleteFile(params.AttachPath + result.safefilename); } else // Dan maar niet, we vergroten niet. { h = oIMG.Height; w = oIMG.Width; } } if (!result.message && (oIMG.Height != h || oIMG.Width != w)) { try { __Log("Resize/Cropping from w=" + oIMG.Width + " h=" + oIMG.Height + " to w=" + w + " h=" + h); oIMG.Width = w; oIMG.Height = h; // TODO: Originele type behouden of altijd naar het compactere jpg? var tempfile = Server.MapPath(rooturl + '/temp/img_' + customerId + '_' + filedata.digest + "_" + params.resizeCode + ".jpg"); oIMG.SaveAs(tempfile); filedata.resized = tempfile; if (__Logging == 0) filedata.tempdelete = tempfile; // Moet aanroeper opruimen } catch (e) { result.message = L("lcl_shared_thumbnail_error") + e.description; // Gewoon opruimen // DeleteFile(params.AttachPath + result.safefilename); } } } } if (params.api2name) { var deepurl = HTTP.urlzelf() + "/api2/{0}/{1}/attachments/{2}/{3}".format( params.api2name, pKey, pSubpath, safe.filename(filedata.name) // onze filename is ondertussen dusdanig safe // dat ik het zonder encoding aandurf ); filedata.deepurl = deepurl; } else { if (result.directlink) { filedata.deepurl = HTTP.urlzelfnoroot() + S("res_image_path") + filedata.name; } else // Alleen streaming, bestand staat buiten webroot? { var deepurl = HTTP.urlzelf() + "/appl/shared/BijlagenStream.asp" + "?module=" + pModule + "&key=" + pKey + (pNiveau? "&niveau=" + pNiveau : "") + "&kenmerk_key=" + pSubpath + "&filename=" + Server.URLencode(filedata.name); filedata.deepurl = protectQS.create(deepurl); } } return filedata; } // Plaats automatisch een web.config die asp-Execute van bestanden verbiedt function checkWebconfig(AttachRootPath) { return; // FSN#32282 Geeft te veel problemen if (fso.FolderExists(params.AttachRootPath) && !fso.FileExists(AttachRootPath + "/web.config")) { __DoLog("Placing web.config file in " + AttachRootPath); fso.CopyFile(Server.MapPath("./web_sample.config"), AttachRootPath + "/web.config"); } } function DeleteFile(fullpath) { try { fso.DeleteFile(fullpath, true); } catch (e) { __DoLog("Verwijderen " + fullpath + " mislukt: " + e.description, "#FFFF00"); }; } function CreateFullPath(sPath) { if (!fso.FolderExists(sPath)) { while (!fso.FolderExists(sPath)) { var sParent = sPath; while (sParent && !fso.FolderExists(sParent)) { var sChild = sParent; var sParent = fso.GetParentFolderName(sChild); } if (!sParent) { __DoLog("Cannot create folder {0}, parentfolder does not exist.".format(sPath), "#f00"); INTERN_ERROR_BAD_PATH; } oFolder = fso.CreateFolder(sChild); } } } // Verplaats alle bestanden van één folder // Verplaatst geen subfolders function MoveFlexfiles(vAttachPath, vAttachPath2) { if (vAttachPath == vAttachPath2) { __Log("MoveFlexfiles Skip want twee keer " + vAttachPath); return; } try { var fso = Server.CreateObject("Scripting.FileSystemObject") __Log("Zoeken " + vAttachPath); if (fso.FolderExists(vAttachPath)) { var oFolder = fso.GetFolder(vAttachPath); if (oFolder.files.count > 0) // Anders error { CreateFullPath(vAttachPath2); // het 1000-tal was er misschien nog niet. __Log("Verplaats inhoud " + vAttachPath + "/*.* naar " + vAttachPath2 + "/"); fso.MoveFile (vAttachPath + "/*.*", vAttachPath2 + "/"); } fso.DeleteFolder(vAttachPath); } } catch(ee) { __DoLog("Moving files from " + vAttachPath + "
to " + vAttachPath2 + " failed:
" + ee.description, "#FFFF00"); } fso = null; } // JavaScript is erg slecht in binary data, gebruik streams // gebaseerd op Antonin Foller, http://www.motobit.com // Binary - VT_UI1 | VT_ARRAY data To convert To a string // getest met encoding "bin.hex" en "bin.base64" function encodedString2File(safefullname, attachmentString, encoding) { var BinaryStream = XXXXDecode(attachmentString, encoding); BinaryStream.SaveToFile(safefullname, 2); // adSaveCreateOverWrite } function XXXXDecode(vCode, encoding) { var oXML, oNode oXML = new ActiveXObject("Msxml2.DOMDocument.6.0"); oNode = oXML.createElement("encodeddata"); oNode.dataType = encoding; // Zeer snelle oplossing oNode.text = vCode var Binary = oNode.nodeTypedValue; var adTypeText = 2; var adTypeBinary = 1; // Create Stream object var BinaryStream = new ActiveXObject("ADODB.Stream"); // Specify stream type - we want To save binary data. BinaryStream.Type = adTypeBinary; // Open the stream And write binary data To the object BinaryStream.Open(); BinaryStream.Write(Binary); // Change stream type To text/string BinaryStream.Position = 0; BinaryStream.Type = adTypeText; // Specify charset For the output text (unicode) data. BinaryStream.CharSet = "us-ascii"; // Open the stream And get text/string data from the object return BinaryStream; } // IE doet een beetje raar als er een puntkomma in de content-disposition filenaam zit, dan negeert hij de rest // Een bestand test.exe;.txt wordt dan zo maar 'uitgevoerd' // Een # in de naam gaat ook raar: IE9 vervangt die zelf al door een _ maar daar vertrouwen wij niet op // We hebben er verder geen probleem mee dat ze geupload worden (en ze bestaan ook), anders was // toevoegen aan safe.filename natuurlijk logischer. function safeContentName(fname) { return safe.filename(fname).replace(/[\;\#]+/g, "_") } function StreamFile(filePath, filename, mime, pcontentdp) { if (getQParamInt("zipfile", 0) == 1) { zipfile(filePath + "/" + safe.filename(filename), filename); } pcontentdp = pcontentdp || "attachment"; try { var oStream = Server.CreateObject("ADODB.Stream"); oStream.Open; oStream.Type = 1; // adTypeBinary oStream.LoadFromFile(filePath + "/" + safe.filename(filename)); Response.clear; Response.contenttype = mime; // Known problems: // "Plus+Quote'Spatie Rareé&.txt" non-ASCII karakters in pFilename worden wel eens onbedoeld herkend als UTF8 Response.AddHeader("content-disposition", pcontentdp + "; filename= \"" + safeContentName(filename) + "\""); Response.BinaryWrite(oStream.read(oStream.Size)); Response.End(); } catch(e) { shared.simpel_page(Server.HTMLEncode(filename) + "

" + e.description + "\n

" + Server.HTMLEncode(filePath) + ""); } oStream = null; } function zipfile(fullpath, filename) { var oZIP = new ActiveXObject("SLNKDWF.Zip"); var fso = new ActiveXObject("Scripting.FileSystemObject"); var temp = Server.MapPath("../../temp/" + fso.GetTempName()); var iStream = new ActiveXObject("ADODB.Stream") iStream.Type = 2; // Text iStream.Open(); iStream.CharSet = "utf-8"; try { iStream.LoadFromFile(fullpath); } catch (e) { shared.simpel_page("Error opening " + Server.HTMLEncode(fullpath) + "

"+e.description+""); } oZIP.New(temp) //;; Helaas niet *naar* stream oZIP.ZipFromStream(filename, iStream); oZIP.Close(); iStream.Close() var oStream = new ActiveXObject("ADODB.Stream"); oStream.Open; oStream.Type = 1; // adTypeBinary oStream.LoadFromFile(temp); oStream.Position = 0; fso.DeleteFile(temp); Response.clear; Response.contenttype = 'application/zip'; Response.AddHeader("content-disposition", "attachment; filename= \"" + filename + ".zip\""); Response.BinaryWrite(oStream.read(oStream.Size)); Response.End; } %>