Hi

Just fixed the issue with the execute=always/once packages in my last package download patch. Now its possible to have all kind of packages with downloadable files.

I've also reconstructed the synchronizeProfile() function to be more readable, as its one of the main functions and I couldn't understand it anymore.

Using /install:<packageName> now also supports download feature and downloaded files get purged after successful installation after every package instead of the whole synchronize run, to avoid duplicate files and so on.

        downloadFile() now uses try/catch contruct for better error handling.

The attached patch is against wpkg-0.9.8 and contains all changes, so you don't need the old patch anymore.

        Greets,
                Andre
--- wpkg.js     Mon Apr 24 15:55:19 2006
+++ ../wpkg_0.9.8-test3+patch.js        Tue May  2 15:43:30 2006
@@ -137,6 +137,9 @@
 
 var settings_file_name = "wpkg.xml";
 
+// default value for WPKG_SOURCE temporary path
+var DEFAULT_WPKG_SOURCE = "%TEMP%\\wpkg";
+
 var sRegPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
 // here we indicate our running state
 var sRegWPKG_Running = "HKLM\\Software\\WPKG\\running";
@@ -333,6 +336,26 @@
             ".");
     }
     
+    // set the %SOURCE% environment 
+    var shell = new ActiveXObject("WScript.Shell");
+    var ProcEnv = shell.Environment("PROCESS");
+    if (ProcEnv("WPKG_SOURCE") == "") {
+       var wpkg_source = DEFAULT_WPKG_SOURCE;
+       // try to loop through the environment string, until all environment
+       // vars are resolved. Not very nice as it could end up looping
+       // endless.
+       do {
+           wpkg_source = shell.ExpandEnvironmentStrings(wpkg_source);
+       } while (wpkg_source.indexOf("%") != -1 );
+       // if the folder does not exist, create it.
+       if (!fso.FolderExists(wpkg_source)) {
+           fso.CreateFolder(wpkg_source);
+       }
+       dinfo("WPKG_SOURCE environment not set, using default: " + wpkg_source);
+       ProcEnv("WPKG_SOURCE") = wpkg_source;
+    }
+
+    
     // process command line arguments to determine course of action
     
     if (argn("query") != null) {
@@ -463,8 +486,8 @@
 /**
  * Sends a message to the system console notifying of impending action.
  */
-function notifyUserStart() {
-    if (!was_notified) {
+function notifyUserStart(doNotify) {
+    if (!was_notified || doNotify ) {
         var msg = "";
         msg += "The automated software installation utility has or is ";
         msg += "currently applying software updates to your system. Please ";
@@ -525,86 +548,16 @@
 function synchronizeProfile() {
     // accquire packages that should be present
     var packageArray = getAvailablePackages();
+    dinfo("number of available packages: " + packageArray.length); 
 
-    if (debug) { info("number of available packages: " + packageArray.length); 
}
-
-    
-    // grab currently installed package nodes
-    var installedPackages = settings.selectNodes("package");
-    
-    // loop over each installed package and check whether it still applies
-    for (var i = 0; i < installedPackages.length; i++) {
-        var installedPackageNode = installedPackages(i);
-        if (debug) { info("found installed package: " + 
installedPackageNode.getAttribute("id")); }
-        
-        // search for the installed package in available packages
-        var found = false;
-        for (j in packageArray) {
-            if (debug) { info("testing available package: " + 
packageArray[j].getAttribute("id")); }
-
-
-            if (packageArray[j].getAttribute("id") ==
-                installedPackageNode.getAttribute("id")) {
-                if (debug) { info("package: " + 
installedPackageNode.getAttribute("id") + " found in available packages."); }
-
-                found = true;
-                break;
-            }
-        }
-        
-        // if package is no longer present, remove it
-        if (!found) {
-            if (debug) { info("removing package: " + 
installedPackageNode.getAttribute("id")); }
-
-            notifyUserStart();
-            removePackage(installedPackageNode);
-        }
-    }
-    
-    // create a native jscript array to do the sorting on
-    var sortedPackages = new Array(packageArray.length);
-    for (var i = 0; i < packageArray.length; i++) {
-        sortedPackages[i] = packageArray[i];
-    }
-    
-    // classic bubble-sort algorithm on the "priority" attribute
-    var len = packageArray.length;
-    for (var i = 0; i < len - 1; i++) {
-        for (var j = 0; j < len - 1 - i; j++) {
-            var pri1;
-            var pri2;
-            var szpri1 = sortedPackages[j].getAttribute("priority");
-            var szpri2 = sortedPackages[j + 1].getAttribute("priority");
-            
-            // if a priority is not set, we assume 0
-            
-            if (szpri1 == null) {
-                pri1 = 0;
-            } else {
-                pri1 = parseInt(szpri1);
-            }
-            
-            if (szpri2 == null) {
-                pri2 = 0;
-            } else {
-                pri2 = parseInt(szpri2);
-            }
-            
-            // if the priority of the first one in the list exceeds the second,
-            // swap the packages
-            if (pri1 < pri2) {
-                var tmp = sortedPackages[j];
-                sortedPackages[j] = sortedPackages[j + 1];
-                sortedPackages[j + 1] = tmp;
-            }
-        }
-    }
+    // handle installed packages
+    checkInstalledPackages(packageArray);
     
     // sorting complete
-    packageArray = sortedPackages;
+    packageArray = sortPackageArray(packageArray);
+    listPackagePriorityList(packageArray);
     
-    // loop over each available package and determine whether to install or
-    // upgrade
+    // loop over each available package and determine whether to install or 
upgrade
     for (var i = 0; i < packageArray.length; i++) {
         var packageNode = packageArray[i];
         var packageId   = packageNode.getAttribute("id");
@@ -618,15 +571,13 @@
         var installedPackage = settings.selectSingleNode("[EMAIL PROTECTED]'" +
             packageId + "']");
             
-        if (executeAttr == "once") {
+       switch (executeAttr) {
+           case "once":
             if ((null == installedPackage) |
                ((null != installedPackage) &&
               (parseInt(installedPackage.getAttribute("revision")) < 
packageRev )) ) {
                 try {
-                    if (notifyAttr != "false") {
-                        notifyUserStart();
-                    }
-
+                       notifyUserStart(notifyAttr);
                     executeOnce(packageNode);
                 } catch (e) {
                     throw new Error("Installation error while synchronizing " +
@@ -634,26 +585,22 @@
                         "\n\n" + e.description);
                 }
             }
-        } else if (executeAttr == "always") {
-           // do not look if package is installed
+               break;
+           case "always":
             try {
-                if (notifyAttr != "false") {
-                    notifyUserStart();
-                }
+                   notifyUserStart(notifyAttr);
                 executeOnce(packageNode);
             } catch (e) {
                 throw new Error("Installation error while synchronizing " +
                     "package " + packageName + ", synchronization aborting." +
                     "\n\n" + e.description);
             }
-           
-        } else {
+               break;
+           default:
             // if the package is not installed, install it
             if (installedPackage == null) {
                 try {
-                    if (notifyAttr != "false") {
-                        notifyUserStart();
-                    }
+                       notifyUserStart(notifyAttr);
                     installPackage(packageNode);
                 } catch (e) {
                     throw new Error("Installation error while synchronizing " +
@@ -663,9 +610,7 @@
             } else if (parseInt(installedPackage.getAttribute("revision")) <
                 packageRev) {
                 try {
-                    if (notifyAttr != "false") {
-                        notifyUserStart();
-                    }
+                       notifyUserStart(notifyAttr);
                     upgradePackage(installedPackage, packageNode);
                 } catch (e) {
                     throw new Error("Upgrade error while synchronizing " +
@@ -673,6 +618,7 @@
                         "\n\n" + e.description);
                 }
             }
+               break;
         }
     }
     
@@ -683,6 +629,37 @@
     }
 }
 
+function checkInstalledPackages(packageArray) {
+    // grab currently installed package nodes
+    var installedPackages = settings.selectNodes("package");
+
+    // loop over each installed package and check whether it still applies
+    for (var i = 0; i < installedPackages.length; i++) {
+        var installedPackageNode = installedPackages(i);
+        dinfo("found installed package: " + 
installedPackageNode.getAttribute("id")); 
+        
+        // search for the installed package in available packages
+        var found = false;
+        for (j in packageArray) {
+            if (packageArray[j].getAttribute("id") ==
+                installedPackageNode.getAttribute("id")) {
+                if (debug) { info("package: " + 
installedPackageNode.getAttribute("id") + " found in available packages."); }
+
+                found = true;
+                break;
+            }
+        }
+        
+        // if package is no longer present, remove it
+        if (!found) {
+            dinfo("removing package: " + 
installedPackageNode.getAttribute("id")); 
+            notifyUserStart();
+            removePackage(installedPackageNode);
+        }
+    }
+    dinfo("number of installed packages: " + installedPackages.length);
+}
+
 function queryAllPackages() {
     // retrieve packages
     var settingsNodes = settings.selectNodes("package");
@@ -721,6 +698,116 @@
     info(message);
 }
 
+function downloadPackage(packageNode, downloadList) {
+    var shell = new ActiveXObject("WScript.Shell");
+    var ProcEnv = shell.Environment("PROCESS");
+    var packageName = packageNode.getAttribute("name");
+    var files = packageNode.selectNodes("file");
+
+    if (files.length) info("Downloading files for " + packageName + "...");
+
+    for (var x = 0; x < files.length; x++) {
+       var downloaded = false;
+       var fileNode = files(x);
+       var timeout = parseInt(fileNode.getAttribute("timeout"));
+       if (timeout == null) timeout = 7200;    // default timeout 7200
+       var md5hash = fileNode.getAttribute("md5");
+       var sourceNodes = fileNode.selectNodes("source");
+
+       var sourcefile = fileNode.getAttribute("name");
+       if (sourcefile == null) throw new Error(0, "Wrong download source 
filename defined for " + packageID);
+       var dest = ProcEnv("WPKG_SOURCE") + "\\" + sourcefile ; 
+
+       // loop through sources and try to fetch the file
+       for (var z = 0; z < sourceNodes.length ; z++) {
+           var sourceNode = sourceNodes(z);
+           var url = sourceNode.getAttribute("url");
+           if (url == null) throw new Error(0, "Invalid URL in package 
source.");
+
+           if (downloadFile(url, dest, timeout)) {
+               // MD5 checksum checking (if any)
+               if (md5hash != null) {
+                   if (!md5SumOk(dest, md5hash)) {
+                       throw new Error(0, "MD5 checksum WRONG, original is " + 
md5hash);
+                   } else {
+                       info ("MD5 checksum OK for \"" + sourcefile + "\"");
+                       // save downloaded filenames for later removal
+                       downloadList.push(dest);
+                       downloaded = true;      // indicate success on this file
+                       break;
+                   }
+               }
+           }
+       }
+       if (!downloaded) throw new Error(0, "Could not download required 
files.");
+    }
+}
+
+function purgeDownloadList(downloadList) {
+    var fso = new ActiveXObject("Scripting.FileSystemObject");
+    dinfo("Purging downloaded packages");
+    while (downloadList.length) {
+       var name = downloadList.pop();
+       dinfo("Purging: " + name);
+       // force delete of temporary file 
+       fso.DeleteFile(name, true);
+    }
+}
+
+function sortPackageArray(packageArray) {
+    // create a native jscript array to do the sorting on
+    var sortedPackages = new Array(packageArray.length);
+    for (var i = 0; i < packageArray.length; i++) {
+        sortedPackages[i] = packageArray[i];
+    }
+
+    // classic bubble-sort algorithm on the "priority" attribute
+    var len = packageArray.length;
+    for (var i = 0; i < len - 1; i++) {
+        for (var j = 0; j < len - 1 - i; j++) {
+            var pri1;
+            var pri2;
+            var szpri1 = sortedPackages[j].getAttribute("priority");
+            var szpri2 = sortedPackages[j + 1].getAttribute("priority");
+            
+            // if a priority is not set, we assume 0
+            
+            if (szpri1 == null) {
+                pri1 = 0;
+            } else {
+                pri1 = parseInt(szpri1);
+            }
+            
+            if (szpri2 == null) {
+                pri2 = 0;
+            } else {
+                pri2 = parseInt(szpri2);
+            }
+            
+            // if the priority of the first one in the list exceeds the second,
+            // swap the packages
+            if (pri1 < pri2) {
+                var tmp = sortedPackages[j];
+                sortedPackages[j] = sortedPackages[j + 1];
+                sortedPackages[j + 1] = tmp;
+            }
+        }
+    }
+    return sortedPackages;
+}
+
+function listPackagePriorityList(packageArray) {
+    if (debug && packageArray.length) {
+       info("Package priority listing after sorting: ");
+       info("Number\tPrio\tPackageId");
+       for (var f = 0; f < packageArray.length; f++) {
+           var packageId   = packageArray[f].getAttribute("id");
+           var packageprio = 
parseInt(packageArray[f].getAttribute("priority"));
+           info(f + ":\t" + packageprio + "\t" + packageId);
+       }
+    }
+}
+
 /**
  * Show the user a list of packages that are currently installed.
  */
@@ -1344,9 +1431,12 @@
  * Executes command of the package and registers this fact.
  */
 function executeOnce(packageNode) {
+    var packageFiles = new Array;
     var packageName = packageNode.getAttribute("name");
     var packageId = packageNode.getAttribute("id");
     
+    downloadPackage(packageNode, packageFiles);
+
     info("Executing commands for " + packageName + "...");
         
     // select command lines to install
@@ -1418,6 +1508,8 @@
     settings.appendChild(packageNode);
     saveXml(settings, settings_file);
     
+    purgeDownloadList(packageFiles);
+    
     // reboot the system if this package is suppose to
     if (packageNode.getAttribute("reboot") == "true") {
         info("Execution of commands of " + packageName + " successful, system 
" +
@@ -1441,13 +1533,13 @@
  * Installs the specified package node to the system.
  */
 function installPackage(packageNode) {
+    var packageFiles = new Array;
     var packageName = packageNode.getAttribute("name");
     
     // get a list of checks to perform before installation.
     var checkNodes = packageNode.selectNodes("check");
     var bypass = false;
 
-
     // when "/forceinstall" say "not installed"
     if (!forceInstall) {
         bypass = checkInstalled(packageNode);
@@ -1459,7 +1551,6 @@
                var nodeInst = settings.selectSingleNode("[EMAIL PROTECTED]'" + 
packageID + "']");
 
                if (nodeInst == null) {
-                 
                  if (debug) { 
                    info("Package " + packageName +
                         " missing from settings file, adding it now.");
@@ -1474,6 +1565,9 @@
 
     
     if (!bypass) {
+
+       downloadPackage(packageNode, packageFiles);
+
         info("Installing " + packageName + "...");
         
         // select command lines to install
@@ -1540,11 +1634,12 @@
                             "Failed checking after installation.");
         }
 
-    
        // append new node to local xml
        settings.appendChild(packageNode);
        saveXml(settings, settings_file);
     
+       purgeDownloadList(packageFiles);
+    
        // reboot the system if this package is suppose to
        if (packageNode.getAttribute("reboot") == "true") {
          info("Installation of " + packageName + " successful, system " +
@@ -1560,6 +1655,10 @@
  * Upgrades the old package node to the new package node.
  */
 function upgradePackage(oldPackageNode, newPackageNode) {
+    var packageFiles = new Array;
+
+    downloadPackage(packageNode, packageFiles);
+
     info("Upgrading " + newPackageNode.getAttribute("name") + "...");
     var packageName = newPackageNode.getAttribute("name");
     
@@ -1647,6 +1746,7 @@
         saveXml(settings, settings_file);
     }
 
+    purgeDownloadList(packageFiles);
 
     info("Upgrade of " + newPackageNode.getAttribute("name") + " successful.");
     
@@ -1801,6 +1901,7 @@
             }
         }
             }
+
     }
 
     return packageArray;
@@ -1815,6 +1916,10 @@
 function appendDependencies(appendArray, appendNode, sourceArray, sourceName) {
     // search for package tags in each profile
     var dependsNodes = appendNode.selectNodes("depends");
+
+    var nodePrio = parseInt(appendNode.getAttribute("priority"));
+    if (nodePrio == null) nodePrio = 0;
+
     if (dependsNodes != null) {
        for (var i = 0; i < dependsNodes.length; i++) {
            var dependsId = dependsNodes(i).getAttribute(sourceName + "-id");
@@ -1834,6 +1939,20 @@
            if (searchArray(appendArray, dependsNode)) {
                         continue;
                     } else {
+               // packages get special priority handling
+               if (sourceName == "package") {
+                   var dependsPrio = 
parseInt(dependsNode.getAttribute("priority"));
+                   // if no priority given, start with original node priority
+                   if (dependsPrio == null) dependsPrio = nodePrio;
+                   // increase priority until its higher than the one for the
+                   // original package
+                   if (dependsPrio <= nodePrio) newPrio = nodePrio + 1;
+                   dependsNode.setAttribute("priority", newPrio);
+                   /*
+                   dinfo("nodePrio=" + nodePrio + " dependsPrio=" +
+                           dependsPrio + " newPrio=" + newPrio);
+                    */
+               }
                if (debug) info("Add " + sourceName + " dependecy: " + 
dependsId);
                appendArray.push(dependsNode);
                appendDependencies(appendArray, dependsNode, sourceArray, 
sourceName);
@@ -2420,3 +2539,71 @@
     info(message);
 }
 
+// check MD5 checksum of given file, using external program
+function md5SumOk(sourceFile, checkSum) {
+    var sourceSum;
+    var cmdline;
+    var MD5PROG = "md5.exe";
+    var MD5PROGARGS = "-l -n -c" 
+
+    var fso = new ActiveXObject("Scripting.FileSystemObject");
+    var path = fso.GetParentFolderName(WScript.ScriptFullName);
+
+    cmdline = path + "\\" + MD5PROG + " " + MD5PROGARGS + checkSum + " \"" + 
sourceFile + "\"";
+    if (debug) info("MD5 check cmdline: " + cmdline);
+
+    if (exec (cmdline, 0) == 0) return true
+    else return false;
+}
+
+// download a file via HTTP
+function downloadFile(sourceFile, targetFile, timeout)
+{
+    try {
+       var fso = new ActiveXObject("Scripting.FileSystemObject");
+       var stream = new ActiveXObject("ADODB.Stream");
+       var xmlHttp = new ActiveXObject("Microsoft.XMLHttp");
+
+       if (debug) info("Downloading \"" + sourceFile + "\" to \"" + targetFile 
+ "\"")
+       else info("Downloading: \"" + sourceFile + "\"");
+
+       xmlHttp.Open("GET", sourceFile, true);
+       xmlHttp.Send();
+
+       for (var t = 0; t < timeout * 10; t++) {
+           //info("sleeping t=" + t + " timeout=" + timeout + " readystate=" + 
xmlHttp.ReadyState);
+           if (xmlHttp.ReadyState == 4) break;
+           WScript.sleep(100);
+       }
+
+       // abort download on timeout
+       if (xmlHttp.ReadyState != 4) {
+           xmlHttp.abort();
+           throw new Error(0, "HTTP Timeout after " + timeout + " seconds.");
+       }
+
+       if (xmlHttp.status != 200) {
+           throw new Error(0, "HTTP Error: " + xmlHttp.status + " " + 
xmlHttp.StatusText);
+       }
+
+       stream.open();
+       stream.type = 1;
+
+       stream.write(xmlHttp.responseBody);
+       stream.position = 0;
+
+       if (fso.fileExists(targetFile)) {
+           fso.deleteFile(targetFile);
+       }
+
+       stream.saveToFile(targetFile);
+       stream.close();
+
+       fso = stream = xmlHttp = null;
+    } catch (e) {
+       info("Download failed: " + e.description);
+       return false;
+    }
+
+    return true;
+}
begin:vcard
fn:Andre Ilie
n:Ilie;Andre
org:Photonic Sense GmbH;IT NOC
adr:;;Am Goldberg 3;Eisenach;TH;99817;Germany
email;internet:[EMAIL PROTECTED]
title:Systemadministration
tel;work:+49 3691 73 18 0
tel;fax:+49 3691 73 18 79
note:I haven't lost my mind, it's backed up on tape somewhere....
x-mozilla-html:FALSE
url:http://www.photonic-sense.com/
version:2.1
end:vcard

Reply via email to