line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
# $Id: Admin.pm,v 1.24 2008/11/07 00:46:29 Martin Exp $ |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
=head1 NAME |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
Win32::IIS::Admin - Administer Internet Information Service on Windows |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 SYNOPSIS |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use Win32::IIS::Admin; |
11
|
|
|
|
|
|
|
my $oWIA = new Win32::IIS::Admin; |
12
|
|
|
|
|
|
|
$oWIA->create_virtual_dir(-dir_name => 'cgi-bin', |
13
|
|
|
|
|
|
|
-path => 'C:\wwwroot\cgi-bin', |
14
|
|
|
|
|
|
|
-executable => 1); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 DESCRIPTION |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Enables you to do a few administration tasks on a IIS webserver. |
19
|
|
|
|
|
|
|
Currently only works for IIS 5 (i.e. Windows 2000 Server). |
20
|
|
|
|
|
|
|
Currently there are very few tasks it can do. |
21
|
|
|
|
|
|
|
On non-Windows systems, the module can be loaded, but |
22
|
|
|
|
|
|
|
new() always returns undef. |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 METHODS |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=over |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=cut |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
package Win32::IIS::Admin; |
31
|
|
|
|
|
|
|
|
32
|
4
|
|
|
4
|
|
131297
|
use strict; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
136
|
|
33
|
4
|
|
|
4
|
|
23
|
use warnings; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
103
|
|
34
|
|
|
|
|
|
|
|
35
|
4
|
|
|
4
|
|
3419
|
use Data::Dumper; |
|
4
|
|
|
|
|
30753
|
|
|
4
|
|
|
|
|
243
|
|
36
|
4
|
|
|
4
|
|
3526
|
use File::Spec::Functions; |
|
4
|
|
|
|
|
3689
|
|
|
4
|
|
|
|
|
358
|
|
37
|
4
|
|
|
4
|
|
3495
|
use IO::String; |
|
4
|
|
|
|
|
18924
|
|
|
4
|
|
|
|
|
136
|
|
38
|
|
|
|
|
|
|
|
39
|
4
|
|
|
4
|
|
37
|
use constant DEBUG => 0; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
285
|
|
40
|
4
|
|
|
4
|
|
20
|
use constant DEBUG_EXEC => 0; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
153
|
|
41
|
4
|
|
|
4
|
|
20
|
use constant DEBUG_EXT => 0; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
148
|
|
42
|
4
|
|
|
4
|
|
20
|
use constant DEBUG_FETCH => 0; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
139
|
|
43
|
4
|
|
|
4
|
|
53
|
use constant DEBUG_PARSE => 0; |
|
4
|
|
|
|
|
32
|
|
|
4
|
|
|
|
|
183
|
|
44
|
4
|
|
|
4
|
|
20
|
use constant DEBUG_SET => 0; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
16488
|
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
our |
47
|
|
|
|
|
|
|
$VERSION = do { my @r = (q$Revision: 1.24 $ =~ /\d+/g); sprintf "%d."."%03d" x $#r, @r }; |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=item new |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
Returns a new Win32::IIS::Admin object, or undef if there is any problem |
52
|
|
|
|
|
|
|
(such as, IIS is not installed on the local machine!). |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=cut |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub new |
57
|
|
|
|
|
|
|
{ |
58
|
4
|
|
|
4
|
1
|
681
|
my ($class, %parameters) = @_; |
59
|
4
|
50
|
|
|
|
27
|
if ($^O ne 'MSWin32') |
60
|
|
|
|
|
|
|
{ |
61
|
4
|
|
|
|
|
6
|
DEBUG && print STDERR " DDD this is not windows\n"; |
62
|
4
|
|
|
|
|
17
|
return undef; |
63
|
|
|
|
|
|
|
} # if |
64
|
|
|
|
|
|
|
# Find out where IIS is installed. |
65
|
|
|
|
|
|
|
# Find the cscript executable: |
66
|
0
|
|
|
|
|
|
my (@asTry, $sCscript); |
67
|
0
|
|
|
|
|
|
push @asTry, catfile($ENV{windir}, 'system32', 'cscript.exe'); |
68
|
0
|
|
|
|
|
|
foreach my $sTry (@asTry) |
69
|
|
|
|
|
|
|
{ |
70
|
0
|
0
|
|
|
|
|
if (-f $sTry) |
71
|
|
|
|
|
|
|
{ |
72
|
0
|
|
|
|
|
|
$sCscript = $sTry; |
73
|
0
|
|
|
|
|
|
last; |
74
|
|
|
|
|
|
|
} # if |
75
|
|
|
|
|
|
|
} # foreach |
76
|
0
|
|
|
|
|
|
DEBUG && print STDERR " DDD cscript is ==$sCscript==\n"; |
77
|
0
|
0
|
|
|
|
|
if ($sCscript eq '') |
78
|
|
|
|
|
|
|
{ |
79
|
0
|
|
|
|
|
|
warn "can not find executable cscript\n"; |
80
|
0
|
|
|
|
|
|
return undef; |
81
|
|
|
|
|
|
|
} # if |
82
|
|
|
|
|
|
|
# Get a list of logical drives: |
83
|
0
|
|
|
|
|
|
eval q{use Win32API::File qw( :DRIVE_ )}; |
84
|
0
|
0
|
|
|
|
|
if ($@) |
85
|
|
|
|
|
|
|
{ |
86
|
0
|
|
|
|
|
|
DEBUG && warn " EEE can not use Win32API::File because $@\n"; |
87
|
0
|
|
|
|
|
|
return undef; |
88
|
|
|
|
|
|
|
} # if |
89
|
0
|
|
|
|
|
|
my @asDrive = Win32API::File::getLogicalDrives(); |
90
|
0
|
|
|
|
|
|
DEBUG && print STDERR " DDD logical drives are: @asDrive\n"; |
91
|
|
|
|
|
|
|
# See which ones are hard drives: |
92
|
0
|
|
|
|
|
|
my @asHD; |
93
|
0
|
|
|
|
|
|
foreach my $sDrive (@asDrive) |
94
|
|
|
|
|
|
|
{ |
95
|
0
|
|
|
|
|
|
my $sType = Win32API::File::GetDriveType($sDrive); |
96
|
0
|
0
|
|
|
|
|
push @asHD, $sDrive if ($sType eq eval'DRIVE_FIXED'); |
97
|
|
|
|
|
|
|
} # foreach |
98
|
0
|
|
|
|
|
|
DEBUG && print STDERR " DDD hard drives are: @asHD\n"; |
99
|
|
|
|
|
|
|
# Find the adsutil.vbs script: |
100
|
0
|
|
|
|
|
|
my $sAdsutil = ''; |
101
|
0
|
|
|
|
|
|
@asTry = (); |
102
|
|
|
|
|
|
|
# This is the default location, according to microsoft.com: |
103
|
0
|
|
|
|
|
|
push @asTry, catdir($ENV{windir}, qw( System32 Inetsrv AdminSamples )); |
104
|
|
|
|
|
|
|
# This is where I find it on my old IIS installation: |
105
|
0
|
|
|
|
|
|
push @asTry, map { catdir($_, qw( inetpub AdminScripts )) } @asHD; |
|
0
|
|
|
|
|
|
|
106
|
0
|
|
|
|
|
|
@asTry = map { catfile($_, 'adsutil.vbs') } @asTry; |
|
0
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
foreach my $sTry (@asTry) |
108
|
|
|
|
|
|
|
{ |
109
|
0
|
0
|
|
|
|
|
if (-f $sTry) |
110
|
|
|
|
|
|
|
{ |
111
|
0
|
|
|
|
|
|
$sAdsutil = $sTry; |
112
|
0
|
|
|
|
|
|
last; |
113
|
|
|
|
|
|
|
} # if |
114
|
|
|
|
|
|
|
} # foreach |
115
|
0
|
|
|
|
|
|
DEBUG && print STDERR " DDD adsutil is ==$sAdsutil==\n"; |
116
|
0
|
0
|
|
|
|
|
if ($sAdsutil eq '') |
117
|
|
|
|
|
|
|
{ |
118
|
0
|
|
|
|
|
|
warn "can not find adsutil.vbs\n"; |
119
|
0
|
|
|
|
|
|
return undef; |
120
|
|
|
|
|
|
|
} # if |
121
|
|
|
|
|
|
|
# Now we have all the info we need to get started: |
122
|
0
|
|
|
|
|
|
my %hash = ( |
123
|
|
|
|
|
|
|
adsutil => $sAdsutil, |
124
|
|
|
|
|
|
|
cscript => $sCscript, |
125
|
|
|
|
|
|
|
); |
126
|
0
|
|
0
|
|
|
|
my $self = bless (\%hash, ref ($class) || $class); |
127
|
0
|
|
|
|
|
|
return $self; |
128
|
|
|
|
|
|
|
} # new |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
# Not published. |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub _config_set_value |
134
|
|
|
|
|
|
|
{ |
135
|
0
|
|
|
0
|
|
|
my $self = shift; |
136
|
0
|
|
|
|
|
|
local $" = ','; |
137
|
0
|
|
|
|
|
|
DEBUG_SET && print STDERR " DDD _config_set_value(@_)\n"; |
138
|
|
|
|
|
|
|
# Required arg1 = section: |
139
|
0
|
|
0
|
|
|
|
my $sSection = shift || ''; |
140
|
0
|
0
|
|
|
|
|
return unless ($sSection ne ''); |
141
|
|
|
|
|
|
|
# Required arg2 = parameter name: |
142
|
0
|
|
0
|
|
|
|
my $sParameter = shift || ''; |
143
|
0
|
0
|
|
|
|
|
return unless ($sParameter ne ''); |
144
|
|
|
|
|
|
|
# Remaining arg(s) will be taken as the value(s) for this parameter. |
145
|
0
|
0
|
|
|
|
|
return unless @_; |
146
|
0
|
|
|
|
|
|
my $sRes = $self->_execute_script('adsutil', 'SET', "$sSection/$sParameter", map { qq/"$_"/ } @_); |
|
0
|
|
|
|
|
|
|
147
|
0
|
0
|
|
|
|
|
if ($sRes =~ m!ERROR TRYING TO GET THE SCHEMA!i) |
148
|
|
|
|
|
|
|
{ |
149
|
|
|
|
|
|
|
# Unknown parameter name: |
150
|
0
|
|
|
|
|
|
$self->_add_error($sRes); |
151
|
0
|
|
|
|
|
|
return; |
152
|
|
|
|
|
|
|
} # if |
153
|
0
|
0
|
|
|
|
|
if ($sRes =~ m!ERROR TRYING TO GET THE OBJECT!i) |
154
|
|
|
|
|
|
|
{ |
155
|
|
|
|
|
|
|
# Section does not exist: |
156
|
0
|
|
|
|
|
|
$self->_add_error($sRes); |
157
|
0
|
|
|
|
|
|
return; |
158
|
|
|
|
|
|
|
} # if |
159
|
0
|
0
|
|
|
|
|
if ($sRes =~ m!ERROR TRYING TO SET THE PROPERTY!i) |
160
|
|
|
|
|
|
|
{ |
161
|
|
|
|
|
|
|
# Type mismatch |
162
|
0
|
|
|
|
|
|
$self->_add_error($sRes); |
163
|
0
|
|
|
|
|
|
return; |
164
|
|
|
|
|
|
|
} # if |
165
|
|
|
|
|
|
|
# Assume success at this point: |
166
|
0
|
|
|
|
|
|
return ''; |
167
|
|
|
|
|
|
|
} # _config_set_value |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
# Not published. |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub _config_get_value |
173
|
|
|
|
|
|
|
{ |
174
|
0
|
|
|
0
|
|
|
my $self = shift; |
175
|
0
|
|
|
|
|
|
local $" = ','; |
176
|
0
|
|
|
|
|
|
DEBUG_FETCH && print STDERR " DDD _config_get_value(@_)\n"; |
177
|
|
|
|
|
|
|
# Required arg1 = section: |
178
|
0
|
|
0
|
|
|
|
my $sSection = shift || ''; |
179
|
0
|
0
|
|
|
|
|
return unless ($sSection ne ''); |
180
|
|
|
|
|
|
|
# Required arg2 = parameter name: |
181
|
0
|
|
0
|
|
|
|
my $sParameter = shift || ''; |
182
|
0
|
0
|
|
|
|
|
return unless ($sParameter ne ''); |
183
|
0
|
|
|
|
|
|
my $sRes = $self->_execute_script('adsutil', 'GET', "$sSection/$sParameter"); |
184
|
0
|
0
|
|
|
|
|
if ($sRes =~ m!ERROR TRYING TO GET!i) |
185
|
|
|
|
|
|
|
{ |
186
|
0
|
|
|
|
|
|
$self->_add_error($sRes); |
187
|
0
|
|
|
|
|
|
return; |
188
|
|
|
|
|
|
|
} # if |
189
|
0
|
|
|
|
|
|
my $oIS = IO::String->new($sRes); |
190
|
0
|
|
|
|
|
|
my $sLine = <$oIS>; |
191
|
0
|
0
|
|
|
|
|
if ($sLine =~ m!\A(\S+)\s+:\s+\((\S+)\)\s*(.+)\Z!) |
192
|
|
|
|
|
|
|
{ |
193
|
0
|
|
|
|
|
|
my ($sProperty, $sType, $sValue) = ($1, $2, $3); |
194
|
0
|
|
|
|
|
|
my @asValue; |
195
|
0
|
0
|
|
|
|
|
if ($sType eq 'STRING') |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
196
|
|
|
|
|
|
|
{ |
197
|
|
|
|
|
|
|
# Protect backslashes, in case this value is a dir/file path: |
198
|
0
|
|
|
|
|
|
$sValue =~ s!\\!/!g; |
199
|
0
|
|
|
|
|
|
$sValue = eval $sValue; |
200
|
0
|
|
|
|
|
|
return $sValue; |
201
|
|
|
|
|
|
|
} # if STRING |
202
|
|
|
|
|
|
|
elsif ($sType eq 'INTEGER') |
203
|
|
|
|
|
|
|
{ |
204
|
0
|
|
|
|
|
|
$sValue = eval $sValue; |
205
|
0
|
|
|
|
|
|
return $sValue; |
206
|
|
|
|
|
|
|
} # if INTEGER |
207
|
|
|
|
|
|
|
elsif ($sType eq 'EXPANDSZ') |
208
|
|
|
|
|
|
|
{ |
209
|
|
|
|
|
|
|
# Protect backslashes, this value is a dir/file path: |
210
|
0
|
|
|
|
|
|
$sValue =~ s!\\!/!g; |
211
|
0
|
|
|
|
|
|
$sValue = eval $sValue; |
212
|
0
|
|
|
|
|
|
$sValue =~ s!%([^%]+)%!$ENV{$1}!g; |
213
|
0
|
|
|
|
|
|
return $sValue; |
214
|
|
|
|
|
|
|
} # if INTEGER |
215
|
|
|
|
|
|
|
elsif ($sType eq 'BOOLEAN') |
216
|
|
|
|
|
|
|
{ |
217
|
0
|
|
|
|
|
|
$sValue = ($sValue eq 'True'); |
218
|
0
|
|
|
|
|
|
return $sValue; |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
elsif ($sType eq 'LIST') |
221
|
|
|
|
|
|
|
{ |
222
|
0
|
|
|
|
|
|
my @asValue = (); |
223
|
0
|
0
|
|
|
|
|
if ($sValue =~ m!(\d+)\sItems!) |
224
|
|
|
|
|
|
|
{ |
225
|
0
|
|
|
|
|
|
my $iCount = 0 + $1; |
226
|
|
|
|
|
|
|
ITEM_OF_LIST: |
227
|
0
|
|
|
|
|
|
for (1..$iCount) |
228
|
|
|
|
|
|
|
{ |
229
|
0
|
|
|
|
|
|
my $sSubline = <$oIS>; |
230
|
0
|
0
|
|
|
|
|
if ($sSubline =~ m!\A\s+\042([^"]+)\042!) # |
231
|
|
|
|
|
|
|
{ |
232
|
0
|
|
|
|
|
|
push @asValue, $1; |
233
|
|
|
|
|
|
|
} # if |
234
|
|
|
|
|
|
|
else |
235
|
|
|
|
|
|
|
{ |
236
|
0
|
|
|
|
|
|
print STDERR " WWW list item does not look like string, in line ==$sLine==\n"; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
} # for ITEM_OF_LIST |
239
|
|
|
|
|
|
|
} # if |
240
|
|
|
|
|
|
|
else |
241
|
|
|
|
|
|
|
{ |
242
|
0
|
|
|
|
|
|
print STDERR " WWW found LIST type but not item count at line ==$sLine==\n"; |
243
|
0
|
|
|
|
|
|
next LINE_OF_CONFIG; |
244
|
|
|
|
|
|
|
} |
245
|
0
|
|
|
|
|
|
return \@asValue; |
246
|
|
|
|
|
|
|
} # if LIST |
247
|
|
|
|
|
|
|
elsif ($sType eq 'MimeMapList') |
248
|
|
|
|
|
|
|
{ |
249
|
0
|
|
|
|
|
|
my %hash; |
250
|
0
|
|
|
|
|
|
while ($sValue =~ m!"(\S+)"!g) |
251
|
|
|
|
|
|
|
{ |
252
|
0
|
|
|
|
|
|
my ($sExt, $sType) = split(',', $1); |
253
|
0
|
|
|
|
|
|
$hash{$sExt} = $sType; |
254
|
|
|
|
|
|
|
} # while |
255
|
0
|
|
|
|
|
|
return \%hash; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
else |
258
|
|
|
|
|
|
|
{ |
259
|
0
|
|
|
|
|
|
print STDERR " EEE unknown type =$sType=\n"; |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
} # if PropertyName : (TYPE) value |
262
|
|
|
|
|
|
|
else |
263
|
|
|
|
|
|
|
{ |
264
|
0
|
|
|
|
|
|
DEBUG_PARSE && print STDERR " WWW unparsable line ==$sLine==\n"; |
265
|
|
|
|
|
|
|
} |
266
|
0
|
|
|
|
|
|
return; |
267
|
|
|
|
|
|
|
} # _config_get_value |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=item iis_version |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Returns the version of IIS found on this machine, |
273
|
|
|
|
|
|
|
in a decimal number format like "6.0". |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=cut |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub iis_version |
278
|
|
|
|
|
|
|
{ |
279
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
280
|
0
|
0
|
|
|
|
|
if (! defined $self->{_iss_version_}) |
281
|
|
|
|
|
|
|
{ |
282
|
0
|
|
|
|
|
|
my $iMajor = $self->_config_get_value('/W3SVC/Info', |
283
|
|
|
|
|
|
|
'MajorIIsVersionNumber'); |
284
|
0
|
|
|
|
|
|
my $iMinor = $self->_config_get_value('/W3SVC/Info', |
285
|
|
|
|
|
|
|
'MinorIIsVersionNumber'); |
286
|
0
|
|
|
|
|
|
$self->{_iss_version_} = "$iMajor.$iMinor"; |
287
|
|
|
|
|
|
|
} # if |
288
|
0
|
|
|
|
|
|
return $self->{_iss_version_}; |
289
|
|
|
|
|
|
|
} # iis_version |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=item get_timeout |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
Returns the IIS timeout value. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=cut |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
sub get_timeout |
299
|
|
|
|
|
|
|
{ |
300
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
301
|
0
|
|
|
|
|
|
$self->_config_get_value('/W3SVC', 'CGITimeout'); |
302
|
|
|
|
|
|
|
} # set_timeout |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
=item set_timeout |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
Given an integer, |
308
|
|
|
|
|
|
|
sets the IIS timeout to that value. |
309
|
|
|
|
|
|
|
Does no checking on the value passed in, so use carefully! |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=cut |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
sub set_timeout |
314
|
|
|
|
|
|
|
{ |
315
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
316
|
|
|
|
|
|
|
# Required arg1 = an integer: |
317
|
0
|
|
|
|
|
|
my $iArg = shift() + 0; |
318
|
0
|
|
|
|
|
|
$self->_config_set_value('/W3SVC', 'CGITimeout', $iArg); |
319
|
|
|
|
|
|
|
} # set_timeout |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=item path_of_virtual_dir |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
Given the name of a virtual directory (or 'ROOT'), |
325
|
|
|
|
|
|
|
returns the absolute full path of where the physical files are located. |
326
|
|
|
|
|
|
|
Returns undef if there is no virtual directory matching the name given. |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=cut |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
sub path_of_virtual_dir |
331
|
|
|
|
|
|
|
{ |
332
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
333
|
0
|
|
0
|
|
|
|
my $sDir = shift || ''; |
334
|
0
|
0
|
|
|
|
|
if ($sDir eq '') |
335
|
|
|
|
|
|
|
{ |
336
|
0
|
|
|
|
|
|
$self->_add_error(qq(Argument is required on path_of_virtual_dir.)); |
337
|
0
|
|
|
|
|
|
return; |
338
|
|
|
|
|
|
|
} # if |
339
|
|
|
|
|
|
|
# We cravenly refuse to modify anything but the default #1 webserver: |
340
|
0
|
|
|
|
|
|
my $sWebsite = 1; |
341
|
0
|
0
|
|
|
|
|
if ($sDir eq 'ROOT') |
342
|
|
|
|
|
|
|
{ |
343
|
0
|
|
|
|
|
|
goto ROOT; |
344
|
|
|
|
|
|
|
} # if |
345
|
0
|
|
|
|
|
|
my $sVersion = $self->iis_version; |
346
|
0
|
0
|
|
|
|
|
if ("6.0" le $sVersion) |
347
|
|
|
|
|
|
|
{ |
348
|
0
|
|
|
|
|
|
my $sSection = join('/', 'W3SVC', $sWebsite); |
349
|
0
|
|
0
|
|
|
|
my $sRes .= $self->_execute_script('iisvdir', '/query', $sSection) || ''; |
350
|
0
|
0
|
|
|
|
|
if ($sRes =~ m!Error!) |
351
|
|
|
|
|
|
|
{ |
352
|
0
|
|
|
|
|
|
$self->_add_error($sRes); |
353
|
0
|
|
|
|
|
|
return; |
354
|
|
|
|
|
|
|
} # if |
355
|
0
|
|
|
|
|
|
DEBUG_FETCH && print STDERR " DDD iisvdir returned:", $sRes; |
356
|
0
|
|
|
|
|
|
my $oIS = IO::String->new($sRes); |
357
|
|
|
|
|
|
|
FIND_DIVIDER_LINE: |
358
|
0
|
|
|
|
|
|
while (my $sLine = <$oIS>) |
359
|
|
|
|
|
|
|
{ |
360
|
0
|
0
|
|
|
|
|
last if ($sLine =~ m!={22}!); |
361
|
|
|
|
|
|
|
} # while FIND_DIVIDER_LINE |
362
|
|
|
|
|
|
|
VIR_DIR_LINE: |
363
|
0
|
|
|
|
|
|
while (my $sLine = <$oIS>) |
364
|
|
|
|
|
|
|
{ |
365
|
0
|
|
|
|
|
|
chomp $sLine; |
366
|
0
|
|
|
|
|
|
my ($sVirDir, $sPath) = split(/ +/, $sLine); |
367
|
0
|
|
|
|
|
|
DEBUG_FETCH && print STDERR " DDD found virdir=$sVirDir==>$sPath\n"; |
368
|
|
|
|
|
|
|
# Question: do we want to match the vir-dir name |
369
|
|
|
|
|
|
|
# case-INsensitively? |
370
|
0
|
0
|
|
|
|
|
if ($sVirDir =~ m!\A/?$sDir\Z!) |
371
|
|
|
|
|
|
|
{ |
372
|
0
|
|
|
|
|
|
return $sPath; |
373
|
|
|
|
|
|
|
} # if |
374
|
|
|
|
|
|
|
} # while VIR_DIR_LINE |
375
|
0
|
|
|
|
|
|
return ''; |
376
|
|
|
|
|
|
|
} # if |
377
|
|
|
|
|
|
|
ROOT: |
378
|
|
|
|
|
|
|
# If we get here, we must be using IIS 5.0: |
379
|
0
|
|
|
|
|
|
my $sSection = join('/', '', 'W3SVC', $sWebsite, 'ROOT'); |
380
|
0
|
0
|
|
|
|
|
if ($sDir !~ m!\AROOT\Z!i) |
381
|
|
|
|
|
|
|
{ |
382
|
0
|
|
|
|
|
|
$sSection .= "/$sDir"; |
383
|
|
|
|
|
|
|
} # if |
384
|
0
|
|
0
|
|
|
|
my $sPath = $self->_config_get_value($sSection, 'Path') || ''; |
385
|
0
|
|
|
|
|
|
return $sPath; |
386
|
|
|
|
|
|
|
} # path_of_virtual_dir |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
=item create_virtual_dir |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
Given the following named arguments, create a virtual directory on the |
392
|
|
|
|
|
|
|
default #1 server on the local machine's IIS instance. |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
=over |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=item -dir_name => 'virtual' |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
This is the virtual directory name as it will appear to your browsers. |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
=item -path => 'C:/local/path' |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
This is the full path the the actual location of the data files. |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=item -executable => 1 |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
Give this argument if your virtual directory holds executable programs. |
407
|
|
|
|
|
|
|
Default is 0 (NOT executable). |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=back |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
=cut |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
sub create_virtual_dir |
414
|
|
|
|
|
|
|
{ |
415
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
416
|
0
|
|
|
|
|
|
my %hArgs = @_; |
417
|
0
|
|
0
|
|
|
|
$hArgs{-dir_name} ||= ''; |
418
|
0
|
0
|
|
|
|
|
if ($hArgs{-dir_name} eq '') |
419
|
|
|
|
|
|
|
{ |
420
|
0
|
|
|
|
|
|
$self->_add_error(qq(Argument -dir_name is required on create_virtual_dir.)); |
421
|
0
|
|
|
|
|
|
return; |
422
|
|
|
|
|
|
|
} # if |
423
|
0
|
|
0
|
|
|
|
$hArgs{-path} ||= ''; |
424
|
0
|
0
|
|
|
|
|
if ($hArgs{-path} eq '') |
425
|
|
|
|
|
|
|
{ |
426
|
0
|
|
|
|
|
|
$self->_add_error(qq(Argument -path is required on create_virtual_dir.)); |
427
|
0
|
|
|
|
|
|
return; |
428
|
|
|
|
|
|
|
} # if |
429
|
0
|
|
0
|
|
|
|
$hArgs{-executable} ||= 0; |
430
|
|
|
|
|
|
|
# print STDERR Dumper(\%hArgs); |
431
|
|
|
|
|
|
|
# We cravenly refuse to modify anything but the default #1 webserver: |
432
|
0
|
|
|
|
|
|
my $sWebsite = 1; |
433
|
|
|
|
|
|
|
# First, see if a virtual directory with the same name is already |
434
|
|
|
|
|
|
|
# exists: |
435
|
0
|
|
|
|
|
|
my $sPath = $self->path_of_virtual_dir($hArgs{-dir_name}); |
436
|
0
|
|
|
|
|
|
my $sRes = ''; |
437
|
0
|
0
|
|
|
|
|
if ($sPath ne '') |
438
|
|
|
|
|
|
|
{ |
439
|
|
|
|
|
|
|
# There is already a virtual directory with that name. Create a |
440
|
|
|
|
|
|
|
# sensible error message: |
441
|
0
|
0
|
|
|
|
|
if ($sPath ne $hArgs{-path}) |
442
|
|
|
|
|
|
|
{ |
443
|
0
|
|
|
|
|
|
$self->_add_error(qq(There is already a virtual directory named '$hArgs{-dir_name}', but it points to $sPath)); |
444
|
0
|
|
|
|
|
|
return; |
445
|
|
|
|
|
|
|
} # if |
446
|
0
|
|
|
|
|
|
$self->_add_error(qq(There is already a virtual directory named '$hArgs{-dir_name}' pointing to $sPath)); |
447
|
|
|
|
|
|
|
# Fall through and (try to) set the access rules. |
448
|
|
|
|
|
|
|
} # if |
449
|
|
|
|
|
|
|
else |
450
|
|
|
|
|
|
|
{ |
451
|
|
|
|
|
|
|
# Virtual dir not there, create it: |
452
|
0
|
|
|
|
|
|
my @asArgs = ('mkwebdir', |
453
|
|
|
|
|
|
|
qq(-v "$hArgs{-dir_name}","$hArgs{-path}"), |
454
|
|
|
|
|
|
|
qq(-w $sWebsite), |
455
|
|
|
|
|
|
|
# qq(-c $sComputer), |
456
|
|
|
|
|
|
|
); |
457
|
0
|
0
|
|
|
|
|
if ('6.0' le $self->iis_version) |
458
|
|
|
|
|
|
|
{ |
459
|
0
|
|
|
|
|
|
@asArgs = ('iisvdir', '/create', "W3SVC/$sWebsite", |
460
|
|
|
|
|
|
|
$hArgs{-dir_name}, $hArgs{-path}); |
461
|
|
|
|
|
|
|
} # if |
462
|
0
|
|
0
|
|
|
|
$sRes .= $self->_execute_script(@asArgs) || ''; |
463
|
0
|
0
|
|
|
|
|
if ($sRes =~ m!Error!) |
464
|
|
|
|
|
|
|
{ |
465
|
0
|
|
|
|
|
|
$self->_add_error($sRes); |
466
|
0
|
|
|
|
|
|
return; |
467
|
|
|
|
|
|
|
} # if |
468
|
|
|
|
|
|
|
} # else |
469
|
|
|
|
|
|
|
# Whether the dir was already defined or not, try to set permissions |
470
|
|
|
|
|
|
|
# as requested: |
471
|
0
|
0
|
|
|
|
|
if ($hArgs{-executable}) |
472
|
|
|
|
|
|
|
{ |
473
|
0
|
|
|
|
|
|
my $sSection = join('/', '', 'W3SVC', $sWebsite, 'Root', $hArgs{-dir_name}); |
474
|
0
|
0
|
|
|
|
|
if ('6.0' le $self->iis_version) |
475
|
|
|
|
|
|
|
{ |
476
|
0
|
|
|
|
|
|
$sRes .= $self->_config_set_value($sSection, "AccessExecute", 'True'); |
477
|
|
|
|
|
|
|
# These seem to get turned on by default, but we'll make them |
478
|
|
|
|
|
|
|
# explicit anyway: |
479
|
0
|
|
|
|
|
|
$sRes .= $self->_config_set_value($sSection, "AccessScript", 'True'); |
480
|
0
|
|
|
|
|
|
$sRes .= $self->_config_set_value($sSection, "AccessRead", 'True'); |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
else |
483
|
|
|
|
|
|
|
{ |
484
|
|
|
|
|
|
|
# For some reason, the argument to chaccess has no leading slash |
485
|
|
|
|
|
|
|
# (some other scripts require leading slash): |
486
|
0
|
|
|
|
|
|
$sSection =~ s!\A/!!; |
487
|
|
|
|
|
|
|
# Set accesses for execution: |
488
|
0
|
|
|
|
|
|
$sRes .= $self->_execute_script('chaccess', |
489
|
|
|
|
|
|
|
-a => $sSection, |
490
|
|
|
|
|
|
|
qw( +execute +read +script ), |
491
|
|
|
|
|
|
|
); |
492
|
|
|
|
|
|
|
} # else |
493
|
|
|
|
|
|
|
} # if |
494
|
0
|
|
|
|
|
|
return $sRes; |
495
|
|
|
|
|
|
|
} # create_virtual_dir |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=item add_extension_restriction |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
Given the following named arguments, |
501
|
|
|
|
|
|
|
adds an "extension restriction" to |
502
|
|
|
|
|
|
|
the default #1 server on the local machine's IIS instance. |
503
|
|
|
|
|
|
|
Only works on IIS version 6.0. |
504
|
|
|
|
|
|
|
Note: no checking is done on the arguments, |
505
|
|
|
|
|
|
|
so it is possible to add bogus/duplicate/conflicting/illegal values to your IIS configuration. |
506
|
|
|
|
|
|
|
For more information, see |
507
|
|
|
|
|
|
|
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/79652e88-e713-4aa5-a88c-8e2bd6a2955e.mspx?mfr=true |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
=over |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=item -allow => <0, 1> |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
Send 0 if this is a "deny" rule; send 1 if this is an "allow" rule. |
514
|
|
|
|
|
|
|
The default is 0, deny. |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=item -path => |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
The full path to the executable or extension. |
519
|
|
|
|
|
|
|
This argument is required. |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
=item -groupid => |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
"A non-localizable string used to identify groups of extensions." |
524
|
|
|
|
|
|
|
Default is empty string. |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
=item -description => |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
"A localizable description of the extension." |
529
|
|
|
|
|
|
|
Default is empty string. |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
=back |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=cut |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
sub add_extension_restriction |
536
|
|
|
|
|
|
|
{ |
537
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
538
|
|
|
|
|
|
|
# print STDERR " DDD add_extension_restriction()\n"; |
539
|
0
|
0
|
|
|
|
|
if ($self->iis_version < 6.0) |
540
|
|
|
|
|
|
|
{ |
541
|
0
|
|
|
|
|
|
return; |
542
|
|
|
|
|
|
|
} # if |
543
|
|
|
|
|
|
|
# Set defaults, and get arguments: |
544
|
0
|
|
|
|
|
|
my %hArgs = ( |
545
|
|
|
|
|
|
|
-allow => 0, |
546
|
|
|
|
|
|
|
-groupid => '', |
547
|
|
|
|
|
|
|
-description => '', |
548
|
|
|
|
|
|
|
@_, |
549
|
|
|
|
|
|
|
# At present, this argument is not alterable: |
550
|
|
|
|
|
|
|
-deletable => 1, |
551
|
|
|
|
|
|
|
); |
552
|
|
|
|
|
|
|
# Verify all argument values: |
553
|
0
|
0
|
|
|
|
|
$hArgs{-allow} = 0 if ($hArgs{-allow} ne '1'); |
554
|
0
|
0
|
|
|
|
|
if (! exists $hArgs{-path}) |
555
|
|
|
|
|
|
|
{ |
556
|
0
|
|
|
|
|
|
$self->add_error("add_extension_restriction() called without required argument -path"); |
557
|
0
|
|
|
|
|
|
return; |
558
|
|
|
|
|
|
|
} # if |
559
|
|
|
|
|
|
|
# Construct the new Registry value: |
560
|
0
|
|
|
|
|
|
my $s = join(',', @hArgs{qw( -allow -path -deletable -groupid -description )}); |
561
|
|
|
|
|
|
|
# print STDERR " DDD s=$s=\n"; |
562
|
0
|
|
|
|
|
|
my $ra = $self->_config_get_value('/W3SVC', 'WebSvcExtRestrictionList'); |
563
|
|
|
|
|
|
|
# print STDERR " DDD before, list is ", Dumper($ra); |
564
|
0
|
|
|
|
|
|
push @{$ra}, $s; |
|
0
|
|
|
|
|
|
|
565
|
0
|
|
|
|
|
|
$self->_config_set_value('/W3SVC', 'WebSvcExtRestrictionList', @{$ra}); |
|
0
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
} # add_extension_restriction |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
=item remove_extension_restriction |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
Given the full path of an existing "extension restriction" in |
572
|
|
|
|
|
|
|
the default #1 server on the local machine's IIS instance, |
573
|
|
|
|
|
|
|
removes that restriction. |
574
|
|
|
|
|
|
|
If more than one restriction refers to the same path, |
575
|
|
|
|
|
|
|
they will all be removed. |
576
|
|
|
|
|
|
|
Only works on IIS version 6.0. |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
=cut |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
sub remove_extension_restriction |
581
|
|
|
|
|
|
|
{ |
582
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
583
|
|
|
|
|
|
|
# Required arg1 = path element: |
584
|
0
|
|
0
|
|
|
|
my $sPath = shift || ''; |
585
|
0
|
|
|
|
|
|
DEBUG_EXT && print STDERR " DDD remove_extension_restriction($sPath)\n"; |
586
|
0
|
|
|
|
|
|
$self->_remove_extension_restriction_by_elem($sPath, 1); |
587
|
|
|
|
|
|
|
} # remove_extension_restriction |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
=item remove_extension_restriction_group |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
Given the group ID of an existing "extension restriction" in |
593
|
|
|
|
|
|
|
the default #1 server on the local machine's IIS instance, |
594
|
|
|
|
|
|
|
removes all restrictions of that group. |
595
|
|
|
|
|
|
|
Only works on IIS version 6.0. |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
=cut |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
sub remove_extension_restriction_group |
600
|
|
|
|
|
|
|
{ |
601
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
602
|
|
|
|
|
|
|
# Required arg1 = path element: |
603
|
0
|
|
0
|
|
|
|
my $sValue = shift || ''; |
604
|
0
|
|
|
|
|
|
DEBUG_EXT && print STDERR " DDD remove_extension_restriction_group($sValue)\n"; |
605
|
0
|
|
|
|
|
|
$self->_remove_extension_restriction_by_elem($sValue, 3); |
606
|
|
|
|
|
|
|
} # remove_extension_restriction_group |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
sub _remove_extension_restriction_by_elem |
610
|
|
|
|
|
|
|
{ |
611
|
0
|
|
|
0
|
|
|
my $self = shift; |
612
|
|
|
|
|
|
|
# Required arg1 = path element: |
613
|
0
|
|
0
|
|
|
|
my $sValue = shift || ''; |
614
|
|
|
|
|
|
|
# Required arg2 = element number: |
615
|
0
|
|
|
|
|
|
my $iElem = shift; |
616
|
|
|
|
|
|
|
# Verify all argument values: |
617
|
0
|
0
|
|
|
|
|
return if ! defined($iElem); |
618
|
0
|
0
|
|
|
|
|
return if ($iElem < 0); |
619
|
0
|
0
|
|
|
|
|
return if (4 < $iElem); |
620
|
0
|
0
|
|
|
|
|
if ($sValue eq '') |
621
|
|
|
|
|
|
|
{ |
622
|
0
|
|
|
|
|
|
return; |
623
|
|
|
|
|
|
|
} # if |
624
|
0
|
0
|
|
|
|
|
if ($self->iis_version < 6.0) |
625
|
|
|
|
|
|
|
{ |
626
|
0
|
|
|
|
|
|
return; |
627
|
|
|
|
|
|
|
} # if |
628
|
0
|
|
|
|
|
|
my $rasOrig = $self->_config_get_value('/W3SVC', 'WebSvcExtRestrictionList'); |
629
|
0
|
|
|
|
|
|
DEBUG_EXT && print STDERR " DDD before, list is ", Dumper($rasOrig); |
630
|
0
|
|
|
|
|
|
my @asNew; |
631
|
0
|
|
|
|
|
|
foreach my $s (@$rasOrig) |
632
|
|
|
|
|
|
|
{ |
633
|
0
|
|
|
|
|
|
my @asElem = split(',', $s); |
634
|
0
|
0
|
0
|
|
|
|
if (($asElem[$iElem] || '') eq $sValue) |
635
|
|
|
|
|
|
|
{ |
636
|
0
|
|
|
|
|
|
DEBUG_EXT && print STDERR " DDD found one to remove\n"; |
637
|
|
|
|
|
|
|
} |
638
|
|
|
|
|
|
|
else |
639
|
|
|
|
|
|
|
{ |
640
|
0
|
|
|
|
|
|
push @asNew, $s; |
641
|
|
|
|
|
|
|
} |
642
|
|
|
|
|
|
|
} # foreach |
643
|
0
|
|
|
|
|
|
DEBUG_EXT && print STDERR " DDD after, list is ", Dumper(\@asNew); |
644
|
0
|
|
|
|
|
|
$self->_config_set_value('/W3SVC', 'WebSvcExtRestrictionList', @asNew); |
645
|
|
|
|
|
|
|
} # _remove_extension_restriction_by_elem |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
=item restart_iis |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
Restarts the IIS service on the local machine. |
651
|
|
|
|
|
|
|
Assumes that IISReset.exe is in your path. |
652
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
=cut |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
sub restart_iis |
656
|
|
|
|
|
|
|
{ |
657
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
658
|
|
|
|
|
|
|
# Assume that IISReset is in the path: |
659
|
0
|
|
|
|
|
|
my $sProg = 'IISReset'; |
660
|
0
|
|
|
|
|
|
my $iRes = system(qq'$sProg /RESTART'); |
661
|
0
|
0
|
|
|
|
|
if ($iRes) |
662
|
|
|
|
|
|
|
{ |
663
|
|
|
|
|
|
|
# print STDERR "$sProg failed: $!"; # for debugging |
664
|
0
|
|
|
|
|
|
$self->add_error("$sProg failed: $!"); |
665
|
|
|
|
|
|
|
} # if |
666
|
|
|
|
|
|
|
} # restart_iis |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=item errors |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
Method not implemented. |
672
|
|
|
|
|
|
|
In the current version, error messages are printed to STDERR as they occur. |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
=cut |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
sub errors |
677
|
0
|
|
|
0
|
1
|
|
{ |
678
|
|
|
|
|
|
|
} # errors |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
sub _add_error |
681
|
|
|
|
|
|
|
{ |
682
|
0
|
|
|
0
|
|
|
my $self = shift; |
683
|
0
|
|
|
|
|
|
print STDERR "@_\n"; |
684
|
|
|
|
|
|
|
} # add_error |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
sub _execute_script |
687
|
|
|
|
|
|
|
{ |
688
|
0
|
|
|
0
|
|
|
my $self = shift; |
689
|
0
|
|
|
|
|
|
my $sVBS = shift; |
690
|
|
|
|
|
|
|
# Figure out exactly which script the caller wants to execute. |
691
|
|
|
|
|
|
|
# Cscript needs the full path: |
692
|
0
|
|
|
|
|
|
my $sScriptFname; |
693
|
0
|
0
|
|
|
|
|
if (defined $self->{$sVBS}) |
694
|
|
|
|
|
|
|
{ |
695
|
|
|
|
|
|
|
# User requested a script which we have already located. |
696
|
0
|
|
|
|
|
|
$sScriptFname = $self->{$sVBS}; |
697
|
|
|
|
|
|
|
} |
698
|
|
|
|
|
|
|
else |
699
|
|
|
|
|
|
|
{ |
700
|
|
|
|
|
|
|
# adsutil.vbs is the only script we bother to physically locate; |
701
|
|
|
|
|
|
|
# all other scripts are next to cscript itself: |
702
|
0
|
|
|
|
|
|
$sScriptFname = $self->{cscript}; |
703
|
0
|
|
|
|
|
|
$sScriptFname =~ s!cscript\.exe!$sVBS.vbs!i; |
704
|
|
|
|
|
|
|
} |
705
|
0
|
|
|
|
|
|
my $sCmd = join(' ', $self->{cscript}, '-nologo', $sScriptFname, @_); |
706
|
0
|
|
|
|
|
|
DEBUG_EXEC && print STDERR " DDD exec ==$sCmd==\n"; |
707
|
0
|
|
|
|
|
|
my $sRes = qx/$sCmd/; |
708
|
0
|
|
|
|
|
|
print STDERR " DDD result ===$sRes===\n" if (1 < DEBUG_EXEC); |
709
|
0
|
|
|
|
|
|
return $sRes; |
710
|
|
|
|
|
|
|
} # _execute_script |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
=back |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
=head1 BUGS |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
To report a bug, please use L. |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
=head1 AUTHOR |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
Martin Thurn C |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
=head1 COPYRIGHT |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
This program is free software; you can redistribute |
725
|
|
|
|
|
|
|
it and/or modify it under the same terms as Perl itself. |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
=cut |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
1; |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
__END__ |