Camarade_Tux Posted October 21, 2007 Share Posted October 21, 2007 (edited) Hi,During the last holidays I wrote a program that would parse the now famous mssecure.xml file in order to retrieve updates automatically.The result is a 130-lines ocaml code which atm relies on an external wget (will be fixed once I get the ocaml terminology for networks):exception Xml_not_found_by_name_in_xml_listexception Missing_mssecure_cabexception Bad_number_of_characters_read_from_mssecure_cabexception Error_during_expansion_of_mssecure_cab of intexception Xml_not_found_by_attrib_name_and_value_in_xml_list of string * stringlet lang_code=ref ""let lang_string=ref ""let product=ref ""let service_pack=ref ""let product_id=ref ""let product_family_id=ref ""let service_pack_level=ref 0let service_pack_id=ref ""let dest_dir=ref "Windows XP Professional SP2 English"let number_of_updates=ref 0let rec find_xml_by_name_in_xml_list name=function |xml::q->if (name=Xml.tag xml) then xml else find_xml_by_name_in_xml_list name q |[]->Printf.printf "%s" name; raise Xml_not_found_by_name_in_xml_listlet rec find_xml_by_attrib_name_and_value_in_xml_list attrib_name attrib_value=function |xml::q->if try attrib_value=Xml.attrib xml attrib_name with _->false then xml else find_xml_by_attrib_name_and_value_in_xml_list attrib_name attrib_value q |[]->raise (Xml_not_found_by_attrib_name_and_value_in_xml_list (attrib_name,attrib_value))let set_lang ()= Printf.printf "language ?\n"; lang_string:=read_line (); lang_code:=match !lang_string with |"English"->"1033" |"French"->"1036" |"German"->"1031" |"Japanese"->"1041" |_->read_line ()let set_product ()= Printf.printf "product ?\n"; product:=read_line ()let set_service_pack ()= Printf.printf "service pack level ?\n"; service_pack_level:=int_of_string (read_line ())let set_destdir ()= dest_dir:=!product^" "^"SP"^(string_of_int !service_pack_level)^" "^(!lang_string)let localized_mssecure_cab_location=function |"1033"->"http://go.microsoft.com/fwlink/?LinkId=18922" |"1036"->"http://go.microsoft.com/fwlink/?LinkId=18122" |"1031"->"http://go.microsoft.com/fwlink/?LinkId=18121" |"1041"->"http://go.microsoft.com/fwlink/?LinkId=18120" |_->assert false(* [url="http://go.microsoft.com/fwlink/?LinkID=74689"]http://go.microsoft.com/fwlink/?LinkID=74689[/url] *)let rec update_concerns_product=function |xml::q->(("AffectedProduct"=(Xml.tag xml)) && (!product_id=Xml.attrib xml "ProductID") && (!service_pack_id<>"") && (int_of_string !service_pack_id = int_of_string (Xml.attrib (List.hd (Xml.children xml)) "ServicePackID"))) || (update_concerns_product q) (* est-ce qu'il n'y aura toujours qu'un seul "AffectedServicePack" ? *) |[]->falselet rec list_updates_for_product_out_of_bulletin=function |xml::q->if ((update_concerns_product (Xml.children xml)) && ("0"=Xml.attrib xml "SBID")) then (Xml.attrib xml "PatchLocationID")::(list_updates_for_product_out_of_bulletin q) else list_updates_for_product_out_of_bulletin q |[]->[]let rec list_updates=function |xml::q->let patches_list=try Xml.children (find_xml_by_name_in_xml_list "Patches" (Xml.children xml)) with _->[] in let updates=list_updates_for_product_out_of_bulletin patches_list in if updates!=[] then updates@(list_updates q) else list_updates q |[]->[] let rec list_locations updates locations= match updates,locations with |[],_ |_,[]->[] |(update::update_queue),(xml::xml_queue)->begin match compare update (Xml.attrib xml "LocationID") with |0->((Xml.attrib xml "Path")^"\n")::(list_locations update_queue xml_queue) |_->list_locations (update::update_queue) xml_queue endlet rec run_wget_for_each_element_of_the_list n=function |t::q->let _=Printf.printf "downloading update %d of %d\n" n !number_of_updates in let _=flush stdout in let _=Unix.system ("..\\wget.exe -N -nv \""^t^"\"") in let _=print_endline "" in run_wget_for_each_element_of_the_list (n+1) q |[]->Printf.printf "All %d updates successfully downloaded in %s.\n" (n-1) !dest_dirlet solve_escaped_quote in_channel= let mssecure_xml_length=in_channel_length in_channel in let s=String.create mssecure_xml_length in let _=try really_input in_channel s 0 mssecure_xml_length with End_of_file -> raise Bad_number_of_characters_read_from_mssecure_cab in let i=ref 0 in let _=while (try s.[!i]<>'3' || s.[!i+1]<>'2' || s.[!i+2]<>'\\' || s.[!i+3]<>'\"' with _->false) do incr i; done in let _=if !i<(mssecure_xml_length-2) then (s.[!i+2] <- '\"'; s.[!i+3]<-' ') else Printf.printf "Seems MS has fixed the \\\" problem in mssecure.xml\n" in s;;set_lang (); set_product (); set_service_pack (); set_destdir (); print_endline "";;let _=print_endline "\nDownloading the localized mssecure cab-file." inlet _=Unix.system (".\\wget.exe -N -nv \""^(localized_mssecure_cab_location !lang_code)^"\"") inlet _=if (Sys.file_exists ("MSSecure_"^(!lang_code)^".cab")) then let expand_exit_code=Sys.command ("expand MSSecure_"^(!lang_code)^".cab mssecure.xml") in if expand_exit_code<>0 then raise (Error_during_expansion_of_mssecure_cab expand_exit_code) else () else raise Missing_mssecure_cabin let xml_parsed=Xml.parse_string (solve_escaped_quote (open_in_bin "mssecure.xml")) inlet this_product_xml= find_xml_by_attrib_name_and_value_in_xml_list "Name" !product (Xml.children (find_xml_by_name_in_xml_list "Products" (Xml.children xml_parsed))) inlet _=product_id:= Xml.attrib this_product_xml "ProductID" inlet _=product_family_id:= Xml.attrib (List.hd (Xml.children (find_xml_by_name_in_xml_list "ProductFamilies" (Xml.children this_product_xml)))) "ProductFamilyID" inlet _=service_pack_id:= Xml.attrib (List.nth (Xml.children (find_xml_by_name_in_xml_list "AvailableSPs" (Xml.children this_product_xml))) (!service_pack_level-1)) "ServicePackID" inlet bulletins=find_xml_by_name_in_xml_list "Bulletins" (Xml.children xml_parsed) inlet updates=list_updates (Xml.children bulletins) inlet locations=Xml.children (find_xml_by_name_in_xml_list "Locations" (Xml.children xml_parsed)) inlet _=if not (Sys.file_exists !dest_dir) then Unix.mkdir !dest_dir 0o777 else () inlet _=Unix.chdir !dest_dir inlet urls=list_locations updates locations inlet _=number_of_updates:=List.length urls inlet _=Printf.printf "%d updates and %d URLs collected, beginning download :\n" (List.length updates) !number_of_updates inlet _=run_wget_for_each_element_of_the_list 1 urls inlet _=print_endline "All done. The program will now exit." inread_line ();;(all rights for this source code belong to me, will give a nicer license later on)Just compile it with "ocamlopt.opt -o upddl.exe unix.cmxa xml-light.cmxa main.ml".What ? You don't have an ocaml compiler on your computer ! OK, you can have binaries too : http://tools.yaxm.org/upddl.7z Just expand and double-click the upddl.exe file but read the instructions and details that follow. It should work for any product, service pack and language (Japanese is problematic in fact) described in mssecure.xml a.I get 64 critical updates and HFNetChk returns only this : * WINDOWS XP SP2 Patch NOT Installed MS06-014 911562 File C:\Programs\Fichiers communs\system\msadc\msadco.dll has a file version [2.81.1117.0] that is less than what is expected [2.81.1124.0]. * INTERNET EXPLORER 6 SP2 Information There are no entries for Internet Explorer 6 SP2 in the XML file.The use is a bit strict at the moment : it needs a precise string and is case-sensitive. - You have four choices for language : French, German, Japanese, English. - For the product, you have much more choices as this program is not limited to windows, here is the part relevant to hfslip (don't forget, precise names, unlocalized and case-sensitive, I'll make it nicer next week) : - And for the service pack level, 0, 1, 2 and so on.For XP SP2 french, I type:French<return>Windows XP Professional<return>2<return>edit:Internet Explorer are in another place and can be downloaded with "Internet Explorer 5.5", "Internet Explorer 6", "Internet Explorer 6.0 for Windows Server 2003" as product.Same goes for MSXML, Outlook Express, WMP (which won't appear in hfnetchk's log as it has been removed by nlite).But of course there's a problem.Microsoft just discontinued mssecure.xml files. They are still availables but not updated anymore (probably the reason why I lack some recent updates).There's a new format but there's no information available about it : http://support.microsoft.com/kb/927745Basically what is available is "the v2 format is compatible with the v1 [which is not mssecure.xml], refer to information about v1" but there's no way to find information about v1 as everything links to v2...So I can't have recent hotfixes.I think I understood the spec but it uses UIDs instead of names (as Microsoft Windows XP) for which I don't have a list. If anyone has a list of UIDs for microsoft products, please share it. Thanks. Have fun. :beer: Edited October 21, 2007 by Camarade_Tux Link to comment Share on other sites More sharing options...
Camarade_Tux Posted October 21, 2007 Author Share Posted October 21, 2007 Note : there's an uncaught exception if you want SP0 (-1 has never been a positive integer) or a SP that is bigger than what is available.Will fix next week, I got work for tomorrow. Link to comment Share on other sites More sharing options...
murvun Posted October 25, 2007 Share Posted October 25, 2007 (edited) try ct offline updateHeise is a german publisher and ct a german computer newspaper. This is the version 4 of offline-updates.offline-updates is a collection of scripts, some are compiled auto-it-scripts. Source is provided.It is also based on wgetEdit: new version (4.1) fixed some errors and now supports more languages Edited November 2, 2007 by murvun Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now