Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

401 lines
10 KiB

  1. # ======================================================================
  2. #
  3. # Copyright (C) 2000-2001 Paul Kulchenko ([email protected])
  4. # SOAP::Lite is free software; you can redistribute it
  5. # and/or modify it under the same terms as Perl itself.
  6. #
  7. # $Id: XMLRPC::Lite.pm,v 0.51 2001/07/18 15:15:14 $
  8. #
  9. # ======================================================================
  10. package XMLRPC::Lite;
  11. use SOAP::Lite;
  12. use strict;
  13. use vars qw($VERSION);
  14. $VERSION = '0.51';
  15. # ======================================================================
  16. package XMLRPC::Constants;
  17. BEGIN {
  18. no strict 'refs';
  19. for (qw(
  20. FAULT_CLIENT FAULT_SERVER
  21. HTTP_ON_SUCCESS_CODE HTTP_ON_FAULT_CODE
  22. DO_NOT_USE_XML_PARSER DO_NOT_USE_CHARSET
  23. )) {
  24. *$_ = \${'SOAP::Constants::' . $_}
  25. }
  26. }
  27. # ======================================================================
  28. package XMLRPC::Data;
  29. @XMLRPC::Data::ISA = qw(SOAP::Data);
  30. # ======================================================================
  31. package XMLRPC::Serializer;
  32. @XMLRPC::Serializer::ISA = qw(SOAP::Serializer);
  33. sub new {
  34. my $self = shift;
  35. unless (ref $self) {
  36. my $class = ref($self) || $self;
  37. $self = $class->SUPER::new(
  38. typelookup => {
  39. base64 => [10, sub {$_[0] =~ /[^\x09\x0a\x0d\x20-\x7f]/}, 'as_base64'],
  40. int => [20, sub {$_[0] =~ /^[+-]?\d+$/}, 'as_int'],
  41. double => [30, sub {$_[0] =~ /^(-?(?:\d+(?:\.\d*)?|\.\d+|NaN|INF)|([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?)$/}, 'as_double'],
  42. dateTime => [35, sub {$_[0] =~ /^\d{8}T\d\d:\d\d:\d\d$/}, 'as_dateTime'],
  43. string => [40, sub {1}, 'as_string'],
  44. },
  45. attr => {},
  46. namespaces => {},
  47. @_,
  48. );
  49. }
  50. return $self;
  51. }
  52. sub envelope {
  53. my $self = shift->new;
  54. my $type = shift;
  55. my($body);
  56. if ($type eq 'method' || $type eq 'response') {
  57. my $method = shift or die "Unspecified method for XMLRPC call\n";
  58. if ($type eq 'response') {
  59. $body = XMLRPC::Data->name(methodResponse => \XMLRPC::Data->value(
  60. XMLRPC::Data->type(params => [@_])
  61. ));
  62. } else {
  63. $body = XMLRPC::Data->name(methodCall => \XMLRPC::Data->value(
  64. XMLRPC::Data->type(methodName => UNIVERSAL::isa($method => 'XMLRPC::Data') ? $method->name : $method),
  65. XMLRPC::Data->type(params => [@_])
  66. ));
  67. }
  68. } elsif ($type eq 'fault') {
  69. $body = XMLRPC::Data->name(methodResponse =>
  70. \XMLRPC::Data->type(fault => {faultCode => $_[0], faultString => $_[1]}),
  71. );
  72. } else {
  73. die "Wrong type of envelope ($type) for XMLRPC call\n";
  74. }
  75. $self->xmlize($self->encode_object($body));
  76. }
  77. sub encode_object {
  78. my $self = shift;
  79. my @encoded = $self->SUPER::encode_object(@_);
  80. return $encoded[0]->[0] =~ /^(?:array|struct|i4|int|boolean|string|double|dateTime\.iso8601|base64)$/o
  81. ? ['value', {}, [@encoded]] : @encoded;
  82. }
  83. sub encode_scalar {
  84. my $self = shift;
  85. return ['value', {}] unless defined $_[0];
  86. return $self->SUPER::encode_scalar(@_);
  87. }
  88. sub encode_array {
  89. my($self, $array) = @_;
  90. return ['array', {}, [
  91. ['data', {}, [map {$self->encode_object($_)} @$array]]
  92. ]];
  93. }
  94. sub encode_hash {
  95. my($self, $hash) = @_;
  96. return ['struct', {}, [
  97. map {
  98. ['member', {}, [['name', {}, $_], $self->encode_object($hash->{$_})]]
  99. } keys %$hash
  100. ]];
  101. }
  102. sub as_methodName {
  103. my $self = shift;
  104. my($value, $name, $type, $attr) = @_;
  105. return ['methodName', $attr, $value];
  106. }
  107. sub as_params {
  108. my $self = shift;
  109. my($params, $name, $type, $attr) = @_;
  110. return ['params', $attr, [
  111. map {
  112. ['param', {}, [$self->encode_object($_)]]
  113. } @$params
  114. ]];
  115. }
  116. sub as_fault {
  117. my($self, $fault) = @_;
  118. return ['fault', {}, [$self->encode_object($fault)]];
  119. }
  120. sub BEGIN {
  121. no strict 'refs';
  122. for my $type (qw(double i4 int)) {
  123. my $method = 'as_' . $type;
  124. *$method = sub {
  125. my($self, $value) = @_;
  126. return [$type, {}, $value];
  127. }
  128. }
  129. }
  130. sub as_base64 {
  131. my $self = shift;
  132. my $value = shift;
  133. require MIME::Base64;
  134. return ['base64', {}, MIME::Base64::encode_base64($value,'')];
  135. }
  136. sub as_string {
  137. my $self = shift;
  138. my $value = shift;
  139. return ['string', {}, SOAP::Utils::encode_data($value)];
  140. }
  141. sub as_dateTime {
  142. my $self = shift;
  143. my $value = shift;
  144. return ['dateTime.iso8601', {}, $value];
  145. }
  146. sub as_boolean {
  147. my $self = shift;
  148. my $value = shift;
  149. return ['boolean', {}, $value ? 1 : 0];
  150. }
  151. # ======================================================================
  152. package XMLRPC::SOM;
  153. @XMLRPC::SOM::ISA = qw(SOAP::SOM);
  154. sub BEGIN {
  155. no strict 'refs';
  156. my %path = (
  157. root => '/',
  158. envelope => '/[1]',
  159. method => '/methodCall/methodName',
  160. fault => '/methodResponse/fault',
  161. );
  162. for my $method (keys %path) {
  163. *$method = sub {
  164. my $self = shift;
  165. ref $self or return $path{$method};
  166. Carp::croak "Method '$method' is readonly and doesn't accept any parameters" if @_;
  167. $self->valueof($path{$method});
  168. };
  169. }
  170. my %fault = (
  171. faultcode => 'faultCode',
  172. faultstring => 'faultString',
  173. );
  174. for my $method (keys %fault) {
  175. *$method = sub {
  176. my $self = shift;
  177. ref $self or Carp::croak "Method '$method' doesn't have shortcut";
  178. Carp::croak "Method '$method' is readonly and doesn't accept any parameters" if @_;
  179. defined $self->fault ? $self->fault->{$fault{$method}} : undef;
  180. };
  181. }
  182. my %results = (
  183. result => '/methodResponse/params/[1]',
  184. paramsin => '/methodCall/params/param',
  185. paramsall => '/methodResponse/params/param',
  186. );
  187. for my $method (keys %results) {
  188. *$method = sub {
  189. my $self = shift;
  190. ref $self or return $results{$method};
  191. Carp::croak "Method '$method' is readonly and doesn't accept any parameters" if @_;
  192. defined $self->fault ? undef : $self->valueof($results{$method});
  193. };
  194. }
  195. }
  196. # ======================================================================
  197. package XMLRPC::Deserializer;
  198. @XMLRPC::Deserializer::ISA = qw(SOAP::Deserializer);
  199. sub deserialize {
  200. bless shift->SUPER::deserialize(@_) => 'XMLRPC::SOM';
  201. }
  202. sub decode_value {
  203. my $self = shift;
  204. my $ref = shift;
  205. my($name, $attrs, $childs, $value) = @$ref;
  206. if ($name eq 'value') {
  207. $childs ? $self->decode_value($childs->[0]) : $value;
  208. } elsif ($name eq 'array') {
  209. return [map {scalar(($self->decode_object($_))[1])} @{$childs->[0]->[2] || []}];
  210. } elsif ($name eq 'struct') {
  211. return {map {
  212. my %hash = map {$_->[0] => $_} @{$_->[2] || []};
  213. # v----- scalar is required here, because 5.005 evaluates 'undef' in list context as empty array
  214. ($hash{name}->[3] => scalar(($self->decode_object($hash{value}))[1]));
  215. } @{$childs || []}};
  216. } elsif ($name eq 'base64') {
  217. require MIME::Base64;
  218. MIME::Base64::decode_base64($value);
  219. } elsif ($name =~ /^(?:int|i4|boolean|string|double|dateTime\.iso8601|methodName)$/) {
  220. return $value;
  221. } elsif ($name =~ /^(?:params)$/) {
  222. return [map {scalar(($self->decode_object($_))[1])} @{$childs || []}];
  223. } elsif ($name =~ /^(?:methodResponse|methodCall)$/) {
  224. return +{map {$self->decode_object($_)} @{$childs || []}};
  225. } elsif ($name =~ /^(?:param|fault)$/) {
  226. return scalar(($self->decode_object($childs->[0]))[1]);
  227. } else {
  228. die "wrong element '$name'\n";
  229. }
  230. }
  231. # ======================================================================
  232. package XMLRPC::Server;
  233. @XMLRPC::Server::ISA = qw(SOAP::Server);
  234. sub initialize {
  235. return (
  236. deserializer => XMLRPC::Deserializer->new,
  237. serializer => XMLRPC::Serializer->new,
  238. on_action => sub {},
  239. on_dispatch => sub { return map {s!\.!/!; $_} shift->method =~ /^(?:(.*)\.)?(\w+)$/ },
  240. );
  241. }
  242. # ======================================================================
  243. package XMLRPC::Server::Parameters;
  244. @XMLRPC::Server::Parameters::ISA = qw(SOAP::Server::Parameters);
  245. # ======================================================================
  246. package XMLRPC;
  247. @XMLRPC::ISA = qw(SOAP);
  248. # ======================================================================
  249. package XMLRPC::Lite;
  250. @XMLRPC::Lite::ISA = qw(SOAP::Lite);
  251. sub new {
  252. my $self = shift;
  253. unless (ref $self) {
  254. my $class = ref($self) || $self;
  255. $self = $class->SUPER::new(
  256. serializer => XMLRPC::Serializer->new,
  257. deserializer => XMLRPC::Deserializer->new,
  258. on_action => sub {return},
  259. uri => 'http://unspecified/',
  260. @_
  261. );
  262. }
  263. return $self;
  264. }
  265. # ======================================================================
  266. 1;
  267. __END__
  268. =head1 NAME
  269. XMLRPC::Lite - client and server implementation of XML-RPC protocol
  270. =head1 SYNOPSIS
  271. =over 4
  272. =item Client
  273. use XMLRPC::Lite;
  274. print XMLRPC::Lite
  275. -> proxy('http://betty.userland.com/RPC2')
  276. -> call('examples.getStateStruct', {state1 => 12, state2 => 28})
  277. -> result;
  278. =item CGI server
  279. use XMLRPC::Transport::HTTP;
  280. my $server = XMLRPC::Transport::HTTP::CGI
  281. -> dispatch_to('methodName')
  282. -> handle
  283. ;
  284. =item Daemon server
  285. use XMLRPC::Transport::HTTP;
  286. my $daemon = XMLRPC::Transport::HTTP::Daemon
  287. -> new (LocalPort => 80)
  288. -> dispatch_to('methodName')
  289. ;
  290. print "Contact to XMLRPC server at ", $daemon->url, "\n";
  291. $daemon->handle;
  292. =back
  293. =head1 DESCRIPTION
  294. XMLRPC::Lite is a Perl modules which provides a simple nterface to the
  295. XML-RPC protocol both on client and server side. Based on SOAP::Lite module,
  296. it gives you access to all features and transports available in that module.
  297. See F<t/26-xmlrpc.t> for client examples and F<examples/XMLRPC/*> for server
  298. implementations.
  299. =head1 DEPENDENCIES
  300. SOAP::Lite
  301. =head1 SEE ALSO
  302. SOAP::Lite
  303. =head1 CREDITS
  304. The B<XML-RPC> standard is Copyright (c) 1998-2001, UserLand Software, Inc.
  305. See <http://www.xmlrpc.com> for more information about the B<XML-RPC>
  306. specification.
  307. =head1 COPYRIGHT
  308. Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.
  309. This library is free software; you can redistribute it and/or modify
  310. it under the same terms as Perl itself.
  311. =head1 AUTHOR
  312. Paul Kulchenko (paulclinger@yahoo.com)
  313. =cut