Jump to content

XML DOM wrapper (COM)


eltorro
 Share

Recommended Posts

Can anyone help me with this XML problem. I wrote little function that i use to create temp .xml file and it seems that when the first value always gets written properly, the 2nd one doesn't.

#Include <_XMLDomWrapper.au3>

Global $settings_temporary = @ScriptDir & "\post_deployment_temporary.xml"

If RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system", "legalnoticetext") <> "" Then _TempXMLSetting("legalnoticetext", RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system", "legalnoticetext"), "write")
If RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system", "legalnoticecaption") <> "" Then _TempXMLSetting("legalnoticecaption", RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system", "legalnoticecaption"), "write")

If _TempXMLSetting("legalnoticecaption", "", "read") <> "" Then MsgBox(0,"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system - legalnoticecaption", _TempXMLSetting("legalnoticecaption", "", "read"))
If _TempXMLSetting("legalnoticetext", "", "read") <> "" Then MsgBox(0,"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system - legalnoticetext", _TempXMLSetting("legalnoticetext", "", "read"))

Func _TempXMLSetting($temp_setting_update, $temp_setting_value, $option) ; temp variable in .xml / temp value in .xml for that value / read or write
    Local $main_node_to_temporary = "temporary"
    If $option = "read" Then
        If FileExists($settings_temporary) Then
            $mySettings = _XMLFileOpen ($settings_temporary)
            ;MsgBox(0,0,_GetFirstValue($main_node_to_temporary & "/" & $temp_setting_update))
            Return _GetFirstValue($main_node_to_temporary & "/" & $temp_setting_update)
        Else
            Return ""
        EndIf
    EndIf
    If $option = "write" Then
        If FileExists($settings_temporary) Then
            MsgBox(0,"file exists",$temp_setting_update & " _ " & $temp_setting_value & " _ " &  $option )
            $mySettings = _XMLFileOpen ($settings_temporary)
            If $mySettings = -1 Then MsgBox(0,0, "Error 1")
            _XMLUpdateField ($main_node_to_temporary & "/" & $temp_setting_update, $temp_setting_value)
            _XMLTransform ($mySettings)
            $mySettings.Save ($settings_temporary)
            Return ""
        Else
            _XMLCreateFile ($settings_temporary, "temporary", True)
            MsgBox(0,"file NOT exists",$temp_setting_update & " _ " & $temp_setting_value & " _ " &  $option )
            $mySettings = _XMLFileOpen ($settings_temporary)
            If $mySettings = -1 Then MsgBox(0,0, "Error 2")
            _XMLCreateRootChild ($temp_setting_update, $temp_setting_value)
            _XMLTransform ($mySettings)
            $mySettings.Save ($settings_temporary)
            Return ""
        EndIf
    EndIf
EndFunc   ;==>_TempXMLSetting

Func _GetFirstValue($node)
    $ret_val = _XMLGetValue ($node)
    If IsArray($ret_val) Then
        Return ($ret_val[1])
    Else
        Return SetError(1, 3, 0)
    EndIf
EndFunc   ;==>_GetFirstValue

Thank You

EDIT: Forgot to add 2 first lines.

EDIT2: Forgot to add _GetFirstValue function, also note that 'reading' doesnt' seems to work aswell. I have added 2 more lines at the top for reading and it never returns array so _GetFirstValue doesn;t work ;(

Edited by MadBoy

My little company: Evotec (PL version: Evotec)

Link to comment
Share on other sites

Can anyone help me with this XML problem. I wrote little function that i use to create temp .xml file and it seems that when the first value always gets written properly, the 2nd one doesn't.

#Include <_XMLDomWrapper.au3>

Global $settings_temporary = @ScriptDir & "\post_deployment_temporary.xml"

If RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system", "legalnoticetext") <> "" Then _TempXMLSetting("legalnoticetext", RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system", "legalnoticetext"), "write")
If RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system", "legalnoticecaption") <> "" Then _TempXMLSetting("legalnoticecaption", RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system", "legalnoticecaption"), "write")

If _TempXMLSetting("legalnoticecaption", "", "read") <> "" Then MsgBox(0,"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system - legalnoticecaption", _TempXMLSetting("legalnoticecaption", "", "read"))
If _TempXMLSetting("legalnoticetext", "", "read") <> "" Then MsgBox(0,"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system - legalnoticetext", _TempXMLSetting("legalnoticetext", "", "read"))

Func _TempXMLSetting($temp_setting_update, $temp_setting_value, $option) ; temp variable in .xml / temp value in .xml for that value / read or write
    Local $main_node_to_temporary = "temporary"
    If $option = "read" Then
        If FileExists($settings_temporary) Then
            $mySettings = _XMLFileOpen ($settings_temporary)
            ;MsgBox(0,0,_GetFirstValue($main_node_to_temporary & "/" & $temp_setting_update))
            Return _GetFirstValue($main_node_to_temporary & "/" & $temp_setting_update)
        Else
            Return ""
        EndIf
    EndIf
    If $option = "write" Then
        If FileExists($settings_temporary) Then
            MsgBox(0,"file exists",$temp_setting_update & " _ " & $temp_setting_value & " _ " &  $option )
            $mySettings = _XMLFileOpen ($settings_temporary)
            If $mySettings = -1 Then MsgBox(0,0, "Error 1")
            _XMLUpdateField ($main_node_to_temporary & "/" & $temp_setting_update, $temp_setting_value)
            _XMLTransform ($mySettings)
            $mySettings.Save ($settings_temporary)
            Return ""
        Else
            _XMLCreateFile ($settings_temporary, "temporary", True)
            MsgBox(0,"file NOT exists",$temp_setting_update & " _ " & $temp_setting_value & " _ " &  $option )
            $mySettings = _XMLFileOpen ($settings_temporary)
            If $mySettings = -1 Then MsgBox(0,0, "Error 2")
            _XMLCreateRootChild ($temp_setting_update, $temp_setting_value)
            _XMLTransform ($mySettings)
            $mySettings.Save ($settings_temporary)
            Return ""
        EndIf
    EndIf
EndFunc   ;==>_TempXMLSetting

Func _GetFirstValue($node)
    $ret_val = _XMLGetValue ($node)
    If IsArray($ret_val) Then
        Return ($ret_val[1])
    Else
        Return SetError(1, 3, 0)
    EndIf
EndFunc   ;==>_GetFirstValue

Thank You

EDIT: Forgot to add 2 first lines.

EDIT2: Forgot to add _GetFirstValue function, also note that 'reading' doesnt' seems to work aswell. I have added 2 more lines at the top for reading and it never returns array so _GetFirstValue doesn;t work ;(

The node has to exist before _XMLUpdateField can be used. Check the return or @error from _XMLUpdateField. If there is an error, then use _XMLCreateChildNode.

Link to comment
Share on other sites

The node has to exist before _XMLUpdateField can be used. Check the return or @error from _XMLUpdateField. If there is an error, then use _XMLCreateChildNode.

Thank you @eltorro. I have fixed the other problem with reading aswell so all works now! Thanks!

My little company: Evotec (PL version: Evotec)

Link to comment
Share on other sites

Hi,

I have been searchin for info about how to delete XML nodes but I can't find any.

I'm trying to delete a node(with sub nodes) identfied by an attribute (name=SQLExpress).

But I may be a bit thick because I just dont understand how to do this.

The xml file from wich I try to delete is containing several nodes with de same name (Package) but

different names in the attribute "name". XML files is new for me so I'm well confused about all this with node and atrributes andso on.

Attached an example of the xml file below, the part I want to delete is in bold text.

<?xml version="1.0" encoding="utf-8"?>

<Packages xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<Package name="SQLExpress" displayName="SQLExpress" version="1.0.0.00" displayVersion="2.0.0.00" category="Applications" description=""

<Conditions />

<PreProcess />

<PostProcess />

<Install>

<Command groupCondition="" accountid=""/>

</Install>

<Uninstall />

<Repair />

<Run />

<PatchDependencies />

<Dependencies />

</Package>

<Package name="AcroRead" displayName="Acrobat Reader" version="100">

<Conditions/>

<PreProcess/>

<PostProcess/>

<Install>

<Command groupCondition=""/>

</Install>

<Uninstall>

</Uninstall>

<Repair>

<Command groupCondition="" accountid="" filename="MsiExec.exe" arguments="/FOMUS &quot;%PACKAGE_SOURCE%

</Package>

</Packages>

I tried: _XMLDeleteAttrNode('/Packages/Package', 'name=SQLExpress')

but this must be wrong?

Please help

Edited by zandztrom
Link to comment
Share on other sites

Try _XMLDeleteNode('/Packages/Package[@ name="SQLExpress"]') . Name is an attribute.

;change paths and filenames respectively 
#Include "_XMLDomWrapper.au3"
_XMLFileOpen("packages.xml")
_XMLDeleteNode('/Packages/Package[@ name="SQLExpress"]')
;
Link to comment
Share on other sites

Try _XMLDeleteNode('/Packages/Package[@ name="SQLExpress"]') . Name is an attribute.

;change paths and filenames respectively 
#Include "_XMLDomWrapper.au3"
_XMLFileOpen("packages.xml")
_XMLDeleteNode('/Packages/Package[@ name="SQLExpress"]')
;

Great, worked like a charm... So easy when you know how; )

Thank you so much for your help!

Link to comment
Share on other sites

Perhaps I'm slow but I really don't see how to do a lot of stuff here. I'm trying to create a quick and dirty GUI for editing sudoers.xml from Sudo For Windows. I've created a gui framework with the autoit gui builder. What I can't see how to do is say, put info from the XML file into anything. I always get -1 returned for any function call I use from the XML wrapper.

I have this XML file:

<sudoers xmlns="http://sudowin.sourceforge.net/schemas/XmlAuthorizationPlugin/"

privilegesGroup="Administrators"

invalidLogons="3"

timesExceededInvalidLogons="3"

invalidLogonTimeout="180"

lockoutTimeout="180"

logonTimeout="180"

startTime="00:00:00.00000"

endTime="23:59:59.99999"

loggingLevel="Both"

allowAllCommands="false">

<users>

<userGroup name="Administrators">

<users>

<user name="jp10558" allowAllCommands="true">

</user>

</users>

</userGroup>

<userGroup name="Domain Users">

<users>

<user name="vis10" allowAllCommands="false">

</user>

<user name="user2" allowAllCommands="false">

<commands>

<command path="C:\Program Files\UltraVNC\winvnc.exe" />

</commands>

</user>

</users>

<commandGroupRefs>

<commandGroupRef commandGroupName="Domain" />

</commandGroupRefs>

</userGroup>

</users>

<commands>

<commandGroup name="Domain">

<command path="c:\windows\system32\mmc.exe" argumentString="devmgmt.msc" />

<command path="c:\windows\system32\rundll32.exe"

argumentString="/shell32.dll,((SHHelpShortcuts_RunDLL AddPrinter)|(Control_RunDLL powercfg.cpl))/" />

</commandGroup>

<commandGroup name="standard">

<!--

Windows XP SP2 files - checksums may vary per operating system, service pack

-->

<command path="c:\windows\system32\cmd.exe" md5Checksum="eeb024f2c81f0d55936fb825d21a91d6"

argumentString="/^/K echo.*$/"/>

<command path="c:\windows\explorer.exe" md5Checksum="45757077a47c68a603a79b03a1a836ab" />

<command path="c:\windows\system32\notepad.exe"

md5Checksum="388b8fbc36a8558587afc90fb23a3b99" allowedNetworks="192.168.0.226" />

</commandGroup>

</commands>

</sudoers>

How do I pull out the user groups and users from this? What I'd like to do is take this gui:

CODE
GuiCreate("Edit sudoers.xml", 559, 468,-1, -1 , BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPSIBLINGS))

$Label_1 = GuiCtrlCreateLabel("Group", 10, 10, 40, 20)

$Combo_2 = GuiCtrlCreateCombo("", 60, 10, 120, 21)

$Label_3 = GuiCtrlCreateLabel("User", 10, 40, 40, 20)

$Combo_4 = GuiCtrlCreateCombo("Combo4", 60, 40, 120, 21)

$Checkbox_5 = GuiCtrlCreateCheckbox("Allow all commands", 200, 20, 130, 20)

$Label_6 = GuiCtrlCreateLabel("Commands allowed", 130, 80, 100, 20)

$List_7 = GuiCtrlCreateList("", 130, 100, 420, 344)

$Input_8 = GuiCtrlCreateInput("", 10, 160, 110, 20)

$Label_9 = GuiCtrlCreateLabel("Add new command", 10, 140, 110, 20)

$Input_10 = GuiCtrlCreateInput("", 10, 210, 110, 20)

$Label_11 = GuiCtrlCreateLabel("Allowed arguments", 10, 190, 100, 20)

$Button_12 = GuiCtrlCreateButton("Add", 40, 250, 60, 20)

$Button_13 = GuiCtrlCreateButton("Delete", 280, 70, 60, 20)

GuiSetState()

And put the usergroups in the combobox and then put in the users that are in that group in the users combo box. I also like to know how I read in info like allowAllCommands="false" for a user so I can then update the checkbox... listbox etc. How do you deal with files that you're not sure how many nodes are in them? The example script knows what data fields to expect, but I don't know how many users there might be, or how many commands might be defined.

Link to comment
Share on other sites

There was a problem with the order in which certain properties were created on opening an XML file. This was causing MSXML to ignore a namespace setting thus preventing the finding of things within the document. It has been corrected. Please download the "latest greatest". Links are in the first post.

Link to comment
Share on other sites

Perhaps I'm slow but I really don't see how to do a lot of stuff here. I'm trying to create a quick and dirty GUI for editing sudoers.xml from Sudo For Windows. I've created a gui framework with the autoit gui builder. What I can't see how to do is say, put info from the XML file into anything. I always get -1 returned for any function call I use from the XML wrapper.

I have this XML file:

<sudoers    xmlns="[url="http://sudowin.sourceforge.net/schemas/XmlAuthorizationPlugin/"]http://sudowin.sourceforge.net/schemas/XmlAuthorizationPlugin/[/url]"
              privilegesGroup="Administrators" 
              invalidLogons="3"
              timesExceededInvalidLogons="3"
              invalidLogonTimeout="180"
              lockoutTimeout="180" 
              logonTimeout="180" 
              startTime="00:00:00.00000" 
              endTime="23:59:59.99999" 
              loggingLevel="Both" 
              allowAllCommands="false">
      <users>
          <userGroup name="Administrators">
              <users>
                  <user name="jp10558" allowAllCommands="true">
                  </user>
                  
              </users>
          </userGroup>
          <userGroup name="Domain Users">
              <users>
                  <user name="vis10" allowAllCommands="false">
                  </user>
                  <user name="user2" allowAllCommands="false">
                      <commands>
                          <command path="C:\Program Files\UltraVNC\winvnc.exe" />
                      </commands>
                  </user>
                  
              </users>
              <commandGroupRefs>
                  <commandGroupRef commandGroupName="Domain" />
              </commandGroupRefs>
          </userGroup>
      </users>
      <commands>
          <commandGroup name="Domain">
              <command path="c:\windows\system32\mmc.exe" argumentString="devmgmt.msc" />
              <command path="c:\windows\system32\rundll32.exe" 
  
  argumentString="/shell32.dll,((SHHelpShortcuts_RunDLL AddPrinter)|(Control_RunDLL powercfg.cpl))/" />
          </commandGroup>
          <commandGroup name="standard">
              
              <command path="c:\windows\system32\cmd.exe" md5Checksum="eeb024f2c81f0d55936fb825d21a91d6" 
  
  argumentString="/^/K echo.*$/"/>
              <command path="c:\windows\explorer.exe" md5Checksum="45757077a47c68a603a79b03a1a836ab" />
              <command path="c:\windows\system32\notepad.exe" 
  
  md5Checksum="388b8fbc36a8558587afc90fb23a3b99" allowedNetworks="192.168.0.226" />
          </commandGroup>
      </commands>
  </sudoers>

How do I pull out the user groups and users from this?

#Include <GuiConstants.au3>
#Include <GuiCombo.au3>
#Include "_XMLDomWrapper.au3"

GuiCreate("Edit sudoers.xml", 559, 468,-1, -1 , BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPSIBLINGS))
$Label_1 = GuiCtrlCreateLabel("Group", 10, 10, 40, 20)
$Combo_2 = GuiCtrlCreateCombo("", 60, 10, 120, 21)
$Label_3 = GuiCtrlCreateLabel("User", 10, 40, 40, 20)
$Combo_4 = GuiCtrlCreateCombo("", 60, 40, 120, 21)
$Checkbox_5 = GuiCtrlCreateCheckbox("Allow all commands", 200, 20, 130, 20)
$Label_6 = GuiCtrlCreateLabel("Commands allowed", 130, 80, 100, 20)
$List_7 = GuiCtrlCreateList("List_7", 130, 100, 420, 344)
$Input_8 = GuiCtrlCreateInput("", 10, 160, 110, 20)
$Label_9 = GuiCtrlCreateLabel("Add new command", 10, 140, 110, 20)
$Input_10 = GuiCtrlCreateInput("", 10, 210, 110, 20)
$Label_11 = GuiCtrlCreateLabel("Allowed arguments", 10, 190, 100, 20)
$Button_12 = GuiCtrlCreateButton("Add", 40, 250, 60, 20)
$Button_13 = GuiCtrlCreateButton("Delete", 280, 70, 60, 20)
GuiSetState()
main()
Exit
Func main()
    _Init()
    Local $nMsg
    While 1
        $nMsg = GuiGetMsg()
        Switch $nMsg
            case $GUI_EVENT_CLOSE
                ExitLoop
            case $Combo_2
                Local $userNames = _GetUsers(GUICtrlRead($Combo_2))
                _GUICtrlComboResetContent ($Combo_4)
                GuiCtrlSetData($Combo_4,$userNames,StringLeft($userNames,StringInstr($userNames,"|")-1)) 
                _GetAllowAll(GUICtrlRead($Combo_2),GUICtrlRead($Combo_4))
            Case $Combo_4
                _GetAllowAll(GUICtrlRead($Combo_2),GUICtrlRead($Combo_4))
            Case Else
        EndSwitch
    WEnd
EndFunc

Func _Init()
    
    If _XMLUDFVersion()<> "1.0.3.79" Then
        Local $msg = "Your version:"&_XMLUDFVersion() &" is outdated. Please update to version 1.0.3.79"&@LF
                $msg &="Versions prior to 1.0.3.79 contain a bug that may effect XML data containing namespaces."
        MsgBox(266288,"_XMLDomWrapper",$msg)
        Exit
    EndIf

    _SetDebug(True)
    ;It is necessary to specify a key-ref for the name space in order to be able to identify the nodes.
    $xmlns = "xmlns:sudo='[url="http://sudowin.sourceforge.net/schemas/XmlAuthorizationPlugin/"]http://sudowin.sourceforge.net/schemas/XmlAuthorizationPlugin/[/url]'"
    _XMLFileOpen("sudoers.xml",$xmlns)
    If @error Then
        MsgBox(266304,"Error","File could not be opened")
        Exit
    EndIf
    Local $userGroups = _GetUserGroups()
    GUICtrlSetData($Combo_2,$userGroups,StringLeft($userGroups,StringInstr($userGroups,"|")-1)) 
    Local $userNames = _GetUsers(GUICtrlRead($Combo_2))
    GuiCtrlSetData($Combo_4,$userNames,StringLeft($userNames,StringInstr($userNames,"|")-1)) 
    _GetAllowAll(GUICtrlRead($Combo_2),GUICtrlRead($Combo_4))
EndFunc

Func _GetUserGroups()
Local $userGroup = _XMLGetChildNodes("//sudo:sudoers/sudo:users")
    If IsArray($userGroup) Then
        $groups = ""
        For $x = 1 to UBound($userGroup)-1
            $groupname =  _XMLGetAttrib (StringFormat("//sudo:sudoers/sudo:users/sudo:userGroup[%s]",$x),"name" )
            if $groupname <> "" Then
                    $groups &= $groupname & "|"
            EndIf
        Next
        ConsoleWrite($groups&@LF)
        Return $groups
    EndIf
Return ""    
EndFunc

Func _GetUsers($userGroup)
    if $userGroup = "" Then Return
    Local $userNodes = _XMLGetChildNodes(StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users',$userGroup))
    If IsArray($userNodes) Then
        $users = ""
        For $x = 1 to UBound($userNodes)-1
            ;StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:user[%d]',$userGroup,$x)
            Local $username =  _XMLGetAttrib (StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:user[%d]',$userGroup,$x),"name" )
            if $username <> "" Then
                    $users &= $username &"|"
            EndIf
        Next
        ConsoleWrite($users&@LF)
        Return $users
    EndIf
Return ""    
EndFunc    

Func _GetAllowAll($userGroup,$user)
    If $userGroup = "" or $user = "" Then
        Return SetError(1,0,0)
    EndIf
    Local $allowall =  _XMLGetAttrib (StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:user[@name="%s"]',$userGroup,$user),"allowAllCommands" )
    If StringLower($allowall) = "true" Then 
        GuiCtrlSetState($Checkbox_5,$GUI_CHECKED)
        Return 1
    EndIf
    GuiCtrlSetState($Checkbox_5,$GUI_UNCHECKED)
    Return 0
EndFunc

Func _GetAvailableCommands($userGroup)
    if $userGroup = "" Then Return
    Local $userNodes = _XMLGetChildNodes(StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users',$userGroup))
    If IsArray($userNodes) Then
        $users = ""
        For $x = 1 to UBound($userNodes)-1
            Local $username =  _XMLGetAttrib (StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:user[%d]',$userGroup,$x),"name" )
            if $username <> "" Then
                    $users &= $username &"|"
            EndIf
        Next
        ConsoleWrite($users&@LF)
        Return $users
    EndIf
Return ""    
EndFunc

Edit: added version check

Edited by eltorro
Link to comment
Share on other sites

Ok, I'm looking at this, and I'm not really sure what's going on. I tried to edit the _GetAvailableCommands as it didn't seem to do anything and I decided for starters to try and just return what (if any) commandGroupRefs it used.

So, I didn't change as many variables as I would have liked as I wasn't sure what they were doing but here it is:

Func _GetAvailableCommands($userGroup)

if $userGroup = "" Then Return

Local $userNodes = _XMLGetChildNodes(StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:commandGroupRefs',$userGroup)); here I thought I could point it to not Users, but the commandGroupRefs that is just subordinate to the first Users.

If IsArray($userNodes) Then

$users = ""

For $x = 1 to UBound($userNodes)-1

Local $username = _XMLGetAttrib (StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:commandGroupRefs[%d]',$userGroup,$x),"commandGroupName" ); here I thought I would point to instead of the name field, the field name I wanted.

if $username <> "" Then

$users &= $username &"|"

EndIf

Next

ConsoleWrite($users&@LF)

Return $users; Here may be where I'm screwed up... What is this returning? A variable or an array?

EndIf

Return ""

EndFunc

Then I tried to add a case to fill/create a lable with the commandGroupRefs name (I think there may only be one, but here let's assume there is only one per usergroup):

Case $Label_13

$command = _GetAvailableCommands(GUICtrlRead($Combo_2))

$Label_13 = GuiCtrlCreateLabel($command, 440, 15, 100, 20)

This has no discrnable effect - perhaps because $command is an array, or something - doesn't look like an array though.

Maybe this isn't possible, but it would be really nice if there was something like the ini functions built into autoit - that is I say _read(/settings/user,username) and have _write(/settings/user,field,data).

Perhaps it's just because I don't understand this well enough.

Link to comment
Share on other sites

Ok, I'm looking at this, and I'm not really sure what's going on. I tried to edit the _GetAvailableCommands as it didn't seem to do anything and I decided for starters to try and just return what (if any) commandGroupRefs it used.

So, I didn't change as many variables as I would have liked as I wasn't sure what they were doing but here it is:

Func _GetAvailableCommands($userGroup)

if $userGroup = "" Then Return

Local $userNodes = _XMLGetChildNodes(StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:commandGroupRefs',$userGroup)); here I thought I could point it to not Users, but the commandGroupRefs that is just subordinate to the first Users.

If IsArray($userNodes) Then

$users = ""

For $x = 1 to UBound($userNodes)-1

Local $username = _XMLGetAttrib (StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:commandGroupRefs[%d]',$userGroup,$x),"commandGroupName" ); here I thought I would point to instead of the name field, the field name I wanted.

if $username <> "" Then

$users &= $username &"|"

EndIf

Next

ConsoleWrite($users&@LF)

Return $users; Here may be where I'm screwed up... What is this returning? A variable or an array?

EndIf

Return ""

EndFunc

Then I tried to add a case to fill/create a lable with the commandGroupRefs name (I think there may only be one, but here let's assume there is only one per usergroup):

Case $Label_13

$command = _GetAvailableCommands(GUICtrlRead($Combo_2))

$Label_13 = GuiCtrlCreateLabel($command, 440, 15, 100, 20)

This has no discrnable effect - perhaps because $command is an array, or something - doesn't look like an array though.

Maybe this isn't possible, but it would be really nice if there was something like the ini functions built into autoit - that is I say _read(/settings/user,username) and have _write(/settings/user,field,data).

Perhaps it's just because I don't understand this well enough.

That was my fault, I forgot to pull the code for that out.

This will read the command group from the usergroup then load the paths from the commands to the list box.

#Include <GuiConstants.au3>
#Include <GuiCombo.au3>
#Include <GuiList.au3>

#Include "Z:\fileman\_XMLDomWrapper.au3"

GuiCreate("Edit sudoers.xml", 559, 468,-1, -1 , BitOR($WS_OVERLAPPEDWINDOW, $WS_CLIPSIBLINGS))
$Label_1 = GuiCtrlCreateLabel("Group", 10, 10, 40, 20)
$Combo_2 = GuiCtrlCreateCombo("", 60, 10, 120, 21)
$Label_3 = GuiCtrlCreateLabel("User", 10, 40, 40, 20)
$Combo_4 = GuiCtrlCreateCombo("", 60, 40, 120, 21)
$Checkbox_5 = GuiCtrlCreateCheckbox("Allow all commands", 200, 20, 130, 20)
$Label_6 = GuiCtrlCreateLabel("Commands allowed", 130, 80, 100, 20)
$List_7 = GuiCtrlCreateList("", 130, 100, 420, 344)
$Input_8 = GuiCtrlCreateInput("", 10, 160, 110, 20)
$Label_9 = GuiCtrlCreateLabel("Add new command", 10, 140, 110, 20)
$Input_10 = GuiCtrlCreateInput("", 10, 210, 110, 20)
$Label_11 = GuiCtrlCreateLabel("Allowed arguments", 10, 190, 100, 20)
$Button_12 = GuiCtrlCreateButton("Add", 40, 250, 60, 20)
$Button_13 = GuiCtrlCreateButton("Delete", 280, 70, 60, 20)
GuiSetState()
main()
Exit
Func main()
    _Init()
    Local $nMsg
    While 1
        $nMsg = GuiGetMsg()
        Switch $nMsg
            case $GUI_EVENT_CLOSE
                ExitLoop
            case $Combo_2
                Local $userNames = _GetUsers(GUICtrlRead($Combo_2))
                _GUICtrlComboResetContent ($Combo_4)
                GuiCtrlSetData($Combo_4,$userNames,StringLeft($userNames,StringInstr($userNames,"|")-1)) 
                _UpdateUi(GUICtrlRead($Combo_2),GUICtrlRead($Combo_4))
            Case $Combo_4
                _UpdateUi(GUICtrlRead($Combo_2),GUICtrlRead($Combo_4))
            Case Else
        EndSwitch
    WEnd
EndFunc

Func _Init()
    
    If _XMLUDFVersion()<> "1.0.3.79" Then
        Local $msg = "Your version:"&_XMLUDFVersion() &" is outdated. Please update to version 1.0.3.79"&@LF
                $msg &="Versions prior to 1.0.3.79 contain a bug that may effect XML data containing namespaces."
        MsgBox(266288,"_XMLDomWrapper",$msg)
        Exit
    EndIf

    _SetDebug(True)
    ;It is necessary to specify a key-ref for the name space in order to be able to identify the nodes.
    $xmlns = "xmlns:sudo='http://sudowin.sourceforge.net/schemas/XmlAuthorizationPlugin/'"
    _XMLFileOpen("sudoers.xml",$xmlns)
    If @error Then
        MsgBox(266304,"Error","File could not be opened")
        Exit
    EndIf
    Local $userGroups = _GetUserGroups()
    GUICtrlSetData($Combo_2,$userGroups,StringLeft($userGroups,StringInstr($userGroups,"|")-1)) 
    Local $userNames = _GetUsers(GUICtrlRead($Combo_2))
    GuiCtrlSetData($Combo_4,$userNames,StringLeft($userNames,StringInstr($userNames,"|")-1)) 
    _GetAllowAll(GUICtrlRead($Combo_2),GUICtrlRead($Combo_4))
EndFunc

Func _UpdateUi($group,$user)
    _GetAllowAll($group,$user)
    Local $commandList = _GetAvailableCommands($group)
        _GUICtrlListClear ($List_7)
        GuiCtrlSetData($List_7,$commandList)
EndFunc

Func _GetUserGroups()
Local $userGroup = _XMLGetChildNodes("//sudo:sudoers/sudo:users")
    If IsArray($userGroup) Then
        $groups = ""
        For $x = 1 to UBound($userGroup)-1
            $groupname =  _XMLGetAttrib (StringFormat("//sudo:sudoers/sudo:users/sudo:userGroup[%s]",$x),"name" )
            if $groupname <> "" Then
                    $groups &= $groupname & "|"
            EndIf
        Next
        ConsoleWrite($groups&@LF)
        Return $groups
    EndIf
Return ""    
EndFunc

Func _GetUsers($userGroup)
    if $userGroup = "" Then Return
    Local $userNodes = _XMLGetChildNodes(StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users',$userGroup))
    If IsArray($userNodes) Then
        $users = ""
        For $x = 1 to UBound($userNodes)-1
            ;StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:user[%d]',$userGroup,$x)
            Local $username =  _XMLGetAttrib (StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:user[%d]',$userGroup,$x),"name" )
            if $username <> "" Then
                    $users &= $username &"|"
            EndIf
        Next
        ConsoleWrite($users&@LF)
        Return $users
    EndIf
Return ""    
EndFunc    

Func _GetAllowAll($userGroup,$user)
    If $userGroup = "" or $user = "" Then
        Return SetError(1,0,0)
    EndIf
    Local $allowall =  _XMLGetAttrib (StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:user[@name="%s"]',$userGroup,$user),"allowAllCommands" )
    If StringLower($allowall) = "true" Then 
        GuiCtrlSetState($Checkbox_5,$GUI_CHECKED)
        Return 1
    EndIf
    GuiCtrlSetState($Checkbox_5,$GUI_UNCHECKED)
    Return 0
EndFunc

Func _GetAvailableCommands($userGroup)
    if $userGroup = "" Then Return
    Local $commandGroup =  _XMLGetAttrib (StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:commandGroupRefs/sudo:commandGroupRef',$userGroup),"commandGroupName" )
    if @error = 0 And $commandGroup <> ""  Then
        ConsoleWrite("CommandGroup="&$commandGroup&@LF)
        Local $commandCount = _XMLGetChildNodes(StringFormat('//sudo:sudoers/sudo:commands/sudo:commandGroup[@name="%s"]',$commandGroup))
        if IsArray($commandCount) Then
            Local $commands = ""
            Local $c = 0
            For $x = 0 to UBound($commandCount)-1
                if $commandCount[$x] = "command" Then
                    $c+=1
                    Local $command = _XMLGetAttrib(StringFormat('//sudo:sudoers/sudo:commands/sudo:commandGroup[@name="%s"]/sudo:command[%d]',$commandGroup,$c),"path")
                    if $command <> "" Then
                        $commands &= $command &"|"
                    EndIf
                EndIf
            Next
            Return $commands
        EndIf    
    EndIf
Return ""    
EndFunc
Link to comment
Share on other sites

How to improve speed?

I have a working code to produce very complex XML. But. The speed is terrific. I mean process is really slow. I have debugged

my code with timecodes and what I have discovered is that:

_XMLCreateChildNode ("/Schedule/Group/Items", "Clip")

At this point code is fast enough. But in for-loop...

_XMLCreateChildNode ("/Schedule/Group/Items/Clip["&$iClip&"]/SubStreams/SubStream["&$iSubstream&"]", "Event")

Everything is slowing down. On every run there is at least 25 lines of "_XMLCreateChildNode" funcrtions adding nodes and setting values for

those nodes.

With 5 clips having 3 substreams containing 4 event on each takes about 20 seconds. Am I doing something wrong or is the parser really that slow?

Is there any way to speed up this script?

And ElTorro - thank you for this really fantastic UDF. And BTW thank you finding that 'magick fix' for namespaces. You helped me a lot with that!

Link to comment
Share on other sites

How do you write to a specific xml node when, like in my case, the difference is in an attribute like

<userGroup name="Administrators">
?

I tried

_XMLCreateChildWAttr ( '/sudoers/users/userGroup name="'& GuiCtrlRead($Combo_2) & '"/users', "user", "name", GUICtrlRead($Combo_4), "","" )
but that gave a COM error - also, I need to create the node with both the name and allowAllCommands="true" or allowAllCommands="false" depending on the checkbox (but I just want to write one or the other here...
Link to comment
Share on other sites

How to improve speed?

I have a working code to produce very complex XML. But. The speed is terrific. I mean process is really slow. I have debugged

my code with timecodes and what I have discovered is that:

_XMLCreateChildNode ("/Schedule/Group/Items", "Clip")

At this point code is fast enough. But in for-loop...

_XMLCreateChildNode ("/Schedule/Group/Items/Clip["&$iClip&"]/SubStreams/SubStream["&$iSubstream&"]", "Event")

Everything is slowing down. On every run there is at least 25 lines of "_XMLCreateChildNode" funcrtions adding nodes and setting values for

those nodes.

With 5 clips having 3 substreams containing 4 event on each takes about 20 seconds. Am I doing something wrong or is the parser really that slow?

Is there any way to speed up this script?

And ElTorro - thank you for this really fantastic UDF. And BTW thank you finding that 'magick fix' for namespaces. You helped me a lot with that!

Well, it's not a speed demon but if your using the latest version, try _XMLSetAutoSave(False) before beginning a long series. If you do that, be sure to call _XMLSaveDoc() because your changes/additions won't be committed unless you do. You can restore built in saving with _XMLSetAutoSave().
Link to comment
Share on other sites

How do you write to a specific xml node when, like in my case, the difference is in an attribute like

<userGroup name="Administrators">
?

I tried

_XMLCreateChildWAttr ( '/sudoers/users/userGroup name="'& GuiCtrlRead($Combo_2) & '"/users', "user", "name", GUICtrlRead($Combo_4), "","" )
but that gave a COM error - also, I need to create the node with both the name and allowAllCommands="true" or allowAllCommands="false" depending on the checkbox (but I just want to write one or the other here...
$Group = "Administrators"
    $User = "Josef"
    $AllowAll = "true"
    $ns = '[url="http://sudowin.sourceforge.net/schemas/XmlAuthorizationPlugin/"]http://sudowin.sourceforge.net/schemas/XmlAuthorizationPlugin/[/url]' ;define this globally at start of script.
    ;;; create a new user
    Local $aAttrs[2]=["name","allowAllCommands"]
    Local $aVals[2] =[$User,$AllowAll]
    _XMLCreateChildWAttr(StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users',$Group),"user",$aAttrs,$aVals,"",$ns)


   ;;; Change a user
_XMLSetAttrib(StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:users/sudo:user[@name="%s"]' ,$Group,$User),"allowAllCommands",$AllowAll )
Link to comment
Share on other sites

Can this perform conversions from csv to xml, by chance?

There is no built in function to do it. With a good csv parser it would not be hard to write a UDF to do it.

Link to comment
Share on other sites

Say I want to delete something from the file - is there some guide to how to write the XPath?

Specifically I think I'd want to delete the user by the Name attribute...

Also, I have adding a user worked out, but it's creating

<user name="test" allowAllCommands="true"/>

Instead of the reference

<user name="test" allowAllCommands="true">
</user>

I'm not sure it this will cause parsing issues for sudowin or not.

Link to comment
Share on other sites

Say I want to delete something from the file - is there some guide to how to write the XPath?

Specifically I think I'd want to delete the user by the Name attribute...

To delete a node, use something like

_XMLDeleteNode(StringFormat('//sudo:sudoers/sudo:users/sudo:userGroup[@name="%s"]/sudo:user[@name="%s"]',$userGroup,$userName))

Also, I have adding a user worked out, but it's creating

<user name="test" allowAllCommands="true"/>

Instead of the reference

<user name="test" allowAllCommands="true">
 </user>

I'm not sure it this will cause parsing issues for sudowin or not.

There is not any functionally difference between them.

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...