sabato 11 settembre 2021

Appunti su REST

 Rest(Representational State Transfer) è uno stile architetturale per i sistemi distribuiti ,esso non definisce né il formato della risposta ( ad esempio Json) nè il protocollo utilizzato. REST può essere applicato sia ad un URI sia al protocollo HTTP ,a tal proposito si può vedere il capitolo 6 della dissertazione di Roy Thomas Fielding :   https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf .

REST può essere definito attraverso l'esplicitazione di alcuni principi che ne modellano il funzionamento :

  1. client(consumatore del servizio) e server(fornitore del servizio) devono ignorare reciprocamente le logiche di funzionamento interne

  2. il servizio deve essere stateless

  3. cache: per migliorare il funzionamento del network è necessario che la response ad una request del client sia implicitamente marcata come cacheable o no cacheable ( vedi pag. 79 del testo sopracitato di Fielding)

  4. ogni risorsa deve essere univoca

  5. le risposte devono contenere le informazioni necessarie a fare il discovery ed ad informare il client su come utilizzare altre risorse , a tal fine la risposta contiene degli hypermedia (HATEOAS (Hypermedia as the Engine of Application State) , https://en.wikipedia.org/wiki/HATEOAS)


Per valutare quanto un API sia conforme ai principi REST si può utilizzare il Richardson Maturity Model (RMM , https://en.wikipedia.org/wiki/Richardson_Maturity_Model ,  https://martinfowler.com/articles/richardsonMaturityModel.html) ,l'RMM prevede quattro livelli ,dal meno conforme a REST (0) al più aderente(3) :

  • livello 0 : viene usato lo stesso endpoint per fare tutte le chiamate sul server

  • livello 1 : vengono resi disponibili endpoint differenti per risorse differenti ,ad esempio :

    Uri                                    Operations

    /bookingDestinations       retrieve

    /bookingReservations      add/cancel reservations

  • livello 2 : in questo caso si utilizzano i verbi http per chiamare risorse differenti quindi non si crea un endpoint “getreservations” ma si utilizza il verbo http “get” sull'indirizzo “reservations”, ad esempio :

    URI               HttpVerb   Operation

    /reservations   GET         get reservations

    /reservations   POST       add reservation

  • livello 3 : HATEOAS , ogni risposta contiene anche come svolgere altre azioni relative all'elemento in questione ,ad esempio se creiamo un Cliente ci potranno essere restituite nella risposta dal server anche le informazioni necessarie per visualizzarlo ed altre informazioni tramite hypermedia (https://en.wikipedia.org/wiki/HATEOAS)

L'argomento può essere approfondito  tramite l'opera sopracitata di Roy Thomas Fielding.


lunedì 5 aprile 2021

Eseguire automaticamente un antivirus su un file scaricato usando Chrome , alla fine del download

 Il codice è in versione pre-alpha . Qui il codice sorgente https://sourceforge.net/projects/antivirusdefenderforchrome/  . 
Supponiamo di utilizzare su un pc due antivirus: ad esempio Avira e Defender , il primo di occupa della scansione a realtime , il secondo viene utilizzato per eseguire delle scansioni periodiche , in questo modo si può usufruire,su richiesta, di due distinte liste aggiornate di segnature di virus per effettuare le scansioni e di due motori euristici .
Durante il download, il file scaricato da Chrome nella dir Download assume una o più fra tre estensioni temporanee : ".tmp" , ".crdownload",".part" ,gli altri browser hanno funzionamenti differenti ed il codice seguente richiede l'uso di una versione attuale di Chrome ,se il file ha un altra estensione significa che il download è finito, il cambiamento del nome del file viene intercettato dall'evento Renamed  dell'oggetto FileSystemWatcher  e l'estensione è verificata dal metodo FindExtension :
scegliamo la directory da monitorare :







 public partial class Form1 : Form

    {
        string selectedPath = null;
        FileSystemWatcher watcher = new FileSystemWatcher();
        
        public Form1()
        {
            InitializeComponent();
        }             

        private void button1_Click(object sender, EventArgs e)
        {
            DialogResult result = this.folderBrowserDialog1.ShowDialog();
            if (result == DialogResult.OK)
            {
                selectedPath = folderBrowserDialog1.SelectedPath;
                this.textBox1.Text = selectedPath;
            }
            watcher.Path = selectedPath;
            watcher.NotifyFilter = NotifyFilters.FileName;
            watcher.Filter = "*.*";
            watcher.Created += new FileSystemEventHandler(OnCreated);
            watcher.Renamed += new RenamedEventHandler(OnRenamed);
            watcher.EnableRaisingEvents = true;            
        }


 per eseguire chiamate  threadsafe  al controllo textBox2 utilizziamo la classe ParametrizedThread  ,

 il percorso sul vostro pc del file MpCmdRun.exe (l'eseguibile da linea di comando di Defender) potrebbe essere diverso da  "C:\Program Files\Windows Defender\MpCmdRun.exe" :

private void OnCreated(object source, FileSystemEventArgs e)
        {
            string name = e.Name;
            string s = this.textBox2.Text;
            s = s + name + " created file " + Environment.NewLine;
            ParametrizedThread p = new ParametrizedThread();
            p.currentForm = this;
            p.c = this.textBox2;
            p.text = s;
            Thread t = new Thread(p.ThreadProcSafe);
            t.Start();
        }

private void OnRenamed(object source, FileSystemEventArgs e)

        {   
            string ext=Path.GetExtension(e.FullPath);
            bool b = FindExtension(ext);
            if (!b)
            {
                string name = e.Name;
                string s = this.textBox2.Text;
                s = s + name + " renamed file completo" + Environment.NewLine;
                ParametrizedThread p = new ParametrizedThread();
                p.currentForm = this;
                p.c = this.textBox2;
                p.text = s;
                Thread t = new Thread(p.ThreadProcSafe);
                t.Start();
                
                ProcessStartInfo info = new ProcessStartInfo(@"C:\Program Files\Windows Defender\MpCmdRun.exe");               
                string fileName = e.FullPath;
                info.Arguments = " -Scan -ScanType 3 -File " + '"' + fileName + '"';
                info.WindowStyle = ProcessWindowStyle.Maximized;
                info.UseShellExecute = false;
                info.RedirectStandardOutput = true;
                Process proc = Process.Start(info);
                StreamReader sr = proc.StandardOutput;
                string msg = sr.ReadToEnd();
                string w = this.textBox2.Text;
                w = w + msg + Environment.NewLine;
                ParametrizedThread pt = new ParametrizedThread();
                pt.currentForm = this;
                pt.c = this.textBox2;
                pt.text = w;
                Thread t1 = new Thread(pt.ThreadProcSafe);
                t1.Start();
            } else { 
                string name = e.Name;
                string s = this.textBox2.Text;
                s = s + name + " renamed" + Environment.NewLine;
                ParametrizedThread p = new ParametrizedThread();
                p.currentForm = this;
                p.c = this.textBox2;
                p.text = s;
                Thread t = new Thread(p.ThreadProcSafe);
                t.Start();
            }
        }

         private bool FindExtension(string ext )
        {
            bool b = true;
            List<string> l = new List<string>();
            //funziona solo con chrome
            l.Add(".tmp");
            l.Add(".crdownload");
            l.Add(".part");            
            int result=l.FindIndex(element => element==ext);
            if(result == -1)
            {
                b = false;
            }
            return b;
        }
         ...................................
         ................................
         ...........................


    public class ParametrizedThread
    {

        public TextBox c = null;
        public string text = null;        
        delegate void SetTextCallback(string text ,Control c);       
        public Form currentForm = null;        
        public ParametrizedThread()
        {
        }
        public void ThreadProcSafe()
        {
            SetText(this.text,this.c);
        }           

        private void SetText(string text,Control c)
        {            
            if (c.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                currentForm.Invoke(d, new object[] { text, c});
            }
            else
            {                
                c.Text = text;                
            }
        }        
    }









domenica 4 aprile 2021

Una newsletter a cui iscriversi

 In questo post vorrei segnalare la newsletter giornaliera di un blog che quotidianamente pubblica articoli sul framework .Net ,  snippet di codice (generalmente .Net) , link a interessanti software gratuiti (tra cui giochi) ed altri argomenti di  interesse per chi programma ma non solo , il sito è http://emanuelemattei.blogspot.com/  . In alto a destra sul blog di Emanuele trovate un text box in cui inserire l'indirizzo email a cui verrà inviata la newsletter .

Crittografia e WCF per passare una password ( od una qualsiasi altra stringa (xml,json, etc.etc.) ) da un applicazione ad un' altra in sicurezza

 Il codice che segue è da considerarsi in alpha e da non utilizzare in un ambiente di produzione , qui potete trovare il  "progetto...