Jump to content

_IEAttach Attaches to First Tab eventho I am on the Second Tab


Zohar
 Share

Recommended Posts

Hello

I use _IEAttach($hWnd,"hwnd") to attach to current IE Window,

and it generally works well if there's 1 Tab,

but if there's more than 1 Tab, for example 2 Tabs, and the Second Tab is Focussed,

then it attaches to the First Tab.. even tho the 2nd is the focussed one.

How can I make _IEAttach($hWnd,"hwnd") attach to the currently displayed Tab and not always to the first tab?

I would like it to work well in an IE window with multiple tabs.

Thank you

Edited by Zohar
Link to comment
Share on other sites

Hi and thank you for your reply

using _IEAttach($url,"URL") will not be good, since it often happens for me where I have seveal IE windows with the same URL.

I need something more deterministic, and _IEAttach($hWnd,"hwnd") is exactly that - it will only attach to current window(when I supply it with current window's handle).

I just need it to work well with tabs.

Edited by Zohar
Link to comment
Share on other sites

Juvigy it's very kind of you,

however I will need to attach to Current IE Window, and Current Tab in it.

And I think that only "hWnd" will be the good option for it, so all other options of _IEAttach will not be good.

I hope DaleHohm will see this post, because he's the creator of IE.UDF file..

Link to comment
Share on other sites

The current IE window is easy. But to get the current/selected/focused tab in it is not possible i think.

You will have to find another way to identify it. There should be some thing special in the IE page that this tab holds.

You will need to identify it.

Link to comment
Share on other sites

The current IE window is easy. But to get the current/selected/focused tab in it is not possible i think.

You will have to find another way to identify it. There should be some thing special in the IE page that this tab holds.

You will need to identify it.

I ran across a similar problem and used this little test to find the tab I needed to attach:

#include <IE.au3>


$WinHandle = WinGetHandle("Windows Media Guide", "")
If Not @error Then
    MsgBox(4096, "Success", "Found window")
ElseIf @error Then
    MsgBox(4096, "Error", "Window Not Found")
EndIf

$oIE = _IEAttach($WinHandle, "HWND");

Use the tab's window title, run the test to see if it works then just use the $WinHandle line in your code.

edit: If the tabs have the same titles then you need to use the instance number.

$oIE = _IEAttach("", "instance", 2)

Edited by rezz
Link to comment
Share on other sites

This is actually an interesting issue.

The way that _IEAttach works with an hwnd is that it will match and return the first member of the Shell.Windows collection having the specified hwnd. I haven't looked at this code for a long time and I wrote it before tabs existed in IE. The side issue here is that I forbid the use of the instance parameter when using the hwnd mode (actually I force it to 1) and with tabs, that is no longer necessary and it would allow you to attach to any of the tabs in a given IE container (and also allow you to figure out how many tabs there were by incrementing the instance number till you got NOMATCH). I will put this enhancement into the pipeline.

Regarding the hwnd mode reurning the active IE instance, use the embedded mode for _IEAttach. It will return a reference to IE in the currently active tab. Please read the remarks about the embedded and dialogbox modes in the helpfile for information about limitations and recommendations.

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

rezz:

Thanks man, I will go and play with it now and see what I can get..

Dale:

Thank you.

I will read about it.

If I may recommend, If you update the code to work with tabs,

then please consider updating _IEAttach($hWnd,"hwnd") to attach to the Current Tab in the window specified by hWnd.

That is the most natural thing to expect, IMHO, on an IE window that has several tabs.

BTW, since the Tab Headers(the Tab Control) is not a regular control, but a DirectUIHWND control, I could not find a way to tell which tab number is active.

(If it was a regular Tab control then it would've been possible easily).

I even tried to look in IE's Menu for some menu that will show a list of all tabs and a "V" near the active tab, and could not find one.

(usualy in a multiple document window, there is such menu)

Edited by Zohar
Link to comment
Share on other sites

I understand your desire, but as I tried to point out, the IE API does not make this possible. As you reiterate, it does little to expose the tab interface and I believe this is done on purpose to make it hard to spoof users with tabs.

The _IEAttach embedded suggestion is the best work around I can offer -- it sounds like you have not gone to read about it yet in the helpfile - please do so and it will become clearer why I cannot make this work the way you wish it.

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

You can also use:

Ctrl + Tab# to make a particular tab active

Ctrl + Tab to create new tab

mmm

that would not be relevant to what I am trying..

Ctrl-1..9 Changes the currently active Tab..

I need the exact opposite: I need to tell which tab # is active.

Ctrl-T Opens a new Tab, but what I am looking for is not to open a new 1, but to attach to current 1..

If I understood Dale's idea, I can attach to a certain tab #, if I know its number.

but since I cannot "extract" the number of the currently active tab, then I am not sure that I will be able to accomplish what I want..

Link to comment
Share on other sites

I found this in the forums somewhere:

$title = "[Class:IEFrame]"
$awin = WinList($title)

Sleep(2000)

For $i = 1 To $awin[0][0]
    $state = WinGetState($awin[$i][0])
    If BitAND($state, 8) Then
        MsgBox(0,"",$awin[$i][0] & " Is active" & @LF & "Handle = " & $awin[$i][1])
    EndIf
Next

It will get the name of the active tab.

Excuse me if I don't know what I'm talking about. :x

Link to comment
Share on other sites

If I understood Dale's idea, I can attach to a certain tab #, if I know its number.

but since I cannot "extract" the number of the currently active tab, then I am not sure that I will be able to accomplish what I want..

I quess you don't understand what I am talking about.

Use $oIE = _IEAttach($hwnd, "embedded")

it will give you the active tab... but, read the recommendations and limitations in the helpfile in the Remarks section of _IEAttach for some important information.

Please make it clear that you have read that documentation before you ask another question here.

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

rezz:

(:

the code you posted finds the currently active window, not tab.

BTW for getting it one can simply use WinGetHandle("") - will get the same result.

but you are so nice =)

*big hug*

Dale:

You are right, I completely misunderstood.. I am sorry =)

I used the embedded mode in the past, to get a Browser control inside an application.

I didn't know the embedded can give me the current tab in IE also..

I now tried what you explained.

I opened a new IE, created 3 tabs in it, and in them navigated to the same URL: google.com

(all 3 of them are on google.com)

then I switched to the second tab, and ran 2 pieces of code:

The first, regular hwnd attach:

$oIE    =_IEAttach(WinGetHandle(""),"hwnd")
Local   $PO_SearchString    =$oIE.document.getElementsByName("q").item(0)   ;TextBox:   Search String
$PO_SearchString.innerText  ="hi :)"

when running it, it attached to the first tab, despite the fact that I am on the second tab.

The second, using embedded mode - your suggestion:

$oIE    =_IEAttach(WinGetHandle(""),"embedded")
Local   $PO_SearchString    =$oIE.document.getElementsByName("q").item(0)   ;TextBox:   Search String
$PO_SearchString.innerText  ="hi :)"

when running it, it attached to the second tab, which is the active tab! :x

it works well

thank you very much dale (:

regarding the Remarks in the IEAttach's page in the helpfile,

there isn't any problem mentioned there regarding what I wish to do.

It only talks about the use of "$i_instance" with the "embedded" mode, which I don't use..

but I must say it raises a curiosity here.

let's say in the future I want to do something else:

let say I have an IE with 10 tabs, and I want to iterate all of them.

this will require to attach to a certain tab, knowing it's # only, and not necessarily having it being the active tab, like in current situation..

will that be possible too, using existing IE functions?

(before any updates I mean)

this would also require a way to get the number of tabs existing in current IE window..

so I guess that would not be possible yet..

I tried looking in MSDN under the topic "Internet Explorer Developement" for any mentioning of Tabs,

I did not find something..

(doesn't say there isn't.. but I personally did not find..)

Edited by Zohar
Link to comment
Share on other sites

I've covered all of that ground in my replies to this topic already. I suggest you collect up just my replies to you here and reread them carefully. Also, you need to read the helpfile more carefully before telling me what I told you to go in search of was no there. Here is the appropriate text from the Remarks section of _IEAttach:

DialogBox and Embedded modes can be used to attach to standard browser windows, but the object returned is that if the top level Window in the browser and not the InternetExplorer object. Window objects do not offer access to all of the attributes of the InternetExplorer object (e.g. status text, address bar etc.). As well, if you attempt to use a function like _IENavigate on such an object you may receive COM errors due to the way that IE7 has implemented Tabs. It may be useful to find browser instances in this way, but it is recommended that you immediately use _IEAttach using one of the other modes and using information that you may have obtained from the Window object in order to get a reference to the associated InternetExplorer object.

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

Hi Dale

You are right again.

I focussed on the other paragraph, instead of this one, not noticing it is relevant for what I do.

I am sorry, thanks for not giving up on me on this..

Regarding the workaround and the mentioned paragraph,

If I use _IEAttach() with embedded mode, and "the object returned is that of the top level Window in the browser and not the InternetExplorer object",

then, will doing $WindowObject.document solve the limitation mentioned in this paragraph?

I am asking about using $WindowObject.document (or any appropriate $WindowObject.<Property>) instead of the other way you offered

It may be useful to find browser instances in this way, but it is recommended that you immediately use _IEAttach using one of the other modes and using information that you may have obtained from the Window object in order to get a reference to the associated InternetExplorer object.

because my fear is, that after I do the first Attach - the embedded one,

then the parameters that I will take from the Window object will not be unique enough to later identify it with the other Attach types..

(for example, If I take the URL from the WindowObject, and then do IEAttach("url",$URL), and more windows with this URL exist,

then again it will have a problem of not identifyng the right one..)

Edited by Zohar
Link to comment
Share on other sites

Whether it offers a perfect solution for you or not, it is the best I have to offer. You can use _IEBodyReadHTML to get the entire source of the body and match it with the HTML mode of _IEAttach. You also have the HWND, so you would only fail if you had two windows with the exact same HTML content in the same tabbed browser.

If that still isn't good enough, you can inject some unique HTML into the original document with _IEDocInsertHTML before looking for it with _IEAttach. You can make this a non-displaying element like a <DIV>.

Time for you to write some code...

Dale

P.S. The window object may be fine for your application - you won't know until you try

Edited by DaleHohm

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

#include <AutoItObject.au3>
#include <IE.au3>
#include <WinAPI.au3>
Opt("MustDeclareVars", 1)

Global Const $tagVARIANT = "int[4];"

;===============================================================================
#interface "IAccessible"
Global Const $sIID_IAccessible = "{618736e0-3c3d-11cf-810c-00aa00389b71}"
; Definition
Global $dtagIAccessible = $dtagIDispatch & _
    "get_accParent hresult(ptr*);" & _
    "get_accChildCount hresult(int*);" & _
    "get_accChild hresult(int;int;int;int;ptr*);" & _
    "get_accName hresult(int;int;int;int;ptr*);" & _
    "get_accValue hresult(int;int;int;int;ptr*);" & _
    "get_accDescription hresult(int;int;int;int;ptr*);" & _
    "get_accRole hresult(int;int;int;int;ptr);" & _
    "get_accState hresult(int;int;int;int;ptr);" & _
    "get_accHelp hresult(int;int;int;int;ptr*);" & _
    "get_accHelpTopic hresult(ptr*;int;int;int;int;int*);" & _
    "get_accKeyboardShortcut hresult(int;int;int;int;ptr*);" & _
    "get_accFocus hresult(ptr);" & _
    "get_accSelection hresult(ptr);" & _
    "get_accDefaultAction hresult(int;int;int;int;ptr*);" & _
    "accSelect hresult(int;int;int;int;int);" & _
    "accLocation hresult(int*;int*;int*;int*;int;int;int;int);" & _
    "accNavigate hresult(int;int;int;int;int;ptr);" & _
    "accHitTest hresult(int;int;ptr);" & _
    "accDoDefaultAction hresult(int;int;int;int);" & _
    "put_accName hresult(int;int;int;int;ptr);" & _
    "put_accValue hresult(int;int;int;int;ptr);"
; List
Global $ltagIAccessible = $ltagIDispatch & _
    "get_accParent;" & _
    "get_accChildCount;" & _
    "get_accChild;" & _
    "get_accName;" & _
    "get_accValue;" & _
    "get_accDescription;" & _
    "get_accRole;" & _
    "get_accState;" & _
    "get_accHelp;" & _
    "get_accHelpTopic;" & _
    "get_accKeyboardShortcut;" & _
    "get_accFocus;" & _
    "get_accSelection;" & _
    "get_accDefaultAction;" & _
    "accSelect;" & _
    "accLocation;" & _
    "accNavigate;" & _
    "accHitTest;" & _
    "accDoDefaultAction;" & _
    "put_accName;" & _
    "put_accValue;"
;===============================================================================

_AutoItObject_Startup()

Global $hOLEACC = DllOpen("oleacc.dll")
Global $oMyError = ObjEvent("AutoIt.Error", "_ErrFunc")

Global $hIEFrame = WinGetHandle("[CLASS:IEFrame]")

Global $oIE = _IEAttachActiveTab($hIEFrame)
If Not @error Then
    ConsoleWrite(_IEPropertyGet($oIE, "title") & @CRLF)
    _IENavigate($oIE, "www.autoitscript.com", False)
EndIf

DllClose($hOLEACC)
_AutoItObject_Shutdown()

; No error checkings -whatsoever-
Func _IEAttachActiveTab($hWnd)

    Local Const $OBJID_CLIENT = 0xFFFFFFFC
    Local Const $CHILDID_SELF = 0
    Local Const $ROLE_SYSTEM_PAGETABLIST = 60
    Local Const $STATE_SYSTEM_SELECTED = 2

    Local $oAccObj, $oTabs, $oTab
    Local $tTabs, $tTab, $tSelfChild
    Local $tTabRole, $pTabRole, $tTabState, $pTabState
;~  Local $pBSTR, $sStr
    Local $iAccChildren, $iTabChildren, $iSelectedTab
    Local $hTab
    Local $aResult

    ; Get a handle to the tabs UI control.
    $hTab = ControlGetHandle($hWnd, "", "[CLASS:DirectUIHWND]")

    $oAccObj = _AutoItObject_WrapperCreate(_AccessibleObjectFromWindow($hTab, $OBJID_CLIENT, $sIID_IAccessible), $dtagIAccessible)
    $aResult = $oAccObj.get_accChildCount(0)
    $iAccChildren = $aResult[1]

    $tTabs = _AccessibleChildren($oAccObj.__ptr__, 0, $iAccChildren)

    ; A VARIANT that specifies to query information of -this- object
    $tSelfChild = DllStructCreate($tagVARIANT)
    DllStructSetData($tSelfChild, 1, $__Au3Obj_VT_I4, 1)
    DllStructSetData($tSelfChild, 1, $CHILDID_SELF, 2)

    $tTabRole = DllStructCreate($tagVARIANT)
    $pTabRole = Number(DllStructGetPtr($tTabRole))

    $tTabState = DllStructCreate($tagVARIANT)
    $pTabState = Number(DllStructGetPtr($tTabState))

    $iSelectedTab = -1
    For $i = 1 To $iAccChildren

        ; If VARIANT.pdispVal has information then proceed.
        ; if (vTabs[i].vt == VT_DISPATCH)
        If BitAND(DllStructGetData($tTabs, $i, 1), 0xFFFF) = $__Au3Obj_VT_DISPATCH Then

            ; Get an object interface.
            $oTabs = _AutoItObject_WrapperCreate(DllStructGetData($tTabs, $i, 3), $dtagIAccessible)

            ; Retrieve information that describes the role of the object.
            $oTabs.get_accRole(DllStructGetData($tSelfChild, 1, 1), _
                               DllStructGetData($tSelfChild, 1, 2), _
                               DllStructGetData($tSelfChild, 1, 3), _
                               DllStructGetData($tSelfChild, 1, 4), _
                               $pTabRole)

            ; If its role is to tab-list then proceed
            ; if (vTab.lVal == ROLE_SYSTEM_PAGETABLIST)
            If DllStructGetData($tTabRole, 1, 3) = $ROLE_SYSTEM_PAGETABLIST Then

                ; So this is a tab-list control, which in part is a container.

                ; Get child count.
                $aResult = $oTabs.get_accChildCount(0)
                $iTabChildren = $aResult[1]

                ; Retrieve IDispatch interfaces or child IDs of children.
                $tTab = _AccessibleChildren($oTabs.__ptr__, 0, $iTabChildren)

                For $j = 1 To $iTabChildren
                    ; Get a tab object interface.
                    $oTab = _AutoItObject_WrapperCreate(DllStructGetData($tTab, $j, 3), $dtagIAccessible)

                    ; Get the tab object's name (for comparisons purpose, etc).
                    ; Much like getting an internet explorer object's current title property.
    ;~              $aResult = $oTab.get_accName(DllStructGetData($tSelfChild, 1, 1), _
    ;~                                           DllStructGetData($tSelfChild, 1, 2), _
    ;~                                           DllStructGetData($tSelfChild, 1, 3), _
    ;~                                           DllStructGetData($tSelfChild, 1, 4), _
    ;~                                           0) ; BSTR* (i.e., ptr*)

    ;~              $pBSTR = $aResult[5]
    ;~              $sStr  = __Au3Obj_SysReadString($pBSTR)
    ;~                 ConsoleWrite($sStr & @CRLF)

    ;~              __Au3Obj_SysFreeString($pBSTR)

                    ; Get the current tab state.
                    $oTab.get_accState(DllStructGetData($tSelfChild, 1, 1), _
                                       DllStructGetData($tSelfChild, 1, 2), _
                                       DllStructGetData($tSelfChild, 1, 3), _
                                       DllStructGetData($tSelfChild, 1, 4), _
                                       $pTabState)

                    If BitAND(DllStructGetData($tTabState, 1, 3), $STATE_SYSTEM_SELECTED) Then
                        $iSelectedTab = $j - 1
                        ExitLoop 2
                    EndIf

                Next
            EndIf
        EndIf
    Next

    If $iSelectedTab < 0 Then Return SetError(1, 0, -1)
    Return _IEAttach($hWnd, "hwnd", $iSelectedTab)
EndFunc


Func _AccessibleObjectFromWindow($hWnd, $iObjId, $sRefIID)
    Local $aResult, $tRefIID

    $tRefIID = _WinAPI_GUIDFromString($sRefIID)
    $aResult = DllCall($hOLEACC, "long", "AccessibleObjectFromWindow", "hwnd", $hWnd, "uint", $iObjId, "ptr", DllStructGetPtr($tRefIID), "ptr*", 0)

    If @error Or $aResult[0] Then Return SetError(1, 0 ,0)
    Return $aResult[4]
EndFunc

Func _AccessibleChildren($pAccContainer, $iChildStart, $iChildren)

    Local $tVARIANT, $pVARIANT
    Local $sStruct
    Local $aResult

    $sStruct = ""
    For $i = 1 To $iChildren
        $sStruct &= $tagVARIANT
    Next

    $tVARIANT = DllStructCreate($sStruct)
    $pVARIANT = DllStructGetPtr($tVARIANT)

    $aResult = DllCall($hOLEACC, "int", "AccessibleChildren", "ptr", $pAccContainer, "int", $iChildStart, "int", $iChildren, "ptr", $pVARIANT, "int*", 0)
    If @error Or $aResult[0] Then Return SetError(1, 0, 0)

    Return SetExtended($aResult[5], $tVARIANT)

EndFunc

Func _WindowFromAccessibleObject($pAccessible)
    Local $aResult = DllCall($hOLEACC, "int", "WindowFromAccessibleObject", "ptr", $pAccessible, "hwnd*", 0)

    If @error Or $aResult[0] Then Return SetError(1, 0, 0)
    Return $aResult[2]
EndFunc

Func _ErrFunc()
    ConsoleWrite("--- COM Error, number = " & Ptr($oMyError.number) & ", description: " & $oMyError.windescription)
EndFunc

Tested on IE7 only.

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...