Protected export of WSF_RESPONSE_MESSAGE.send_to
Added WSF_DEFAULT_RESPONSE_SERVICE Added simple WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI class to load launch option from ini file. Removed a few obsolete features
This commit is contained in:
@@ -24,36 +24,9 @@ For now, you just need to know EWF is compliant with EWSGI specification.
|
|||||||
= Tutorial =
|
= Tutorial =
|
||||||
|
|
||||||
Now let's discover the Eiffel Web Framework with this tutorial.
|
Now let's discover the Eiffel Web Framework with this tutorial.
|
||||||
1 - You will learn first, how to get and install EWF.
|
# [[step_1.wiki|Step #1]]: You will learn first, how to get and install EWF.
|
||||||
2 - build a simple Hello World application
|
# [[step_2.wiki|Step #2]]: build a simple Hello World application
|
||||||
3 - use the query and form parameter to build dynamic service
|
# [[step_3.wiki|Step #3]]: use the query and form parameter to build dynamic service
|
||||||
4 - And you will learn how to dispatch URL
|
# [[step_4.wiki|Step #4]]: And you will learn how to dispatch URL
|
||||||
|
|
||||||
== Get EWF package ==
|
|
||||||
=== From the archive ===
|
|
||||||
- to be completed
|
|
||||||
|
|
||||||
=== From the source ===
|
|
||||||
- Requirement: install git on your machine (http://www.git-scm.org/)
|
|
||||||
|
|
||||||
git clone --recursive https://github.com/EiffelWebFramework/EWF.git ewf
|
|
||||||
|
|
||||||
And that's it for now.
|
|
||||||
|
|
||||||
== Install EWF ==
|
|
||||||
For now, there is nothing specific to do.
|
|
||||||
|
|
||||||
(Note: if you want to use the "http_client" library, you will need to do a few extra steps to eventually compile Eiffel Curl.)
|
|
||||||
|
|
||||||
== Step 1 ==
|
|
||||||
[[tutorial_1.wiki|Check the first step]]
|
|
||||||
|
|
||||||
== Step 2 ==
|
|
||||||
|
|
||||||
== Step 3 ==
|
|
||||||
|
|
||||||
== Step 4 ==
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
22
examples/tutorial/step_1.wiki
Normal file
22
examples/tutorial/step_1.wiki
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[[README.wiki|Back to tutorial index]]
|
||||||
|
|
||||||
|
= Tutorial Step 1 =
|
||||||
|
* '''Goal''': learn how to get and install the Eiffel Web Framework
|
||||||
|
* '''Requirement''': EiffelStudio should be installed
|
||||||
|
|
||||||
|
== Get EWF package ==
|
||||||
|
=== From the archive ===
|
||||||
|
* to be completed
|
||||||
|
|
||||||
|
=== From the source ===
|
||||||
|
* '''Requirement''': install [http://www.git-scm.org/ git] on your machine
|
||||||
|
|
||||||
|
git clone --recursive https://github.com/EiffelWebFramework/EWF.git ewf
|
||||||
|
|
||||||
|
== Install EWF ==
|
||||||
|
For now, there is nothing specific to do.
|
||||||
|
|
||||||
|
(Note: if you want to use the "http_client" library, you will need to do a few extra steps to eventually compile Eiffel Curl.)
|
||||||
|
|
||||||
|
----
|
||||||
|
Back to the [[README.wiki|index]] | Go to [[step_2.wiki|step 2]]
|
||||||
27
examples/tutorial/step_2.wiki
Normal file
27
examples/tutorial/step_2.wiki
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
[[README.wiki|Back to tutorial index]]
|
||||||
|
|
||||||
|
= Tutorial Step 2 =
|
||||||
|
* '''Goal''': Build a simple Hello World application
|
||||||
|
* '''Requirements''':
|
||||||
|
** know how to compile with Eiffel (EiffelStudio).
|
||||||
|
** [[step_1.wiki|Previous step]] completed
|
||||||
|
|
||||||
|
|
||||||
|
== Create "hello" project ==
|
||||||
|
=== From the archive ===
|
||||||
|
- to be completed
|
||||||
|
|
||||||
|
=== From the source ===
|
||||||
|
- Requirement: install git on your machine (http://www.git-scm.org/)
|
||||||
|
|
||||||
|
git clone --recursive https://github.com/EiffelWebFramework/EWF.git ewf
|
||||||
|
|
||||||
|
And that's it for now.
|
||||||
|
|
||||||
|
== Install EWF ==
|
||||||
|
For now, there is nothing specific to do.
|
||||||
|
|
||||||
|
(Note: if you want to use the "http_client" library, you will need to do a few extra steps to eventually compile Eiffel Curl.)
|
||||||
|
|
||||||
|
----
|
||||||
|
Previous [[step_1|step 1]] | Go to [[step_3.wiki|step 3]]
|
||||||
38
examples/tutorial/step_2/hello/application.e
Normal file
38
examples/tutorial/step_2/hello/application.e
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
note
|
||||||
|
description: "[
|
||||||
|
APPLICATION implements the "Hello World" service.
|
||||||
|
|
||||||
|
It inherits from WSF_DEFAULT_SERVICE to get default EWF connector ready
|
||||||
|
only `execute' needs to be implemented.
|
||||||
|
|
||||||
|
]"
|
||||||
|
|
||||||
|
class
|
||||||
|
APPLICATION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_RESPONSE_SERVICE
|
||||||
|
redefine
|
||||||
|
initialize
|
||||||
|
end
|
||||||
|
|
||||||
|
create
|
||||||
|
make_and_launch
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
initialize
|
||||||
|
do
|
||||||
|
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("ewf.ini")
|
||||||
|
Precursor
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
response (req: WSF_REQUEST): WSF_PAGE_RESPONSE
|
||||||
|
do
|
||||||
|
create Result.make
|
||||||
|
Result.put_string ("Hello World")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
4
examples/tutorial/step_2/hello/ewf.ini
Normal file
4
examples/tutorial/step_2/hello/ewf.ini
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# For nino connector, use port 9999
|
||||||
|
port=9999
|
||||||
|
|
||||||
|
#verbose=true
|
||||||
20
examples/tutorial/step_2/hello/hello.ecf
Normal file
20
examples/tutorial/step_2/hello/hello.ecf
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-9-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-9-0 http://www.eiffel.com/developers/xml/configuration-1-9-0.xsd" name="hello" uuid="25B014D9-CC71-484D-93D9-5E93B51C6B36">
|
||||||
|
|
||||||
|
<target name="hello">
|
||||||
|
<file_rule>
|
||||||
|
<exclude>/EIFGENs$</exclude>
|
||||||
|
<exclude>/CVS$</exclude>
|
||||||
|
<exclude>/.svn$</exclude>
|
||||||
|
</file_rule>
|
||||||
|
<root class="APPLICATION" feature="make_and_launch"/>
|
||||||
|
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||||
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||||
|
</option>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<library name="wsf" location="..\..\..\..\library\server\wsf\wsf-safe.ecf"/>
|
||||||
|
<library name="default_nino" location="..\..\..\..\library\server\wsf\default\nino-safe.ecf"/>
|
||||||
|
<cluster name="hello" location=".\" recursive="true"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</system>
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
= Tutorial Step 1 =
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
= Tutorial Step 2 =
|
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
WSF_DEFAULT_RESPONSE_SERVICE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
|
||||||
|
WSF_RESPONSE_SERVICE
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
source: "[
|
||||||
|
Eiffel Software
|
||||||
|
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||||
|
Telephone 805-685-1006, Fax 805-685-6869
|
||||||
|
Website http://www.eiffel.com
|
||||||
|
Customer support http://support.eiffel.com
|
||||||
|
]"
|
||||||
|
end
|
||||||
@@ -14,8 +14,7 @@ create
|
|||||||
make,
|
make,
|
||||||
make_and_launch,
|
make_and_launch,
|
||||||
make_callback,
|
make_callback,
|
||||||
make_callback_and_launch,
|
make_callback_and_launch
|
||||||
make_and_launch_with_options -- obsolete
|
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
WSF_DEFAULT_RESPONSE_SERVICE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
|
||||||
|
WSF_RESPONSE_SERVICE
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
source: "[
|
||||||
|
Eiffel Software
|
||||||
|
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||||
|
Telephone 805-685-1006, Fax 805-685-6869
|
||||||
|
Website http://www.eiffel.com
|
||||||
|
Customer support http://support.eiffel.com
|
||||||
|
]"
|
||||||
|
end
|
||||||
@@ -14,8 +14,7 @@ create
|
|||||||
make,
|
make,
|
||||||
make_and_launch,
|
make_and_launch,
|
||||||
make_callback,
|
make_callback,
|
||||||
make_callback_and_launch,
|
make_callback_and_launch
|
||||||
make_and_launch_with_options -- obsolete
|
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
note
|
||||||
|
description: "Summary description for {WSF_DEFAULT_RESPONSE_SERVICE}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
WSF_DEFAULT_RESPONSE_SERVICE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_DEFAULT_SERVICE
|
||||||
|
|
||||||
|
WSF_RESPONSE_SERVICE
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
|
source: "[
|
||||||
|
Eiffel Software
|
||||||
|
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||||
|
Telephone 805-685-1006, Fax 805-685-6869
|
||||||
|
Website http://www.eiffel.com
|
||||||
|
Customer support http://support.eiffel.com
|
||||||
|
]"
|
||||||
|
end
|
||||||
@@ -15,8 +15,7 @@ create
|
|||||||
make,
|
make,
|
||||||
make_and_launch,
|
make_and_launch,
|
||||||
make_callback,
|
make_callback,
|
||||||
make_callback_and_launch,
|
make_callback_and_launch
|
||||||
make_and_launch_with_options -- obsolete
|
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ feature -- Element change
|
|||||||
answer_head_request_method := b
|
answer_head_request_method := b
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Basic operations
|
feature {WSF_SERVICE, WSF_RESPONSE} -- Basic operations
|
||||||
|
|
||||||
send_to (res: WSF_RESPONSE)
|
send_to (res: WSF_RESPONSE)
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ feature -- Element change
|
|||||||
update_content_length
|
update_content_length
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Output
|
feature {WSF_SERVICE, WSF_RESPONSE} -- Output
|
||||||
|
|
||||||
send_to (res: WSF_RESPONSE)
|
send_to (res: WSF_RESPONSE)
|
||||||
local
|
local
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ feature -- Element change
|
|||||||
body := b
|
body := b
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Output
|
feature {WSF_SERVICE, WSF_RESPONSE} -- Output
|
||||||
|
|
||||||
send_to (res: WSF_RESPONSE)
|
send_to (res: WSF_RESPONSE)
|
||||||
local
|
local
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ feature -- Element change
|
|||||||
l_body.append (a_string)
|
l_body.append (a_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Output
|
feature {WSF_SERVICE, WSF_RESPONSE} -- Output
|
||||||
|
|
||||||
send_to (res: WSF_RESPONSE)
|
send_to (res: WSF_RESPONSE)
|
||||||
local
|
local
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ feature -- Element change
|
|||||||
content_type := Void
|
content_type := Void
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Output
|
feature {WSF_SERVICE, WSF_RESPONSE} -- Output
|
||||||
|
|
||||||
send_to (res: WSF_RESPONSE)
|
send_to (res: WSF_RESPONSE)
|
||||||
local
|
local
|
||||||
|
|||||||
@@ -11,13 +11,20 @@ inherit
|
|||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make_and_launch
|
frozen make_and_launch
|
||||||
local
|
local
|
||||||
l_launcher: G
|
l_launcher: G
|
||||||
do
|
do
|
||||||
|
initialize
|
||||||
create l_launcher.make_and_launch (Current, service_options)
|
create l_launcher.make_and_launch (Current, service_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
initialize
|
||||||
|
-- Initialize current service
|
||||||
|
--| Could be redefine to set custom service option(s)
|
||||||
|
do
|
||||||
|
end
|
||||||
|
|
||||||
service_options: detachable WSF_SERVICE_LAUNCHER_OPTIONS
|
service_options: detachable WSF_SERVICE_LAUNCHER_OPTIONS
|
||||||
|
|
||||||
feature -- Default service options
|
feature -- Default service options
|
||||||
|
|||||||
@@ -66,13 +66,6 @@ feature {NONE} -- Initialization
|
|||||||
make (create {WSF_CALLBACK_SERVICE}.make (a_callback), a_options)
|
make (create {WSF_CALLBACK_SERVICE}.make (a_callback), a_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
frozen make_and_launch_with_options (a_callback: like {WSF_CALLBACK_SERVICE}.callback; a_options: like options)
|
|
||||||
obsolete
|
|
||||||
"[2012-Mars-20] Use make_callback_and_launch (a_callback, a_options)"
|
|
||||||
do
|
|
||||||
make_callback_and_launch (a_callback, a_options)
|
|
||||||
end
|
|
||||||
|
|
||||||
initialize
|
initialize
|
||||||
-- Initialize Current using `options' if attached
|
-- Initialize Current using `options' if attached
|
||||||
-- and build the connector
|
-- and build the connector
|
||||||
|
|||||||
@@ -14,7 +14,14 @@ note
|
|||||||
class
|
class
|
||||||
WSF_SERVICE_LAUNCHER_OPTIONS
|
WSF_SERVICE_LAUNCHER_OPTIONS
|
||||||
|
|
||||||
|
inherit
|
||||||
|
ANY
|
||||||
|
redefine
|
||||||
|
default_create
|
||||||
|
end
|
||||||
|
|
||||||
create
|
create
|
||||||
|
default_create,
|
||||||
make,
|
make,
|
||||||
make_from_array
|
make_from_array
|
||||||
|
|
||||||
@@ -23,9 +30,15 @@ convert
|
|||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
default_create
|
||||||
|
do
|
||||||
|
Precursor
|
||||||
|
create options.make (0)
|
||||||
|
end
|
||||||
|
|
||||||
make
|
make
|
||||||
do
|
do
|
||||||
create options.make (0)
|
default_create
|
||||||
end
|
end
|
||||||
|
|
||||||
make_from_array (a_options: ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]])
|
make_from_array (a_options: ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]])
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
note
|
||||||
|
description: "[
|
||||||
|
Options used by WSF_SERVICE_LAUNCHER
|
||||||
|
Built from ini configuration file
|
||||||
|
]"
|
||||||
|
|
||||||
|
class
|
||||||
|
WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI
|
||||||
|
|
||||||
|
inherit
|
||||||
|
WSF_SERVICE_LAUNCHER_OPTIONS
|
||||||
|
|
||||||
|
create
|
||||||
|
make_from_file
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make_from_file (a_filename: READABLE_STRING_32)
|
||||||
|
-- Initialize `Current'.
|
||||||
|
do
|
||||||
|
make
|
||||||
|
import (a_filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
import (a_filename: READABLE_STRING_32)
|
||||||
|
-- Import ini file content
|
||||||
|
local
|
||||||
|
f: PLAIN_TEXT_FILE
|
||||||
|
l,v: STRING_8
|
||||||
|
p: INTEGER
|
||||||
|
do
|
||||||
|
--FIXME: handle unicode filename here.
|
||||||
|
create f.make (a_filename)
|
||||||
|
if f.exists and f.is_readable then
|
||||||
|
f.open_read
|
||||||
|
from
|
||||||
|
f.read_line
|
||||||
|
until
|
||||||
|
f.exhausted
|
||||||
|
loop
|
||||||
|
l := f.last_string
|
||||||
|
l.left_adjust
|
||||||
|
if not l.is_empty and then l[1] /= '#' then
|
||||||
|
p := l.index_of ('=', 1)
|
||||||
|
if p > 1 then
|
||||||
|
v := l.substring (p + 1, l.count)
|
||||||
|
l.keep_head (p - 1)
|
||||||
|
v.left_adjust
|
||||||
|
v.right_adjust
|
||||||
|
l.right_adjust
|
||||||
|
set_option (l.as_lower, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f.read_line
|
||||||
|
end
|
||||||
|
f.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -265,22 +265,6 @@ feature -- Output operation
|
|||||||
|
|
||||||
feature -- Response object
|
feature -- Response object
|
||||||
|
|
||||||
put_response (a_message: WSF_RESPONSE_MESSAGE)
|
|
||||||
-- Set `a_message' as the whole response to the client
|
|
||||||
--| `a_message' is responsible to sent the status code, the header and the content
|
|
||||||
obsolete
|
|
||||||
"[2012-Mars-19] Use `send (a_message)' "
|
|
||||||
require
|
|
||||||
header_not_committed: not header_committed
|
|
||||||
status_not_committed: not status_committed
|
|
||||||
no_message_committed: not message_committed
|
|
||||||
do
|
|
||||||
a_message.send_to (Current)
|
|
||||||
ensure
|
|
||||||
status_committed: status_committed
|
|
||||||
header_committed: header_committed
|
|
||||||
end
|
|
||||||
|
|
||||||
send (a_message: WSF_RESPONSE_MESSAGE)
|
send (a_message: WSF_RESPONSE_MESSAGE)
|
||||||
-- Set `a_message' as the whole response to the client
|
-- Set `a_message' as the whole response to the client
|
||||||
--| `a_message' is responsible to sent the status code, the header and the content
|
--| `a_message' is responsible to sent the status code, the header and the content
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ note
|
|||||||
deferred class
|
deferred class
|
||||||
WSF_RESPONSE_MESSAGE
|
WSF_RESPONSE_MESSAGE
|
||||||
|
|
||||||
feature -- Output
|
feature {WSF_SERVICE, WSF_RESPONSE} -- Output
|
||||||
|
|
||||||
send_to (res: WSF_RESPONSE)
|
send_to (res: WSF_RESPONSE)
|
||||||
|
-- Send Current message to `res'
|
||||||
|
--| This should not be called by user's code directly
|
||||||
require
|
require
|
||||||
header_not_committed: not res.header_committed
|
header_not_committed: not res.header_committed
|
||||||
status_not_committed: not res.status_committed
|
status_not_committed: not res.status_committed
|
||||||
|
|||||||
Reference in New Issue
Block a user