Source code of Windows XP (NT5)
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.

1379 lines
37 KiB

  1. #######################################################################
  2. #
  3. # Win32::Internet - Perl Module for Internet Extensions
  4. # ^^^^^^^^^^^^^^^
  5. # This module creates an object oriented interface to the Win32
  6. # Internet Functions (WININET.DLL).
  7. #
  8. # Version: 0.08 (14 Feb 1997)
  9. #
  10. #######################################################################
  11. # changes:
  12. # - fixed 2 bugs in Option(s) related subs
  13. # - works with build 30x also
  14. package Win32::Internet;
  15. require Exporter; # to export the constants to the main:: space
  16. require DynaLoader; # to dynuhlode the module.
  17. # use Win32::WinError; # for windows constants.
  18. @ISA= qw( Exporter DynaLoader );
  19. @EXPORT = qw(
  20. HTTP_ADDREQ_FLAG_ADD
  21. HTTP_ADDREQ_FLAG_REPLACE
  22. HTTP_QUERY_ALLOW
  23. HTTP_QUERY_CONTENT_DESCRIPTION
  24. HTTP_QUERY_CONTENT_ID
  25. HTTP_QUERY_CONTENT_LENGTH
  26. HTTP_QUERY_CONTENT_TRANSFER_ENCODING
  27. HTTP_QUERY_CONTENT_TYPE
  28. HTTP_QUERY_COST
  29. HTTP_QUERY_CUSTOM
  30. HTTP_QUERY_DATE
  31. HTTP_QUERY_DERIVED_FROM
  32. HTTP_QUERY_EXPIRES
  33. HTTP_QUERY_FLAG_REQUEST_HEADERS
  34. HTTP_QUERY_FLAG_SYSTEMTIME
  35. HTTP_QUERY_LANGUAGE
  36. HTTP_QUERY_LAST_MODIFIED
  37. HTTP_QUERY_MESSAGE_ID
  38. HTTP_QUERY_MIME_VERSION
  39. HTTP_QUERY_PRAGMA
  40. HTTP_QUERY_PUBLIC
  41. HTTP_QUERY_RAW_HEADERS
  42. HTTP_QUERY_RAW_HEADERS_CRLF
  43. HTTP_QUERY_REQUEST_METHOD
  44. HTTP_QUERY_SERVER
  45. HTTP_QUERY_STATUS_CODE
  46. HTTP_QUERY_STATUS_TEXT
  47. HTTP_QUERY_URI
  48. HTTP_QUERY_USER_AGENT
  49. HTTP_QUERY_VERSION
  50. HTTP_QUERY_WWW_LINK
  51. ICU_BROWSER_MODE
  52. ICU_DECODE
  53. ICU_ENCODE_SPACES_ONLY
  54. ICU_ESCAPE
  55. ICU_NO_ENCODE
  56. ICU_NO_META
  57. ICU_USERNAME
  58. INTERNET_CONNECT_FLAG_PASSIVE
  59. INTERNET_FLAG_ASYNC
  60. INTERNET_HYPERLINK
  61. INTERNET_FLAG_KEEP_CONNECTION
  62. INTERNET_FLAG_MAKE_PERSISTENT
  63. INTERNET_FLAG_NO_AUTH
  64. INTERNET_FLAG_NO_AUTO_REDIRECT
  65. INTERNET_FLAG_NO_CACHE_WRITE
  66. INTERNET_FLAG_NO_COOKIES
  67. INTERNET_FLAG_READ_PREFETCH
  68. INTERNET_FLAG_RELOAD
  69. INTERNET_FLAG_RESYNCHRONIZE
  70. INTERNET_FLAG_TRANSFER_ASCII
  71. INTERNET_FLAG_TRANSFER_BINARY
  72. INTERNET_INVALID_PORT_NUMBER
  73. INTERNET_INVALID_STATUS_CALLBACK
  74. INTERNET_OPEN_TYPE_DIRECT
  75. INTERNET_OPEN_TYPE_PROXY
  76. INTERNET_OPEN_TYPE_PROXY_PRECONFIG
  77. INTERNET_OPTION_CONNECT_BACKOFF
  78. INTERNET_OPTION_CONNECT_RETRIES
  79. INTERNET_OPTION_CONNECT_TIMEOUT
  80. INTERNET_OPTION_CONTROL_SEND_TIMEOUT
  81. INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT
  82. INTERNET_OPTION_DATA_SEND_TIMEOUT
  83. INTERNET_OPTION_DATA_RECEIVE_TIMEOUT
  84. INTERNET_OPTION_HANDLE_SIZE
  85. INTERNET_OPTION_LISTEN_TIMEOUT
  86. INTERNET_OPTION_PASSWORD
  87. INTERNET_OPTION_READ_BUFFER_SIZE
  88. INTERNET_OPTION_USER_AGENT
  89. INTERNET_OPTION_USERNAME
  90. INTERNET_OPTION_VERSION
  91. INTERNET_OPTION_WRITE_BUFFER_SIZE
  92. INTERNET_SERVICE_FTP
  93. INTERNET_SERVICE_GOPHER
  94. INTERNET_SERVICE_HTTP
  95. INTERNET_STATUS_CLOSING_CONNECTION
  96. INTERNET_STATUS_CONNECTED_TO_SERVER
  97. INTERNET_STATUS_CONNECTING_TO_SERVER
  98. INTERNET_STATUS_CONNECTION_CLOSED
  99. INTERNET_STATUS_HANDLE_CLOSING
  100. INTERNET_STATUS_HANDLE_CREATED
  101. INTERNET_STATUS_NAME_RESOLVED
  102. INTERNET_STATUS_RECEIVING_RESPONSE
  103. INTERNET_STATUS_REDIRECT
  104. INTERNET_STATUS_REQUEST_COMPLETE
  105. INTERNET_STATUS_REQUEST_SENT
  106. INTERNET_STATUS_RESOLVING_NAME
  107. INTERNET_STATUS_RESPONSE_RECEIVED
  108. INTERNET_STATUS_SENDING_REQUEST
  109. );
  110. #######################################################################
  111. # This AUTOLOAD is used to 'autoload' constants from the constant()
  112. # XS function. If a constant is not found then control is passed
  113. # to the AUTOLOAD in AutoLoader.
  114. #
  115. sub AUTOLOAD {
  116. my($constname);
  117. ($constname = $AUTOLOAD) =~ s/.*:://;
  118. #reset $! to zero to reset any current errors.
  119. $!=0;
  120. my $val = constant($constname, @_ ? $_[0] : 0);
  121. if ($! != 0) {
  122. # [dada] This results in an ugly Autoloader error
  123. #if ($! =~ /Invalid/) {
  124. # $AutoLoader::AUTOLOAD = $AUTOLOAD;
  125. # goto &AutoLoader::AUTOLOAD;
  126. #} else {
  127. # [dada] ... I prefer this one :)
  128. ($pack,$file,$line) = caller; undef $pack;
  129. die "Win32::Internet::$constname is not defined, used at $file line $line.";
  130. #}
  131. }
  132. eval "sub $AUTOLOAD { $val }";
  133. goto &$AUTOLOAD;
  134. }
  135. #######################################################################
  136. # STATIC OBJECT PROPERTIES
  137. #
  138. $VERSION = "0.08";
  139. %callback_code = ();
  140. %callback_info = ();
  141. #######################################################################
  142. # PUBLIC METHODS
  143. #
  144. #======== ### CLASS CONSTRUCTOR
  145. sub new {
  146. #========
  147. my($class, $useragent, $opentype, $proxy, $proxybypass, $flags) = @_;
  148. my $self = {};
  149. if(ref($useragent) and ref($useragent) eq "HASH") {
  150. $opentype = $useragent->{'opentype'};
  151. $proxy = $useragent->{'proxy'};
  152. $proxybypass = $useragent->{'proxybypass'};
  153. $flags = $useragent->{'flags'};
  154. my $myuseragent = $useragent->{'useragent'};
  155. undef $useragent;
  156. $useragent = $myuseragent;
  157. }
  158. $useragent = "Perl-Win32::Internet/".$VERSION unless defined($useragent);
  159. $opentype = constant("INTERNET_OPEN_TYPE_DIRECT",0) unless defined($opentype);
  160. $proxy = "" unless defined($proxy);
  161. $proxybypass = "" unless defined($proxybypass);
  162. $flags = 0 unless defined($flags);
  163. my $handle = InternetOpen($useragent, $opentype, $proxy, $proxybypass, $flags);
  164. if ($handle) {
  165. $self->{'connections'} = 0;
  166. $self->{'pasv'} = 0;
  167. $self->{'handle'} = $handle;
  168. $self->{'useragent'} = $useragent;
  169. $self->{'proxy'} = $proxy;
  170. $self->{'proxybypass'} = $proxybypass;
  171. $self->{'flags'} = $flags;
  172. $self->{'Type'} = "Internet";
  173. # [dada] I think it's better to call SetStatusCallback explicitly...
  174. #if($flags & constant("INTERNET_FLAG_ASYNC",0)) {
  175. # my $callbackresult=InternetSetStatusCallback($handle);
  176. # if($callbackresult==&constant("INTERNET_INVALID_STATUS_CALLBACK",0)) {
  177. # $self->{'Error'} = -2;
  178. # }
  179. #}
  180. bless $self;
  181. } else {
  182. $self->{'handle'} = undef;
  183. bless $self;
  184. }
  185. $self;
  186. }
  187. #============
  188. sub OpenURL {
  189. #============
  190. my($self,$new,$URL) = @_;
  191. return undef unless ref($self);
  192. my $newhandle=InternetOpenUrl($self->{'handle'},$URL,"",0,0,0);
  193. if(!$newhandle) {
  194. $self->{'Error'} = "Cannot open URL.";
  195. return undef;
  196. } else {
  197. $self->{'connections'}++;
  198. $_[1] = _new($newhandle);
  199. $_[1]->{'Type'} = "URL";
  200. $_[1]->{'URL'} = $URL;
  201. return $newhandle;
  202. }
  203. }
  204. #================
  205. sub TimeConvert {
  206. #================
  207. my($self, $sec, $min, $hour, $day, $mon, $year, $wday, $rfc) = @_;
  208. return undef unless ref($self);
  209. if(!defined($rfc)) {
  210. return InternetTimeToSystemTime($sec);
  211. } else {
  212. return InternetTimeFromSystemTime($sec, $min, $hour,
  213. $day, $mon, $year,
  214. $wday, $rfc);
  215. }
  216. }
  217. #=======================
  218. sub QueryDataAvailable {
  219. #=======================
  220. my($self) = @_;
  221. return undef unless ref($self);
  222. return InternetQueryDataAvailable($self->{'handle'});
  223. }
  224. #=============
  225. sub ReadFile {
  226. #=============
  227. my($self, $buffersize) = @_;
  228. return undef unless ref($self);
  229. my $howmuch = InternetQueryDataAvailable($self->{'handle'});
  230. $buffersize = $howmuch unless defined($buffersize);
  231. return InternetReadFile($self->{'handle'}, ($howmuch<$buffersize) ? $howmuch
  232. : $buffersize);
  233. }
  234. #===================
  235. sub ReadEntireFile {
  236. #===================
  237. my($handle) = @_;
  238. my $content = "";
  239. my $buffersize = 16000;
  240. my $howmuch = 0;
  241. my $buffer = "";
  242. $handle = $handle->{'handle'} if defined($handle) and ref($handle);
  243. $howmuch = InternetQueryDataAvailable($handle);
  244. # print "\nReadEntireFile: $howmuch bytes to read...\n";
  245. while($howmuch>0) {
  246. $buffer = InternetReadFile($handle, ($howmuch<$buffersize) ? $howmuch
  247. : $buffersize);
  248. # print "\nReadEntireFile: ", length($buffer), " bytes read...\n";
  249. if(!defined($buffer)) {
  250. return undef;
  251. } else {
  252. $content .= $buffer;
  253. }
  254. $howmuch = InternetQueryDataAvailable($handle);
  255. # print "\nReadEntireFile: still $howmuch bytes to read...\n";
  256. }
  257. return $content;
  258. }
  259. #=============
  260. sub FetchURL {
  261. #=============
  262. # (OpenURL+Read+Close)...
  263. my($self, $URL) = @_;
  264. return undef unless ref($self);
  265. my $newhandle = InternetOpenUrl($self->{'handle'}, $URL, "", 0, 0, 0);
  266. if(!$newhandle) {
  267. $self->{'Error'} = "Cannot open URL.";
  268. return undef;
  269. } else {
  270. my $content = ReadEntireFile($newhandle);
  271. InternetCloseHandle($newhandle);
  272. return $content;
  273. }
  274. }
  275. #================
  276. sub Connections {
  277. #================
  278. my($self) = @_;
  279. return undef unless ref($self);
  280. return $self->{'connections'} if $self->{'Type'} eq "Internet";
  281. return undef;
  282. }
  283. #================
  284. sub GetResponse {
  285. #================
  286. my($num, $text) = InternetGetLastResponseInfo();
  287. return $text;
  288. }
  289. #===========
  290. sub Option {
  291. #===========
  292. my($self, $option, $value) = @_;
  293. return undef unless ref($self);
  294. my $retval = 0;
  295. $option = constant("INTERNET_OPTION_USER_AGENT", 0) unless defined($option);
  296. if(!defined($value)) {
  297. $retval = InternetQueryOption($self->{'handle'}, $option);
  298. } else {
  299. $retval = InternetSetOption($self->{'handle'}, $option, $value);
  300. }
  301. return $retval;
  302. }
  303. #==============
  304. sub UserAgent {
  305. #==============
  306. my($self, $value) = @_;
  307. return undef unless ref($self);
  308. return Option($self, constant("INTERNET_OPTION_USER_AGENT", 0), $value);
  309. }
  310. #=============
  311. sub Username {
  312. #=============
  313. my($self, $value) = @_;
  314. return undef unless ref($self);
  315. if($self->{'Type'} ne "HTTP" and $self->{'Type'} ne "FTP") {
  316. $self->{'Error'} = "Username() only on FTP or HTTP sessions.";
  317. return undef;
  318. }
  319. return Option($self, constant("INTERNET_OPTION_USERNAME", 0), $value);
  320. }
  321. #=============
  322. sub Password {
  323. #=============
  324. my($self, $value)=@_;
  325. return undef unless ref($self);
  326. if($self->{'Type'} ne "HTTP" and $self->{'Type'} ne "FTP") {
  327. $self->{'Error'} = "Password() only on FTP or HTTP sessions.";
  328. return undef;
  329. }
  330. return Option($self, constant("INTERNET_OPTION_PASSWORD", 0), $value);
  331. }
  332. #===================
  333. sub ConnectTimeout {
  334. #===================
  335. my($self, $value) = @_;
  336. return undef unless ref($self);
  337. return Option($self, constant("INTERNET_OPTION_CONNECT_TIMEOUT", 0), $value);
  338. }
  339. #===================
  340. sub ConnectRetries {
  341. #===================
  342. my($self, $value) = @_;
  343. return undef unless ref($self);
  344. return Option($self, constant("INTERNET_OPTION_CONNECT_RETRIES", 0), $value);
  345. }
  346. #===================
  347. sub ConnectBackoff {
  348. #===================
  349. my($self,$value)=@_;
  350. return undef unless ref($self);
  351. return Option($self, constant("INTERNET_OPTION_CONNECT_BACKOFF", 0), $value);
  352. }
  353. #====================
  354. sub DataSendTimeout {
  355. #====================
  356. my($self,$value) = @_;
  357. return undef unless ref($self);
  358. return Option($self, constant("INTERNET_OPTION_DATA_SEND_TIMEOUT", 0), $value);
  359. }
  360. #=======================
  361. sub DataReceiveTimeout {
  362. #=======================
  363. my($self, $value) = @_;
  364. return undef unless ref($self);
  365. return Option($self, constant("INTERNET_OPTION_DATA_RECEIVE_TIMEOUT", 0), $value);
  366. }
  367. #==========================
  368. sub ControlReceiveTimeout {
  369. #==========================
  370. my($self, $value) = @_;
  371. return undef unless ref($self);
  372. return Option($self, constant("INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT", 0), $value);
  373. }
  374. #=======================
  375. sub ControlSendTimeout {
  376. #=======================
  377. my($self, $value) = @_;
  378. return undef unless ref($self);
  379. return Option($self, constant("INTERNET_OPTION_CONTROL_SEND_TIMEOUT", 0), $value);
  380. }
  381. #================
  382. sub QueryOption {
  383. #================
  384. my($self, $option) = @_;
  385. return undef unless ref($self);
  386. return InternetQueryOption($self->{'handle'}, $option);
  387. }
  388. #==============
  389. sub SetOption {
  390. #==============
  391. my($self, $option, $value) = @_;
  392. return undef unless ref($self);
  393. return InternetSetOption($self->{'handle'}, $option, $value);
  394. }
  395. #=============
  396. sub CrackURL {
  397. #=============
  398. my($self, $URL, $flags) = @_;
  399. return undef unless ref($self);
  400. $flags = constant("ICU_ESCAPE", 0) unless defined($flags);
  401. my @newurl = InternetCrackUrl($URL, $flags);
  402. if(!defined($newurl[0])) {
  403. $self->{'Error'} = "Cannot crack URL.";
  404. return undef;
  405. } else {
  406. return @newurl;
  407. }
  408. }
  409. #==============
  410. sub CreateURL {
  411. #==============
  412. my($self, $scheme, $hostname, $port,
  413. $username, $password,
  414. $path, $extrainfo, $flags) = @_;
  415. return undef unless ref($self);
  416. if(ref($scheme) and ref($scheme) eq "HASH") {
  417. $flags = $hostname;
  418. $hostname = $scheme->{'hostname'};
  419. $port = $scheme->{'port'};
  420. $username = $scheme->{'username'};
  421. $password = $scheme->{'password'};
  422. $path = $scheme->{'path'};
  423. $extrainfo = $scheme->{'extrainfo'};
  424. my $myscheme = $scheme->{'scheme'};
  425. undef $scheme;
  426. $scheme = $myscheme;
  427. }
  428. $hostname = "" unless defined($hostname);
  429. $port = 0 unless defined($port);
  430. $username = "" unless defined($username);
  431. $password = "" unless defined($password);
  432. $path = "" unless defined($path);
  433. $extrainfo = "" unless defined($extrainfo);
  434. $flags = constant("ICU_ESCAPE", 0) unless defined($flags);
  435. my $newurl = InternetCreateUrl($scheme, $hostname, $port,
  436. $username, $password,
  437. $path, $extrainfo, $flags);
  438. if(!defined($newurl)) {
  439. $self->{'Error'} = "Cannot create URL.";
  440. return undef;
  441. } else {
  442. return $newurl;
  443. }
  444. }
  445. #====================
  446. sub CanonicalizeURL {
  447. #====================
  448. my($self, $URL, $flags) = @_;
  449. return undef unless ref($self);
  450. my $newurl = InternetCanonicalizeUrl($URL, $flags);
  451. if(!defined($newurl)) {
  452. $self->{'Error'} = "Cannot canonicalize URL.";
  453. return undef;
  454. } else {
  455. return $newurl;
  456. }
  457. }
  458. #===============
  459. sub CombineURL {
  460. #===============
  461. my($self, $baseURL, $relativeURL, $flags) = @_;
  462. return undef unless ref($self);
  463. my $newurl = InternetCombineUrl($baseURL, $relativeURL, $flags);
  464. if(!defined($newurl)) {
  465. $self->{'Error'} = "Cannot combine URL(s).";
  466. return undef;
  467. } else {
  468. return $newurl;
  469. }
  470. }
  471. #======================
  472. sub SetStatusCallback {
  473. #======================
  474. my($self) = @_;
  475. return undef unless ref($self);
  476. my $callback = InternetSetStatusCallback($self->{'handle'});
  477. print "callback=$callback, constant=",constant("INTERNET_INVALID_STATUS_CALLBACK", 0), "\n";
  478. if($callback == constant("INTERNET_INVALID_STATUS_CALLBACK", 0)) {
  479. return undef;
  480. } else {
  481. return $callback;
  482. }
  483. }
  484. #======================
  485. sub GetStatusCallback {
  486. #======================
  487. my($self, $context) = @_;
  488. $context = $self if not defined $context;
  489. return($callback_code{$context}, $callback_info{$context});
  490. }
  491. #==========
  492. sub Error {
  493. #==========
  494. my($self) = @_;
  495. return undef unless ref($self);
  496. my $errtext = "";
  497. my $tmp = "";
  498. my $errnum = Win32::GetLastError();
  499. if($errnum < 12000) {
  500. $errtext = Win32::FormatMessage($errnum);
  501. $errtext =~ s/[\r\n]//g;
  502. } elsif($errnum == 12003) {
  503. ($tmp, $errtext) = InternetGetLastResponseInfo();
  504. chomp $errtext;
  505. 1 while($errtext =~ s/(.*)\n//); # the last line should be significative...
  506. # otherwise call GetResponse() to get it whole
  507. } elsif($errnum >= 12000) {
  508. $errtext = FormatMessage($errnum);
  509. $errtext =~ s/[\r\n]//g;
  510. } else {
  511. $errtext="Error";
  512. }
  513. if($errnum == 0 and defined($self->{'Error'})) {
  514. if($self->{'Error'} == -2) {
  515. $errnum = -2;
  516. $errtext = "Asynchronous operations not available.";
  517. } else {
  518. $errnum = -1;
  519. $errtext = $self->{'Error'};
  520. }
  521. }
  522. return (wantarray)? ($errnum, $errtext) : "\[".$errnum."\] ".$errtext;
  523. }
  524. #============
  525. sub Version {
  526. #============
  527. my $dll = InternetDllVersion();
  528. $dll =~ s/\0//g;
  529. return (wantarray)? ($Win32::Internet::VERSION, $dll)
  530. : $Win32::Internet::VERSION."/".$dll;
  531. }
  532. #==========
  533. sub Close {
  534. #==========
  535. my($self, $handle) = @_;
  536. if(!defined($handle)) {
  537. return undef unless ref($self);
  538. $handle = $self->{'handle'};
  539. }
  540. InternetCloseHandle($handle);
  541. }
  542. #######################################################################
  543. # FTP CLASS METHODS
  544. #
  545. #======== ### FTP CONSTRUCTOR
  546. sub FTP {
  547. #========
  548. my($self, $new, $server, $username, $password, $port, $pasv, $context) = @_;
  549. return undef unless ref($self);
  550. if(ref($server) and ref($server) eq "HASH") {
  551. $port = $server->{'port'};
  552. $username = $server->{'username'};
  553. $password = $password->{'host'};
  554. my $myserver = $server->{'server'};
  555. $pasv = $server->{'pasv'};
  556. $context = $server->{'context'};
  557. undef $server;
  558. $server = $myserver;
  559. }
  560. $server = "" unless defined($server);
  561. $username = "anonymous" unless defined($username);
  562. $password = "" unless defined($password);
  563. $port = 21 unless defined($port);
  564. $context = 0 unless defined($context);
  565. if(defined($pasv)) {
  566. $pasv=constant("INTERNET_CONNECT_FLAG_PASSIVE",0) if $pasv ne 0;
  567. } else {
  568. $pasv=$self->{'pasv'};
  569. }
  570. my $newhandle = InternetConnect($self->{'handle'}, $server, $port,
  571. $username, $password,
  572. constant("INTERNET_SERVICE_FTP", 0),
  573. $pasv, $context);
  574. if($newhandle) {
  575. $self->{'connections'}++;
  576. $_[1] = _new($newhandle);
  577. $_[1]->{'Type'} = "FTP";
  578. $_[1]->{'Mode'} = "bin";
  579. $_[1]->{'pasv'} = $pasv;
  580. $_[1]->{'username'} = $username;
  581. $_[1]->{'password'} = $password;
  582. $_[1]->{'server'} = $server;
  583. return $newhandle;
  584. } else {
  585. return undef;
  586. }
  587. }
  588. #========
  589. sub Pwd {
  590. #========
  591. my($self) = @_;
  592. return undef unless ref($self);
  593. if($self->{'Type'} ne "FTP" or !defined($self->{'handle'})) {
  594. $self->{'Error'} = "Pwd() only on FTP sessions.";
  595. return undef;
  596. }
  597. return FtpGetCurrentDirectory($self->{'handle'});
  598. }
  599. #=======
  600. sub Cd {
  601. #=======
  602. my($self, $path) = @_;
  603. return undef unless ref($self);
  604. if($self->{'Type'} ne "FTP" || !defined($self->{'handle'})) {
  605. $self->{'Error'} = "Cd() only on FTP sessions.";
  606. return undef;
  607. }
  608. my $retval = FtpSetCurrentDirectory($self->{'handle'}, $path);
  609. if(!defined($retval)) {
  610. return undef;
  611. } else {
  612. return $path;
  613. }
  614. }
  615. #====================
  616. sub Cwd { Cd(@_); }
  617. sub Chdir { Cd(@_); }
  618. #====================
  619. #==========
  620. sub Mkdir {
  621. #==========
  622. my($self, $path) = @_;
  623. return undef unless ref($self);
  624. if($self->{'Type'} ne "FTP" or !defined($self->{'handle'})) {
  625. $self->{'Error'} = "Mkdir() only on FTP sessions.";
  626. return undef;
  627. }
  628. my $retval = FtpCreateDirectory($self->{'handle'}, $path);
  629. $self->{'Error'} = "Can't create directory." unless defined($retval);
  630. return $retval;
  631. }
  632. #====================
  633. sub Md { Mkdir(@_); }
  634. #====================
  635. #=========
  636. sub Mode {
  637. #=========
  638. my($self, $value) = @_;
  639. return undef unless ref($self);
  640. if($self->{'Type'} ne "FTP" or !defined($self->{'handle'})) {
  641. $self->{'Error'} = "Mode() only on FTP sessions.";
  642. return undef;
  643. }
  644. if(!defined($value)) {
  645. return $self->{'Mode'};
  646. } else {
  647. my $modesub = ($value =~ /^a/i) ? "Ascii" : "Binary";
  648. $self->$modesub($_[0]);
  649. }
  650. return $self->{'Mode'};
  651. }
  652. #==========
  653. sub Rmdir {
  654. #==========
  655. my($self, $path) = @_;
  656. return undef unless ref($self);
  657. if($self->{'Type'} ne "FTP" or !defined($self->{'handle'})) {
  658. $self->{'Error'} = "Rmdir() only on FTP sessions.";
  659. return undef;
  660. }
  661. my $retval = FtpRemoveDirectory($self->{'handle'}, $path);
  662. $self->{'Error'} = "Can't remove directory." unless defined($retval);
  663. return $retval;
  664. }
  665. #====================
  666. sub Rd { Rmdir(@_); }
  667. #====================
  668. #=========
  669. sub Pasv {
  670. #=========
  671. my($self, $value) = @_;
  672. return undef unless ref($self);
  673. if(defined($value) and $self->{'Type'} eq "Internet") {
  674. if($value == 0) {
  675. $self->{'pasv'} = 0;
  676. } else {
  677. $self->{'pasv'} = 1;
  678. }
  679. }
  680. return $self->{'pasv'};
  681. }
  682. #=========
  683. sub List {
  684. #=========
  685. my($self, $pattern, $retmode) = @_;
  686. return undef unless ref($self);
  687. my $retval = "";
  688. my $size = "";
  689. my $attr = "";
  690. my $ctime = "";
  691. my $atime = "";
  692. my $mtime = "";
  693. my $csec = 0; my $cmin = 0; my $chou = 0; my $cday = 0; my $cmon = 0; my $cyea = 0;
  694. my $asec = 0; my $amin = 0; my $ahou = 0; my $aday = 0; my $amon = 0; my $ayea = 0;
  695. my $msec = 0; my $mmin = 0; my $mhou = 0; my $mday = 0; my $mmon = 0; my $myea = 0;
  696. my $newhandle = 0;
  697. my $nextfile = 1;
  698. my @results = ();
  699. my ($filename, $altname, $file);
  700. if($self->{'Type'} ne "FTP") {
  701. $self->{'Error'} = "List() only on FTP sessions.";
  702. return undef;
  703. }
  704. $pattern = "" unless defined($pattern);
  705. $retmode = 1 unless defined($retmode);
  706. if($retmode == 2) {
  707. ( $newhandle,$filename, $altname, $size, $attr,
  708. $csec, $cmin, $chou, $cday, $cmon, $cyea,
  709. $asec, $amin, $ahou, $aday, $amon, $ayea,
  710. $msec, $mmin, $mhou, $mday, $mmon, $myea
  711. ) = FtpFindFirstFile($self->{'handle'}, $pattern, 0, 0);
  712. if(!$newhandle) {
  713. $self->{'Error'} = "Can't read FTP directory.";
  714. return undef;
  715. } else {
  716. while($nextfile) {
  717. $ctime = join(",", ($csec, $cmin, $chou, $cday, $cmon, $cyea));
  718. $atime = join(",", ($asec, $amin, $ahou, $aday, $amon, $ayea));
  719. $mtime = join(",", ($msec, $mmin, $mhou, $mday, $mmon, $myea));
  720. push(@results, $filename, $altname, $size, $attr, $ctime, $atime, $mtime);
  721. ( $nextfile, $filename, $altname, $size, $attr,
  722. $csec, $cmin, $chou, $cday, $cmon, $cyea,
  723. $asec, $amin, $ahou, $aday, $amon, $ayea,
  724. $msec, $mmin, $mhou, $mday, $mmon, $myea
  725. ) = InternetFindNextFile($newhandle);
  726. }
  727. InternetCloseHandle($newhandle);
  728. return @results;
  729. }
  730. } elsif($retmode == 3) {
  731. ( $newhandle,$filename, $altname, $size, $attr,
  732. $csec, $cmin, $chou, $cday, $cmon, $cyea,
  733. $asec, $amin, $ahou, $aday, $amon, $ayea,
  734. $msec, $mmin, $mhou, $mday, $mmon, $myea
  735. ) = FtpFindFirstFile($self->{'handle'}, $pattern, 0, 0);
  736. if(!$newhandle) {
  737. $self->{'Error'} = "Can't read FTP directory.";
  738. return undef;
  739. } else {
  740. while($nextfile) {
  741. $ctime = join(",", ($csec, $cmin, $chou, $cday, $cmon, $cyea));
  742. $atime = join(",", ($asec, $amin, $ahou, $aday, $amon, $ayea));
  743. $mtime = join(",", ($msec, $mmin, $mhou, $mday, $mmon, $myea));
  744. $file = { "name" => $filename,
  745. "altname" => $altname,
  746. "size" => $size,
  747. "attr" => $attr,
  748. "ctime" => $ctime,
  749. "atime" => $atime,
  750. "mtime" => $mtime,
  751. };
  752. push(@results, $file);
  753. ( $nextfile, $filename, $altname, $size, $attr,
  754. $csec, $cmin, $chou, $cday, $cmon, $cyea,
  755. $asec, $amin, $ahou, $aday, $amon, $ayea,
  756. $msec, $mmin, $mhou, $mday, $mmon, $myea
  757. ) = InternetFindNextFile($newhandle);
  758. }
  759. InternetCloseHandle($newhandle);
  760. return @results;
  761. }
  762. } else {
  763. ($newhandle, $filename) = FtpFindFirstFile($self->{'handle'}, $pattern, 0, 0);
  764. if(!$newhandle) {
  765. $self->{'Error'} = "Can't read FTP directory.";
  766. return undef;
  767. } else {
  768. while($nextfile) {
  769. push(@results, $filename);
  770. ($nextfile, $filename) = InternetFindNextFile($newhandle);
  771. # print "List.no more files\n" if !$nextfile;
  772. }
  773. InternetCloseHandle($newhandle);
  774. return @results;
  775. }
  776. }
  777. }
  778. #====================
  779. sub Ls { List(@_); }
  780. sub Dir { List(@_); }
  781. #====================
  782. #=================
  783. sub FileAttrInfo {
  784. #=================
  785. my($self,$attr) = @_;
  786. my @attrinfo = ();
  787. push(@attrinfo, "READONLY") if $attr & 1;
  788. push(@attrinfo, "HIDDEN") if $attr & 2;
  789. push(@attrinfo, "SYSTEM") if $attr & 4;
  790. push(@attrinfo, "DIRECTORY") if $attr & 16;
  791. push(@attrinfo, "ARCHIVE") if $attr & 32;
  792. push(@attrinfo, "NORMAL") if $attr & 128;
  793. push(@attrinfo, "TEMPORARY") if $attr & 256;
  794. push(@attrinfo, "COMPRESSED") if $attr & 2048;
  795. return (wantarray)? @attrinfo : join(" ", @attrinfo);
  796. }
  797. #===========
  798. sub Binary {
  799. #===========
  800. my($self) = @_;
  801. return undef unless ref($self);
  802. if($self->{'Type'} ne "FTP") {
  803. $self->{'Error'} = "Binary() only on FTP sessions.";
  804. return undef;
  805. }
  806. $self->{'Mode'} = "bin";
  807. return undef;
  808. }
  809. #======================
  810. sub Bin { Binary(@_); }
  811. #======================
  812. #==========
  813. sub Ascii {
  814. #==========
  815. my($self) = @_;
  816. return undef unless ref($self);
  817. if($self->{'Type'} ne "FTP") {
  818. $self->{'Error'} = "Ascii() only on FTP sessions.";
  819. return undef;
  820. }
  821. $self->{'Mode'} = "asc";
  822. return undef;
  823. }
  824. #=====================
  825. sub Asc { Ascii(@_); }
  826. #=====================
  827. #========
  828. sub Get {
  829. #========
  830. my($self, $remote, $local, $overwrite, $flags, $context) = @_;
  831. return undef unless ref($self);
  832. if($self->{'Type'} ne "FTP") {
  833. $self->{'Error'} = "Get() only on FTP sessions.";
  834. return undef;
  835. }
  836. my $mode = ($self->{'Mode'} eq "asc" ? 1 : 2);
  837. $remote = "" unless defined($remote);
  838. $local = $remote unless defined($local);
  839. $overwrite = 0 unless defined($overwrite);
  840. $flags = 0 unless defined($flags);
  841. $context = 0 unless defined($context);
  842. my $retval = FtpGetFile($self->{'handle'},
  843. $remote,
  844. $local,
  845. $overwrite,
  846. $flags,
  847. $mode,
  848. $context);
  849. $self->{'Error'} = "Can't get file." unless defined($retval);
  850. return $retval;
  851. }
  852. #===========
  853. sub Rename {
  854. #===========
  855. my($self, $oldname, $newname) = @_;
  856. return undef unless ref($self);
  857. if($self->{'Type'} ne "FTP") {
  858. $self->{'Error'} = "Rename() only on FTP sessions.";
  859. return undef;
  860. }
  861. my $retval = FtpRenameFile($self->{'handle'}, $oldname, $newname);
  862. $self->{'Error'} = "Can't rename file." unless defined($retval);
  863. return $retval;
  864. }
  865. #======================
  866. sub Ren { Rename(@_); }
  867. #======================
  868. #===========
  869. sub Delete {
  870. #===========
  871. my($self, $filename) = @_;
  872. return undef unless ref($self);
  873. if($self->{'Type'} ne "FTP") {
  874. $self->{'Error'} = "Delete() only on FTP sessions.";
  875. return undef;
  876. }
  877. my $retval = FtpDeleteFile($self->{'handle'}, $filename);
  878. $self->{'Error'} = "Can't delete file." unless defined($retval);
  879. return $retval;
  880. }
  881. #======================
  882. sub Del { Delete(@_); }
  883. #======================
  884. #========
  885. sub Put {
  886. #========
  887. my($self, $local, $remote, $context) = @_;
  888. return undef unless ref($self);
  889. if($self->{'Type'} ne "FTP") {
  890. $self->{'Error'} = "Put() only on FTP sessions.";
  891. return undef;
  892. }
  893. my $mode = ($self->{'Mode'} eq "asc" ? 1 : 2);
  894. $context = 0 unless defined($context);
  895. my $retval = FtpPutFile($self->{'handle'}, $local, $remote, $mode, $context);
  896. $self->{'Error'} = "Can't put file." unless defined($retval);
  897. return $retval;
  898. }
  899. #######################################################################
  900. # HTTP CLASS METHODS
  901. #
  902. #========= ### HTTP CONSTRUCTOR
  903. sub HTTP {
  904. #=========
  905. my($self, $new, $server, $username, $password, $port, $flags, $context) = @_;
  906. return undef unless ref($self);
  907. if(ref($server) and ref($server) eq "HASH") {
  908. my $myserver = $server->{'server'};
  909. $username = $server->{'username'};
  910. $password = $password->{'host'};
  911. $port = $server->{'port'};
  912. $flags = $server->{'flags'};
  913. $context = $server->{'context'};
  914. undef $server;
  915. $server = $myserver;
  916. }
  917. $server = "" unless defined($server);
  918. $username = "anonymous" unless defined($username);
  919. $password = "" unless defined($username);
  920. $port = 80 unless defined($port);
  921. $flags = 0 unless defined($flags);
  922. $context = 0 unless defined($context);
  923. my $newhandle = InternetConnect($self->{'handle'}, $server, $port,
  924. $username, $password,
  925. constant("INTERNET_SERVICE_HTTP", 0),
  926. $flags, $context);
  927. if($newhandle) {
  928. $self->{'connections'}++;
  929. $_[1] = _new($newhandle);
  930. $_[1]->{'Type'} = "HTTP";
  931. $_[1]->{'username'} = $username;
  932. $_[1]->{'password'} = $password;
  933. $_[1]->{'server'} = $server;
  934. $_[1]->{'accept'} = "text/*\0image/gif\0image/jpeg";
  935. return $newhandle;
  936. } else {
  937. return undef;
  938. }
  939. }
  940. #================
  941. sub OpenRequest {
  942. #================
  943. # alternatively to Request:
  944. # it creates a new HTTP_Request object
  945. # you can act upon it with AddHeader, SendRequest, ReadFile, QueryInfo, Close, ...
  946. my($self, $new, $path, $method, $version, $referer, $accept, $flags, $context) = @_;
  947. return undef unless ref($self);
  948. if($self->{'Type'} ne "HTTP") {
  949. $self->{'Error'} = "OpenRequest() only on HTTP sessions.";
  950. return undef;
  951. }
  952. if(ref($path) and ref($path) eq "HASH") {
  953. $method = $path->{'method'};
  954. $version = $path->{'version'};
  955. $referer = $path->{'referer'};
  956. $accept = $path->{'accept'};
  957. $flags = $path->{'flags'};
  958. $context = $path->{'context'};
  959. my $mypath = $path->{'path'};
  960. undef $path;
  961. $path = $mypath;
  962. }
  963. $method = "GET" unless defined($method);
  964. $path = "/" unless defined($path);
  965. $version = "HTTP/1.0" unless defined($version);
  966. $referer = "" unless defined($referer);
  967. $accept = $self->{'accept'} unless defined($accept);
  968. $flags = 0 unless defined($flags);
  969. $context = 0 unless defined($context);
  970. $path = "/".$path if substr($path,0,1) ne "/";
  971. my $newhandle = HttpOpenRequest($self->{'handle'},
  972. $method,
  973. $path,
  974. $version,
  975. $referer,
  976. $accept,
  977. $flags,
  978. $context);
  979. if($newhandle) {
  980. $_[1] = _new($newhandle);
  981. $_[1]->{'Type'} = "HTTP_Request";
  982. $_[1]->{'method'} = $method;
  983. $_[1]->{'request'} = $path;
  984. $_[1]->{'accept'} = $accept;
  985. return $newhandle;
  986. } else {
  987. return undef;
  988. }
  989. }
  990. #================
  991. sub SendRequest {
  992. #================
  993. my($self, $postdata) = @_;
  994. return undef unless ref($self);
  995. if($self->{'Type'} ne "HTTP_Request") {
  996. $self->{'Error'} = "SendRequest() only on HTTP requests.";
  997. return undef;
  998. }
  999. $postdata = "" unless defined($postdata);
  1000. return HttpSendRequest($self->{'handle'}, "", $postdata);
  1001. }
  1002. #==============
  1003. sub AddHeader {
  1004. #==============
  1005. my($self, $header, $flags) = @_;
  1006. return undef unless ref($self);
  1007. if($self->{'Type'} ne "HTTP_Request") {
  1008. $self->{'Error'} = "AddHeader() only on HTTP requests.";
  1009. return undef;
  1010. }
  1011. $flags = constant("HTTP_ADDREQ_FLAG_ADD", 0) if (!defined($flags) or $flags == 0);
  1012. return HttpAddRequestHeaders($self->{'handle'}, $header, $flags);
  1013. }
  1014. #==============
  1015. sub QueryInfo {
  1016. #==============
  1017. my($self, $header, $flags) = @_;
  1018. return undef unless ref($self);
  1019. if($self->{'Type'} ne "HTTP_Request") {
  1020. $self->{'Error'}="QueryInfo() only on HTTP requests.";
  1021. return undef;
  1022. }
  1023. $flags = constant("HTTP_QUERY_CUSTOM", 0) if (!defined($flags) and defined($header));
  1024. my @queryresult = HttpQueryInfo($self->{'handle'}, $flags, $header);
  1025. return (wantarray)? @queryresult : join(" ", @queryresult);
  1026. }
  1027. #============
  1028. sub Request {
  1029. #============
  1030. # HttpOpenRequest+HttpAddHeaders+HttpSendRequest+InternetReadFile+HttpQueryInfo
  1031. my($self, $path, $method, $version, $referer, $accept, $flags, $postdata) = @_;
  1032. return undef unless ref($self);
  1033. if($self->{'Type'} ne "HTTP") {
  1034. $self->{'Error'} = "Request() only on HTTP sessions.";
  1035. return undef;
  1036. }
  1037. if(ref($path) and ref($path) eq "HASH") {
  1038. $method = $path->{'method'};
  1039. $version = $path->{'version'};
  1040. $referer = $path->{'referer'};
  1041. $accept = $path->{'accept'};
  1042. $flags = $path->{'flags'};
  1043. $postdata = $path->{'postdata'};
  1044. my $mypath = $path->{'path'};
  1045. undef $path;
  1046. $path = $mypath;
  1047. }
  1048. my $content = "";
  1049. my $result = "";
  1050. my @queryresult = ();
  1051. my $statuscode = "";
  1052. my $headers = "";
  1053. $path = "/" unless defined($path);
  1054. $method = "GET" unless defined($method);
  1055. $version = "HTTP/1.0" unless defined($version);
  1056. $referer = "" unless defined($referer);
  1057. $accept = $self->{'accept'} unless defined($accept);
  1058. $flags = 0 unless defined($flags);
  1059. $postdata = "" unless defined($postdata);
  1060. $path = "/".$path if substr($path,0,1) ne "/";
  1061. my $newhandle = HttpOpenRequest($self->{'handle'},
  1062. $method,
  1063. $path,
  1064. $version,
  1065. $referer,
  1066. $accept,
  1067. 0,
  1068. $flags);
  1069. if($newhandle) {
  1070. $result = HttpSendRequest($newhandle, "", $postdata);
  1071. if(defined($result)) {
  1072. $statuscode = HttpQueryInfo($newhandle,
  1073. constant("HTTP_QUERY_STATUS_CODE", 0), "");
  1074. $headers = HttpQueryInfo($newhandle,
  1075. constant("HTTP_QUERY_RAW_HEADERS_CRLF", 0), "");
  1076. $content = ReadEntireFile($newhandle);
  1077. InternetCloseHandle($newhandle);
  1078. return($statuscode, $headers, $content);
  1079. } else {
  1080. return undef;
  1081. }
  1082. } else {
  1083. return undef;
  1084. }
  1085. }
  1086. #######################################################################
  1087. # END OF THE PUBLIC METHODS
  1088. #
  1089. #========= ### SUB-CLASSES CONSTRUCTOR
  1090. sub _new {
  1091. #=========
  1092. my $self = {};
  1093. if ($_[0]) {
  1094. $self->{'handle'} = $_[0];
  1095. bless $self;
  1096. } else {
  1097. undef($self);
  1098. }
  1099. $self;
  1100. }
  1101. #============ ### CLASS DESTRUCTOR
  1102. sub DESTROY {
  1103. #============
  1104. my($self) = @_;
  1105. # print "Closing handle $self->{'handle'}...\n";
  1106. InternetCloseHandle($self->{'handle'});
  1107. # [dada] rest in peace
  1108. }
  1109. #=============
  1110. sub callback {
  1111. #=============
  1112. my($name, $status, $info) = @_;
  1113. $callback_code{$name} = $status;
  1114. $callback_info{$name} = $info;
  1115. }
  1116. #######################################################################
  1117. # dynamically load in the Internet.pll module.
  1118. #
  1119. bootstrap Win32::Internet;
  1120. # Preloaded methods go here.
  1121. #Currently Autoloading is not implemented in Perl for win32
  1122. # Autoload methods go after __END__, and are processed by the autosplit program.
  1123. 1;
  1124. __END__