Click here to Skip to main content
15,894,017 members
Articles / Desktop Programming / Windows Forms

A Tool to Strip Zips of Unwanted Files before Submitting to CodeProject - Version 2

Rate me:
Please Sign up or sign in to vote.
4.17/5 (6 votes)
24 Dec 2008CPOL8 min read 32.2K   329   19  
An article on some minor modifications to CPZipStripper
/*
 * CPZipStripper 1.0
 * Written by Nishant Sivakumar [http://blog.voidnish.com] 
*/

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Xml;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using ICSharpCode.SharpZipLib.Zip;
using Microsoft.Win32;

namespace CPZipStripper
{	
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class MainForm : System.Windows.Forms.Form
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetSystemMenu(
            IntPtr hWnd, bool bRevert);

        [DllImport("user32.dll")]
        private static extern bool AppendMenu (
            IntPtr hMenu, Int32 wFlags, Int32 wIDNewItem, 
            string lpNewItem);

        public const Int32 WM_SYSCOMMAND = 0x112;
        public const Int32 MF_SEPARATOR = 0x800;
        public const Int32 MF_STRING = 0x0;
        public const Int32 IDM_ABOUT  = 5000;

        private CPZipStripperSettings zsSettings = new CPZipStripperSettings();

        private System.Windows.Forms.Panel panel1;
        private System.Windows.Forms.Panel panel2;
        private System.Windows.Forms.ListBox listBox1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Button BtnConfig;
        private System.Windows.Forms.Button BtnRefresh;
        private System.Windows.Forms.Button BtnExit;
        private System.Windows.Forms.Button BtnStrip;
        private System.Windows.Forms.StatusBar statusBar1;
        private System.Windows.Forms.ToolTip MainToolTip;
        private System.Windows.Forms.Button BtnEditor;
        private System.ComponentModel.IContainer components;

        public MainForm()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            zsSettings.LoadAppSettings();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
            MainToolTip.SetToolTip(BtnRefresh,"Refresh list of files");
            MainToolTip.SetToolTip(BtnExit,"Close the program");			
            MainToolTip.SetToolTip(BtnConfig,"Open config XML in your XML editor");
            MainToolTip.SetToolTip(listBox1,"List of files in zip file, red ones will be stripped");
            MainToolTip.SetToolTip(panel1,"Drag and drop any zip file into this window to strip it of unwanted files");
            MainToolTip.SetToolTip(panel2,"Drag and drop any zip file into this window to strip it of unwanted files");
            MainToolTip.SetToolTip(label1,"Drag and drop any zip file into this window to strip it of unwanted files");			
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.panel1 = new System.Windows.Forms.Panel();
            this.BtnEditor = new System.Windows.Forms.Button();
            this.BtnStrip = new System.Windows.Forms.Button();
            this.BtnExit = new System.Windows.Forms.Button();
            this.BtnRefresh = new System.Windows.Forms.Button();
            this.BtnConfig = new System.Windows.Forms.Button();
            this.panel2 = new System.Windows.Forms.Panel();
            this.listBox1 = new System.Windows.Forms.ListBox();
            this.label1 = new System.Windows.Forms.Label();
            this.statusBar1 = new System.Windows.Forms.StatusBar();
            this.MainToolTip = new System.Windows.Forms.ToolTip(this.components);
            this.panel1.SuspendLayout();
            this.panel2.SuspendLayout();
            this.SuspendLayout();
            // 
            // panel1
            // 
            this.panel1.Controls.Add(this.BtnEditor);
            this.panel1.Controls.Add(this.BtnStrip);
            this.panel1.Controls.Add(this.BtnExit);
            this.panel1.Controls.Add(this.BtnRefresh);
            this.panel1.Controls.Add(this.BtnConfig);
            this.panel1.Dock = System.Windows.Forms.DockStyle.Left;
            this.panel1.Location = new System.Drawing.Point(0, 24);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(224, 272);
            this.panel1.TabIndex = 0;
            // 
            // BtnEditor
            // 
            this.BtnEditor.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.BtnEditor.Location = new System.Drawing.Point(24, 8);
            this.BtnEditor.Name = "BtnEditor";
            this.BtnEditor.Size = new System.Drawing.Size(168, 32);
            this.BtnEditor.TabIndex = 5;
            this.BtnEditor.Text = "Set Xml Editor";
            this.BtnEditor.Click += new System.EventHandler(this.BtnEditor_Click);
            // 
            // BtnStrip
            // 
            this.BtnStrip.Enabled = false;
            this.BtnStrip.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.BtnStrip.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.BtnStrip.Location = new System.Drawing.Point(24, 136);
            this.BtnStrip.Name = "BtnStrip";
            this.BtnStrip.Size = new System.Drawing.Size(168, 72);
            this.BtnStrip.TabIndex = 3;
            this.BtnStrip.Text = "Strip Unwanted files";
            this.BtnStrip.Click += new System.EventHandler(this.BtnStrip_Click);
            // 
            // BtnExit
            // 
            this.BtnExit.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.BtnExit.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.BtnExit.Location = new System.Drawing.Point(24, 224);
            this.BtnExit.Name = "BtnExit";
            this.BtnExit.Size = new System.Drawing.Size(168, 32);
            this.BtnExit.TabIndex = 4;
            this.BtnExit.Text = "Exit Program";
            this.BtnExit.Click += new System.EventHandler(this.BtnExit_Click);
            // 
            // BtnRefresh
            // 
            this.BtnRefresh.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.BtnRefresh.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.BtnRefresh.Location = new System.Drawing.Point(24, 88);
            this.BtnRefresh.Name = "BtnRefresh";
            this.BtnRefresh.Size = new System.Drawing.Size(168, 32);
            this.BtnRefresh.TabIndex = 2;
            this.BtnRefresh.Text = "Refresh Listbox";
            this.BtnRefresh.Click += new System.EventHandler(this.BtnRefresh_Click);
            // 
            // BtnConfig
            // 
            this.BtnConfig.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.BtnConfig.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.BtnConfig.Location = new System.Drawing.Point(24, 48);
            this.BtnConfig.Name = "BtnConfig";
            this.BtnConfig.Size = new System.Drawing.Size(168, 32);
            this.BtnConfig.TabIndex = 1;
            this.BtnConfig.Text = "Modify Configuration";
            this.BtnConfig.Click += new System.EventHandler(this.BtnConfig_Click);
            // 
            // panel2
            // 
            this.panel2.Controls.Add(this.listBox1);
            this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
            this.panel2.DockPadding.All = 4;
            this.panel2.Location = new System.Drawing.Point(224, 24);
            this.panel2.Name = "panel2";
            this.panel2.Size = new System.Drawing.Size(482, 272);
            this.panel2.TabIndex = 1;
            // 
            // listBox1
            // 
            this.listBox1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.listBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
            this.listBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.listBox1.HorizontalScrollbar = true;
            this.listBox1.ItemHeight = 16;
            this.listBox1.Location = new System.Drawing.Point(4, 4);
            this.listBox1.Name = "listBox1";
            this.listBox1.Size = new System.Drawing.Size(474, 260);
            this.listBox1.Sorted = true;
            this.listBox1.TabIndex = 0;
            this.listBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.listBox1_DrawItem);
            // 
            // label1
            // 
            this.label1.BackColor = System.Drawing.SystemColors.ControlDark;
            this.label1.Dock = System.Windows.Forms.DockStyle.Top;
            this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 11.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
            this.label1.ForeColor = System.Drawing.SystemColors.ControlLight;
            this.label1.Location = new System.Drawing.Point(0, 0);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(706, 24);
            this.label1.TabIndex = 2;
            this.label1.Text = "Drag and drop any zip file into this window to strip it of unwanted files";
            // 
            // statusBar1
            // 
            this.statusBar1.Location = new System.Drawing.Point(0, 296);
            this.statusBar1.Name = "statusBar1";
            this.statusBar1.Size = new System.Drawing.Size(706, 22);
            this.statusBar1.TabIndex = 3;
            this.statusBar1.Text = "No file is currently open";
            // 
            // MainForm
            // 
            this.AllowDrop = true;
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(706, 318);
            this.Controls.Add(this.panel2);
            this.Controls.Add(this.panel1);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.statusBar1);
            this.MinimumSize = new System.Drawing.Size(714, 352);
            this.Name = "MainForm";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "CodeProject Zip Stripper 1.1";
            this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing);
            this.Load += new System.EventHandler(this.MainForm_Load);
            this.DragDrop += new System.Windows.Forms.DragEventHandler(this.MainForm_DragDrop);
            this.DragEnter += new System.Windows.Forms.DragEventHandler(this.MainForm_DragEnter);
            this.panel1.ResumeLayout(false);
            this.panel2.ResumeLayout(false);
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() 
        {
            if(File.Exists(cfgxmlpath))
            {
                Application.Run(new MainForm());
            }
            else
            {
                MessageBox.Show(strErrXmlFile, strErrXmlFileTitle);
            }
        }

        //class to hold list item data
        class ZipDataItem
        {
            public string Name;
            public bool IsTrash;
            public ZipDataItem(string name, bool istrash)
            {
                Name = name;
                IsTrash = istrash;
            }		
            public override string ToString()
            {				
                return Name;
            }
        }

        //Nish's delegates
        private delegate void DroppedFileHandler(string s);

        //Nish's member variables
        private ArrayList m_extensions = new ArrayList();	
        private ArrayList m_paths = new ArrayList();	
        private ArrayList m_files = new ArrayList();	
        private string m_curfile = "";
        private bool bContainsTrash = false;

        private static string cfgxmlpath = Path.GetDirectoryName(
            Application.ExecutablePath) + "\\CPZipStripperCfg.xml";
        private static string strAbout = "About CPZipStripper...";
        public static string strErrXmlFile = 
            "Configuration file CPZipStripperCfg.xml could not be found " +
            "in the executable's directory.";
        public static string strErrXmlFileTitle = "Error - Missing Config file!";

        private void MainForm_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        {
            Array arr = (Array)e.Data.GetData(DataFormats.FileDrop);
            if(arr != null)
            {				
                BeginInvoke(new DroppedFileHandler(FilterZip),
                    new object[] {arr.GetValue(0).ToString()});
            }			
        }

        private void MainForm_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
        {
            e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? 
                DragDropEffects.Copy : DragDropEffects.None;
        }

        private void FilterZip(string strFile)
        {
            try
            {
                ZipFile zf = null;
                zf = new ZipFile(strFile);	
                bContainsTrash = false;				
                listBox1.Items.Clear();
                foreach(ZipEntry ze in zf)
                {
                    string nam = ze.Name;	
                    bool bistrash = IsFileStrippable(nam);
                    listBox1.Items.Add(new ZipDataItem(nam,bistrash));						
                    if(bistrash)
                        bContainsTrash = true;
                }
                zf.Close();
                statusBar1.Text = m_curfile = strFile;
                if(bContainsTrash)
                {
                    MainToolTip.SetToolTip(BtnStrip,"Strip zip off unwanted files");
                    BtnStrip.Enabled = true;
					
                }
                else
                {
                    MainToolTip.SetToolTip(BtnStrip,"");
                    BtnStrip.Enabled = false;					
                }
            }
            catch(Exception)
            {	
                MessageBox.Show(
                    "Please drag/drop only valid zip files.",
                    "Error : Unexpected file type!",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }		

        private void listBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
        {
            if(e.Index >= 0)
            {
                ZipDataItem zdi = (ZipDataItem)listBox1.Items[e.Index];
                string str = zdi.Name;
                Font nfont = new Font("Microsoft Sans Serif",10);
                SolidBrush fillBrush = null;
                SolidBrush drawBrush = null;
                bool bMark = zdi.IsTrash;									
                if((e.State & DrawItemState.Focus)==0)
                {
                    fillBrush = new SolidBrush(SystemColors.Window);
                    drawBrush = new SolidBrush(SystemColors.WindowText);					
                }
                else
                {
                    fillBrush = new SolidBrush(SystemColors.Highlight);
                    drawBrush = new SolidBrush(SystemColors.HighlightText);
                }
                if(bMark)
                    drawBrush = new SolidBrush(Color.Red);
                e.Graphics.FillRectangle(fillBrush,
                    e.Bounds.X,e.Bounds.Y,e.Bounds.Width,e.Bounds.Height);
                e.Graphics.DrawString(str,nfont,drawBrush,
                    e.Bounds.X*2,e.Bounds.Y);								
            }				
        }

        private void MainForm_Load(object sender, System.EventArgs e)
        {		
            AddContextMenuItem(".zip", "ZipStrip", "Open with &ZipStrip",
                "\"" + Application.ExecutablePath + "\" \"%1\"");
            IntPtr sysMenuHandle = GetSystemMenu(Handle, false);
            AppendMenu(sysMenuHandle, MF_SEPARATOR, 0, string.Empty);
            AppendMenu(sysMenuHandle, MF_STRING, IDM_ABOUT, strAbout);			
            ReadConfig();	
            listBox1.Select();
            string[] argv = Environment.GetCommandLineArgs();
            if(argv.Length == 2)
            {
                StringBuilder strLongPath = new StringBuilder(512);
                FilterZip(argv[1]);	
            }			
        }

        private bool IsFileStrippable(string fname)
        {
            bool ret = false;
            string path = null, name = null, ext = null;
            SplitString(fname, ref path, ref name, ref ext);
            if( m_extensions.Contains(ext) )
                ret = true;
            foreach(string pathstr in m_paths)
            {
                if(("/" + path).IndexOf("/" + pathstr + "/" ) != -1)				
                {
                    ret = true;
                    break;
                }
            }						
            if( m_files.Contains(name + "." + ext) )
                ret = true;
            return ret;
        }

        private void SplitString(string fname, ref string path, 
            ref string name, ref string ext)
        {	
            path = name = ext = "";
            if(fname.Length!=0)
            {
                int slashpos = fname.LastIndexOf ("/");
                if(slashpos != -1)			
                {	
                    path = fname.Substring(0,slashpos+1);			
                }
                name =  fname.Substring(path.Length);
                int dotpos = name.LastIndexOf (".");
                if(dotpos != -1)
                {
                    ext = name.Substring(dotpos+1);
                    name = name.Substring(0,dotpos);
                }
            }
            path = path.ToLower();
            name = name.ToLower();
            ext = ext.ToLower();
        }

        private void ReadConfig()
        {
            XmlDocument xd = new XmlDocument();
            try
            {
                m_extensions.Clear();
                m_paths.Clear();
                xd.Load(cfgxmlpath);	
                XmlNode xnext = xd["config"]["extensions"];
                if(xnext!=null)
                {
                    foreach(XmlNode xn in xnext.ChildNodes)
                    {
                        m_extensions.Add(xn.InnerXml);						
                    }	
                }
                XmlNode xnpath = xd["config"]["paths"];
                if(xnpath!=null)
                {
                    foreach(XmlNode xn in xnpath.ChildNodes)
                    {
                        m_paths.Add(xn.InnerXml);						
                    }	
                }
                XmlNode xnfile = xd["config"]["files"];
                if(xnfile!=null)
                {
                    foreach(XmlNode xn in xnfile.ChildNodes)
                    {
                        m_files.Add(xn.InnerXml);						
                    }	
                }
            }
            catch(Exception)
            {				
            }
        }

        private void BtnExit_Click(object sender, 
            System.EventArgs e)
        {
            Close();
        }

        private void BtnRefresh_Click(object sender, 
            System.EventArgs e)
        {
            if(m_curfile.Length>0)
            {
                ReadConfig();
                FilterZip(m_curfile);
            }
        }

        private void BtnConfig_Click(object sender, System.EventArgs e)
        {
            ProcessStartInfo psi = new ProcessStartInfo();
            bool edited = false;

            if (!this.zsSettings.SetByUser)
            {
                try
                {
                    // Look for system default Editor
                    psi.FileName = cfgxmlpath;
                    psi.Verb = "Edit";
                    psi.UseShellExecute = true;
                    Process.Start(psi);
                    edited = true;
                }
                catch (Exception)
                {
                    // No App listed for Edit, try Open.
                    try
                    {
                        psi.FileName = cfgxmlpath;
                        psi.Verb = "Open";
                        psi.UseShellExecute = true;
                        Process.Start(psi);
                        edited = true;
                    }
                    catch
                    {
                        if (!this.zsSettings.SetByUser)
                        {
                            // No Edit OR Open, Ask user for App.
                            if (MessageBox.Show("Your system does not have a specified XML editor." +
                                Environment.NewLine + "Do you want to select a default application to edit XML files?",
                                "No Default XML Editor Found!",
                                MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                            {

                                this.GetNewXmlEditor();
                            }
                        }
                    }
                }
            }

            if (!edited)
            {
                try
                {
                    string editorfile = (string)this.zsSettings.XmlEditor;
                    if (cfgxmlpath.IndexOf(" ") >= 0)
                    {
                        Process.Start(editorfile, "\"" + cfgxmlpath + "\"");
                    }
                    else
                    {
                        Process.Start(editorfile, cfgxmlpath);
                    }
                }
                catch
                {
                    MessageBox.Show("This tool is unable to edit the configuration file." + Environment.NewLine +
                        "Close this application and try editing it manually, then restart this program.");
                }
            }
        }

        private void BtnStrip_Click(object sender, System.EventArgs e)
        {
            if (m_curfile.Length > 0)
            {
                string strNewFile = m_curfile.Remove(m_curfile.Length-3, 3) + "tmp";
                ZipOutputStream zos = new ZipOutputStream(File.Create(strNewFile));	

                ZipInputStream zis = new ZipInputStream(File.OpenRead(m_curfile));					
                ZipEntry ze = null;
                while ((ze = zis.GetNextEntry()) != null)
                {	
                    if (!IsFileStrippable(ze.Name))		
                    {					
                        zos.PutNextEntry(new ZipEntry(ze.Name));					
						
                        byte[] buff = new byte[2048];
                        int bytes = 0;
                        while ((bytes = zis.Read(buff, 0, buff.Length)) > 0)
                        {							
                            zos.Write(buff, 0, bytes);
                        }
                        zos.CloseEntry();							
                    }			
                }
                zis.Close();	
                zos.Close();		

                System.IO.File.Move(m_curfile, m_curfile + ".old");
                System.IO.File.Move(strNewFile, m_curfile);

                FilterZip(m_curfile);
            }
        }
	
        protected override void WndProc(ref Message m)
        {
            if(m.Msg == WM_SYSCOMMAND)
            {
                switch(m.WParam.ToInt32())
                {
                    case IDM_ABOUT : 
                        MessageBox.Show(
                            "CodeProject Zip Stripper 1.0\r\n" +
                            "Copyright(C) Nishant Sivakumar 2004\r\n" +
                            "Web :- http://www.voidnish.com/\r\n" +
                            "Blog :- http://blog.voidnish.com/", strAbout);
                        return;
                    default:
                        break;
                } 
            }
            base.WndProc (ref m);
        }	
	
        private bool AddContextMenuItem(string Extension, string MenuName, string MenuDescription, string MenuCommand)
        {
            bool ret = false;
            RegistryKey rkey = Registry.ClassesRoot.OpenSubKey(Extension);
            if (rkey != null)
            {
                string extstring = rkey.GetValue("").ToString();
                rkey.Close();												
                if (extstring != null)
                {
                    if (extstring.Length > 0)
                    {
                        rkey = Registry.ClassesRoot.OpenSubKey(extstring, true);
                        if (rkey != null)
                        {
                            string strkey = "shell\\" + MenuName + "\\command";						
                            RegistryKey subky = rkey.CreateSubKey(strkey);
                            if(subky != null)
                            {
                                subky.SetValue("", MenuCommand);
                                subky.Close();
                                subky = rkey.OpenSubKey("shell\\" + MenuName, true);
                                if (subky != null)
                                {
                                    subky.SetValue("", MenuDescription);
                                    subky.Close();
                                }								
                                ret = true;
                            }
                            rkey.Close();
                        }
                    }
                }
            }
            return ret;
        }

        private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            this.zsSettings.SaveAppSettings();
        }

        private void BtnEditor_Click(object sender, System.EventArgs e)
        {
            GetNewXmlEditor();
        }

        private void GetNewXmlEditor()
        {
            XMLEditorChooser.Show(this.zsSettings);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired
United Kingdom United Kingdom
Retired Systems Admin, Programmer, Dogsbody.
Mainly on Systems for Local Government, Health Authorities,
Insurance Industry - (COBOL eeeeeeeugh).
Inventor of Synchronized Shopping.

Comments and Discussions