From: Richard W.M. Jones Date: Fri, 17 Dec 2010 14:24:22 +0000 (+0000) Subject: Version 0.1.3. X-Git-Tag: 0.1.3^0 X-Git-Url: http://git.annexia.org/?a=commitdiff_plain;h=c1ae4bad9c38874b90a43985d6ec3d163dae74bf;p=guestfs-browser.git Version 0.1.3. --- diff --git a/configure.ac b/configure.ac index 05a7dcf..67272ef 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ dnl You should have received a copy of the GNU General Public License along dnl with this program; if not, write to the Free Software Foundation, Inc., dnl 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -AC_INIT([guestfs-browser],[0.1.2]) +AC_INIT([guestfs-browser],[0.1.3]) AM_INIT_AUTOMAKE([foreign]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/filetree.ml b/filetree.ml index a007d97..2bf0b3d 100644 --- a/filetree.ml +++ b/filetree.ml @@ -155,9 +155,9 @@ and button_press ({ model = model; view = view } as t) ev = (* Based on number of selected rows and what is selected, construct * the context menu. *) - if paths <> [] then ( - let menu = make_context_menu t paths in - menu#popup ~button ~time + (match make_context_menu t paths with + | Some menu -> menu#popup ~button ~time + | None -> () ); (* Return true so no other handler will run. *) @@ -170,9 +170,6 @@ and make_context_menu t paths = let menu = GMenu.menu () in let factory = new GMenu.factory menu in - let item = factory#add_item "Open" in - item#misc#set_sensitive false; - let rec add_file_items path = let item = factory#add_item "File information" in item#misc#set_sensitive false; @@ -202,46 +199,70 @@ and make_context_menu t paths = let item = factory#add_item "Download list of filenames ..." in ignore (item#connect#activate ~callback:(download_dir_find0 t path)); - and add_os_items path = + and add_top_os_items path = let item = factory#add_item "Operating system information" in ignore (item#connect#activate ~callback:(display_inspection_data t path)); ignore (factory#add_separator ()); - add_volume_items path + add_top_volume_items path - and add_volume_items path = + and add_top_volume_items path = let item = factory#add_item "Filesystem used & free" in item#misc#set_sensitive false; let item = factory#add_item "Block device information" in item#misc#set_sensitive false; ignore (factory#add_separator ()); add_directory_items path + + and add_topwinreg_items path = + let item = factory#add_item "Download hive file ..." in + item#misc#set_sensitive false; + ignore (factory#add_separator ()); + add_regkey_items path + + and add_regkey_items path = + let item = factory#add_item "Download as .reg file ..." in + item#misc#set_sensitive false + + and add_regvalue_items path = + let item = factory#add_item "Copy value to clipboard" in + ignore (item#connect#activate ~callback:(copy_regvalue t path)); + in - (match paths with - (* single selection *) - | [path, { content=Top (Slave.OS os)} ] -> (* top level operating system *) - add_os_items path + let has_menu = + match paths with + | [] -> false - | [path, { content=Top (Slave.Volume dev) }] -> (* top level volume *) - add_volume_items path + (* single selection *) + | [path, { content=Top (Slave.OS os)} ] -> (* top level operating system *) + add_top_os_items path; true - | [path, { content=Directory direntry }] -> (* directory *) - add_directory_items path + | [path, { content=Top (Slave.Volume dev) }] -> (* top level volume *) + add_top_volume_items path; true - | [path, { content=File direntry }] -> (* file *) - add_file_items path + | [path, { content=Directory _ }] -> (* directory *) + add_directory_items path; true - | [_, { content=Loading }] - | [_, { content=ErrorMessage _ }] -> () + | [path, { content=File _ }] -> (* file *) + add_file_items path; true - | _ -> - (* At the moment multiple selection is disabled. When/if we - * enable it we should do something intelligent here. XXX - *) - () - ); + | [path, { content=TopWinReg _ }] -> (* top level registry node *) + add_topwinreg_items path; true + + | [path, { content=RegKey _ }] -> (* registry node *) + add_regkey_items path; true + + | [path, { content=RegValue _ }] -> (* registry key/value pair *) + add_regvalue_items path; true - menu + | [_, { content=(Loading|ErrorMessage _|Info _) }] -> false + + | _::_::_ -> + (* At the moment multiple selection is disabled. When/if we + * enable it we should do something intelligent here. XXX + *) + false in + if has_menu then Some menu else None let clear { model = model; hash = hash } = model#clear (); @@ -435,6 +456,12 @@ and when_read_directory ({ model = model } as t) path entries = let row = model#get_iter path in + (* Sort the entries by lexicographic ordering. *) + let cmp { Slave.dent_name = n1 } { Slave.dent_name = n2 } = + UTF8.compare n1 n2 + in + let entries = List.sort ~cmp entries in + (* Add the entries. *) List.iter ( fun direntry -> @@ -543,7 +570,7 @@ and expand_hive_node ({ model = model } as t) row node = * to the tree. *) let values = Hivex.node_values h node in - let cmp v1 v2 = compare (Hivex.value_key h v1) (Hivex.value_key h v2) in + let cmp v1 v2 = UTF8.compare (Hivex.value_key h v1) (Hivex.value_key h v2) in Array.sort cmp values; Array.iter ( fun value -> @@ -555,7 +582,7 @@ and expand_hive_node ({ model = model } as t) row node = ) values; let children = Hivex.node_children h node in - let cmp n1 n2 = compare (Hivex.node_name h n1) (Hivex.node_name h n2) in + let cmp n1 n2 = UTF8.compare (Hivex.node_name h n1) (Hivex.node_name h n2) in Array.sort cmp children; Array.iter ( fun node -> diff --git a/filetree_markup.ml b/filetree_markup.ml index beb41b2..a890cca 100644 --- a/filetree_markup.ml +++ b/filetree_markup.ml @@ -90,7 +90,6 @@ and markup_of_regkey ?(visited = false) h node = (* Mark up a registry value. *) and markup_of_regvalue ?(visited = false) h value = - debug "markup_of_regvalue"; let k = Hivex.value_key h value in let k = if k = "" then "@" else k in let t, v = Hivex.value_value h value in @@ -98,56 +97,13 @@ and markup_of_regvalue ?(visited = false) h value = (* Ignore long values. *) let len = String.length v in let v = - if len >= 256 then - sprintf "<%d bytes not printed>" len - else ( - (* Deal as best we can with printing the value. *) - match t with - | Hivex.REG_NONE -> if v = "" then "" else markup_hex_data v - | Hivex.REG_SZ -> markup_windows_string v - | Hivex.REG_EXPAND_SZ -> markup_windows_string v - | Hivex.REG_BINARY -> markup_hex_data v - | Hivex.REG_DWORD -> - (bitmatch Bitstring.bitstring_of_string v with - | { i : 32 : littleendian } -> sprintf "%08lx" i - | { _ } -> markup_hex_data v) - | Hivex.REG_DWORD_BIG_ENDIAN -> - (bitmatch Bitstring.bitstring_of_string v with - | { i : 32 : bigendian } -> sprintf "%08lx" i - | { _ } -> markup_hex_data v) - | Hivex.REG_LINK -> markup_hex_data v - | Hivex.REG_MULTI_SZ -> (* XXX could do better with this *) - markup_hex_data v - | Hivex.REG_RESOURCE_LIST -> markup_hex_data v - | Hivex.REG_FULL_RESOURCE_DESCRIPTOR -> markup_hex_data v - | Hivex.REG_RESOURCE_REQUIREMENTS_LIST -> markup_hex_data v - | Hivex.REG_QWORD -> - (bitmatch Bitstring.bitstring_of_string v with - | { i : 64 : littleendian } -> sprintf "%016Lx" i - | { _ } -> markup_hex_data v) - | Hivex.REG_UNKNOWN i32 -> markup_hex_data v - ) in + if len >= 512 then sprintf "<%d bytes not printed>" len + else markup_escape (printable_hivex_value ~split_long_lines:true t v) in let fg = if not visited then normal file_color else darken file_color in sprintf "%s=%s" fg (markup_escape k) fg v -(* Mark up registry value as hex data. *) -and markup_hex_data v = - let vs = String.explode v in - let vs = List.mapi ( - fun i c -> - sprintf "%s%02x" (if i mod 16 = 0 then "\n" else "") (int_of_char c) - ) vs in - String.concat "," vs - -(* Best guess the format of the string and convert to UTF-8. *) -and markup_windows_string v = - try markup_escape (windows_string_to_utf8 v) - with CharEncoding.Malformed_code | CharEncoding.Out_of_range -> - (* Fallback to displaying the string as hex. *) - markup_hex_data v - and normal (r, g, b) = let r = if r < 0 then 0 else if r > 255 then 255 else r in let g = if g < 0 then 0 else if g > 255 then 255 else g in diff --git a/filetree_ops.ml b/filetree_ops.ml index 5946a81..801f50a 100644 --- a/filetree_ops.ml +++ b/filetree_ops.ml @@ -226,3 +226,16 @@ let display_inspection_data ({ model = model } as t) path () = model#set ~row ~column:t.name_col data ) + +(* Copy registry key value to clipboard. *) +let copy_regvalue ({ model = model } as t) path () = + let row = model#get_iter path in + let hdata = get_hdata t row in + match hdata with + | { content=RegValue value; hiveh = Some h } -> + let t, v = Hivex.value_value h value in + let v = printable_hivex_value t v in + let cb = GData.clipboard Gdk.Atom.clipboard in + cb#set_text v + + | _ -> () (* not a registry value row, ignore *) diff --git a/filetree_ops.mli b/filetree_ops.mli index 9191ad4..a30b390 100644 --- a/filetree_ops.mli +++ b/filetree_ops.mli @@ -28,6 +28,8 @@ (**/**) +val copy_regvalue : Filetree_type.t -> Gtk.tree_path -> unit -> unit + val disk_usage : Filetree_type.t -> Gtk.tree_path -> unit -> unit val display_inspection_data : Filetree_type.t -> Gtk.tree_path -> unit -> unit diff --git a/guestfs-browser.spec.in b/guestfs-browser.spec.in index 889ea95..05dc733 100644 --- a/guestfs-browser.spec.in +++ b/guestfs-browser.spec.in @@ -16,6 +16,7 @@ BuildRequires: libguestfs-devel >= 1.7.24 BuildRequires: libvirt-devel BuildRequires: ocaml BuildRequires: ocaml-bitstring-devel +BuildRequires: ocaml-camlp4-devel BuildRequires: ocaml-camomile-devel, ocaml-camomile-data BuildRequires: ocaml-extlib-devel BuildRequires: ocaml-findlib-devel diff --git a/slave.ml b/slave.ml index 8cf8199..01105ef 100644 --- a/slave.ml +++ b/slave.ml @@ -292,7 +292,7 @@ and execute_command = function dom_name = D.get_name d; dom_state = (D.get_info d).D.state } ) doms in - let cmp { dom_name = n1 } { dom_name = n2 } = compare n1 n2 in + let cmp { dom_name = n1 } { dom_name = n2 } = UTF8.compare n1 n2 in let doms = List.sort ~cmp doms in status "Connected to %s" printable_name; diff --git a/utils.ml b/utils.ml index f9cf35d..95c1289 100644 --- a/utils.ml +++ b/utils.ml @@ -17,6 +17,7 @@ *) open ExtString +open ExtList open CamomileLibrary open Default.Camomile @@ -176,3 +177,44 @@ let windows_string_to_utf8 str = String.sub str 0 (UTF8.last str) else str + +(* Best effort convert hive value to printable string. *) +let rec printable_hivex_value ?split_long_lines t v = + let hex = reg_hex_of_string ?split_long_lines in + match t with + | Hivex.REG_NONE -> if v = "" then "" else hex v + | Hivex.REG_SZ -> + (try windows_string_to_utf8 v with _ -> hex v) + | Hivex.REG_EXPAND_SZ -> + (try windows_string_to_utf8 v with _ -> hex v) + | Hivex.REG_BINARY -> hex v + | Hivex.REG_DWORD -> + (bitmatch Bitstring.bitstring_of_string v with + | { i : 32 : littleendian } -> sprintf "%08lx" i + | { _ } -> hex v) + | Hivex.REG_DWORD_BIG_ENDIAN -> + (bitmatch Bitstring.bitstring_of_string v with + | { i : 32 : bigendian } -> sprintf "%08lx" i + | { _ } -> hex v) + | Hivex.REG_LINK -> hex v + | Hivex.REG_MULTI_SZ -> (* XXX should be better for this one *) + hex v + | Hivex.REG_RESOURCE_LIST -> hex v + | Hivex.REG_FULL_RESOURCE_DESCRIPTOR -> hex v + | Hivex.REG_RESOURCE_REQUIREMENTS_LIST -> hex v + | Hivex.REG_QWORD -> + (bitmatch Bitstring.bitstring_of_string v with + | { i : 64 : littleendian } -> sprintf "%016Lx" i + | { _ } -> hex v) + | Hivex.REG_UNKNOWN i32 -> hex v + +(* Convert binary data to a hex string. This includes line breaks. *) +and reg_hex_of_string ?(split_long_lines=false) v = + let vs = String.explode v in + let vs = List.mapi ( + fun i c -> + sprintf "%s%02x" + (if split_long_lines && i mod 16 = 0 then "\n" else "") + (int_of_char c) + ) vs in + String.concat "," vs diff --git a/utils.mli b/utils.mli index 92e2bb6..7a15144 100644 --- a/utils.mli +++ b/utils.mli @@ -121,3 +121,7 @@ val windows_string_to_utf8 : string -> string This may fail in multiple ways, raising a Camomile exception which you probably need to catch. *) + +val printable_hivex_value : ?split_long_lines:bool -> Hivex.hive_type -> string -> string + (** [printable_hivex_value t v] converts raw registry value + [v] of type [t] to a printable string. *)