Leaderboard
Popular Content
Showing content with the highest reputation on 05/25/2018 in all areas
-
MX records for a specific domain
argumentum reacted to trancexx for a topic
Being new to AutoIt, I feel rush with every new script I make, do you? Retrieving MX records for a specific domain is something that you will probably never need to do. Or would you? In case you would... There is few tools on the net that will do it for you, or you can use 'nslookup.exe' that ships with your windows. There is few scripts here on forum that is automating nslookup (chiefly unsuccessful scripts). But that is not what I was thinking. AutoIt is very powerful scripting language, and almost ideal for this kind of tasks. MX records are retrieved after doing so called MX look up (this is smart, right?), and that is done by sending query, request to some DNS server. This communication is done on port 53, binary protocol is used by sending and receiving UDP packages. It is very hard to find some documentation on this (written for average human being to understand). So, this script (what scrip?) is written mostly relying on RFC1034 and RFC1035. It will not check for online status so if you run it off line it will just take 10-15 sec of your precious time. Domain name should be in form of ...domain name lol (example.com). It is ease to 'upgrade' it to check for online status, or to query MX records for IP-adress, or to query for example SOA records or ANAME or... Main function is made of three (sub)functions, to keep thingh as transparent as possible. Each of them can be replaced with better ones. First one will connect to the DNS server, ask the question and provide us with answer, second one will extract interesting parts of that answer and last one will sort things up. Commented only the interesting parts. Script will not use any external program or whatever to get us MX records! Question was what script. Well, this one: Opt("MustDeclareVars", 1) Dim $domain = "autoit.com" ; change it to domain of your interest Dim $mx = MXRecords($domain) If IsArray($mx) Then Local $au For $j = 1 To $mx[0][0] $au &= $mx[0][$j] & " - " & $mx[1][$j] & @CRLF Next MsgBox(0, "MX records for " & $domain, $au) Else MsgBox(0, "MX records for " & $domain, "No Records") EndIf Func MXRecords($domain) Local $binary_data = MXQueryServer($domain) If $binary_data = -1 Then Return -1 Local $output = ExtractMXServerData($binary_data) SortArray($output) Return $output EndFunc ;==>MXRecords Func MXQueryServer($domain) Local $domain_array $domain_array = StringSplit($domain, ".", 1) Local $binarydom For $el = 1 To $domain_array[0] $binarydom &= Hex(BinaryLen($domain_array[$el]), 2) & StringTrimLeft(StringToBinary($domain_array[$el]), 2) Next $binarydom &= "00" ; for example, 'gmail.com' will be '05676D61696C03636F6D00' and 'autoit.com' will be '066175746F697403636F6D00' Local $identifier = Hex(Random(0, 1000, 1), 2) ; random hex number serving as a handle for the data that will be received Local $server_bin = "0x00" & $identifier & "01000001000000000000" & $binarydom & "000F0001" ; this is our query Local $num_time, $data For $num_time = 1 To 10 Local $query_server ; ten(10) DNS servers, we'll start with one that is our's default, if no response or local one switch to public free servers Switch $num_time Case 1 Local $loc_serv = StringSplit(RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters", "DhcpNameServer"), " ", 1) If $loc_serv[0] > 0 Then If StringLeft($loc_serv[1], 3) <> "192" Then ; this kind of server is not what we want $query_server = $loc_serv[1] EndIf EndIf Case 2 $query_server = "4.2.2.1" Case 3 $query_server = "67.138.54.100" Case 4 $query_server = "208.67.222.222" Case 5 $query_server = "4.2.2.2" Case 6 $query_server = "4.2.2.3" Case 7 $query_server = "208.67.220.220" Case 8 $query_server = "4.2.2.4" Case 9 $query_server = "4.2.2.5" Case 10 $query_server = "4.2.2.6" Case 11 Return -1 EndSwitch If $query_server <> "" Then UDPStartup() Local $sock $sock = UDPOpen($query_server, 53) If $sock = -1 Then ; ok, that happens UDPCloseSocket($sock) UDPShutdown() ContinueLoop ; change server and try again EndIf UDPSend($sock, $server_bin) ; sending query Local $tik = 0 Do $data = UDPRecv($sock, 512) $tik += 1 Sleep(100) Until $data <> "" Or $tik = 8 ; waiting reasonable time for the response UDPShutdown() ; stopping service If $data <> "" And StringRight(BinaryMid($data, 2, 1), 2) = $identifier Then Return $data ; if there is data for us, return EndIf EndIf Next Return -1 EndFunc ;==>MXQueryServer Func ExtractMXServerData($binary_data) Local $num_answ = Dec(StringMid($binary_data, 15, 4)) ; representing number of answers provided by the server Local $arr = StringSplit($binary_data, "C00C000F0001", 1) ; splitting input; "C00C000F0001" - translated to human: "this is the answer for your MX query" If $num_answ <> $arr[0] - 1 Or $num_answ = 0 Then Return -1 ; dealing with possible options Local $pref[$arr[0]] ; preference number(s) Local $server[$arr[0]] ; server name(s) Local $output[2][$arr[0]] ; this goes out containing both server names and coresponding preference numbers $output[0][0] = $arr[0] - 1 Local $offset = 10 ; initial offset For $i = 2 To $arr[0] $arr[$i] = "0x" & $arr[$i] ; well, it is binary data $pref[$i - 1] = Dec(StringRight(BinaryMid($arr[$i], 7, 2), 4)) $offset += BinaryLen($arr[$i - 1]) + 6 ; adding lenght of every past part plus lenght of that "C00C000F0001" used for splitting Local $array = ReadBinary($binary_data, $offset) ; extraction of server names starts here While $array[1] = 192 ; dealing with special case $array = ReadBinary($binary_data, $array[6] + 2) WEnd $server[$i - 1] &= $array[2] & "." While $array[3] <> 0 ; the end will obviously be at $array[3] = 0 If $array[3] = 192 Then $array = ReadBinary($array[0], $array[4] + 2) If $array[3] = 0 Then $server[$i - 1] &= $array[2] ExitLoop Else $server[$i - 1] &= $array[2] & "." EndIf Else $array = ReadBinary($array[0], $array[5]) If $array[3] = 0 Then $server[$i - 1] &= $array[2] ExitLoop Else $server[$i - 1] &= $array[2] & "." EndIf EndIf WEnd $output[0][$i - 1] = $server[$i - 1] ; assigning $output[1][$i - 1] = $pref[$i - 1] ; part Next Return $output ; two-dimensional array EndFunc ;==>ExtractMXServerData Func ReadBinary($binary_data, $offset) Local $len = Dec(StringRight(BinaryMid($binary_data, $offset - 1, 1), 2)) Local $data_bin = BinaryMid($binary_data, $offset, $len) Local $checker = Dec(StringRight(BinaryMid($data_bin, 1, 1), 2)) Local $data = BinaryToString($data_bin) Local $triger = Dec(StringRight(BinaryMid($binary_data, $offset + $len, 1), 2)) Local $new_offset = Dec(StringRight(BinaryMid($binary_data, $offset + $len + 1, 1), 2)) Local $another_offset = $offset + $len + 1 Local $array[7] = [$binary_data, $len, $data, $triger, $new_offset, $another_offset, $checker] ; bit of this and bit of that Return $array EndFunc ;==>ReadBinary Func SortArray(ByRef $array) ; this will sort our $array by preferance numbers (in case of identical preferance, lower in order goes first - that's cool) If IsArray($array) Then ReDim $array[2][2 * $array[0][0] + 1] For $ij = $array[0][0] + 1 To 2 * $array[0][0] $array[1][$ij] = 1 Next For $bf = 1 To $array[0][0] For $cf = 1 To $array[0][0] If $array[1][$cf] - $array[1][$bf] > 0 Then $array[1][$cf + $array[0][0]] += 1 Next Next For $df = $array[0][0] + 1 To 2 * $array[0][0] For $ef = $array[0][0] + 1 To 2 * $array[0][0] If $ef = $df Then ContinueLoop If $array[1][$ef] - $array[1][$df] = 0 Then $array[1][$ef] += 1 Next Next Dim $aux_array[2][$array[0][0] + 1] $aux_array[0][0] = $array[0][0] For $ff = 1 To $array[0][0] $aux_array[1][$array[1][$ff + $array[0][0]]] = $array[1][$ff] $aux_array[0][$array[1][$ff + $array[0][0]]] = $array[0][$ff] Next $array = $aux_array Return $aux_array EndIf Return -1 EndFunc ;==>SortArray Please comment if you see any flaws.1 point -
Identify the excel file that may need a password
water reacted to JLogan3o13 for a topic
Last I knew there was no way to know if a workbook was password protected without opening it (someone may prove me wrong). About the best you could do was loop through your list of files and try to open them (look at _Excel_BookOpen) by specifying the password parameter (a simple "abc" will suffice). If the workbook has no password on it, it will open with a code 0; if it does have a password it will throw an @error of 3 and @extended of -2147352567. You can then move the file. Pseudo: #include <Excel.au3> Local $oExcel = _Excel_Open() Local $oWorkbook = _Excel_BookOpen($oExcel, @DesktopDir & "\test.xlsx", True, True, "abc", "abc") If @error Then if @extended = "-2147352567" Then ;Move file Else ;Handle other @error such as missing file EndIf Else ;File not password protected, do whatever EndIf _Excel_BookClose($oWorkbook) _Excel_Close($oExcel)1 point -
Write inputs values into Colum and Raw in CSV
Xandy reacted to JLogan3o13 for a topic
First off, you will not get the pretty column separation in a CSV, you will need to save to Excel instead. For your _ExportData function you could do something like this: Func _ExportData() Local $oExcel = _Excel_Open() Local $oWorkBook If Not FileExists($sDataFilePath) Then $oWorkBook = _Excel_BookNew($oExcel) Else $oWorkBook = _Excel_BookOpen($oExcel, $sDataFilePath) EndIf _Excel_RangeWrite($oWorkBook, Default, GUICtrlRead($Input1), "A1") _Excel_RangeWrite($oWorkBook, Default, GUICtrlRead($Input2), "B1") _Excel_RangeWrite($oWorkBook, Default, GUICtrlRead($Input3), "C1") If FileExists($sDataFilePath) Then _Excel_BookSave($oWorkBook) Else _Excel_BookSaveAs($oWorkBook, $sDataFilePath) EndIf _Excel_BookClose($oWorkBook) _Excel_Close($oExcel) EndFunc ;==>_ExportData This gives you a rough idea; you would have to work out cycling through the lines as you add further entries, but you should be able to do that simply enough. The problem with this approach would be the constant opening and closing of Excel (or leaving it open and running into an issue if the script fails). It would be a better practice to save all of your entries in an array until you're ready to do a single commit. Something like this: #include <Array.au3> #include <Excel.au3> #include <MsgBoxConstants.au3> Global Const $GUI_EVENT_CLOSE = -3 Local $aArray[1][3] = [["Name","ID","Phone"]] Local $sDataFilePath = @ScriptDir & "\Records" #region ### START Koda GUI section ### Form= $Form1 = GUICreate("Demo1: New Record", 580, 115) $Input1 = GUICtrlCreateInput("", 10, 30, 270, 21) $Input2 = GUICtrlCreateInput("", 300, 30, 270, 21) $Input3 = GUICtrlCreateInput("", 10, 80, 270, 21) $Label1 = GUICtrlCreateLabel("Name:", 10, 10, 35, 17) $Label2 = GUICtrlCreateLabel("ID:", 300, 10, 18, 17) $Label3 = GUICtrlCreateLabel("Phone No:", 10, 60, 55, 17) $Button1 = GUICtrlCreateButton("Add Record", 450, 70, 120, 30) $Button2 = GUICtrlCreateButton("Save to Excel", 300, 70, 120, 30) GUISetState(@SW_SHOW) #endregion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $Button1 _ArrayAdd($aArray, GUICtrlRead($Input1) & "|" & GUICtrlRead($Input2) & "|" & GUICtrlRead($Input3)) MsgBox($MB_OK, "Demo", "Record Added") Case $Button2 _ExportData($aArray) EndSwitch WEnd Func _ExportData($aArray) Local $oExcel = _Excel_Open() Local $oWorkBook If Not FileExists($sDataFilePath) Then $oWorkBook = _Excel_BookNew($oExcel) Else $oWorkBook = _Excel_BookOpen($oExcel, $sDataFilePath) EndIf _Excel_RangeWrite($oWorkBook, Default, $aArray, Default) $oWorkBook.Worksheets("Sheet1").Columns("A:C").AutoFit If FileExists($sDataFilePath) Then _Excel_BookSave($oWorkBook) Else _Excel_BookSaveAs($oWorkBook, $sDataFilePath) EndIf _Excel_BookClose($oWorkBook) _Excel_Close($oExcel) EndFunc ;==>_ExportData Any questions please ask1 point -
MsgBox(0,"User Full Name",GetFullName(@UserName)) Func GetFullName($sUserName) $colItems = "" $strComputer = "localhost" $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2") $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_UserAccount WHERE Name = '" & $sUserName & "'", "WQL", 0x10 + 0x20) If IsObj($colItems) then For $objItem In $colItems Return $objItem.FullName Next Else Return SetError(1,0,"") Endif EndFunc1 point