Process.pm.svn-base
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:9k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. #########################################################################
  2. #  OpenKore - Ragnarok Online Assistent
  3. #
  4. #  This software is open source, licensed under the GNU General Public
  5. #  License, version 2.
  6. #  Basically, this means that you're allowed to modify and distribute
  7. #  this software. However, if you distribute modified versions, you MUST
  8. #  also distribute the source code.
  9. #  See http://www.gnu.org/licenses/gpl.html for the full license.
  10. #
  11. #  $Revision$
  12. #  $Id$
  13. #
  14. #########################################################################
  15. ##
  16. # MODULE DESCRIPTION: Object for obtaining web server request info and sending response messages
  17. #
  18. # This is the object you use for obtaining information about a request, and to reply to a request.
  19. # It has a PHP-like interface.
  20. #
  21. # You should also read <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">the HTTP specification</a>.
  22. package Base::WebServer::Process;
  23. use strict;
  24. use IO::Socket::INET;
  25. use Encode;
  26. use Utils qw(urldecode);
  27. # Internal function; do not use directly!
  28. sub new {
  29. my ($class, $socket, $query, $headers) = @_;
  30. my $self = {
  31. socket => $socket,
  32. query => $query,
  33. headers => $headers || {},
  34. buffer => '',
  35. outHeaders => {},
  36. outHeadersLC => {}
  37. };
  38. bless $self, $class;
  39. $self->{file} = $query;
  40. $self->{file} =~ s/?.*//;
  41. my $vars = $query;
  42. my %GET;
  43. $vars =~ s/.*??//;
  44. foreach my $entry (split /&/, $vars) {
  45. my ($key, $value) = split /=/, $entry, 2;
  46. $key = urldecode($key);
  47. $GET{$key} = urldecode($value);
  48. }
  49. $self->{GET} = %GET;
  50. $self->status(200, "OK");
  51. $self->header("Content-Type", "text/html; charset=utf-8");
  52. $self->header("Date", Base::WebServer::_dateString(time()));
  53. $self->header("Server", "OpenKore Web Server");
  54. return $self;
  55. }
  56. sub DESTROY {
  57. my ($self) = @_;
  58. $self->_sendHeaders;
  59. if ($self->{socket} && $self->{socket}->connected) {
  60. if ($self->{chunkedEncoding}) {
  61. # Finish sending chunked encoded data.
  62. eval {
  63. $self->{socket}->send("0x0Dx0Ax0Dx0A", 0);
  64. $self->{socket}->flush;
  65. };
  66. undef $@;
  67. }
  68. my $key = $self->{outHeadersLC}{connection};
  69. if ($key && $self->{outHeaders}{$key} eq 'close') {
  70. $self->{socket}->close;
  71. }
  72. }
  73. }
  74. ##
  75. # void $BaseWebServerProcess->shortResponse(String content)
  76. # content: the data to send to the web browser.
  77. # Requires: defined($content)
  78. #
  79. # Send data (usually HTML) to the web server. This function also automatically sets the HTTP Content-Length
  80. # header for you, allowing the browser to keep the HTTP connection persistent, and to display download
  81. # progress information.
  82. #
  83. # <b>Warning:</b> after calling this function, you shouldn't call any of the other functions in this class
  84. # which send data to the web server. It is undefined what will happen if you do so.
  85. #
  86. # This function should only be used for small amount of data, because the entire content has to be in memory.
  87. # For larger amounts of data, you should send small chunks of data incrementally using $BaseWebServerProcess->print().
  88. #
  89. # The default status message is "200 OK". The default Content-Type is "text/html; charset=utf-8".
  90. sub shortResponse {
  91. my ($self, $content) = @_;
  92. $self->header("Content-Length", length($content));
  93. $self->print($content);
  94. }
  95. ##
  96. # void $BaseWebServerProcess->status(int statusCode, String statusMsg)
  97. # statusCode: a HTTP status code.
  98. # statusMsg: the associated HTTP status message.
  99. # Requires:
  100. #    defined($statusMsg)  <br>
  101. #    $BaseWebServerProcess->print() or $BaseWebServerProcess->shortResponse() must not have been called before.
  102. #
  103. # Schedule a HTTP response status message for sending. See <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">the
  104. # HTTP specification</a> (section 10) for a list of codes. This status code will be sent when the connection to
  105. # the web browser is closed, or when you first call $BaseWebServerProcess->print() or $BaseWebServerProcess->shortResponse().
  106. # If you have sent a HTTP status before, the previous status is overwritten by this one.
  107. #
  108. # See also: $BaseWebServerProcess->header()
  109. #
  110. # Example:
  111. # $BaseWebServerProcess->status(404, "File Not Found");
  112. sub status {
  113. my ($self, $statusCode, $statusMsg) = @_;
  114. if ($self->{sentHeaders}) {
  115. warn "Cannot send HTTP response status - content already sent";
  116. } else {
  117. $self->{outStatus} = "HTTP/1.1 $statusCode $statusMsg";
  118. }
  119. }
  120. ##
  121. # void $BaseWebServerProcess->header(String name, String value)
  122. # name: the name of the header.
  123. # value: the value of the header.
  124. # Requires:
  125. #    defined(name)      <br>
  126. #    defined(value)     <br>
  127. #    $BaseWebServerProcess->print() or $BaseWebServerProcess->shortResponse() must not have been called before.
  128. #
  129. # Schedule a HTTP header for sending. This header will be sent when the connection to the web browser is closed,
  130. # or when you first call $BaseWebServerProcess->print() or $BaseWebServerProcess->shortResponse(). If you have sent a header with
  131. # the same name before, the previous header is overwritten by this one.
  132. #
  133. # For sending HTTP status messages, you should use $BaseWebServerProcess->status() instead.
  134. #
  135. # Example:
  136. # $BaseWebServerProcess->header("WWW-Authenticate", "Negotiate");
  137. # $BaseWebServerProcess->header("WWW-Authenticate", "NTLM");
  138. sub header {
  139. my ($self, $name, $value) = @_;
  140. if ($self->{sentHeaders}) {
  141. warn "Cannot send HTTP header - content already sent";
  142. } else {
  143. # outHeadersLC maps lowercase key names to actual key names.
  144. # This prevents us from sending duplicate header keys.
  145. my $actualKey = $self->{outHeadersLC}{lc($name)} || $name;
  146. $self->{outHeaders}{$actualKey} = $value;
  147. $self->{outHeadersLC}{lc($actualKey)} = $actualKey;
  148. }
  149. }
  150. ##
  151. # void $BaseWebServerProcess->print(String content)
  152. # content: the content to print.
  153. # Requires: defined($content)
  154. #
  155. # Output a string to the web browser. Any scheduled headers and status message will be sent first.
  156. # So after calling this function, you cannot send headers or a status message anymore.
  157. #
  158. # The default status message is "200 OK". The default Content-Type is "text/html; charset=utf-8".
  159. #
  160. # Should should send the Content-Length header (see HTTP specification) before calling this function,
  161. # if possible. That header allows the web browser to keep persistent connections to the server,
  162. # and to display download progress.
  163. sub print {
  164. my $self = shift;
  165. if (!$self->{sentHeaders}) {
  166. # This is the first time print is called, and we haven't sent
  167. # headers yet, so do so.
  168. # The client specifically requested that it doesn't
  169. # want a persistent connection.
  170. if ($self->{headers}{connection} eq 'close') {
  171. $self->header("Connection", "close");
  172. }
  173. # We don't know the content length, so send in chuncked
  174. # encoding.
  175. if (!$self->{outHeadersLC}{'content-length'}) {
  176. $self->{chunkedEncoding} = 1;
  177. $self->header("Transfer-Encoding", "chunked");
  178. }
  179. $self->_sendHeaders;
  180. }
  181. my $data = $_[0];
  182. if (Encode::is_utf8($data)) {
  183. Encode::_utf8_off($data);
  184. }
  185. eval {
  186. if ($self->{chunkedEncoding}) {
  187. $self->{socket}->send(_encodeChunk($data));
  188. } else {
  189. $self->{socket}->send($data);
  190. }
  191. $self->{socket}->flush;
  192. };
  193. undef $@;
  194. }
  195. ##
  196. # String $BaseWebServerProcess->file()
  197. # Ensures: defined(result)
  198. #
  199. # Returns the name of the file that the web browser requested.
  200. # The return value does not include the host name and does not include everythign after '?', so it will be something like "/foo/bar.html".
  201. sub file {
  202. my ($self) = @_;
  203. return $self->{file};
  204. }
  205. ##
  206. # Hash<Bytes>* $BaseWebServerProcess->GET()
  207. # Returns: a reference to a hash.
  208. #
  209. # Returns a reference to a hash, which contains variables provided via
  210. # the URL query string.
  211. sub GET {
  212. return $_[0]->{GET};
  213. }
  214. ##
  215. # String $BaseWebServerProcess->clientHeader(String name)
  216. # name: the name of the header you want to lookup.
  217. # Returns: the value of the header, or undef if the browser didn't send that header.
  218. #
  219. # Lookup the value of a header the browser sent you.
  220. sub clientHeader {
  221. my ($self, $name) = @_;
  222. return $self->{headers}{lc($name)};
  223. }
  224. # Send a HTTP error and disconnect the client.
  225. sub _killClient {
  226. my ($self, $errorID, $errorMsg) = @_;
  227. if (!$self->{sentHeaders}) {
  228. $self->status($errorID, $errorMsg);
  229. $self->print("<h1>HTTP $errorID - $errorMsg</h1>n");
  230. $self->{socket}->close if ($self->{socket} && $self->{socket}->connected);
  231. }
  232. }
  233. sub _sendHeaders {
  234. my ($self) = @_;
  235. return if ($self->{sentHeaders});
  236. my $text = "$self->{outStatus}rn";
  237. foreach my $key (keys %{$self->{outHeaders}}) {
  238. $text .= "$key: $self->{outHeaders}{$key}rn";
  239. }
  240. $text .= "rn";
  241. #print "Response:n$text";
  242. eval {
  243. $self->{socket}->send($text);
  244. $self->{socket}->flush;
  245. };
  246. undef $@;
  247. $self->{sentHeaders} = 1;
  248. }
  249. # Encode a string using HTTP chunked encoding.
  250. sub _encodeChunk {
  251. return sprintf("%X", length($_[0])) . "x0Dx0A$_[0]x0Dx0A";
  252. }
  253. 1;