using System; using System.Collections.Generic; using System.Linq; using System.Web; using ETS_Data; using NLog; using System.Net.Mail; using System.IO; namespace ETS_DIP { public class WebShipUtils { /// /// componente logger /// protected Logger lg; /// /// oggetto singleton accesso classe /// public static WebShipUtils mng = new WebShipUtils(); /// /// metodo di avvio protected /// protected WebShipUtils() { lg = LogManager.GetCurrentClassLogger(); } /// /// calcolo automatico path da metadati /// /// /// public static string path(docMetaDataSet metaDati) { string answ = ""; try { // calcolo valori data e maxPathLenght string aammgg = metaDati.dataDoc.ToString("yyMMdd"); int maxFullPathLenght = utils.obj.confReadInt("maxFullPathLenght"); int maxPathLenght = utils.obj.confReadInt("maxPathLenght"); // calcolo il path, ipotizzando di lasciare ad oggetto max 200 char - con pulizia eventuali doppie barre answ = string.Format("/{0}/{1}/{2}/{3}/{4}_{5}/", utils.cleanPathName(metaDati.commessa), utils.cleanPathName(metaDati.fase), metaDati.InOut, utils.cleanPathName(metaDati.fonte), aammgg, utils.shrinkString(utils.cleanPathName(metaDati.oggetto), maxPathLenght)).Replace("//", "/").Replace("//", "/").Replace("//", "/"); // se la lungh totale è > maxPathLenght (restano 260-maxPathLenght char x nome file...) trimmo oggetto! if (answ.Length > maxFullPathLenght) { // ricalcolo riducendo oggetto: maxPathLenght - (answ.Length - maxPathLenght) - con pulizia eventuali doppie barre answ = string.Format("/{0}/{1}/{2}/{3}/{4}_{5}/", utils.cleanPathName(metaDati.commessa), utils.cleanPathName(metaDati.fase), metaDati.InOut, utils.cleanPathName(metaDati.fonte), aammgg, utils.shrinkString(utils.cleanPathName(metaDati.oggetto), maxPathLenght - (answ.Length - maxFullPathLenght))).Replace("//", "/").Replace("//", "/").Replace("//", "/"); } } catch { } // return! return answ; } /// /// path caricamento temporaneo utente /// public string UserTempPath { get { string path = ""; // prima il path try { if (utils.obj.StringSessionObj("UserTempPath") != "") { path = utils.obj.StringSessionObj("UserTempPath"); } else { path = string.Format("{0}/{1}", utils.obj.confReadString("tempUplDir"), utils.obj.currUser_FS); utils.obj.setSessionVal("UserTempPath", path); } } catch (Exception exc) { lg.Info("errore check directory: {0}", exc); } return path; } } /// /// metadati documento attualmente in sessione /// public docMetaDataSet currMetaData { get { docMetaDataSet answ = new docMetaDataSet(); try { answ = (docMetaDataSet)utils.obj.objSessionObj("metaDatiDoc"); } catch { } return answ; } set { utils.obj.setSessionVal("metaDatiDoc", value); } } /// /// inizializza e restituisce un oggetto metadati da un idxFile /// /// /// public docMetaDataSet docMetaFromIdxFile(int idxFile) { docMetaDataSet currMeta = new docMetaDataSet(); try { DS_WebScip.tbDocumentiRow rigaDoc = utils.obj.taDoc.getByIdxFile(idxFile)[0]; // assegno valori meta! currMeta.commessa = rigaDoc.Commessa; currMeta.dataDoc = rigaDoc.DataDoc; currMeta.dataRic = rigaDoc.DataRic; currMeta.fase = rigaDoc.Fase; currMeta.fonte = rigaDoc.Fonte; currMeta.InOut = rigaDoc.InOut; currMeta.isRed = rigaDoc.isRed; currMeta.oggetto = rigaDoc.Oggetto; currMeta.path = rigaDoc.fullPath.Replace(utils.obj.confReadString("archiveDirRed"), "").Replace(utils.obj.confReadString("archiveDir"), ""); currMeta.reqProto = (rigaDoc.Numero > 0); // recupero tags! DS_WebScip.Tags2DocDataTable tabTags = utils.obj.taTags2Doc.getByIdxFile(idxFile); List tags = new List(); foreach (DS_WebScip.Tags2DocRow tag in tabTags) { tags.Add(tag.idxTag.ToString()); } currMeta.tags = tags; } catch (Exception exc) { lg.Error("Errore creazione oggetot meta da idxFile: {0}", exc); } return currMeta; } /// /// idxFile da editare (in sessione) /// public int idxFileEdit { get { return utils.obj.IntSessionObj("idxFileEdit"); } set { utils.obj.setSessionVal("idxFileEdit", value); } } /// /// calcola se i metadati NECESSARI siano compilati/presenti in session, ovvero /// - commessa /// - fase /// - fonte /// - oggetto /// - in/out /// - dataDoc /// public bool metaPresent { get { bool answ = false; try { answ = (currMetaData.commessa != "" && currMetaData.fase != "" && currMetaData.fonte != "" && currMetaData.oggetto != "" && currMetaData.InOut != "" && currMetaData.dataDoc.ToShortDateString() != ""); } catch { } return answ; } } /// /// nome del file da idx DB /// /// /// public static string nomeFileFromIdxFile(int idxFile) { string answ = ""; try { answ = utils.obj.taDoc.getByIdxFile(idxFile)[0].NomeFile; } catch { } return answ; } /// /// nome del file da idx DB /// /// /// public static string nomeFileFullFromIdxFile(int idxFile) { string answ = ""; try { answ = utils.obj.taDoc.getByIdxFile(idxFile)[0].Nome; } catch { } return answ; } /// /// protocollo del file da idx DB /// /// /// public static string protocolloFromIdxFile(int idxFile) { string answ = ""; try { answ = string.Format("{0}-{1}", utils.obj.taDoc.getByIdxFile(idxFile)[0].Numero, utils.obj.taDoc.getByIdxFile(idxFile)[0].Anno); } catch { } return answ; } /// /// commessa del file da idx DB /// /// /// public static string commessaFromIdxFile(int idxFile) { string answ = ""; try { answ = string.Format("{0}", utils.obj.taDoc.getByIdxFile(idxFile)[0].Commessa); } catch { } return answ; } /// /// oggetto del file da idx DB /// /// /// public static string oggettoFromIdxFile(int idxFile) { string answ = ""; try { answ = string.Format("{0}", utils.obj.taDoc.getByIdxFile(idxFile)[0].Oggetto); } catch { } return answ; } /// /// fonte del file da idx DB /// /// /// public static string fonteFromIdxFile(int idxFile) { string answ = ""; try { answ = string.Format("{0}", utils.obj.taDoc.getByIdxFile(idxFile)[0].Fonte); } catch { } return answ; } /// /// statored/pubblico da idx DB /// /// /// public static bool isRedFromIdxFile(int idxFile) { bool answ = false; try { answ = utils.obj.taDoc.getByIdxFile(idxFile)[0].isRed; } catch { } return answ; } /// /// redattore da idx DB /// /// /// public static string redattoreFromIdxFile(int idxFile) { string answ = ""; try { answ = utils.obj.taDoc.getByIdxFile(idxFile)[0].Redattore; } catch { } return answ; } /// /// path da idx DB /// /// /// public static string pathFromIdxFile(int idxFile) { string answ = ""; try { answ = utils.obj.taDoc.getByIdxFile(idxFile)[0].fullPath; } catch { } return answ; } /// /// fornisce email dato codice fornitore /// /// /// public static string emailDaCodForn(string codForn) { string answ = codForn; try { answ = utils.obj.taEmailForn.getByCodForn(codForn)[0].Email; } catch { } return answ; } /// /// converte una lista tags in una stringa unica con separatore /// /// /// /// public static string stringFromList(List tags, string separatore) { string answ = ""; if (tags.Capacity > 0) { foreach (string item in tags) { answ += string.Format("{0}{1}", item, separatore); } // tolgo ultimo separatore answ = answ.Substring(0, answ.Length - separatore.Length); } return answ; } /// /// converte una stringa unica con separatore in una lista tags /// /// /// /// public static List listFromString(string elenco, string separatore) { List answ = new List(); if (elenco.Length > 0) { char sep = Convert.ToChar(separatore); answ = elenco.Split(sep).ToList(); } return answ; } /// /// Creates an eml file to be delivered with the default mail client /// /// address that sends the email /// address to which send the email /// subject /// body /// list of attachments /// destination folder to store the file /// The complete path of the newely generated EML file public static string CreaEml(string from, string to, string subject, string body, IEnumerable attachments, string destFolder) { using (MailMessage mail = new MailMessage()) { mail.From = new MailAddress(from); mail.To.Add(to); mail.Subject = subject; mail.Body = body; if (attachments != null) foreach (var attachment in attachments) mail.Attachments.Add(attachment); SmtpClient smtpClient = new SmtpClient { PickupDirectoryLocation = destFolder, DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory }; smtpClient.Send(mail); } DirectoryInfo dir = new DirectoryInfo(destFolder); FileInfo file = dir.GetFiles("*.eml", SearchOption.TopDirectoryOnly).OrderByDescending(m => m.CreationTimeUtc).First(); // hack: inserisco il campo "non inviato" nel file di testo della email... "X-Unsent: 1" va messo all'inizio x cui rileggo file e lo riscrivo! string nomeFile = file.Name; string contenutoEmail = "X-Unsent: 1"; contenutoEmail += Environment.NewLine; StreamReader sr = file.OpenText(); contenutoEmail += sr.ReadToEnd(); sr.Close(); // scrivo nuovo testo! StreamWriter sw = file.CreateText(); sw.Write(contenutoEmail); sw.Flush(); return file.Name; } /// /// effettua operazione di archiviazione file /// /// oggetto metadati documento /// path origine del file /// path di destinazione del file /// nome del file da archiviare /// redattore /// restituisce valore INT del nuovo file archiviato public static int archiviaFile(docMetaDataSet docsData, string pathOrig, string pathDest, string nomeFile, string redattore) { Logger lg = LogManager.GetCurrentClassLogger(); int answ = 0; string autore = ""; // tolto! string numComm = ""; string annoComm = ""; // ricavo num ed anno commessa... try { numComm = docsData.commessa.Substring(0, docsData.commessa.IndexOf("-")); annoComm = docsData.commessa.Substring(docsData.commessa.IndexOf("-") + 1); } catch { } // salvo su db le info del file... int? newIdxFile = 0; utils.obj.taDoc.insertQuery(nomeFile, pathDest, utils.obj.currUserAD, docsData.reqProto, docsData.dataRic, docsData.dataDoc, numComm, annoComm, docsData.fase, docsData.fonte, docsData.oggetto, docsData.InOut, autore, redattore, docsData.isRed, ref newIdxFile); // salvo i tags! if (newIdxFile > 0) { // se ho tags... if (docsData.tags.Count > 0) { foreach (string tag in docsData.tags) { try { utils.obj.taTags2Doc.Insert((int)newIdxFile, Convert.ToInt32(tag)); } catch { } } } answ = (int)newIdxFile; } // ricalcolo nome file string newFileName = WebShipUtils.nomeFileFullFromIdxFile((int)newIdxFile); // verifico riesca a creare folder DirectoryInfo _di = fileMover.checkDir(pathDest); // controllo buon fine! bool fatto = false; if (_di != null) { string fullNameDest = string.Format("{0}/{1}", pathDest, newFileName).Replace("//", "/"); // controllo possa creare file... if (fileMover.fileCouldExist(fullNameDest)) { // sposto file fatto = fileMover.obj.muoviFile(pathOrig, pathDest, nomeFile, newFileName, true); } else { lg.Error(string.Format("Impossibile creare file con questo nome: {0}", fullNameDest)); } } // restituisco idxFile... return answ; } /// /// aggiorna file archiviato (prendendo da temp utente!) /// /// public void aggiornaFileArchiviato(string nomeFile) { lg.Info("Caricato file {0} per sostituzione", nomeFile); int idxFile = WebShipUtils.mng.idxFileEdit; // effettuo operazioni sostituzione file! docMetaDataSet docsData = WebShipUtils.mng.docMetaFromIdxFile(idxFile); string path = docsData.path; if (path != "") { // calcolo path path = string.Format("{0}{1}", utils.obj.confReadString("archiveDir"), docsData.path); // elimino file vecchio fileMover.obj.eliminaFile(path, WebShipUtils.nomeFileFullFromIdxFile(idxFile)); // aggiorno su DB utils.obj.taDoc.updateFile(idxFile, utils.obj.currUserAD, nomeFile, path); lg.Info("Aggiornato in db nome file {0} per sostituzione", nomeFile); // ricalcolo nome file string newFileName = WebShipUtils.nomeFileFullFromIdxFile(idxFile); // sposto file fileMover.obj.muoviFile(WebShipUtils.mng.UserTempPath, path, nomeFile, newFileName, true); lg.Info("Spostato file {0} per sostituzione", nomeFile); } } /// /// elimina il file archiviato e resetta metadati a empty /// /// public void deleteRecordAndFile(int idxFile) { string nomeFile = "ETS-Proto.docx"; lg.Info("Eliminato file {0} per svuotamento record", idxFile); // effettuo operazioni sostituzione file! docMetaDataSet docData = WebShipUtils.mng.docMetaFromIdxFile(idxFile); docMetaDataSet docDataEmpty = emptyDocData(DateTime.Now); string numComm = ""; string annoComm = ""; // ricavo num ed anno commessa... try { numComm = docDataEmpty.commessa.Substring(0, docDataEmpty.commessa.IndexOf("-")); annoComm = docDataEmpty.commessa.Substring(docDataEmpty.commessa.IndexOf("-") + 1); } catch { } string path = docData.path; string newPath = ""; if (path != "") { // calcolo path attuale if (docData.isRed) { path = string.Format("{0}{1}", utils.obj.confReadString("archiveDirRed"), docData.path); } else { path = string.Format("{0}{1}", utils.obj.confReadString("archiveDir"), docData.path); } newPath = string.Format("{0}{1}", utils.obj.confReadString("archiveDirRed"), docDataEmpty.path); // elimino file vecchio fileMover.obj.eliminaFile(path, WebShipUtils.nomeFileFullFromIdxFile(idxFile)); // aggiorno su DB utils.obj.taDoc.updateQuery(idxFile, utils.obj.currUserAD, docDataEmpty.dataRic, docDataEmpty.dataDoc, numComm, annoComm, docDataEmpty.fase, docDataEmpty.fonte, docDataEmpty.oggetto, docDataEmpty.InOut, docDataEmpty.isRed); //utils.obj.taDoc.updateFile(idxFile, utils.obj.currUserAD, nomeFile, path); utils.obj.taDoc.updateFile(idxFile, utils.obj.currUserAD, nomeFile, newPath); lg.Info("Aggiornato in db nome file {0} per sostituzione causa svuotamento", nomeFile); // ricalcolo nome file string newFileName = WebShipUtils.nomeFileFullFromIdxFile(idxFile); // sposto file //fileMover.obj.muoviFile("~/DocTemplates/", path, nomeFile, newFileName, false); fileMover.obj.muoviFile("~/DocTemplates/", newPath, nomeFile, newFileName, false); lg.Info("Spostato file {0} per sostituzione causa svuotamento", nomeFile); } } /// /// salva su db il tempalte dei metadati correnti /// /// user id (AD) univoco /// nome del dataset /// metadati public void salvaTemplateMedatati(string userId, string setName, docMetaDataSet docsData) { string tagString = ""; try { if (docsData.tags.Capacity > 0) { tagString = stringFromList(docsData.tags.ToList(), "#"); } } catch { } utils.obj.taTMD.Insert(userId, setName, docsData.commessa, docsData.fase, docsData.fonte, docsData.oggetto, docsData.dataRic, docsData.dataDoc, docsData.path, docsData.InOut, docsData.reqProto, docsData.isRed, tagString); } /// /// restituisce il tempalte metadati /// /// /// /// public docMetaDataSet recuperaTemplateMedatati(string userId, string setName) { docMetaDataSet answ = new docMetaDataSet(); DS_WebScip.tbMetaDataSetRow riga; try { riga = utils.obj.taTMD.getByKey(userId, setName)[0]; answ.commessa = riga.Commessa; answ.fase = riga.Fase; answ.fonte = riga.Fonte; answ.oggetto = riga.Oggetto; answ.dataRic = riga.DataRic; answ.dataDoc = riga.DataDoc; answ.path = riga.path; answ.InOut = riga.InOut; answ.reqProto = riga.isProto; answ.isRed = riga.isRed; answ.tags = listFromString(riga.tags, "#"); } catch { } return answ; } /// /// elimina il tempalte dei metadati indicato /// /// /// public void eliminaTemplateMedatati(string userId, string setName) { utils.obj.taTMD.deleteQuery(userId, setName); } /// /// determina se l'utente possa vedere records taggati Red /// public bool userCanSeeRed { get { bool answ = false; // controllo se in sessione if (utils.obj.isInSessionObject("userCanSeeRed")) { answ = utils.obj.BoolSessionObj("userCanSeeRed"); } else { answ = (userIsUserRed || userIsPowerUserRed); utils.obj.setSessionVal("userCanSeeRed", answ); } return answ; } } /// /// determina se l'utente sia poweruser /// public bool userIsPowerUser { get { bool answ = utils.obj.userHasRight(utils.obj.currUserAD, utils.obj.confReadString("CodModulo"), "PowerUser"); return answ; } } /// /// determina se l'utente sia poweruser /// public bool userIsUserRed { get { bool answ = utils.obj.userHasRight(utils.obj.currUserAD, utils.obj.confReadString("CodModulo"), "UserRed"); return answ; } } /// /// determina se l'utente sia poweruser Red /// public bool userIsPowerUserRed { get { bool answ = utils.obj.userHasRight(utils.obj.currUserAD, utils.obj.confReadString("CodModulo"), "PowerUserRed"); return answ; } } /// /// determina se la data sia coperta da almeno un record segnaposto isRed, altrimenti lo crea! /// /// /// public static void dateIsOk(DateTime data) { bool answ = false; string searchAll = "*"; docMetaDataSet docsData = emptyDocData(data); try { answ = utils.obj.taDoc.getBySearch(data.Date, data.Date.AddDays(1), docsData.commessa, docsData.fase, docsData.fonte, docsData.InOut, searchAll, docsData.isRed).Rows.Count > 0; } catch { } // se non c'è doc hole quotidiano lo crea! if (!answ) { string nomeFile = "ETS-Proto.docx"; WebShipUtils.mng.generaDocDaTemplate(nomeFile, docsData); } } /// /// restituisce un set di dati "empty" utile x reset /// /// /// public static docMetaDataSet emptyDocData(DateTime data) { docMetaDataSet docsData = new docMetaDataSet(); docsData.commessa = string.Format("0000-{0}", data.Year); docsData.dataDoc = data; docsData.dataRic = data; docsData.fase = "ALTRE"; docsData.fonte = "ETS Engineering & Technical Services S.p.A."; docsData.InOut = "Out"; docsData.oggetto = "n.d."; docsData.isRed = true; docsData.path = path(docsData); docsData.reqProto = true; docsData.tags = new List(); return docsData; } /// /// genera un doc da template, tramite /// - salvataggio /// - spostamento "dummy file" /// - enter in modalità editing /// /// file TEMPLATE /// metadati public int generaDocDaTemplate(string nomeTemplate, docMetaDataSet docsData) { int idxFile = 0; fileMover.obj.muoviFile("~/DocTemplates/", UserTempPath, nomeTemplate, false); //check del path string pathDest = docsData.path; if (pathDest != "") { // ulteriore verifica del path sotto dimensione massima... if (pathDest.Length > utils.obj.confReadInt("maxFullPathLenght")) { // loggo! lg.Error("Errore: trovato path troppo lungo ({0} char): {1}", pathDest.Length, pathDest); } // verifico se è comunicazione red = riservata string comPath = ""; if (!docsData.isRed) { comPath = utils.obj.confReadString("archiveDir"); } else { comPath = utils.obj.confReadString("archiveDirRed"); } // aggiunto al path cartella archivio corretta... pathDest = string.Format("{0}{1}", comPath, docsData.path); // fix redattore string redattore = utils.obj.currUserNomeCognome; // usa utente corrente idxFile = WebShipUtils.archiviaFile(docsData, UserTempPath, pathDest, nomeTemplate, redattore); // recupero dati documento docsData = docMetaFromIdxFile(idxFile); // recupero full path del documento string fullPath = HttpContext.Current.Server.MapPath(string.Format("{0}{1}", pathDest, WebShipUtils.nomeFileFullFromIdxFile(idxFile))); string NumProt = WebShipUtils.protocolloFromIdxFile(idxFile); string NumCommessa = WebShipUtils.commessaFromIdxFile(idxFile); string OggettoDoc = WebShipUtils.oggettoFromIdxFile(idxFile); string FonteDoc = WebShipUtils.fonteFromIdxFile(idxFile); string FaxNum = "-"; //Il numero di fax del destinatario (desunto, se c’è, dal DB di TheBook) try { DS_utils.v_selFonti_explDataTable tabVSFE = utils.obj.taVSFE.getByFonte(FonteDoc); if (tabVSFE.Rows.Count > 0) { FaxNum = tabVSFE[0].Fax; } } catch { } // controllo se fax nullo lo intercetto... if (FaxNum == "") { FaxNum = "-"; } // se il nome contiene "docx" faccio sostituzioni... if (nomeTemplate.IndexOf("docx") >= 0) { try { // prendo il nuovo file generato e sostituisco parte del nome con il codice protocollo // link: msdn.microsoft.com/en-us/library/bb508261.aspx officeXmlMan.replaceDocxText(fullPath, "NumProt", NumProt); officeXmlMan.replaceDocxText(fullPath, "DataDoc", docsData.dataDoc.ToShortDateString()); officeXmlMan.replaceDocxText(fullPath, "NumCommessa", NumCommessa); officeXmlMan.replaceDocxText(fullPath, "OggettoDoc", OggettoDoc); officeXmlMan.replaceDocxText(fullPath, "RedattoreDoc", utils.obj.currUserCognomeNome); officeXmlMan.replaceDocxText(fullPath, "FaxNum", FaxNum); officeXmlMan.replaceDocxText(fullPath, "FonteDoc", FonteDoc); } catch (Exception exc) { lg.Error("Errore replace testo: {0}", exc); } } else if (nomeTemplate.IndexOf("eml") >= 0) { // creo un NUOVO file alla destinazione sostituendo l'esistente con apposita classe string mittente = utils.obj.currUserEmail; // controllo, se non è valida carico email "fuffa" if (mittente.IndexOf("@") < 0) { mittente = utils.obj.confReadString("stdEmail"); } // calcolo destinatario string destinatario = WebShipUtils.emailDaCodForn(docsData.fonte); // controllo email dest valida... if (destinatario.IndexOf("@") < 0) { destinatario = mittente; } /* ************************************************************* * Struttura formato campi: * {0} = newline * {1} = oggetto * {2} = numProtocollo (nnnn-aaaa) * {3} = dataDoc * {4} = commessa (nnnn-aaaa) * {5} = redattore * {6} = mittente * *************************************************************/ string subject = string.Format(utils.obj.confReadString("mailSubject"), Environment.NewLine, docsData.oggetto, NumProt, docsData.dataDoc, docsData.commessa, redattore, mittente); string body = ""; body += string.Format(utils.obj.confReadString("mailBody01"), Environment.NewLine, docsData.oggetto, NumProt, docsData.dataDoc, docsData.commessa, redattore, mittente); body += string.Format(utils.obj.confReadString("mailBody02"), Environment.NewLine, docsData.oggetto, NumProt, docsData.dataDoc, docsData.commessa, redattore, mittente); body += string.Format(utils.obj.confReadString("mailBody03"), Environment.NewLine, docsData.oggetto, NumProt, docsData.dataDoc, docsData.commessa, redattore, mittente); body += string.Format(utils.obj.confReadString("mailBody04"), Environment.NewLine, docsData.oggetto, NumProt, docsData.dataDoc, docsData.commessa, redattore, mittente); body += string.Format(utils.obj.confReadString("mailBody05"), Environment.NewLine, docsData.oggetto, NumProt, docsData.dataDoc, docsData.commessa, redattore, mittente); // creo vera email! string newFileName = WebShipUtils.CreaEml(mittente, destinatario, subject, body, null, HttpContext.Current.Server.MapPath(pathDest)); // sostituisco file appena creato con quello nuovo fileMover.obj.muoviFile(pathDest, pathDest, newFileName, WebShipUtils.nomeFileFullFromIdxFile(idxFile), true); } } return idxFile; } } /// /// set metadati x WebShip /// public struct docMetaDataSet { /// /// commessa (formato nnnnnn-yyyy) /// public string commessa; /// /// fase /// public string fase; /// /// fonte (IN/OUT) /// public string fonte; /// /// oggetto /// public string oggetto; /// /// data documento /// public DateTime dataDoc; /// /// data ricevimento doc /// public DateTime dataRic; /// /// path su FS /// public string path; /// /// stringa In/Out /// public string InOut; /// /// boolean: richiesto protocollo /// public bool reqProto; /// /// boolean: comunicazioen RED (riservata) /// public bool isRed; /// /// elenco tags /// public List tags; } }