File Coverage

blib/lib/Mac/Apps/Anarchie.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             #!perl -w
2             package Mac::Apps::Anarchie;
3             require 5.004;
4 1     1   887 use vars qw($VERSION $be @ISA @EXPORT $AUTOLOAD);
  1         2  
  1         157  
5 1     1   7 use strict;
  1         2  
  1         84  
6 1     1   2119 use AutoLoader;
  1         1377  
  1         4  
7 1     1   26 use Exporter;
  1         1  
  1         35  
8 1     1   3 use Carp;
  1         1  
  1         72  
9 1     1   1912 use Mac::AppleEvents;
  0            
  0            
10             use Mac::Apps::Launch;
11             @ISA = qw(Exporter);
12             @EXPORT = ();
13             $VERSION = sprintf("%d.%02d", q$Revision: 1.50 $ =~ /(\d+)\.(\d+)/);
14              
15             #=================================================================
16             # Stuff
17             #=================================================================
18             sub new {
19             my %fields1 = (
20             showabout => ['abou','core'],
21             # help => ['help','core'], #???
22             quit => ['quit','aevt'],
23             'close' => ['clos','core'],
24             closeall => ['Clos','core'],
25             undo => ['undo','core'],
26             cut => ['cut ','core'],
27             copyclip => ['copy','core'],
28             paste => ['past','core'],
29             clear => ['delo','core'],
30             selectall => ['slct','core'],
31             # frontwindowrecord => ['Afwr','Arch'], #???
32             showtranscript => ['STrn','Arch'],
33             showarchie => ['SArI','Arch'],
34             showget => ['SFcI','Arch'],
35             updateserverlist => ['UpSL','Arch'],
36             showlog => ['SLog','Arch'],
37             showmacsearch => ['SMSI','Arch'],
38             showtips => ['STip','Arch'],
39             );
40             my %fields2 = (
41             host => undef,
42             path => undef,
43             user => undef,
44             pass => undef,
45             fire => undef,
46             socks => undef,
47             );
48             my %fields3 = (
49             remove => 'Rmve',
50             removeURL => 'Rmve',
51             'mkdir' => 'MkDr',
52             mkdirURL => 'MkDr',
53             sendcommand => 'SCmd',
54             sendcommandURL => 'SCmd',
55             'index' => 'Indx',
56             indexURL => 'Indx',
57             );
58             my %fields4 = (
59             list => 'List',
60             listURL => 'List',
61             nlist => 'NLst',
62             nlistURL => 'NLst',
63             );
64             my $self = {
65             _p1 => \%fields1,
66             %fields1,
67             _p2 => \%fields2,
68             %fields2,
69             _p3 => \%fields3,
70             %fields3,
71             _p4 => \%fields4,
72             %fields4,
73             };
74             my $that = shift;
75             my $class = ref($that) || $that;
76             bless $self, $class;
77             $self->{ArchAgent} = shift || 'Arch';
78             $self->{WAIT} = eval('kAEWaitReply');
79             &_ArchLaunchApp($self);
80             return $self;
81             }
82             #-----------------------------------------------------------------
83             sub AUTOLOAD {
84             my $self = shift;
85             my $type = ref($self) || croak "$self is not an object\n";
86             my $name = $AUTOLOAD;
87             $name =~ s/.*://;
88             if (exists $self->{_p1}->{$name}) {
89             $be = &_ArchAeBuild($self,$self->{$name}[0],$self->{$name}[1]);
90             return &_ArchAeProcess($self)
91             } elsif (exists $self->{_p2}->{$name}) {
92             if (@_) {
93             return $self->{$name} = shift;
94             } else {
95             return $self->{$name};
96             }
97             } elsif (exists $self->{_p3}->{$name}) {
98             if ($name =~ /URL$/) {&_doArchFuncURL($self,$self->{$name},@_)}
99             else {&_doArchFunc($self,$self->{$name},@_)}
100             } elsif (exists $self->{_p4}->{$name}) {
101             if ($name =~ /URL$/) {&_doListFuncURL($self,$self->{$name},@_)}
102             else {&_doListFunc($self,$self->{$name},@_)}
103             } else {
104             $AutoLoader::AUTOLOAD = $AUTOLOAD;
105             &AutoLoader::AUTOLOAD($self,@_) ||
106             croak "Can't access '$name' field in object of class $type\n";
107             }
108             }
109             #-----------------------------------------------------------------
110             sub DESTROY {
111             my $self = shift;
112             &_ArchFrontApp($self,$self->{ArchMainApp}) if ($self->{ArchSwitchApps} && $self->{ArchSwitchApps} == 1 && $self->{ArchMainApp});
113             }
114             #-----------------------------------------------------------------
115             sub getresults {
116             my($self,$res) = @_;
117             $res = 'result' if (!$res);
118             return $self->{results}->{$res};
119             }
120             #-----------------------------------------------------------------
121             sub getresultsall {
122             my($self) = shift;
123             my($results) = $self->{results};
124             return %{$results};
125             }
126             #-----------------------------------------------------------------
127             sub switchapp {
128             my($self,$do,$app) = @_;
129             if (defined $do) {
130             $self->{ArchSwitchApps} = $do;
131             }
132             if ($app) {
133             $self->{ArchMainApp} = $app;
134             }
135             &_ArchFrontApp($self) if ($self->{ArchSwitchApps} == 1);
136             }
137             #-----------------------------------------------------------------
138             sub useagent {
139             my($self,$agent) = @_;
140             if ($agent) {
141             $self->{ArchAgent} = $agent;
142             }
143             &_ArchFrontApp($self) if ($self->{ArchSwitchApps} == 1);
144             }
145             #-----------------------------------------------------------------
146             sub waitreply {
147             my($self,$wait) = @_;
148             if ($wait == 1) {
149             $self->{WAIT} = eval('kAEWaitReply');
150             } elsif ($wait eq '0') {
151             $self->{WAIT} = eval('kAENoReply');
152             }
153             }
154             #-----------------------------------------------------------------
155             sub quit {
156             my($self) = shift;
157             my($be) = AEBuildAppleEvent('aevt','quit',typeApplSignature,$self->{ArchAgent},0,0,'') || croak $^E;
158             AESend($be, kAENoReply) || croak $^E;
159             AEDisposeDesc $be;
160             }
161             #=================================================================
162             # Main subroutines
163             #=================================================================
164             sub _doArchFunc {
165             my(@p) = @_;
166             $be = &_ArchAeBuild($p[0],$p[1]);
167             my($host) = $p[3] || $p[0]->{host};
168             my($user) = $p[4] || $p[0]->{user};
169             my($pass) = $p[5] || $p[0]->{pass};
170             my($fire) = $p[6] || $p[0]->{fire};
171             my($socks) = $p[7] || $p[0]->{socks};
172             if ($p[2]) {&_ArchBText($p[2],'FTPc') }
173             if ($host) {&_ArchBText($host,'FTPh') }
174             if ($user) {&_ArchBText($user,'ArGU') }
175             if ($pass) {&_ArchBText($pass,'ArGp') }
176             if ($fire) {&_ArchBText($fire,'ArGF') }
177             if ($socks) {&_ArchBText($socks,'ArGS') }
178             return &_ArchAeProcess($p[0])
179             }
180             #-----------------------------------------------------------------
181             sub _doArchFuncURL {
182             my(@p) = @_;
183             $be = &_ArchAeBuild($p[0],$p[1]);
184             my($fire) = $p[3] || $p[0]->{fire};
185             my($socks) = $p[4] || $p[0]->{socks};
186             if ($p[2]) {&_ArchBText($p[2],'ArUR') }
187             if ($fire) {&_ArchBText($fire,'ArGF') }
188             if ($socks) {&_ArchBText($socks,'ArGS') }
189             return &_ArchAeProcess($p[0])
190             }
191             #-----------------------------------------------------------------
192             sub _doListFunc {
193             my(@p) = @_;
194             $be = &_ArchAeBuild($p[0],$p[1]);
195             my($host) = $p[5] || $p[0]->{host};
196             my($user) = $p[6] || $p[0]->{user};
197             my($pass) = $p[7] || $p[0]->{pass};
198             my($fire) = $p[8] || $p[0]->{fire};
199             my($socks) = $p[9] || $p[0]->{socks};
200             if ($p[2]) {&_ArchBFile($p[2],'----') } #else {&_ArchError('m','dObj')}
201             if ($p[3]) {&_ArchBText($p[3],'FTPc') }
202             if (defined $p[4]) {&_ArchBBool($p[4],'ArFW') }
203             if ($host) {&_ArchBText($host,'FTPh') }
204             if ($user) {&_ArchBText($user,'ArGU') }
205             if ($pass) {&_ArchBText($pass,'ArGp') }
206             if ($fire) {&_ArchBText($fire,'ArGF') }
207             if ($socks) {&_ArchBText($socks,'ArGS') }
208             return &_ArchAeProcess($p[0])
209             }
210             #-----------------------------------------------------------------
211             sub _doListFuncURL {
212             my(@p) = @_;
213             $be = &_ArchAeBuild($p[0],$p[1]);
214             my($fire) = $p[5] || $p[0]->{fire};
215             my($socks) = $p[6] || $p[0]->{socks};
216             if ($p[2]) {&_ArchBFile($p[2],'----') } #else {&_ArchError('m','dObj')}
217             if ($p[3]) {&_ArchBText($p[3],'ArUR') }
218             if (defined $p[4]) {&_ArchBBool($p[4],'ArFW') }
219             if ($fire) {&_ArchBText($fire,'ArGF') }
220             if ($socks) {&_ArchBText($socks,'ArGS') }
221             return &_ArchAeProcess($p[0])
222             }
223             #-----------------------------------------------------------------
224             sub open {
225             my(@p) = @_;
226             $be = &_ArchAeBuild($p[0],'odoc','aevt');
227             if ($p[1]) {&_ArchBFile($p[1],'----') } else {&_ArchError('m','dObj')}
228             return &_ArchAeProcess($p[0])
229             }
230             #-----------------------------------------------------------------
231             sub geturl {
232             my(@p) = @_;
233             $be = &_ArchAeBuild($p[0],'GURL','GURL');
234             if ($p[1]) {&_ArchBText($p[1],'----') } else {&_ArchError('m','dObj')}
235             if ($p[2]) {&_ArchBFile($p[2],'dest') }
236             return &_ArchAeProcess($p[0])
237             }
238             #=================================================================
239             # Error checking of data
240             #=================================================================
241             sub _twixtOf {
242             my($type,$one,$of) = @_;
243             &_ArchError('d',$type) unless
244             (($one !~ /\D/ && $one >= $$of[0] && $one <= $$of[1]) || ($one == 0));
245             return 1;
246             }
247             #-----------------------------------------------------------------
248             sub _oneOf {
249             my($type,$one,$of,$yes) = @_;
250             foreach (@{$of}) {
251             $yes = 1 if ($one eq $_);
252             }
253             if (!$yes) {
254             &_ArchError('t',$type);
255             }
256             return 1;
257             }
258             #=================================================================
259             # Add AE descriptor records to event
260             #=================================================================
261             sub _ArchBKeyw {
262             my($data,$type,$keys) = @_;
263             AEPutParamDesc($be,$type,(AEBuild($data))) if (&_oneOf($type,$data,$keys));
264             }
265             #-----------------------------------------------------------------
266             sub _ArchBShor {
267             my($data,$type) = @_;
268             my(@datas) = ('0', eval(2**31));
269             AEPutParamDesc($be,$type,(AEBuild($data))) if (&_twixtOf($type,$data,\@datas));
270             }
271             #-----------------------------------------------------------------
272             sub _ArchBBool {
273             my($data,$type) = @_;
274             if ($data eq '1') {
275             $data = 'true';
276             } elsif ($data eq '0') {
277             $data = 'fals';
278             } else {
279             &_ArchError('b',$type);
280             }
281             AEPutParamDesc($be,$type,(AEBuild($data)));
282             }
283             #-----------------------------------------------------------------
284             sub _ArchBText {
285             my($data,$type) = @_;
286             AEPutParamDesc($be,$type,(AEBuild('TEXT(@)',$data)));
287             }
288             #-----------------------------------------------------------------
289             sub _ArchBFile {
290             my($data,$type) = @_;
291             my($file) = AECreateList('', 1);
292             AEPutParam($file, 'want', 'type', 'file');
293             AEPutParam($file, 'from', 'null', '');
294             AEPutParam($file, 'form', 'enum', 'name');
295             AEPutParam($file, 'seld', 'TEXT', $data);
296             my($obj) = AECoerceDesc($file, 'obj ');
297             AEPutParamDesc($be,$type,$obj);
298             }
299             #=================================================================
300             # Main processing
301             #=================================================================
302             sub _ArchLaunchApp {
303             my($self) = shift;
304             my($app) = shift || $self->{ArchAgent};
305             LaunchApps([$app],0);
306             }
307             #-----------------------------------------------------------------
308             sub _ArchFrontApp {
309             my($self) = shift;
310             my($app) = shift || $self->{ArchAgent};
311             LaunchApps([$app],1);
312             }
313             #-----------------------------------------------------------------
314             sub _ArchError {
315             my($type,$info) = @_;
316             if ($type eq 'm') {
317             croak "Missing required element of type: $info.\n";
318             } elsif ($type eq 'd') {
319             croak "Value of $info does not fall within acceptable bounds.\n";
320             } elsif ($type eq 't') {
321             croak "Value of $info does not match acceptable parameters.\n";
322             } elsif ($type eq 'b') {
323             croak "Value of $info must be either 1 or 0 (boolean).\n";
324             } elsif ($type eq 's') {
325             croak "Cannot include signature in self-decrypting files.\n";
326             } else {
327             croak "Unknown error ($type, $info).\n";
328             }
329             }
330             #-----------------------------------------------------------------
331             sub _ArchAeBuild {
332             my($self,$ev,$st) = @_;
333             $st = 'Arch' if (!$st);
334             my($be) = AEBuildAppleEvent($st,$ev,typeApplSignature,$self->{ArchAgent},0,0,'') || croak $^E;
335             return $be;
336             }
337             #-----------------------------------------------------------------
338             sub _ArchAePrint {
339             my($self,$rp) = @_;
340             my(@ar,%ar,$ar,$at);
341             @ar = ('----','errn','errs','outp');
342             foreach $ar(@ar) {
343             if ($at = AEGetParamDesc($rp,$ar)) {
344             $ar{$ar} = AEPrint($at);
345             }
346             }
347             if (exists $ar{'----'}) {
348             $ar{'----'} =~ s/^Ò(.*)Ó$/$1/s;
349             $ar{'result'} = $ar{'----'};
350             carp "Anarchie error: $ar{'----'}" if ($ar{'----'} < 0);
351             }
352             $self->{results} = \%ar;
353             AEDisposeDesc $rp;
354             return $ar{result} || 1;
355             }
356             #-----------------------------------------------------------------
357             sub _ArchAeProcess {
358             my($self) = shift;
359             my($rp) = AESend($be, $self->{WAIT}) || croak $^E;
360             AEDisposeDesc $be;
361             return &_ArchAePrint($self,$rp);
362             }
363             #-----------------------------------------------------------------#
364              
365             =pod
366              
367             =head1 NAME
368              
369             Mac::Apps::Anarchie - Interface to Anarchie 2.01+
370              
371             =head1 SYNOPSIS
372              
373             use Mac::Apps::Anarchie;
374             $ftp = new Mac::Apps::Anarchie;
375             #see description for the rest
376              
377             =head1 DESCRIPTION
378              
379             This is a MacPerl interface to the popular MacOS shareware FTP/archie client, Anarchie. For more info, see the Anarchie documentation.
380              
381             Also required is the Mac::Apps::Launch module, which requires MacPerl 5.1.4r4.
382              
383             NOTE: for some explanations of methods, drop Anarchie on Script Editor, and check the Anarchie docs.
384              
385             Before using, you must autosplit the module. See version notes for 1.4 below.
386              
387             =head2 Standard Suite
388              
389             $ftp->open(ALIAS);
390             $ftp->quit;
391             $ftp->showabout;
392             $ftp->close;
393             $ftp->closeall;
394             $ftp->undo;
395             $ftp->cut;
396             $ftp->copyclip;
397             $ftp->paste;
398             $ftp->clear;
399             $ftp->selectall;
400              
401             =head2 Anarchie Suite
402              
403             NOTE: * denotes compatability with Fetch. Fetch does not use the variables SOCKS, FIRE, BINARY, or TYPE. Fetch implements some of these methods differently than Anarchie. To use Fetch instead of Anarchie for these methods, call the method:
404              
405             $ftp->useagent('FTCh');
406              
407             There are two forms of each of the following methods: "method" and "methodURL".
408             The methodURL version takes the user name, password, host and path in
409             the URL instead of separately. URLs are usually in the form:
410              
411             ftp://user:password@host.com/path/to/file
412             ftp://user:password@host.com//absolute/path/to/file
413              
414             See Anarchie docs for more info on URLs.
415              
416             Also, the host, username, password, proxy firewall and socks firewall can be preset and then omitted during the method call. This saves a lot of code writing if you are going to make multiple calls to the same host. If a method explicitly names any of those strings, it overrides presets. If username and password are not specified anywhere, FTP is done anonymously.
417              
418             $ftp->host(HOST);
419             $ftp->user(USER);
420             $ftp->pass(PASS);
421             $ftp->fire(FIRE);
422             $ftp->socks(SOCKS);
423              
424             =over
425              
426             =item waitreply
427              
428             $ftp->waitreply(BOOLEAN);
429              
430             If you don't want MacPerl to wait for Anarchie to finish what it is doing, then call this with the value 0. You can change it back to 1 if you do want it to wait. The initial setting is 1.
431              
432             =item fetch *
433              
434             $ftp->fetch(FILENAME [, PATH, BINARY, TYPE, HOST, USER, PASS, FIRE, SOCKS]);
435             $ftp->fetchURL(FILENAME [, URL, BINARY, TYPE, FIRE, SOCKS]);
436              
437             Fetches file and saves to FILENAME on local drive. BINARY is boolean for whether file is binary or ascii. TYPE is the creator code to link file to. NOTE: for Fetch, FILENAME must be an existing directory name, NOT a filename. For Anarchie, FILENAME must be a file if the fetched item is a file or a directory if the fetched item is a directory. Anarchie will create FILENAME on the local drive if it does not exist.
438              
439             =item store *
440              
441             $ftp->store(FILENAME [, PATH, BINARY, HOST, USER, PASS, FIRE, SOCKS]);
442             $ftp->storeURL(FILENAME [, URL, BINARY, FIRE, SOCKS]);
443              
444             Stores file FIELNAME from local drive to remote location specified.
445              
446             =item rename *
447              
448             $ftp->rename(NEWNAME [, PATH, HOST, USER, PASS, FIRE, SOCKS]);
449             $ftp->renameURL(NEWNAME [, URL, FIRE, SOCKS]);
450              
451             Renames file NEWNAME to value in PATH or URL.
452              
453             =item remove *
454              
455             $ftp->remove([PATH, HOST, USER, PASS, FIRE, SOCKS]);
456             $ftp->removeURL([URL, FIRE, SOCKS]);
457              
458             Removes file/directory specified in PATH or URL.
459              
460             =item mkdir *
461              
462             $ftp->mkdir([PATH, HOST, USER, PASS, FIRE, SOCKS]);
463             $ftp->mkdirURL([URL, FIRE, SOCKS]);
464              
465             Make directory specified in PATH or URL.
466              
467             =item sendcommand *
468              
469             $ftp->sendcommand([PATH, HOST, USER, PASS, FIRE, SOCKS]);
470             $ftp->sendcommandURL([URL, FIRE, SOCKS]);
471              
472             Send raw FTP command.
473              
474             =item index *
475              
476             $ftp->index([PATH, HOST, USER, PASS, FIRE, SOCKS]);
477             $ftp->indexURL([URL, FIRE, SOCKS]);
478              
479             Display index listing. SITE INDEX command must be implemented on host.
480              
481             =item list *
482              
483             $ftp->list(FILENAME, [PATH, HOST, USER, PASS, FIRE, SOCKS]);
484             $ftp->listURL(FILENAME, [URL, FIRE, SOCKS]);
485              
486             List files in a directory, put into file FILENAME. Fetch apparently only lists to the screen, while Anarchie lists to a file. For Fetch, just put any old text in place of FILENAME and it should work just fine.
487              
488             =item nlist
489              
490             $ftp->nlist(FILENAME, [PATH, HOST, USER, PASS, FIRE, SOCKS]);
491             $ftp->nlistURL(FILENAME, [URL, FIRE, SOCKS]);
492              
493             List names of files in a directory, put into file FILENAME.
494              
495             =head2 Anarchie Suite, Part Deux
496              
497             NOTE: These methods are NOT supported at all by Fetch.
498              
499             =item find
500              
501             $ftp->find(FILENAME [, SERVER, MAX, CASE, REGEX, URL]);
502              
503             Find file containing text FILENAME in Archie SERVER with maximum matches MAX. CASE is boolean (0 or 1) for case sensitive. REGEX is 0, 1 or 2 for denoting that FILENAME is a substring, pattern, or regular expression.
504              
505             =item macsearch
506              
507             $ftp->macsearch(FILENAME);
508              
509             Find Mac file containing text FILENAME on Ambrosia's Mac server.
510              
511             =item others
512              
513             $ftp->showtranscript;
514             $ftp->showarchie;
515             $ftp->showget;
516             $ftp->updateserverlist;
517             $ftp->showlog;
518             $ftp->showmacsearch;
519             $ftp->showtips;
520              
521             =item geturl
522              
523             $ftp->geturl(URL [, FILENAME]);
524              
525             =back
526              
527             =head1 HISTORY
528              
529             =over 4
530              
531             =item v.1.4, January 3, 1998
532              
533             Basic cleanup. Requires MacPerl 5.1.4r4 or better now.
534              
535             =item v.1.4, November 3, 1997
536              
537             Pulled out main functions as autosplit/autoload files. Before using, you must run a script such as the following, in order to AutoSplit the routines:
538              
539             #!perl -w
540             use AutoSplit;
541             $dir = 'HD:MacPerl:site_perl';
542             autosplit("$dir:Mac:Apps:Anarchie.pm","$dir:auto",0,1,1);
543              
544             This also means that the C class is no longer aliased to simply C.
545              
546             =item v.1.3, October 15, 1997
547              
548             Added C method. Fixed error catching. Erorrs still are not descriptive, but now they are reported. :-)
549              
550             =item v.1.2, October 13, 1997
551              
552             Get app launching from Mac::Apps::Launch, fixed descriptor disposing.
553              
554             =item v.1.1 May 4, 1997
555              
556             Whoops, fixed something I broke in the AEPutParamDesc stuff.
557              
558             =item v.1.0 May 4, 1997
559              
560             Finally got around to cleaning it up. Only minor changes.
561              
562             =item v.0.2 March 20, 1997
563              
564             First 'public' beta.
565              
566             =back
567              
568             =head1 BUGS
569              
570             =over
571              
572             =item regex find
573              
574             Still having problems with the substring/pattern/regex option on L<"find">. I am not sure what the problem is.
575              
576             =back
577              
578             =head1 SEE ALSO
579              
580             =over
581              
582             =item Anarchie Home Page
583              
584             http://www.stairways.com/anarchie/index.html
585              
586             =back
587              
588             =head1 AUTHOR
589              
590             Chris Nandor Fpudge@pobox.comE>
591             http://pudge.net/
592              
593             Copyright (c) 1998 Chris Nandor. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Please see the Perl Artistic License.
594              
595             =head1 VERSION
596              
597             Version 1.50 (03 January 1998)
598              
599             =cut
600              
601             __END__