| 1 | 
 /* | 
 
 
 
 
 
 | 2 | 
  * unlink.js | 
 
 
 
 
 
 | 3 | 
  * | 
 
 
 
 
 
 | 4 | 
  * $Id: unlink.js,v cd9a9ac85727 2013/09/20 08:43:04 keithmarshall $ | 
 
 
 
 
 
 | 5 | 
  * | 
 
 
 
 
 
 | 6 | 
  * Invoke the Windows Scripting Host to remove specified files, typically | 
 
 
 
 
 
 | 7 | 
  * from the user's or all users' start menu or desktop directories. | 
 
 
 
 
 
 | 8 | 
  * | 
 
 
 
 
 
 | 9 | 
  * Usage: | 
 
 
 
 
 
 | 10 | 
  *   cscript -nologo unlink.js [--option ...] file ... | 
 
 
 
 
 
 | 11 | 
  * | 
 
 
 
 
 
 | 12 | 
  * Options: | 
 
 
 
 
 
 | 13 | 
  *   --all-users | 
 
 
 
 
 
 | 14 | 
  *              references to desktop or start menu files apply | 
 
 
 
 
 
 | 15 | 
  *              to the directories serving all users | 
 
 
 
 
 
 | 16 | 
  * | 
 
 
 
 
 
 | 17 | 
  *   --desktop  remove files from the user's desktop directory, (or | 
 
 
 
 
 
 | 18 | 
  *              from all users' desktop directory, with --all-users) | 
 
 
 
 
 
 | 19 | 
  * | 
 
 
 
 
 
 | 20 | 
  *   --start-menu | 
 
 
 
 
 
 | 21 | 
  *              remove files from the user's start menu directory, (or | 
 
 
 
 
 
 | 22 | 
  *              from all users' start menu directory, with --all-users) | 
 
 
 
 
 
 | 23 | 
  * | 
 
 
 
 
 
 | 24 | 
  *   --if-linked=target_path | 
 
 
 
 
 
 | 25 | 
  *              do not remove any matched file which is not a shortcut | 
 
 
 
 
 
 | 26 | 
  *              (.lnk or .url) referring to the specified target path; | 
 
 
 
 
 
 | 27 | 
  *              when this option is specified, any specified file name | 
 
 
 
 
 
 | 28 | 
  *              which does not already have a .lnk or .url extension | 
 
 
 
 
 
 | 29 | 
  *              will have .lnk appended, before seeking any match | 
 
 
 
 
 
 | 30 | 
  * | 
 
 
 
 
 
 | 31 | 
  *   --force    override read-only attributes when removing files. | 
 
 
 
 
 
 | 32 | 
  * | 
 
 
 
 
 
 | 33 | 
  * Parameters: | 
 
 
 
 
 
 | 34 | 
  *   file       the path name for a file to be removed; if --desktop | 
 
 
 
 
 
 | 35 | 
  *              or --start-menu is specified, it should be a relative | 
 
 
 
 
 
 | 36 | 
  *              path name, which will then be resolved relative to the | 
 
 
 
 
 
 | 37 | 
  *              appropriate system directory path. | 
 
 
 
 
 
 | 38 | 
  * | 
 
 
 
 
 
 | 39 | 
  * | 
 
 
 
 
 
 | 40 | 
  * This file is a component of mingw-get. | 
 
 
 
 
 
 | 41 | 
  * | 
 
 
 
 
 
 | 42 | 
  * Written by Keith Marshall <keithmarshall@users.sourceforge.net> | 
 
 
 
 
 
 | 43 | 
  * Copyright (C) 2012, 2013, MinGW.org Project | 
 
 
 
 
 
 | 44 | 
  * | 
 
 
 
 
 
 | 45 | 
  * | 
 
 
 
 
 
 | 46 | 
  * Permission is hereby granted, free of charge, to any person obtaining a | 
 
 
 
 
 
 | 47 | 
  * copy of this software and associated documentation files (the "Software"), | 
 
 
 
 
 
 | 48 | 
  * to deal in the Software without restriction, including without limitation | 
 
 
 
 
 
 | 49 | 
  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | 
 
 
 
 
 
 | 50 | 
  * and/or sell copies of the Software, and to permit persons to whom the | 
 
 
 
 
 
 | 51 | 
  * Software is furnished to do so, subject to the following conditions: | 
 
 
 
 
 
 | 52 | 
  * | 
 
 
 
 
 
 | 53 | 
  * The above copyright notice and this permission notice shall be included | 
 
 
 
 
 
 | 54 | 
  * in all copies or substantial portions of the Software. | 
 
 
 
 
 
 | 55 | 
  * | 
 
 
 
 
 
 | 56 | 
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | 
 
 
 
 
 
 | 57 | 
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
 
 
 
 
 
 | 58 | 
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | 
 
 
 
 
 
 | 59 | 
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
 
 
 
 
 
 | 60 | 
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | 
 
 
 
 
 
 | 61 | 
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
 
 
 
 
 
 | 62 | 
  * DEALINGS IN THE SOFTWARE. | 
 
 
 
 
 
 | 63 | 
  * | 
 
 
 
 
 
 | 64 | 
  */ | 
 
 
 
 
 
 | 65 | 
 var cmdName = WScript.ScriptName; | 
 
 
 
 
 
 | 66 | 
 var FileSystem = WScript.CreateObject("Scripting.FileSystemObject"); | 
 
 
 
 
 
 | 67 | 
 var WinShell = WScript.CreateObject("WScript.Shell"); | 
 
 
 
 
 
 | 68 | 
  | 
 
 
 
 
 
 | 69 | 
 /* Strip ".js" suffix from command name. | 
 
 
 
 
 
 | 70 | 
  */ | 
 
 
 
 
 
 | 71 | 
 var i = cmdName.lastIndexOf( ".js" ); | 
 
 
 
 
 
 | 72 | 
 if( (i > 0) &&  (cmdName.substr( i ) == ".js") ) | 
 
 
 
 
 
 | 73 | 
   cmdName = cmdName.substr( 0, i ); | 
 
 
 
 
 
 | 74 | 
  | 
 
 
 
 
 
 | 75 | 
 /* Specify the keywords which identify command line options. | 
 
 
 
 
 
 | 76 | 
  */ | 
 
 
 
 
 
 | 77 | 
 var options = Array( | 
 
 
 
 
 
 | 78 | 
     /* | 
 
 
 
 
 
 | 79 | 
      *  Option              Effect | 
 
 
 
 
 
 | 80 | 
      *  -------------       ------------------------- | 
 
 
 
 
 
 | 81 | 
      */ | 
 
 
 
 
 
 | 82 | 
         "all-users",     /* Resolve file path names in all-users domain... */ | 
 
 
 
 
 
 | 83 | 
         "start-menu",    /* ...relative to user's or all-users' start menu... */ | 
 
 
 
 
 
 | 84 | 
         "desktop",       /* ...or desktop directories. */ | 
 
 
 
 
 
 | 85 | 
         "if-linked",     /* Only delete shortcuts with specified target path */ | 
 
 
 
 
 
 | 86 | 
         "force"          /* Forcibly override read-only attribute */ | 
 
 
 
 
 
 | 87 | 
     ); | 
 
 
 
 
 
 | 88 | 
  | 
 
 
 
 
 
 | 89 | 
 /* Initialise all options as "unassigned". | 
 
 
 
 
 
 | 90 | 
  */ | 
 
 
 
 
 
 | 91 | 
 var unassigned = "+++unassigned+++"; | 
 
 
 
 
 
 | 92 | 
 var assigned = Array( options.length ); | 
 
 
 
 
 
 | 93 | 
 for( i = 0; i < assigned.length; i++ ) | 
 
 
 
 
 
 | 94 | 
   assigned[i] = unassigned; | 
 
 
 
 
 
 | 95 | 
  | 
 
 
 
 
 
 | 96 | 
 /* The "complain" function provides a mechanism for writing | 
 
 
 
 
 
 | 97 | 
  * diagnostic messages to stderr, and optionally aborting the | 
 
 
 
 
 
 | 98 | 
  * calling script. | 
 
 
 
 
 
 | 99 | 
  */ | 
 
 
 
 
 
 | 100 | 
 function complain( condition, message ) | 
 
 
 
 
 
 | 101 | 
 { | 
 
 
 
 
 
 | 102 | 
   WScript.StdErr.WriteLine( cmdName + ": " + message ); | 
 
 
 
 
 
 | 103 | 
   if( condition < 0 ) | 
 
 
 
 
 
 | 104 | 
     WScript.Quit( -condition ); | 
 
 
 
 
 
 | 105 | 
   return condition; | 
 
 
 
 
 
 | 106 | 
 } | 
 
 
 
 
 
 | 107 | 
  | 
 
 
 
 
 
 | 108 | 
 /* Parse the command line, to identify any specified options. | 
 
 
 
 
 
 | 109 | 
  */ | 
 
 
 
 
 
 | 110 | 
 var chklink = ""; | 
 
 
 
 
 
 | 111 | 
 var argv = WScript.Arguments; | 
 
 
 
 
 
 | 112 | 
 for( i = 0; i < argv.length; i++ ) | 
 
 
 
 
 
 | 113 | 
 { | 
 
 
 
 
 
 | 114 | 
   if( argv( i ).indexOf( "--" ) == 0 ) | 
 
 
 
 
 
 | 115 | 
   { | 
 
 
 
 
 
 | 116 | 
     /* Handle arguments specifying options... | 
 
 
 
 
 
 | 117 | 
      */ | 
 
 
 
 
 
 | 118 | 
     var optind; | 
 
 
 
 
 
 | 119 | 
     var matched = 0; | 
 
 
 
 
 
 | 120 | 
     var optname = argv( i ).substr( 2 ); | 
 
 
 
 
 
 | 121 | 
     var optarg = ""; | 
 
 
 
 
 
 | 122 | 
     for( var k = 0; k < options.length; k++ ) | 
 
 
 
 
 
 | 123 | 
     { | 
 
 
 
 
 
 | 124 | 
       /* Try to match each defined option in turn... | 
 
 
 
 
 
 | 125 | 
        */ | 
 
 
 
 
 
 | 126 | 
       var argind = optname.indexOf( "=" ); | 
 
 
 
 
 
 | 127 | 
       if( argind > 0 ) | 
 
 
 
 
 
 | 128 | 
       { | 
 
 
 
 
 
 | 129 | 
         optarg = optname.substr( argind + 1 ); | 
 
 
 
 
 
 | 130 | 
         optname = optname.substr( 0, argind ); | 
 
 
 
 
 
 | 131 | 
       } | 
 
 
 
 
 
 | 132 | 
  | 
 
 
 
 
 
 | 133 | 
       if( optname == options[k] ) | 
 
 
 
 
 
 | 134 | 
       { | 
 
 
 
 
 
 | 135 | 
         /* A exact (complete) match trumps any possible abbreviation... | 
 
 
 
 
 
 | 136 | 
          */ | 
 
 
 
 
 
 | 137 | 
         matched = 1; | 
 
 
 
 
 
 | 138 | 
         assigned[optind = k] = optname; | 
 
 
 
 
 
 | 139 | 
         k = options.length; | 
 
 
 
 
 
 | 140 | 
       } | 
 
 
 
 
 
 | 141 | 
  | 
 
 
 
 
 
 | 142 | 
       else if( options[k].indexOf( optname ) == 0 ) | 
 
 
 
 
 
 | 143 | 
       { | 
 
 
 
 
 
 | 144 | 
         /* Otherwise abbreviations are allowed, but must uniquely | 
 
 
 
 
 
 | 145 | 
          * identify only one defined option name... | 
 
 
 
 
 
 | 146 | 
          */ | 
 
 
 
 
 
 | 147 | 
         if( matched++ > 0 ) | 
 
 
 
 
 
 | 148 | 
           complain( -2, "option '" + argv( i ) + "' is ambiguous" ); | 
 
 
 
 
 
 | 149 | 
         assigned[optind = k] = options[k]; | 
 
 
 
 
 
 | 150 | 
       } | 
 
 
 
 
 
 | 151 | 
     } | 
 
 
 
 
 
 | 152 | 
     if( matched == 0 ) | 
 
 
 
 
 
 | 153 | 
       /* | 
 
 
 
 
 
 | 154 | 
        * Bail out, if no match identified. | 
 
 
 
 
 
 | 155 | 
        */ | 
 
 
 
 
 
 | 156 | 
       complain( -2, "option '" + argv( i ) + "' is undefined" ); | 
 
 
 
 
 
 | 157 | 
  | 
 
 
 
 
 
 | 158 | 
     if( assigned[optind] == "if-linked" ) | 
 
 
 
 
 
 | 159 | 
       chklink = optarg; | 
 
 
 
 
 
 | 160 | 
   } | 
 
 
 
 
 
 | 161 | 
 } | 
 
 
 
 
 
 | 162 | 
  | 
 
 
 
 
 
 | 163 | 
 /* Establish prefix for resolving paths relative to desktop | 
 
 
 
 
 
 | 164 | 
  * or start menu directories, and handle the --force option. | 
 
 
 
 
 
 | 165 | 
  */ | 
 
 
 
 
 
 | 166 | 
 var prefix = ""; | 
 
 
 
 
 
 | 167 | 
 var allusers = false; | 
 
 
 
 
 
 | 168 | 
 var force = false; | 
 
 
 
 
 
 | 169 | 
 for( i = 0; i < options.length; i++ ) | 
 
 
 
 
 
 | 170 | 
 { | 
 
 
 
 
 
 | 171 | 
   switch( assigned[i] ) | 
 
 
 
 
 
 | 172 | 
   { | 
 
 
 
 
 
 | 173 | 
     case "force": | 
 
 
 
 
 
 | 174 | 
       force = true; | 
 
 
 
 
 
 | 175 | 
       break; | 
 
 
 
 
 
 | 176 | 
  | 
 
 
 
 
 
 | 177 | 
     case "all-users": | 
 
 
 
 
 
 | 178 | 
       allusers = true; | 
 
 
 
 
 
 | 179 | 
       break; | 
 
 
 
 
 
 | 180 | 
  | 
 
 
 
 
 
 | 181 | 
     case "start-menu": | 
 
 
 
 
 
 | 182 | 
       prefix = WinShell.SpecialFolders( allusers ? "AllUsersStartMenu" | 
 
 
 
 
 
 | 183 | 
           : "StartMenu" | 
 
 
 
 
 
 | 184 | 
         ) + "\\"; | 
 
 
 
 
 
 | 185 | 
       break; | 
 
 
 
 
 
 | 186 | 
  | 
 
 
 
 
 
 | 187 | 
     case "desktop": | 
 
 
 
 
 
 | 188 | 
       if( prefix != "" ) | 
 
 
 
 
 
 | 189 | 
         complain( -2, "options '--start-menu' and '--desktop' are incompatible" ); | 
 
 
 
 
 
 | 190 | 
       prefix = WinShell.SpecialFolders( allusers ? "AllUsersDesktop" | 
 
 
 
 
 
 | 191 | 
           : "Desktop" | 
 
 
 
 
 
 | 192 | 
         ) + "\\"; | 
 
 
 
 
 
 | 193 | 
   } | 
 
 
 
 
 
 | 194 | 
 } | 
 
 
 
 
 
 | 195 | 
  | 
 
 
 
 
 
 | 196 | 
 /* Parse the command line again, to process path name arguments, | 
 
 
 
 
 
 | 197 | 
  * and delete the specified files. | 
 
 
 
 
 
 | 198 | 
  */ | 
 
 
 
 
 
 | 199 | 
 for( i = 0; i < argv.length; i++ ) | 
 
 
 
 
 
 | 200 | 
 { | 
 
 
 
 
 
 | 201 | 
   if( argv( i ).indexOf( "--" ) != 0 ) | 
 
 
 
 
 
 | 202 | 
   { | 
 
 
 
 
 
 | 203 | 
     /* Not an option argument, so assume it's a path name. | 
 
 
 
 
 
 | 204 | 
      */ | 
 
 
 
 
 
 | 205 | 
     var filename = prefix + argv( i ); | 
 
 
 
 
 
 | 206 | 
     if( chklink != "" ) | 
 
 
 
 
 
 | 207 | 
     { | 
 
 
 
 
 
 | 208 | 
       /* The "--if-linked" option is in effect, and a viable | 
 
 
 
 
 
 | 209 | 
        * target path has been defined.  The file to be deleted | 
 
 
 
 
 
 | 210 | 
        * MUST be a shortcut file, (i.e. it MUST bear a ".lnk" or | 
 
 
 
 
 
 | 211 | 
        * ".url" extension); supply ".lnk" as default, if this is | 
 
 
 
 
 
 | 212 | 
        * not so. | 
 
 
 
 
 
 | 213 | 
        */ | 
 
 
 
 
 
 | 214 | 
       var l = filename.length - 4; | 
 
 
 
 
 
 | 215 | 
       var suffix = (l > 0) ? filename.substr( l ) : 0; | 
 
 
 
 
 
 | 216 | 
       if( (suffix != ".lnk") && (suffix != ".url") ) | 
 
 
 
 
 
 | 217 | 
         filename += ".lnk"; | 
 
 
 
 
 
 | 218 | 
     } | 
 
 
 
 
 
 | 219 | 
     if( FileSystem.FileExists( filename ) ) | 
 
 
 
 
 
 | 220 | 
     { | 
 
 
 
 
 
 | 221 | 
       /* The requisite file DOES exist... | 
 
 
 
 
 
 | 222 | 
        */ | 
 
 
 
 
 
 | 223 | 
       if( chklink != "" ) | 
 
 
 
 
 
 | 224 | 
       { | 
 
 
 
 
 
 | 225 | 
         /* ...but when "--if-linked is in effect, we must verify that | 
 
 
 
 
 
 | 226 | 
          * the link target is matched (case-insensitively), before... | 
 
 
 
 
 
 | 227 | 
          */ | 
 
 
 
 
 
 | 228 | 
         var ref = WinShell.CreateShortcut( filename ); | 
 
 
 
 
 
 | 229 | 
         var chk = WinShell.CreateShortcut( filename ); chk.TargetPath = chklink; | 
 
 
 
 
 
 | 230 | 
         if( ref.TargetPath.toLowerCase() == chk.TargetPath.toLowerCase() ) | 
 
 
 
 
 
 | 231 | 
           /* | 
 
 
 
 
 
 | 232 | 
            * ...we may proceed with deletion. | 
 
 
 
 
 
 | 233 | 
            */ | 
 
 
 
 
 
 | 234 | 
           FileSystem.DeleteFile( filename, force ); | 
 
 
 
 
 
 | 235 | 
       } | 
 
 
 
 
 
 | 236 | 
       else | 
 
 
 
 
 
 | 237 | 
         /* When "--if-linked" is NOT in effect, we may simply | 
 
 
 
 
 
 | 238 | 
          * proceed with deletion, without further ado. | 
 
 
 
 
 
 | 239 | 
          */ | 
 
 
 
 
 
 | 240 | 
         FileSystem.DeleteFile( filename, force ); | 
 
 
 
 
 
 | 241 | 
     } | 
 
 
 
 
 
 | 242 | 
   } | 
 
 
 
 
 
 | 243 | 
 } | 
 
 
 
 
 
 | 244 | 
  | 
 
 
 
 
 
 | 245 | 
 /* $RCSfile: unlink.js,v $: end of file */ |