{*******************************************************} { } { ThdWebUrl } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit ThdWebUrl; interface uses Tocsg.Thread, System.SysUtils, System.Classes, Winapi.Windows, Tocsg.MSAA, Winapi.oleacc, System.Generics.Collections; const BROWSER_LIST = 'iexplore.exe|msedge.exe|whale.exe|chrome.exe|firefox.exe|opera.exe|vivaldi.exe|brave.exe'; // 주의 : 영어는 모두 소문자로 입력해야 한다 URL_ADRESSBAR_ROLE = '편집할 수 있는 텍스트:editable text:可编辑文本:編集可能なテキスト'; URL_ADRESSBAR_IE = 'bing을(를) 사용하여 주소 지정 및 검색:bing 검색엔진을 사용하여 주소 지정 및 검색'; URL_ADRESSBAR_MSEDGE = '주소 표시줄 및 검색 창:address and search bar:地址和搜索栏:アドレスと検索バー:thanh địa chỉ và tìm kiếm'; URL_ADRESSBAR_CHROME = '주소창 및 검색창:address and search bar:地址和搜索栏:アドレス検索バー:thanh địa chỉ và tìm kiếm'; URL_ADRESSBAR_OPERA = '주소 필드:address field:地址栏:アドレス欄:trường địa chỉ'; URL_ADRESSBAR_VIVALDI = '주소를 검색 또는 입력하세요:search or enter an address:search startpage or enter an address:' + 'bing 검색 또는 주소 입력:搜索 bing 或输入网址:bing を検索するか、アドレスを入力してください:' + 'duckduckgo 검색 또는 주소 입력:search duckduckgo or enter an address:搜索 duckduckgo 或输入网址:' + '搜尋 duckduckgo 或輸入網址:duckduckgo で検索するか、 url を入力してください:duckduckgo 검색 [신규] 또는 주소 입력'; URL_ADRESSBAR_FIREFOX = 'google 검색 또는 주소 입력:google로 검색하거나 주소 입력:검색어나 주소 입력:search or enter address:' + '地址和搜索栏:google で検索、または URL を入力します:tìm kiếm với google hoặc nhập địa chỉ'; URL_ADRESSBAR_ETC = '주소창 및 검색창:address and search bar:地址和搜索栏:アドレス検索バー:thanh địa chỉ và tìm kiếm'; type PWbInfo = ^TWbInfo; TWbInfo = record h: HWND; sPName, sTitle: String; UrlList: TStringList; end; TThdWebUrl = class(TTgThread) protected bIsWorking_, bWidgetOn_: Boolean; sMonUrls_, sExcpUrls_, sWebAbUrls_, sLastUrl_, sLastTitle_, sCaptureBlockUrls_: string; hLastHwnd_: HWND; CutUrlList_, ExcpUrlList_, IgrAbUrlList_, BrowserList_, CaptureBlockUrls_: TStringList; DcWbInfo_: TDictionary; procedure OnWbInfoNotify(Sender: TObject; const Item: PWbInfo; Action: TCollectionNotification); procedure Execute; override; public constructor Create; destructor Destroy; override; procedure StartService; procedure StopService; type TTargetKind = (tkBlock, tkAllow, tkExcept); function MatchTarget(const sTarget, sUrl, sTitle: string; TargetKind: TTargetKind): Boolean; procedure GetUrlListFromWbTitle(sTitle: string; var aUrlList: TStringList); property LastUrl: string read sLastUrl_; property LastTitle: string read sLastTitle_; property LastHwnd: HWND read hLastHwnd_; property WidgetOn: Boolean read bWidgetOn_; end; function GetWebUrl2(hWebWnd: HWND): string; //function GetCurBrowserUrl(var AccObj_SubTitle: IAccessible; var varSubTitle: OleVariant; var hEditWnd: HWND): string; implementation uses Tocsg.Exception, ManagerService, Tocsg.WndUtil, Tocsg.Process, Winapi.ActiveX, Tocsg.Strings, System.Variants, Tocsg.Url, GlobalDefine, ManagerModel, Tocsg.Keyboard, Tocsg.Convert, Tocsg.Win32, Tocsg.Safe, DelphiUIAutomation.Automation, DelphiUIAutomation.Window, Condition, UIAutomationClient_TLB; //function GetCurBrowserUrl(var AccObj_SubTitle: IAccessible; var varSubTitle: OleVariant; var hEditWnd: HWND): string; //var // hWebWnd: HWND; // dwPid: DWORD; // sPName, sTitle, sUrl: string; // ChkRoleList: TStringList; // // function GetWndChildClassCustom(h: HWND; const sClassName: string; hPreChild: HWND = 0): HWND; // var // hChild: HWND; // arrClassName: array[0..255] of Char; // begin // Result := 0; // if hPreChild <> 0 then // hChild := GetWindow(hPreChild, GW_HWNDNEXT) // else // hChild := GetWindow(h, GW_CHILD); // // while hChild <> 0 do // begin // if GetClassName(hChild, arrClassName, SizeOf(arrClassName)) > 0 then // begin // if (arrClassName = sClassName) and (GetEditText(hChild) <> '') then // begin // Result := hChild; // exit; // end; // end; // // if GetWindow(hChild, GW_CHILD) <> 0 then // begin // Result := GetWndChildClassCustom(hChild, sClassName); // if Result <> 0 then // exit; // end; // // hChild := GetWindow(hChild, GW_HWNDNEXT); // end; // end; // // function GetWebUrl: string; // var // h: HWND; // ProcEnumAccessible: TProcessEnumAccessible; // sAccResult, sAddressBarName: string; // bRetry: Boolean; // WndList: TStringList; // nHandleIdx, nHandleCnt: Integer; // dwPid: DWORD; // _AccObj_SubTitle: IAccessible; // _varSubTitle: OleVariant; // arrRoleStr: array[0..300] of Char; // label // LB_RETRY, LB_EnumAccessible; // begin // bRetry := false; // Result := ''; // WndList := nil; // nHandleIdx := 0; // nHandleCnt := 0; // // AccObj_SubTitle := nil; // VariantClear(varSubTitle); // _AccObj_SubTitle := nil; // VariantClear(_varSubTitle); // hEditWnd := 0; // //LB_RETRY: // sAccResult := ''; // // if (hWebWnd <> 0) then // begin // ProcEnumAccessible := // procedure(aParentAccObj, aAccObj: IAccessible; varChild: OleVariant; h: HWND; nLevel: Integer; var bContinue: Boolean) // var // sName, sRole: string; // begin // bContinue := true; // try // if Assigned(aAccObj) then // begin // sName := Trim(LowerCase(GetObjectName(aAccObj, varChild))); // ZeroMemory(@arrRoleStr, SizeOf(arrRoleStr)); // if GetObjectRoleString(aAccObj, varChild, @arrRoleStr) then // sRole := LowerCase(DeleteNullTail(string(@arrRoleStr))) // else // sRole := ''; // //// {$IFDEF DEBUG} //// _Trace('ProcEnumAccessible() .. Cap=%s, Name=%s, Role=%s, Level=%d', [GetWindowCaption(h), sName, sRole, nLevel]); //// {$ENDIF} // // // 아래처럼 이름으로 확인 해서 주소 컨트롤을 찾는다. // // 한국어 크롬은 이름으로 "주소창 및 검색창"을 찾으면 되는데 영문판은 어떤지 확인해보지 못했다. // // 대략적으로 줏어본걸로 일단 넣긴함 // if not VarIsNull(varChild) and (Pos(sName, sAddressBarName) > 0) and (ChkRoleList.IndexOf(sRole) <> -1) then // begin // _AccObj_SubTitle := aAccObj; // _varSubTitle := varChild; // sAccResult := GetObjectValue(aAccObj, varChild); // if sAccResult = '' then // sAccResult := '<*Empty>'; // bContinue := false; // end; // end; // except // _AccObj_SubTitle := nil; // VariantClear(_varSubTitle); // end; // end; // //// sAddressBarRole := '편집할 수 있는 텍스트:editable text:可编辑文本'; // 거의 동일 // if sPName = 'iexplore.exe' then // begin // h := GetWndChildClassCustom(hWebWnd, 'Address Band Root'); // // if h <> 0 then // begin // hEditWnd := GetWndChildClassCustom(h, 'Edit'); // if hEditWnd = 0 then // begin // {$IFDEF TRACE_WM} // _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, "Address Band Root" .. ok .. class not found .. "Edit" .. TrayAcc', [sProcName]); // {$ENDIF} // sAddressBarName := URL_ADRESSBAR_IE; // goto LB_EnumAccessible; // end // else // Result := GetEditText(hEditWnd); // end // else // begin // {$IFDEF TRACE_WM} // _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc', [sProcName]); // {$ENDIF} // // // 11버전 이후에 탭 핸들로 걸려서 제대로 수집 안되는 문제가 발생했다... // // 그래서 무조건 최상위 핸들을 얻는걸로 보완 18_0201 15:54:50 sunk //// h := GetWndHandleFromPid(dwPid_); //// if (h <> 0) and (h <> hWindow) then //// begin //// hWindow := h; //// _Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc .. change .. handle', [sProcName]); //// end; // // // 실패 시 찾는 방법 하나 더 추가 18_0116 15:40:27 sunk // // sAddressBarName에 영문 버전을 고려해서 더 추가 정보가 필요하고 // // 이름이 OS 버전마다, 기본 검색엔진마다 다를 수 있으므로 보완이 필요하다 // sAddressBarName := URL_ADRESSBAR_IE; // goto LB_EnumAccessible; // end; // end // else if sPName = 'msedge.exe' then // begin // sAddressBarName := URL_ADRESSBAR_MSEDGE; // goto LB_EnumAccessible; // end // else if sPName = 'chrome.exe' then // begin // hEditWnd := GetWndChildClassCustom(hWebWnd, 'Chrome_OmniboxView'); // if hEditWnd = 0 then // begin // // 크롬 28버전 이후 부터는 다르게 구해줘야 한다 // sAddressBarName := URL_ADRESSBAR_CHROME; // goto LB_EnumAccessible; // end // else // Result := GetEditText(hEditWnd); // end // else if sPName = 'firefox.exe' then // begin // sAddressBarName := URL_ADRESSBAR_FIREFOX; //// EnumAccessible(hWindow, ProcEnumAccessible); // goto LB_EnumAccessible; // end // else if sPName = 'opera.exe' then // begin // sAddressBarName := URL_ADRESSBAR_OPERA; //// EnumAccessible(hWindow, ProcEnumAccessible); // goto LB_EnumAccessible; // end // else if sPName = 'vivaldi.exe' then // begin // sAddressBarName := URL_ADRESSBAR_VIVALDI; // goto LB_EnumAccessible; // end // else //// if sPName = 'brave.exe' then // begin // sAddressBarName := URL_ADRESSBAR_ETC; // goto LB_EnumAccessible; // end; // // exit; // 빠져나가기 주의 ------------------------------------------------ // //LB_EnumAccessible: // // 통합 처리로 수정 18_0117 09:26:19 sunk // EnumAccessible(hWebWnd, ProcEnumAccessible); // if (_AccObj_SubTitle <> nil) and not VarIsNull(_varSubTitle) then // begin // AccObj_SubTitle := _AccObj_SubTitle; // varSubTitle := _varSubTitle; // Result := sAccResult; // end // else // begin // {$IFDEF TRACE_WM} // _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, EnumAccName not found ..', [sProcName]); // {$ENDIF} // // if (dwPid <> 0) and not bRetry then // begin // bRetry := true; // h := GetWndHandleFromPid(dwPid); // if (h <> 0) and (h <> hWebWnd) then // begin // hWebWnd := h; // {$IFDEF TRACE_WM} // _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, init retry .. ok', [sProcName]); // {$ENDIF} // goto LB_RETRY; // end // else // begin // {$IFDEF TRACE_WM} // _Trace('GetCurBrowserUrl() .. GetWebUrl() .. ProcName = %s, init retry .. cancel ..', [sProcName]); // {$ENDIF} // end; // end; // end; // end; // end; // //begin // Result := ''; // try // if (AccObj_SubTitle <> nil) and not VarIsNull(varSubTitle) then // begin // Result := GetObjectValue(AccObj_SubTitle, varSubTitle); // exit; // end // else if hEditWnd <> 0 then // begin // Result := GetEditText(hEditWnd); // end; // // hWebWnd := GetForegroundWindow; // if hWebWnd = 0 then // exit; // // AccObj_SubTitle := nil; // VariantClear(varSubTitle); // // dwPid := GetProcessPIDFromWndHandle(hWebWnd); // if dwPid = 0 then // exit; // // sPName := LowerCase(GetProcessNameByPid(dwPid)); // if Pos(sPName, BROWSER_LIST) = 0 then // exit; // // Guard(ChkRoleList, TStringList.Create); // ChkRoleList.CaseSensitive := false; // SplitString(URL_ADRESSBAR_ROLE, ':', ChkRoleList); // // Result := GetWebUrl; // except // on E: Exception do // ETgException.TraceException(E, 'Fail .. GetCurBrowserUrl()'); // end; //end; { TThdWebUrl } constructor TThdWebUrl.Create; begin inherited Create; bIsWorking_ := false; bWidgetOn_ := false; BrowserList_ := TStringList.Create; BrowserList_.CaseSensitive := false; SplitString(BROWSER_LIST, '|', BrowserList_); if CUSTOMER_TYPE = CUSTOMER_SHCI then begin var i: Integer := BrowserList_.IndexOf('iexplore.exe'); if i <> - 1 then BrowserList_.Delete(i); end; CutUrlList_ := TStringList.Create; ExcpUrlList_ := TStringList.Create; IgrAbUrlList_ := TStringList.Create; sMonUrls_ := ''; sExcpUrls_ := ''; sLastUrl_ := ''; sLastTitle_ := ''; hLastHwnd_ := 0; sWebAbUrls_ := ''; sCaptureBlockUrls_ := ''; CaptureBlockUrls_ := TStringList.Create; DcWbInfo_ := TDictionary.Create; DcWbInfo_.OnValueNotify := OnWbInfoNotify; end; destructor TThdWebUrl.Destroy; begin inherited; FreeAndNil(DcWbInfo_); FreeAndNil(CaptureBlockUrls_); FreeAndNil(IgrAbUrlList_); FreeAndNil(ExcpUrlList_); FreeAndNil(CutUrlList_); FreeAndNil(BrowserList_); end; procedure TThdWebUrl.OnWbInfoNotify(Sender: TObject; const Item: PWbInfo; Action: TCollectionNotification); begin if Action = cnRemoved then begin if Item.UrlList <> nil then FreeAndNil(Item.UrlList); Dispose(Item); end; end; procedure TThdWebUrl.StartService; begin if not bIsWorking_ then begin bIsWorking_ := true; StartThread; end; end; procedure TThdWebUrl.StopService; begin if bIsWorking_ then begin bIsWorking_ := false; PauseThread; end; end; procedure TThdWebUrl.GetUrlListFromWbTitle(sTitle: string; var aUrlList: TStringList); var pInfo: PWbInfo; begin try aUrlList.Clear; Lock; try if DcWbInfo_.ContainsKey(sTitle) then begin pInfo := DcWbInfo_[sTitle]; aUrlList.AddStrings(pInfo.UrlList); end; finally Unlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetUrlListFromWbHwnd()'); end; end; function GetWndChildClassCustom(h: HWND; const sClassName: string; hPreChild: HWND = 0): HWND; var hChild: HWND; arrClassName: array[0..255] of Char; begin Result := 0; if hPreChild <> 0 then hChild := GetWindow(hPreChild, GW_HWNDNEXT) else hChild := GetWindow(h, GW_CHILD); while hChild <> 0 do begin if GetClassName(hChild, arrClassName, SizeOf(arrClassName)) > 0 then begin if (arrClassName = sClassName) and (GetEditText(hChild) <> '') then begin Result := hChild; exit; end; end; if GetWindow(hChild, GW_CHILD) <> 0 then begin Result := GetWndChildClassCustom(hChild, sClassName); if Result <> 0 then exit; end; hChild := GetWindow(hChild, GW_HWNDNEXT); end; end; // yhkim 251202 브라우저 접속 차단/브라우저 파일 차단 URL 및 타이틀 구분 function TThdWebUrl.MatchTarget(const sTarget, sUrl, sTitle: string; TargetKind: TThdWebUrl.TTargetKind): Boolean; var sKwd: string; bTitleMatch: Boolean; begin Result := False; sKwd := sTarget.Trim; bTitleMatch := False; if sKwd.StartsWith('T:', True) then begin // "T:" 제거 후 타이틀 비교 sKwd := Copy(sKwd, 3, Length(sKwd)); if Pos(UpperCase(sKwd), UpperCase(sTitle)) > 0 then begin Result := True; bTitleMatch := True; end; end else begin // URL 비교 if Pos(UpperCase(sKwd), UpperCase(sUrl)) > 0 then begin Result := True; bTitleMatch := False; end; end; if Result then begin case TargetKind of tkBlock: if bTitleMatch then _Trace('차단(Title) : Target=%s, Title=%s', [sKwd, sTitle], 2) else _Trace('차단(URL) : Target=%s, Url=%s', [sKwd, sUrl], 2); tkAllow: if bTitleMatch then _Trace('허용(Title) : Target=%s, Title=%s', [sKwd, sTitle], 2) else _Trace('허용(URL) : Target=%s, Url=%s', [sKwd, sUrl], 2); tkExcept: if bTitleMatch then _Trace('예외(Title) : Target=%s, Title=%s', [sKwd, sTitle], 2) else _Trace('예외(URL) : Target=%s, Url=%s', [sKwd, sUrl], 2); end; end; end; function GetWebUrl2(hWebWnd: HWND): string; var h: HWND; AccObj_SubTitle: Winapi.oleacc.IAccessible; varSubTitle: OleVariant; ProcEnumAccessible: TProcessEnumAccessible; sRecentUrl, sPName, sAccResult, sAddressBarName: string; bRetry: Boolean; WndList: TStringList; nHandleIdx, nHandleCnt: Integer; dwPid: DWORD; arrRoleStr: array[0..300] of Char; ChkRoleList: TStringList; hEditWnd: HWND; label LB_RETRY, LB_EnumAccessible; begin bRetry := false; Result := ''; WndList := nil; nHandleIdx := 0; nHandleCnt := 0; sRecentUrl := ''; Guard(ChkRoleList, TStringList.Create); ChkRoleList.CaseSensitive := false; SplitString(URL_ADRESSBAR_ROLE, ':', ChkRoleList); sPName := GetProcessNameFromWndHandle(hWebWnd); // if (AccObj_SubTitle <> nil) and not VarIsNull(varSubTitle) then // begin // Result := GetObjectValue(AccObj_SubTitle, varSubTitle); // if sRecentUrl <> Result then // begin // sRecentUrl := Result; // exit; // end; // // AccObj_SubTitle := nil; // VariantClear(varSubTitle); // end else // if hEditWnd <> 0 then // begin // Result := GetEditText(hEditWnd); // if sRecentUrl <> Result then // begin // sRecentUrl := Result; // exit; // end; // hEditWnd := 0; // end; LB_RETRY: sAccResult := ''; if (hWebWnd <> 0) then begin ProcEnumAccessible := procedure(aParentAccObj, aAccObj: Winapi.oleacc.IAccessible; varChild: OleVariant; h: HWND; nLevel: Integer; var bContinue: Boolean) var sName, sRole: string; begin bContinue := true; try if Assigned(aAccObj) then begin sName := Trim(LowerCase(GetObjectName(aAccObj, varChild))); ZeroMemory(@arrRoleStr, SizeOf(arrRoleStr)); if GetObjectRoleString(aAccObj, varChild, @arrRoleStr) then sRole := LowerCase(DeleteNullTail(string(@arrRoleStr))) else sRole := ''; // {$IFDEF DEBUG} // _Trace('ProcEnumAccessible() .. Cap=%s, Name=%s, Role=%s, Level=%d', [GetWindowCaption(h), sName, sRole, nLevel]); // {$ENDIF} // 아래처럼 이름으로 확인 해서 주소 컨트롤을 찾는다. // 한국어 크롬은 이름으로 "주소창 및 검색창"을 찾으면 되는데 영문판은 어떤지 확인해보지 못했다. // 대략적으로 줏어본걸로 일단 넣긴함 if not VarIsNull(varChild) and (Pos(sName, sAddressBarName) > 0) and (ChkRoleList.IndexOf(sRole) <> -1) then begin AccObj_SubTitle := aAccObj; varSubTitle := varChild; sAccResult := GetObjectValue(aAccObj, varChild); if sAccResult = '' then sAccResult := '<*Empty>'; bContinue := false; end; end; except AccObj_SubTitle := nil; VariantClear(varSubTitle); end; end; // sAddressBarRole := '편집할 수 있는 텍스트:editable text:可编辑文本'; // 거의 동일 if sPName = 'iexplore.exe' then begin h := GetWndChildClassCustom(hWebWnd, 'Address Band Root'); if h <> 0 then begin hEditWnd := GetWndChildClassCustom(h, 'Edit'); if hEditWnd = 0 then begin {$IFDEF TRACE_WM} _Trace('GetWebUrl() .. ProcName = %s, "Address Band Root" .. ok .. class not found .. "Edit" .. TrayAcc', [sProcName]); {$ENDIF} sAddressBarName := URL_ADRESSBAR_IE; goto LB_EnumAccessible; end else Result := GetEditText(hEditWnd); end else begin {$IFDEF TRACE_WM} _Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc', [sProcName]); {$ENDIF} // 11버전 이후에 탭 핸들로 걸려서 제대로 수집 안되는 문제가 발생했다... // 그래서 무조건 최상위 핸들을 얻는걸로 보완 18_0201 15:54:50 sunk // h := GetWndHandleFromPid(dwPid_); // if (h <> 0) and (h <> hWindow) then // begin // hWindow := h; // _Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc .. change .. handle', [sProcName]); // end; // 실패 시 찾는 방법 하나 더 추가 18_0116 15:40:27 sunk // sAddressBarName에 영문 버전을 고려해서 더 추가 정보가 필요하고 // 이름이 OS 버전마다, 기본 검색엔진마다 다를 수 있으므로 보완이 필요하다 sAddressBarName := URL_ADRESSBAR_IE; goto LB_EnumAccessible; end; end else if sPName = 'msedge.exe' then begin sAddressBarName := URL_ADRESSBAR_MSEDGE; goto LB_EnumAccessible; end else if sPName = 'chrome.exe' then begin hEditWnd := GetWndChildClassCustom(hWebWnd, 'Chrome_OmniboxView'); if hEditWnd = 0 then begin // 크롬 28버전 이후 부터는 다르게 구해줘야 한다 sAddressBarName := URL_ADRESSBAR_CHROME; goto LB_EnumAccessible; end else Result := GetEditText(hEditWnd); end else if sPName = 'firefox.exe' then begin sAddressBarName := URL_ADRESSBAR_FIREFOX; // EnumAccessible(hWindow, ProcEnumAccessible); goto LB_EnumAccessible; end else if sPName = 'opera.exe' then begin sAddressBarName := URL_ADRESSBAR_OPERA; // EnumAccessible(hWindow, ProcEnumAccessible); goto LB_EnumAccessible; end else if sPName = 'vivaldi.exe' then begin sAddressBarName := URL_ADRESSBAR_VIVALDI; goto LB_EnumAccessible; end else // if sPName = 'brave.exe' then begin sAddressBarName := URL_ADRESSBAR_ETC; goto LB_EnumAccessible; end; exit; // 빠져나가기 주의 ------------------------------------------------ LB_EnumAccessible: // 통합 처리로 수정 18_0117 09:26:19 sunk EnumAccessible(hWebWnd, ProcEnumAccessible); if (AccObj_SubTitle <> nil) and not VarIsNull(varSubTitle) then begin Result := sAccResult; end else begin {$IFDEF TRACE_WM} _Trace('GetWebUrl() .. ProcName = %s, EnumAccName not found ..', [sProcName]); {$ENDIF} dwPid := GetProcessPIDFromWndHandle(hWebWnd); if (dwPid <> 0) and not bRetry then begin bRetry := true; h := GetWndHandleFromPid(dwPid); if h <> 0 then begin if h = hWebWnd then h := GetParent(h); if (h <> 0) and (h <> hWebWnd) then begin hWebWnd := h; {$IFDEF TRACE_WM} _Trace('GetWebUrl() .. ProcName = %s, init retry .. ok', [sProcName]); {$ENDIF} goto LB_RETRY; end; // else begin // {$IFDEF TRACE_WM} // _Trace('GetWebUrl() .. ProcName = %s, init retry .. cancel ..', [sProcName]); // {$ENDIF} // end; end; end; end; if sRecentUrl = Result then begin // 이전과 같다면 굳이 같은값 반환하지 말고 초기화만 해주자 18_0201 17:12:37 sunk sRecentUrl := ''; Result := ''; end; end; end; procedure TThdWebUrl.Execute; var hWebWnd, hPrevWebWnd, hEditWnd: HWND; dwPid: DWORD; sPName, sTitle, sOldTitle, sUrl, sRecentUrl: string; AccObj_SubTitle: Winapi.oleacc.IAccessible; varSubTitle: OleVariant; ChkRoleList: TStringList; function GetWndChildClassCustom(h: HWND; const sClassName: string; hPreChild: HWND = 0): HWND; var hChild: HWND; arrClassName: array[0..255] of Char; begin Result := 0; if hPreChild <> 0 then hChild := GetWindow(hPreChild, GW_HWNDNEXT) else hChild := GetWindow(h, GW_CHILD); while hChild <> 0 do begin if GetClassName(hChild, arrClassName, SizeOf(arrClassName)) > 0 then begin if (arrClassName = sClassName) and (GetEditText(hChild) <> '') then begin Result := hChild; exit; end; end; if GetWindow(hChild, GW_CHILD) <> 0 then begin Result := GetWndChildClassCustom(hChild, sClassName); if Result <> 0 then exit; end; hChild := GetWindow(hChild, GW_HWNDNEXT); end; end; function GetWebUrl: string; var h: HWND; ProcEnumAccessible: TProcessEnumAccessible; sAccResult, sAddressBarName: string; bRetry: Boolean; WndList: TStringList; nHandleIdx, nHandleCnt: Integer; dwPid: DWORD; arrRoleStr: array[0..300] of Char; label LB_RETRY, LB_EnumAccessible; begin bRetry := false; Result := ''; WndList := nil; nHandleIdx := 0; nHandleCnt := 0; LB_RETRY: sAccResult := ''; if (hWebWnd <> 0) then begin ProcEnumAccessible := procedure(aParentAccObj, aAccObj: Winapi.oleacc.IAccessible; varChild: OleVariant; h: HWND; nLevel: Integer; var bContinue: Boolean) var sName, sRole: string; begin bContinue := true; try if Assigned(aAccObj) then begin sName := Trim(LowerCase(GetObjectName(aAccObj, varChild))); if Pos('duckduckgo', sName) > 0 then begin sName := sName + ''; end; ZeroMemory(@arrRoleStr, SizeOf(arrRoleStr)); if GetObjectRoleString(aAccObj, varChild, @arrRoleStr) then sRole := LowerCase(DeleteNullTail(string(@arrRoleStr))) else sRole := ''; // {$IFDEF DEBUG} // _Trace('ProcEnumAccessible() .. Cap=%s, Name=%s, Role=%s, Level=%d', [GetWindowCaption(h), sName, sRole, nLevel]); // {$ENDIF} // 아래처럼 이름으로 확인 해서 주소 컨트롤을 찾는다. // 한국어 크롬은 이름으로 "주소창 및 검색창"을 찾으면 되는데 영문판은 어떤지 확인해보지 못했다. // 대략적으로 줏어본걸로 일단 넣긴함 if not VarIsNull(varChild) and (Pos(sName, sAddressBarName) > 0) and (ChkRoleList.IndexOf(sRole) <> -1) then begin AccObj_SubTitle := aAccObj; varSubTitle := varChild; sAccResult := GetObjectValue(aAccObj, varChild); if sAccResult = '' then sAccResult := '<*Empty>'; bContinue := false; end; end; except AccObj_SubTitle := nil; VariantClear(varSubTitle); end; end; // sAddressBarRole := '편집할 수 있는 텍스트:editable text:可编辑文本'; // 거의 동일 if sPName = 'iexplore.exe' then begin h := GetWndChildClassCustom(hWebWnd, 'Address Band Root'); if h <> 0 then begin hEditWnd := GetWndChildClassCustom(h, 'Edit'); if hEditWnd = 0 then begin {$IFDEF TRACE_WM} _Trace('GetWebUrl() .. ProcName = %s, "Address Band Root" .. ok .. class not found .. "Edit" .. TrayAcc', [sProcName]); {$ENDIF} sAddressBarName := URL_ADRESSBAR_IE; goto LB_EnumAccessible; end else Result := GetEditText(hEditWnd); end else begin {$IFDEF TRACE_WM} _Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc', [sProcName]); {$ENDIF} // 11버전 이후에 탭 핸들로 걸려서 제대로 수집 안되는 문제가 발생했다... // 그래서 무조건 최상위 핸들을 얻는걸로 보완 18_0201 15:54:50 sunk // h := GetWndHandleFromPid(dwPid_); // if (h <> 0) and (h <> hWindow) then // begin // hWindow := h; // _Trace('GetWebUrl() .. ProcName = %s, class not found .. "Address Band Root" .. TrayAcc .. change .. handle', [sProcName]); // end; // 실패 시 찾는 방법 하나 더 추가 18_0116 15:40:27 sunk // sAddressBarName에 영문 버전을 고려해서 더 추가 정보가 필요하고 // 이름이 OS 버전마다, 기본 검색엔진마다 다를 수 있으므로 보완이 필요하다 sAddressBarName := URL_ADRESSBAR_IE; goto LB_EnumAccessible; end; end else if sPName = 'msedge.exe' then begin sAddressBarName := URL_ADRESSBAR_MSEDGE; goto LB_EnumAccessible; end else if sPName = 'chrome.exe' then begin hEditWnd := GetWndChildClassCustom(hWebWnd, 'Chrome_OmniboxView'); if hEditWnd = 0 then begin // 크롬 28버전 이후 부터는 다르게 구해줘야 한다 sAddressBarName := URL_ADRESSBAR_CHROME; goto LB_EnumAccessible; end else Result := GetEditText(hEditWnd); end else if sPName = 'firefox.exe' then begin sAddressBarName := URL_ADRESSBAR_FIREFOX; // EnumAccessible(hWindow, ProcEnumAccessible); goto LB_EnumAccessible; end else if sPName = 'opera.exe' then begin sAddressBarName := URL_ADRESSBAR_OPERA; // EnumAccessible(hWindow, ProcEnumAccessible); goto LB_EnumAccessible; end else if sPName = 'vivaldi.exe' then begin sAddressBarName := URL_ADRESSBAR_VIVALDI; goto LB_EnumAccessible; end else // if sPName = 'brave.exe' then begin sAddressBarName := URL_ADRESSBAR_ETC; goto LB_EnumAccessible; end; exit; // 빠져나가기 주의 ------------------------------------------------ LB_EnumAccessible: // 통합 처리로 수정 18_0117 09:26:19 sunk EnumAccessible(hWebWnd, ProcEnumAccessible); if (AccObj_SubTitle <> nil) and not VarIsNull(varSubTitle) then begin Result := sAccResult; end else begin {$IFDEF TRACE_WM} _Trace('GetWebUrl() .. ProcName = %s, EnumAccName not found ..', [sProcName]); {$ENDIF} dwPid := GetProcessPIDFromWndHandle(hWebWnd); if (dwPid <> 0) and not bRetry then begin bRetry := true; h := GetWndHandleFromPid(dwPid); if h <> 0 then begin if h = hWebWnd then h := GetParent(h); if (h <> 0) and (h <> hWebWnd) then begin hWebWnd := h; {$IFDEF TRACE_WM} _Trace('GetWebUrl() .. ProcName = %s, init retry .. ok', [sProcName]); {$ENDIF} goto LB_RETRY; end; // else begin // {$IFDEF TRACE_WM} // _Trace('GetWebUrl() .. ProcName = %s, init retry .. cancel ..', [sProcName]); // {$ENDIF} // end; end; end; end; if sRecentUrl = Result then begin // 이전과 같다면 굳이 같은값 반환하지 말고 초기화만 해주자 18_0201 17:12:37 sunk sRecentUrl := ''; Result := ''; end; end; end; procedure ProcessPopup(sUrl: string; bBlcoked: Boolean); var sMtx: string; begin sMtx := StringReplace(sUrl, ':', '', [rfReplaceAll]); sMtx := StringReplace(sMtx, '/', '', [rfReplaceAll]); if MutexExists(sMtx) then exit; if IsDivPopup then begin if bBlcoked then gMgSvc.PopupMessage(TYPE_MSG_PREVENT_URL, sUrl + '|PV') else gMgSvc.PopupMessage(TYPE_MSG_PREVENT_URL, sUrl); end else if bBlcoked then gMgSvc.PopupMessage(TYPE_MSG_PREVENT_URL, sUrl + '|PV'); end; procedure ProcessUIAuto(h: HWND); var AutoWnd: TAutomationWindow; el: IUIAutomationElement; begin // MSAA 접근이 안되는 브라우저의 경우 아래처럼 한번 돌리면 된다. 25_0206 11:08:52 kku try TUIAuto.CreateUIAuto; try el := TUIAuto.GetElementFromHandle(Pointer(h)); if el <> nil then begin Guard(AutoWnd, TAutomationWindow.Create(el, false {true})); AutoWnd.FindAll; end; finally TUIAuto.DestroyUIAuto; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessUIAuto()'); end; end; function FindWidget: Boolean; var hC: HWND; sClassName: string; llStyle: LONGLONG; nChildCnt: Integer; begin Result := false; llStyle := GetWindowStyle(hWebWnd); sClassName := GetWndClassName(hWebWnd); if ((llStyle and WS_POPUP) <> 0) and (CompareText(sClassName, 'Chrome_WidgetWin_1') = 0) then begin // 웨일 위젯 사이드바 제거 25_0224 13:50:15 kku // PostMessage(hSrc, WM_CLOSE, 0, 0); Result := true; exit; end; nChildCnt := 0; hC := GetWindow(hWebWnd, GW_CHILD); while hC <> 0 do begin llStyle := GetWindowStyle(hC); if (llStyle and WS_VISIBLE) <> 0 then begin sClassName := GetWndClassName(hC); if CompareText(sClassName, 'Chrome_RenderWidgetHostHWND') = 0 then begin Inc(nChildCnt); if nChildCnt >= 2 then begin // 2개 이상 있으면 위젯 사용으로 판단 25_0224 14:55:54 kku Result := true; exit; end; end; end; hC := GetWindow(hC, GW_HWNDNEXT); end; end; var bLog, bPopup, bBlock, bPreWidgetOn: Boolean; i: Integer; sChkUrl, sKwd: string; PO: TPrefModel; sSvrIPort: string; pInfo: PWbInfo; ullWbCheckTick: ULONGLONG; enum: TEnumerator; PidList: TProcessIdList; bScrBlk: Boolean; // 전체 화면 차단 상태 nGetUrlCnt: Integer; CaptureBlockUrlKind: TBlockKind; label LB_GetUrl, LB_BlockAndLog; begin CoInitialize(nil); // CoInitializeEx(nil, COINIT_MULTITHREADED); try bScrBlk := false; hPrevWebWnd := 0; bPreWidgetOn := false; ullWbCheckTick := GetTickCount64; Guard(ChkRoleList, TStringList.Create); ChkRoleList.CaseSensitive := false; SplitString(URL_ADRESSBAR_ROLE, ':', ChkRoleList); Guard(PidList, TProcessIdList.Create); sSvrIPort := StrsReplace(gMgSvc.DestIPort, ['https:', 'http:', '/'], ''); while not Terminated and not GetWorkStop do begin try try if CUSTOMER_TYPE = CUSTOMER_SHCI then begin if gMgSvc.ModePolicy.CaptureBlockUrlKind <> bkNone then begin GetProcessPidsByName('iexplore.exe', PidList); if PidList.Count > 0 then begin var h: HWND; var llStyle: LONGLONG; var b: Boolean := false; for i := 0 to PidList.Count - 1 do begin h := GetWndHandleFromPID(PidList[i]); llStyle := GetWindowStyle(h); if ((llStyle and WS_VISIBLE) <> 0) and ((llStyle and WS_MINIMIZE) = 0) then begin b := true; break; end; end; if bScrBlk <> b then begin bScrBlk := b; PostMessage(gMgSvc.RcvHwnd, WM_SCREEN_CAPTURE_BLOCK, BooleanToInt(b, 1, 0), 0) end; end else if bScrBlk then begin bScrBlk := false; PostMessage(gMgSvc.RcvHwnd, WM_SCREEN_CAPTURE_BLOCK, 0, 0) end; end else if bScrBlk then begin bScrBlk := false; PostMessage(gMgSvc.RcvHwnd, WM_SCREEN_CAPTURE_BLOCK, 0, 0) end; end; if bBlock then begin // 직전에 차단 했다면 hWebWnd 재활용 하도록 보완 bBlock := false; if not IsWindow(hWebWnd) then hWebWnd := GetForegroundWindow; end else hWebWnd := GetForegroundWindow; if hWebWnd = 0 then continue; sChkUrl := GetWndClassName(hWebWnd); if (sChkUrl = '#32770') or (CompareText(sChkUrl, 'Auto-Suggest Dropdown') = 0) then continue; // 위젯 사용 체크 25_0224 14:51:55 kku if gMgSvc.ModePolicy.BlockWidgetAB then begin bWidgetOn_ := FindWidget; if (bPreWidgetOn <> bWidgetOn_) and bWidgetOn_ then begin {$IFDEF DEBUG} _Trace('Widget detected. PName=%s', [GetProcessNameFromWndHandle(hWebWnd)], 3); {$ENDIF} end; bPreWidgetOn := bWidgetOn_; end; sTitle := GetWindowCaption(hWebWnd); // yhkim 251202 타이틀 텍스트를 정상적으로 얻을 수 없는 현상 개선 // - 브라우저는 기본적으로 새탭 생성 시 '제목 없음'이라는 타이틀로 윈도우를 생성한 후 그 위에 텍스트를 Set하는 방식임 // 예를 들어 '네이버 뉴스'를 클릭하는 경우 '제목 없음'으로 윈도우를 생성한 후 '네이버 뉴스'라는 타이틀로 교체 // - 0.5초 주기로 루프를 돌면서 GetWindowCaption()으로 타이틀을 구할때 타이틀이 교체되기 전 '제목 없음' 윈도우인 경우 // 타이틀이 '제목 없음'으로 얻어짐 // - 이를 개선하기 위해 '제목 없음' 인 경우 다시 타이틀을 구할 수 있도록 수정 if Pos('제목 없음', sTitle) = 1 then begin Sleep(400); //_Trace('제목 없음 감지=%s', [sTitle], 2); sTitle := GetWindowCaption(hWebWnd); end; CaptureBlockUrlKind := gMgSvc.ModePolicy.CaptureBlockUrlKind; if (hWebWnd <> hPrevWebWnd) or ((sTitle <> '') and (sTitle <> sOldTitle)) then begin if CUSTOMER_TYPE = CUSTOMER_SHCI then begin // 신한신용 정보에서 ICS 충돌 때문에 iexplore.exe가 실행 되어 있으면 브라우저 화면 마스킹 모두 제거 25_1202 15:27:49 kku // if CaptureBlockUrlKind <> bkNone then // begin // GetProcessPidsByName('iexplore.exe', PidList); // if PidList.Count > 0 then // begin // CaptureBlockUrlKind := bkNone; // if not bScrBlk then // begin // _Trace('iexplore.exe 감지됨, 전체 브라우저 마스킹 해제', 3); // bScrBlk := true; // PidList.Clear; // Lock; // try // Guard(enum, DcWbInfo_.Values.GetEnumerator); // while enum.MoveNext do // begin // if IsWindow(enum.Current.h) then // begin // if PidList.IndexOf(enum.Current.h) = -1 then // begin // PidList.Add(enum.Current.h); // gMgSvc.MgHook.SetCaptureBlock(enum.Current.h, false); // _Trace('%s (hwnd=%d) 브라우저 마스킹 해제', [enum.Current.sPName, enum.Current.h], 3); // end; // end; // end; // finally // Unlock; // end; // end; // end else // if bScrBlk then // begin // _Trace('iexplore.exe 종료 감지됨, 전체 브라우저 마스킹 활성', 3); // bScrBlk := false; // PidList.Clear; // Lock; // try // Guard(enum, DcWbInfo_.Values.GetEnumerator); // while enum.MoveNext do // begin // if IsWindow(enum.Current.h) then // begin // if PidList.IndexOf(enum.Current.h) = -1 then // begin // PidList.Add(enum.Current.h); // gMgSvc.MgHook.SetCaptureBlock(enum.Current.h, true); // _Trace('%s (hwnd=%d) 브라우저 마스킹 활성', [enum.Current.sPName, enum.Current.h], 3); // end; // end; // end; // finally // Unlock; // end; // end; end; hPrevWebWnd := 0; AccObj_SubTitle := nil; VariantClear(varSubTitle); sOldTitle := ''; sRecentUrl := ''; dwPid := GetProcessPIDFromWndHandle(hWebWnd); if dwPid = 0 then continue; sPName := GetProcessNameByPid(dwPid); if BrowserList_.IndexOf(sPName) = -1 then continue; hPrevWebWnd := hWebWnd; end; if ShowTestFun then begin // 원격 연결 했을때 브라우저 마스킹 PO := gMgSvc.ModePolicy; if (PO.CaptureBlockUrlKind = bkBlack) and (PO.CaptureBlockUrls = '') then begin gMgSvc.MgHook.SetCaptureBlock(hWebWnd, gMgSvc.IsRdpLogon); end; end; if ((GetTickCount64 - ullWbCheckTick) >= 5000) and (DcWbInfo_.Count > 0) then begin ullWbCheckTick := GetTickCount64; Lock; try Guard(enum, DcWbInfo_.Values.GetEnumerator); while enum.MoveNext do begin if not IsWindow(enum.Current.h) then DcWbInfo_.Remove(enum.Current.sTitle); end; finally Unlock; end; end; // sTitle := GetWindowCaption(hWebWnd); // 위로 올림 25_0805 16:52:24 kku if (sTitle = '') or (sTitle = sOldTitle) then continue; sOldTitle := sTitle; if DcWbInfo_.ContainsKey(sTitle) then begin pInfo := DcWbInfo_[sTitle]; // if pInfo.sTitle <> sTitle then // begin // pInfo.sTitle := sTitle; // pInfo.UrlList.Clear; // end; end else pInfo := nil; if pInfo = nil then begin New(pInfo); ZeroMemory(pInfo, SizeOf(TWbInfo)); pInfo.h := hWebWnd; pInfo.sPName := sPName; pInfo.sTitle := sTitle; pInfo.UrlList := TStringList.Create; pInfo.UrlList.CaseSensitive := false; Lock; try DcWbInfo_.Add(sTitle, pInfo); finally Unlock; end; end; nGetUrlCnt := 0; LB_GetUrl : sUrl := GetWebUrl; if sUrl = '' then begin ProcessUIAuto(hWebWnd); sUrl := GetWebUrl; end; PO := gMgSvc.ModePolicy; if sUrl = '' then begin var hChkWnd: HWND := GetForegroundWindow; if hWebWnd <> hChkWnd then begin // 탭을 외부로 뺐다 넣었다 반복하면 현재 활성화 윈도우가 바뀔 수 있다 25_0605 10:09:17 kku hWebWnd := hChkWnd; Inc(nGetUrlCnt); if nGetUrlCnt < 3 then goto LB_GetUrl; end; sUrl := EMPTY_URL_MSG; if (PO.WebbMonKind <> wmkNone) and gMgSvc.ModePolicy.BlockNoUrl then begin bBlock := true; bPopup := true; goto LB_BlockAndLog; end; end else if sUrl = '<*Empty>' then // URL 에디트는 찾았지만 값이 없을때 begin sUrl := ''; sLastUrl_ := sUrl; sLastTitle_ := sTitle; hLastHwnd_ := hWebWnd; end; if CaptureBlockUrlKind = bkAll then gMgSvc.MgHook.SetCaptureBlock(hWebWnd, true); if (sUrl <> '') and (sLastUrl_ <> sUrl) then begin sLastUrl_ := sUrl; sLastTitle_ := sTitle; hLastHwnd_ := hWebWnd; if pInfo.UrlList.IndexOf(sUrl) = -1 then pInfo.UrlList.Add(sUrl); _Trace('웹브라우저 URL 감지. PName=%s, Title=%s, URL=%s', [sPName, sTitle, sUrl], 2); if (CaptureBlockUrlKind <> bkNone) and (gMgSvc.MgHook <> nil) then begin // URL에 따라서 화면캡쳐 방지 동작 유무 추가 23_0426 08:51:25 kku try if sCaptureBlockUrls_ <> PO.CaptureBlockUrls then begin sCaptureBlockUrls_ := PO.CaptureBlockUrls; SplitString(UpperCase(sCaptureBlockUrls_), '|', CaptureBlockUrls_); end; sChkUrl := sUrl.ToUpper; bBlock := false; case CaptureBlockUrlKind of bkAll : bBlock := true; bkBlack : begin bBlock := false; for i := 0 to CaptureBlockUrls_.Count - 1 do begin if Pos(CaptureBlockUrls_[i], sChkUrl) > 0 then begin bBlock := true; break; end; end; end; bkWhite : begin bBlock := true; for i := 0 to CaptureBlockUrls_.Count - 1 do begin if Pos(CaptureBlockUrls_[i], sChkUrl) > 0 then begin bBlock := false; break; end; end; end; end; if CaptureBlockUrlKind <> bkAll then begin gMgSvc.MgHook.SetCaptureBlock(hWebWnd, bBlock); if gMgSvc.IsNewApi then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := BooleanToStr(bBlock, PREVENT_CAPTURE_URL, RELEASE_CAPTURE_URL); LogInfo.sAppName := sPName; LogInfo.sSummary := sUrl; LogInfo.sDestIpUrl := sUrl; LogInfo.sDevName := sTitle; gMgSvc.SendEventLogEx(@LogInfo, bBlock); end else begin if bBlock then gMgSvc.SendEventLog(URI_USER_ACTION, PREVENT_CAPTURE_URL, sUrl) else gMgSvc.SendEventLog(URI_USER_ACTION, RELEASE_CAPTURE_URL, sUrl); end; end; except //.. end; end; if PO.WebbMonKind <> wmkNone then begin sKwd := ''; sChkUrl := gMgSvc.GetUrlBlockList; if sMonUrls_ <> sChkUrl then begin sMonUrls_ := sChkUrl; SplitString(UpperCase(sMonUrls_), '|', CutUrlList_); end; if sExcpUrls_ <> (PO.UrlBlockExcpList + '|' + sSvrIPort) then begin sExcpUrls_ := PO.UrlBlockExcpList + '|' + sSvrIPort; // 매니저 접속 URL은 제외 24_0430 15:34:11 kku SplitString(UpperCase(sExcpUrls_), '|', ExcpUrlList_); end; sChkUrl := sUrl.ToUpper; bLog := true; bPopup := false; // todo : 팝업 유무 추가 bBlock := false; if (PO.WebbMonKind = wmkBlock) then begin bBlock := true; bPopup := true; end else if CutUrlList_.Count > 0 then begin case PO.WebbMonKind of wmkIncPop, wmkIncLog, wmkIncBlock: begin bLog := false; for i := 0 to CutUrlList_.Count - 1 do begin if MatchTarget(CutUrlList_[i], sChkUrl, sTitle, tkBlock) then begin if PO.WebbMonKind = wmkIncBlock then bBlock := true; bPopup := PO.WebbMonKind <> wmkIncLog; Break; end; end; end; wmkIncAllow: begin bBlock := true; bPopup := true; for i := 0 to CutUrlList_.Count - 1 do begin if MatchTarget(CutUrlList_[i], sChkUrl, sTitle, tkAllow) then begin bBlock := false; bPopup := false; Break; end; end; end; end; end; if (ExcpUrlList_.Count > 0) and (bBlock or bPopup or bLog) then begin var sChkTitle: string := sTitle.ToUpper; for i := 0 to ExcpUrlList_.Count - 1 do begin if MatchTarget(ExcpUrlList_[i], sChkUrl, sTitle, tkExcept) then begin bBlock := false; bPopup := false; // bLog := (PO.WebbMonKind <> wmkIncLog) and (PO.WebbMonKind <> wmkIncPop); // 로그도 예외 되도록 수정 25_0520 13:55:37 kku case PO.WebbMonKind of wmkLog, wmkIncLog, wmkIncPop : bLog := false; wmkIncAllow : bBlock := true; end; Break; end; end; end; LB_BlockAndLog: if bBlock then begin DcWbInfo_.Remove(sOldTitle); sLastUrl_ := ''; sOldTitle := ''; hPrevWebWnd := 0; SetForegroundWindow(hWebWnd); PressKeys('W', true); end; if IsDivPopup then begin if bBlock then bPopup := PO.UrlBlockNoti else bPopup := PO.UrlAllowNoti; end; if bPopup then ProcessPopup(sUrl, bBlock); // sUrl := GetDomainFromUrl(sUrl); if bLog or bBlock or bPopup then begin if gMgSvc.IsNewApi then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := BooleanToStr(bBlock, LOGCODE_PREVENT_DOMAIN, LOGCODE_MONITOR_DOMAIN); if bBlock or bPopup then begin case PO.WebbMonKind of wmkBlock: LogInfo.sDevSerial := 'PREVENT ALL'; wmkIncAllow: LogInfo.sDevSerial := 'Not in WhiteList'; else LogInfo.sDevSerial := sKwd; end; end; LogInfo.sAppName := sPName; LogInfo.sDevName := sTitle; LogInfo.sSummary := sUrl; LogInfo.sDestIpUrl := sUrl; gMgSvc.SendEventLogEx(@LogInfo, bBlock); end else begin if bBlock then gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_PREVENT_DOMAIN, sUrl) else gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_MONITOR_DOMAIN, sUrl, false); end; end; end; // 브라우저 파일 차단 URL 예외 try case PO.WebbAB.Kind of abkUrlBlock, abkUrlAllow: begin if sWebAbUrls_ <> gMgSvc.ModePolicy.WebABUrlList then begin sWebAbUrls_ := gMgSvc.ModePolicy.WebABUrlList; SplitString(UpperCase(sWebAbUrls_), '|', IgrAbUrlList_); end; end; end; except // .. end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. Execute()'); end; finally Sleep(500); end; end; finally CoUninitialize; end; end; end.