how to authenticate OTRS users via ldap (Active Directory Windows Server 2003) - centos

I have just finish installation of OTRS-3.2.10-02.noarch.rpm and now I am trying to connect it to Windows Server 2003 SP2 based Active Directory (LDAP). Here is the contents of my configuration (from /opt/otrs/Kernel/Config.pm):
# --
# Kernel/Config.pm - Config file for OTRS kernel
# Copyright (C) 2001-2013 OTRS AG, http://otrs.org/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (AGPL). If you
# did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
# --
# Note:
#
# -->> Most OTRS configuration should be done via the OTRS web interface
# and the SysConfig. Only for some configuration, such as database
# credentials and customer data source changes, you should edit this
# file. For changes do customer data sources you can copy the definitions
# from Kernel/Config/Defaults.pm and paste them in this file.
# Config.pm will not be overwritten when updating OTRS.
# --
package Kernel::Config;
use strict;
use warnings;
use utf8;
sub Load {
my $Self = shift;
# ---------------------------------------------------- #
# database settings #
# ---------------------------------------------------- #
# The database host
$Self->{'DatabaseHost'} = 'localhost';
# The database name
$Self->{'Database'} = 'otrs';
# The database user
$Self->{'DatabaseUser'} = 'otrsadmin';
# The password of database user. You also can use bin/otrs.CryptPassword.pl
# for crypted passwords
$Self->{'DatabasePw'} = '76ynhi0r';
# The database DSN for MySQL ==> more: "perldoc DBD::mysql"
$Self->{DatabaseDSN} = "DBI:mysql:database=$Self->{Database};host=$Self->{DatabaseHost};";
# The database DSN for PostgreSQL ==> more: "perldoc DBD::Pg"
# if you want to use a local socket connection
# $Self->{DatabaseDSN} = "DBI:Pg:dbname=$Self->{Database};";
# if you want to use a TCP/IP connection
# $Self->{DatabaseDSN} = "DBI:Pg:dbname=$Self->{Database};host=$Self->{DatabaseHost};";
# if you have PostgresSQL 8.1 or earlier, activate the legacy driver with this line:
# $Self->{DatabasePostgresqlBefore82} = 1;
# The database DSN for Microsoft SQL Server - only supported if OTRS is
# installed on Windows as well
# $Self->{DatabaseDSN} = "DBI:ODBC:driver={SQL Server};Database=$Self->{Database};Server=$Self->{DatabaseHost},1433";
# The database DSN for Oracle ==> more: "perldoc DBD::oracle"
# $ENV{ORACLE_HOME} = '/u01/app/oracle/product/10.2.0/client_1';
# $ENV{NLS_DATE_FORMAT} = 'YYYY-MM-DD HH24:MI:SS';
# $ENV{NLS_LANG} = "american_america.utf8";
# $Self->{DatabaseDSN} = "DBI:Oracle:sid=OTRS;host=$Self->{DatabaseHost};port=1522;";
# ---------------------------------------------------- #
# fs root directory
# ---------------------------------------------------- #
$Self->{Home} = '/opt/otrs';
# ---------------------------------------------------- #
# insert your own config settings "here" #
# config settings taken from Kernel/Config/Defaults.pm #
# ---------------------------------------------------- #
# $Self->{SessionUseCookie} = 0;
# $Self->{CheckMXRecord} = 0;
# ---------------------------------------------------- #
# ---------------------------------------------------- #
# data inserted by installer #
# ---------------------------------------------------- #
$DIBI$
# This is an example configuration for an LDAP auth. backend.
# (take care that Net::LDAP is installed!)
$Self->{AuthModule1} = 'Kernel::System::Auth::LDAP';
$Self->{'AuthModule::LDAP::Host1'} = '192.168.10.10';
$Self->{'AuthModule::LDAP::BaseDN1'} = 'dc=mydomain,dc=com, dc=pk';
$Self->{'AuthModule::LDAP::UID1'} = 'sAMAccountName';
# The following is valid but would only be necessary if the
# anonymous user do NOT have permission to read from the LDAP tree
$Self->{'AuthModule::LDAP::SearchUserDN1'} = 'CN=otrs search,OU=Users,OU=MACPAK,DC=mydomain,DC=com,DC=pk';
$Self->{'AuthModule::LDAP::SearchUserPw1'} = '76Ynhi0r';
# In case you need to use OTRS in iso-charset, you can define this
# by using this option (converts utf-8 data from LDAP to iso).
# $Self->{'AuthModule::LDAP::Charset'} = 'iso-8859-1';
# Net::LDAP new params (if needed - for more info see perldoc Net::LDAP)
$Self->{'AuthModule::LDAP::Params'} = {
port => 389,
timeout => 120,
async => 0,
version => 3,
};
# --------------------------------------------------- #
# authentication sync settings #
# (enable agent data sync. after succsessful #
# authentication) #
# --------------------------------------------------- #
# This is an example configuration for an LDAP auth sync. backend.
# (take care that Net::LDAP is installed!)
$Self->{AuthSyncModule1} = 'Kernel::System::Auth::Sync::LDAP';
$Self->{'AuthSyncModule::LDAP::Host1'} = '192.168.10.10';
$Self->{'AuthSyncModule::LDAP::BaseDN1'} = 'dc=mydomain,dc=com,dc=pk';
$Self->{'AuthSyncModule::LDAP::UID1'} = 'sAMAccountName';
# The following is valid but would only be necessary if the
# anonymous user do NOT have permission to read from the LDAP tree
$Self->{'AuthSyncModule::LDAP::SearchUserDN1'} = 'CN=otrs search,OU=Users,OU=MACPAK,DC=mydomain,DC=com,DC=pk';
$Self->{'AuthSyncModule::LDAP::SearchUserPw1'} = '76Ynhi0r';
# AuthSyncModule::LDAP::UserSyncMap
# (map if agent should create/synced from LDAP to DB after successful login)
$Self->{'AuthSyncModule::LDAP::UserSyncMap1'} = {
# DB -> LDAP
UserFirstname => 'givenName',
UserLastname => 'sn',
UserEmail => 'mail',
};
# In case you need to use OTRS in iso-charset, you can define this
# by using this option (converts utf-8 data from LDAP to iso).
# $Self->{'AuthSyncModule::LDAP::Charset'} = 'iso-8859-1';
# Net::LDAP new params (if needed - for more info see perldoc Net::LDAP)
# $Self->{'AuthSyncModule::LDAP::Params'} = {
# port => 389,
# timeout => 120,
# async => 0,
# version => 3,
# };
#Enable LDAP authentication for Customers / Users
$Self->{'Customer::AuthModule2'} = 'Kernel::System::CustomerAuth::LDAP';
$Self->{'Customer::AuthModule::LDAP::Host2'} = '192.168.10.10';
$Self->{'Customer::AuthModule::LDAP::BaseDN2'} = 'dc=mydomain,dc=com,dc=pk';
$Self->{'Customer::AuthModule::LDAP::UID2'} = 'sAMAccountName';
#The following is valid but would only be necessary if the
#anonymous user do NOT have permission to read from the LDAP tree
$Self->{'Customer::AuthModule::LDAP::SearchUserDN2'} = 'CN=otrs search,OU=Users,OU=MACPAK,DC=mydomain,DC=com,DC=pk';
$Self->{'Customer::AuthModule::LDAP::SearchUserPw2'} = '76Ynhi0r';
#CustomerUser
#(customer user database backend and settings)
$Self->{CustomerUser} = {
Module => 'Kernel::System::CustomerUser::LDAP',
Params => {
Host => '192.168.10.10',
BaseDN => 'dc=mydomain,dc=com,dc=pk,
SSCOPE => 'sub',
UserDN =>'CN=otrs search,OU=Users,OU=MACPAK,DC=mydomain,DC=com,DC=pk',
UserPw => '76Ynhi0r',
},
# customer unique id
CustomerKey => 'sAMAccountName',
# customer #
CustomerID => 'mail',
CustomerUserListFields => ['sAMAccountName', 'cn', 'mail'],
CustomerUserSearchFields => ['sAMAccountName', 'cn', 'mail'],
CustomerUserSearchPrefix => '',
CustomerUserSearchSuffix => '*',
CustomerUserSearchListLimit => 250,
CustomerUserPostMasterSearchFields => ['mail'],
CustomerUserNameFields => ['givenname', 'sn'],
Map => [
# note: Login, Email and CustomerID needed!
# var, frontend, storage, shown, required, storage-type
#[ 'UserSalutation', 'Title', 'title', 1, 0, 'var' ],
[ 'UserFirstname', 'Firstname', 'givenname', 1, 1, 'var' ],
[ 'UserLastname', 'Lastname', 'sn', 1, 1, 'var' ],
[ 'UserLogin', 'Login', 'sAMAccountName', 1, 1, 'var' ],
[ 'UserEmail', 'Email', 'mail', 1, 1, 'var' ],
[ 'UserCustomerID', 'CustomerID', 'mail', 0, 1, 'var' ],
[ 'UserPhone', 'Phone', 'telephonenumber', 1, 0, 'var' ],
#[ 'UserAddress', 'Address', 'postaladdress', 1, 0, 'var' ],
#[ 'UserComment', 'Comment', 'description', 1, 0, 'var' ],
],
};
#Add the following lines when only users are allowed to login if they reside in the spicified security group
#Remove these lines if you want to provide login to all users specified in the User Base DN
#example: $Self->{'Customer::AuthModule::LDAP::BaseDN'} = 'ou=BaseOU, dc=example, dc=com';
$Self->{'Customer::AuthModule::LDAP::GroupDN'} = 'CN=otrs search,OU=Users,OU=MACPAK,DC=mydomain,DC=com,DC=pk';
$Self->{'Customer::AuthModule::LDAP::AccessAttr'} = 'memberUid';
$Self->{'Customer::AuthModule::LDAP::UserAttr'} = 'UID'
# Die if backend can't work, e. g. can't connect to server.
# $Self->{'AuthSyncModule::LDAP::Die'} = 1;
# Die if backend can't work, e. g. can't connect to server.
# $Self->{'AuthModule::LDAP::Die'} = 1;
# ---------------------------------------------------- #
# ---------------------------------------------------- #
# #
# end of your own config options!!! #
# #
# ---------------------------------------------------- #
# ---------------------------------------------------- #
}
# ---------------------------------------------------- #
# needed system stuff (don't edit this) #
# ---------------------------------------------------- #
use strict;
use warnings;
use vars qw(#ISA);
use Kernel::Config::Defaults;
push (#ISA, 'Kernel::Config::Defaults');
# -----------------------------------------------------#;
1;
After this, I am no more able to connect my orts with http://192.168.10.15/otrs/index.pl and when use
cat /var/log/httpd/error_log | tail
its output is ;
[root#macpk-manage ~]# cat /var/log/httpd/error_log | tail
[Fri Aug 30 21:55:36 2013] Config.pm: (Missing operator before $;?)
[Fri Aug 30 21:55:36 2013] Config.pm: Scalar found where operator expected at /opt/otrs//Kernel/Config.pm line 89, near "$;
[Fri Aug 30 21:55:36 2013] Config.pm:
[Fri Aug 30 21:55:36 2013] Config.pm: # This is an example configuration for an LDAP auth. backend.
[Fri Aug 30 21:55:36 2013] Config.pm: # (take care that Net::LDAP is installed!)
[Fri Aug 30 21:55:36 2013] Config.pm:
[Fri Aug 30 21:55:36 2013] Config.pm: $Self"
[Fri Aug 30 21:55:36 2013] Config.pm: (Missing operator before $Self?)
[Fri Aug 30 21:55:36 2013] [error] Illegal declaration of subroutine Kernel::Config:: at /opt/otrs//Kernel/Config.pm line 176.\nCompilation failed in require at /opt/otrs/scripts/apache2-perl-startup.pl line 68.\nBEGIN failed--compilation aborted at /opt/otrs/scripts/apache2-perl-startup.pl line 68.\nCompilation failed in require at (eval 2) line 1.\n
[Fri Aug 30 21:55:36 2013] [error] Can't load Perl file: /opt/otrs/scripts/apache2-perl-startup.pl for server macpk-manage.macrosoftinc.com.pk:80, exiting...
I also tried to restart httpd service but it fails and when even I restart CentOS 6.4, it shows httpd Failed to run, Aanyhelp will be highly appreciated and thanks in advance;

There's a missing quote after BaseDN, see this:
- BaseDN => 'dc=mydomain,dc=com,dc=pk,
+ BaseDN => 'dc=mydomain,dc=com,dc=pk',
https://gist.github.com/mbeijen/72a15954b601eaaae797/revisions
If you want to make sure you balanced your quotes and such correctly, you can type on the command line perl -cw Kernel/Config.pm

You need to comment out the following line:
$DIBI$
and also add this:
$Self->{'DefaultCharset'} = 'utf-8';

I think you need to check this two line with your domin.local
UserDN =>'CN=otrs search,OU=Users,OU=MACPAK,DC=mydomain,DC=com,DC=pk',
UserPw => '76Ynhi0r',

Related

Password-less access to PostgreSQL server from MATLAB (on Windows)?

I'm trying to get password-less access to a PostgreSQL server from within MATLAB, relying on a %APPDATA%\postgresql\pgpass.conf file, as described in the documentation.
The password-less access works as desired when tried from, say, a Perl script1, which suggests that the pgpass.conf file is correctly configured.
But when I try to connect from within a MATLAB session, with2:
>> conn = database('dbname', 'user', '', 'Vendor', 'PostgreSQL', 'Server', 'dbhost');
...I get the following error:
>> conn.Message
The server requested password-based authentication, but no password was provided.
Can MATLAB be made to use %APPDATA%\postgresql\pgpass.conf to connect password-lessly?
1For example, this password-less Perl snippet works fine:
use DBI;
my $c = DBI->connect( 'dbi:Pg:dbname=dbname;host=dbhost',
'user',
undef,
{
RaiseError => 1,
PrintError => 0,
PrintWarn => 0,
} );
( my $s = $c->prepare( 'SELECT * FROM mytable LIMIT 20' ) )->execute;
printf "%s\n", join( "\t", #$_ ) for #{ $s->fetchall_arrayref };
2 Of course, I am not using the strings 'dbname', 'user', etc., but the ones appropriate to the actual database, user, etc. Ditto for the connection parameters in the Perl example shown earlier.

Removing fragments from URLs

I want to get rid of fragments (like #foobar) from URLs, but based on certain rules. Normally a brutal regex would have solved the problem;
$url =~ s/#.+//;
but I want it to take several things into consideration, most notably these transformations
http://www.example.com/#/ => http://www.example.com/
http://www.example.com/#foo/bar#foo => http://www.example.com/#foo/bar
http://www.example.com/#foo?a=1 => http://www.example.com/#foo?a=1
http://www.example.com/#foo/?a=1 => http://www.example.com/#foo/?a=1
So the rules should be:
1) If /#/, just replace it with /.
2) If # is not followed upstream by a / or ?, remove it.
Any ideas how to deal with this properly? One regex or use of other modules?
The regex s{#(?:/|[^?/]*)$}{} will cover these rules as stated:
If /#/, just replace it with /.
If # is not followed upstream by a / or ?, remove it.
And the test suite to demonstrate:
use strict;
use warnings;
use Test;
BEGIN { plan tests => 4 }
while (<DATA>) {
chomp;
my ($source, $goal) = split /\s*=>\s*/;
$source =~ s{#(?:/|[^?/]*)$}{};
ok($source, $goal);
}
__DATA__
http://www.example.com/#/ => http://www.example.com/
http://www.example.com/#foo/bar#foo => http://www.example.com/#foo/bar
http://www.example.com/#foo?a=1 => http://www.example.com/#foo?a=1
http://www.example.com/#foo/?a=1 => http://www.example.com/#foo/?a=1
Output:
1..4
# Running under perl version 5.018002 for MSWin32
# Current time local: Fri May 30 15:01:04 2014
# Current time GMT: Fri May 30 22:01:04 2014
# Using Test.pm version 1.26
ok 1
ok 2
ok 3
ok 4

IRC Client - channel latitude and longitude details

Is there a way to retrieve latitude and longitude details of IRC channel so that I can locate the same on Map.
Thanks.
To get the locations of the people in the channel, you could simply look at their hostname - names on IRC are made up of a nickname, a username, and a hostname in the format nickname!username#hostname.
The hostname could be one of three things - an IP address, a DNS name, or a "cloak". You could use a DNS client to convert the hostname into an IP address, and then with the IP addresses you could use an IP geolocation tool (such as ipinfodb.com which has a nice free API), and retrieve the latitude and longtitude of each user.
If the hostname is a cloak, and the format of this varies between networks, then there's no way (unless you have advanced privileges on the IRC network) to get the real IP/hostname (and hence location) of that user.
Radoslaw Zielinski (radek at pld-linux dot org) wrote a Perl script for geolocation of nicknames in the XChat IRC client:
I wrote a simple plugin to look up the IP address in the Maxmind GeoIP lookup database, you can find it here: xchat-geo.pl. See “perldoc xchat-geo.pl” for the installation instructions.
Usage:
/geo some_nickname
Output:
[17:33] ==> some_nickname | US San Francisco CA 37.7525 -122.3194 n=somenick#some.host
Original blog post: www.radek.cc/2009/09/06/irc-xchat-geolocation-plugin/
It requires that you install:
Perl
one of the Maxmind GeoIP databases (some are free)
the Maxmind Geo::IP module (its API for Perl)
XChat with a Perl scripting interface plugin
xchat-geo.pl, retrieved 2012-03-06:
#!/usr/bin/perl -w
use strict;
use Geo::IP ();
our $VERSION = '0.04';
=head1 NAME
xchat-geo.pl - geolocation plugin for xchat
=head1 SYNOPSIS
perl -MCPAN -e 'install Geo::IP'
chmod +x xchat-geo.pl
mv xchat-geo.pl ~/.xchat/
# in xchat
/unload .xchat/xchat-geo.pl
/load .xchat/xchat-geo.pl
/geo some-nickname
=head1 DESCRIPTION
Usage:
/geo some_nickname
[17:33] ==> some_nickname | US San Francisco CA 37.7525 -122.3194
n=somenick#some.host
Provides a single C</geo> command, which attempts to lookup the IP address in
the maxmind GeoIP database.
Requires the Geo::IP module to be installed, along with the GeoIP City (or its
free GeoLite counterpart); see L<http://www.maxmind.com/app/ip-location> and
L<http://www.maxmind.com/app/geolitecity>.
On my machine, the installed databases look like this:
$ ls -l /usr/share/GeoIP
lrwxrwxrwx 1 root root 15 Sep 6 16:54 GeoIPCity.dat -> GeoLiteCity.dat
-rw-r--r-- 1 root root 877738 Sep 6 16:25 GeoIP.dat
-rw-r--r-- 1 root root 27711885 Sep 6 16:31 GeoLiteCity.dat
Released 2009-09-06
=head1 AUTHOR
Radoslaw Zielinski E<lt>radek#pld-linux.orgE<gt>
http://radek.cc/2009/09/06/irc-xchat-geolocation-plugin/
=head1 LICENSE
GPL v3
=cut
our $geo = Geo::IP->open_type( Geo::IP::GEOIP_CITY_EDITION_REV1 ) # Geo::IP::GEOIP_STANDARD
or die "can't load the GeoIP database";
Xchat::print('xchat geo starting');
Xchat::register( 'xchat geo', $VERSION, 'geo location for xchat', \&unload );
Xchat::hook_print( 'Join', \&Join, );
Xchat::hook_command( 'geo', sub { geo(#_); Xchat::EAT_ALL; }, );
# for debugging / plugin development
#Xchat::hook_command( 'xev', sub { eval $_[1][0]; Xchat::EAT_ALL; }, );
sub Join {
my ( $user, $channel, $host ) = #{ $_[0] };
my $r = record_from_ihost($host);
Xchat::printf( "-\x0311->\x03\t\x02%s \x0f\x0314(\x0311%s\x0314) \x03has joined %s [\x0308%s\x0f]",
$user, $host, $channel,
$r && ref $r
? join( ', ', map { defined $_ ? $_ : '' } $r->country_code, $r->city, $r->region, $r->postal_code, )
: '' );
return Xchat::EAT_XCHAT;
}
# /geo some_nickname
sub geo {
my ($cmd) = #_;
defined $cmd->[1] && length $cmd->[1]
or return Xchat::print('nick?');
my $user = Xchat::user_info( $cmd->[1] )
or return Xchat::print("no such nick $cmd->[1]");
my $r = record_from_ihost( $user->{host} )
or return;
return ref $r
? Xchat::print(
' ==> ' . join "\t", $user->{nick}, $r->country_code, $r->city, $r->region,
$r->latitude, $r->longitude, $r->postal_code, $user->{host}
)
: Xchat::print($r);
}
# input: nick and hostname, as reported by xchat
# - n=user#hostname
# - n=user#IP.address
# - n=user#some/freenode/cloak (useless)
# output: a string with error message or a Geo::IP record
sub record_from_ihost {
my $ihost = shift
or return;
( my $nick = $ihost ) =~ s/^.=|\#.*//g;
$ihost =~ /^ [^#]* \# (?: ((?:\d{1,3}\.){3}\.\d{1,3}) | ([a-zA-Z\d_-]+\.[.a-zA-Z\d_-]+) ) (?: \s.* )? $/x
or return "no useful host for <$nick> -- $ihost";
my $r = ( $1 ? $geo->record_by_ip($1) : $geo->record_by_name($2) )
or return "no useful geo info for <$nick> -- $ihost " . ( $1 ? "1: $1" : "2: $2" );
return $r;
}
sub unload {
undef $geo;
Xchat::print('xchat geo exiting');
}
# vim: ts=4 sw=4 noet

Perl Cygwin fun. Module is loaded, but not being found by the program

Okay a few rules:
No, I cannot install Strawberry Perl on this system. I have to use Cygwin.
This is Perl 5.8.7. I cannot update it.
This is not my system. This is a customer's system, and I cannot modify it to my hearts content.
Now, we've gotten that out of the way...
I have installed Spreadsheet::Read, Spreadsheet::ParseExcel, and Spreadsheet::XLSX on this system. This installed a little Perl script called xlscat. We've done this before on a development box and the UAT box. Now this is the production box.
I am getting the following error:
Parser for XLSX is not installed at /usr/bin/xlscat line 185
I've traced this to Spreadsheet::Read. The relevant code is:
my #parsers = (
[ csv => "Text::CSV_XS" ],
[ csv => "Text::CSV_PP" ], # Version 1.05 and up
[ csv => "Text::CSV" ], # Version 1.00 and up
[ ods => "Spreadsheet::ReadSXC" ],
[ sxc => "Spreadsheet::ReadSXC" ],
[ xls => "Spreadsheet::ParseExcel" ],
[ xlsx => "Spreadsheet::XLSX" ],
[ prl => "Spreadsheet::Perl" ],
# Helper modules
[ ios => "IO::Scalar" ],
);
my %can = map { $_->[0] => 0 } #parsers;
for (#parsers) {
my ($flag, $mod) = #$_;
print STDERR qq(DEBUG: Flag = "$flag" Mod = "$mod"\n);
$can{$flag} and next;
eval "require $mod; \$can{\$flag} = '$mod'";
}
print STDERR Dumper(\%can); #DEBUG:
The lines that start contain the string DEBUG: are mine.
A dump of #parsers shows that everything is loaded correctly. The first debug prints out the value of $flag and $mod correctly.
The problem seems to come from the eval statement. From what I can see, it runs require against a module, and then sets the $can{$flag} variable to $mod if the require succeeds. Apparently, require Spreadsheet::XLSX fails. Here's the relevant output from my debug statements:
DEBUG: Flag = "csv" Mod = "Text::CSV_XS"
DEBUG: Flag = "csv" Mod = "Text::CSV_PP"
DEBUG: Flag = "csv" Mod = "Text::CSV"
DEBUG: Flag = "ods" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "sxc" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "xls" Mod = "Spreadsheet::ParseExcel"
DEBUG: Flag = "xlsx" Mod = "Spreadsheet::XLSX"
DEBUG: Flag = "prl" Mod = "Spreadsheet::Perl"
DEBUG: Flag = "ios" Mod = "IO::Scalar"
$VAR1 = {
'csv' => 'Text::CSV_XS',
'sxc' => 0,
'xlsx' => 0,
'xls' => 'Spreadsheet::ParseExcel',
'ios' => 'IO::Scalar',
'prl' => 0,
'ods' => 0
};
Hmmm... Maybe the module isn't installed?
$ perldoc -l Spreadsheet::XLSX
/usr/lib/perl5/site_perl/5.8/Spreadsheet/XLSX.pm
It shows up in perldoc. Let's write a quick test program:
#! /usr/bin/env perl
use Spreadsheet::Read;
use Spreadsheet::XLSX;
print "It works\n";
And...
$ ./test.pl
DEBUG: Flag = "csv" Mod = "Text::CSV_XS"
DEBUG: Flag = "csv" Mod = "Text::CSV_PP"
DEBUG: Flag = "csv" Mod = "Text::CSV"
DEBUG: Flag = "ods" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "sxc" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "xls" Mod = "Spreadsheet::ParseExcel"
DEBUG: Flag = "xlsx" Mod = "Spreadsheet::XLSX"
DEBUG: Flag = "prl" Mod = "Spreadsheet::Perl"
DEBUG: Flag = "ios" Mod = "IO::Scalar"
$VAR1 = {
'csv' => 'Text::CSV_XS',
'sxc' => 0,
'xlsx' => 0,
'xls' => 'Spreadsheet::ParseExcel',
'ios' => 'IO::Scalar',
'prl' => 0,
'ods' => 0
};
It works
I can pick up Spreadsheet::XLSX via the use Spreadsheet::XLSX in my test program, yet the require in Spreadsheet::Read doesn't seem to see it.
Why?
Addendum
What do you get if you print Dumper( \%INC ) ? – friedo 2 mins ago
I actually did one better. I added the following line in the loop:
require $mod if ($mod eq "Spreadsheet::XLSX"); #DEBUG
And that produced the error message:
Can't locate Spreadsheet::XLSX in #INC (#INC contains:
/usr/lib/perl5/5.8/cygwin /usr/lib/perl5/5.8
/usr/lib/perl5/site_perl/5.8/cygwin
/usr/lib/perl5/site_perl/5.8
/usr/lib/perl5/site_perl/5.8/cygwin
/usr/lib/perl5/site_perl/5.8
/usr/lib/perl5/vendor_perl/5.8/cygwin
/usr/lib/perl5/vendor_perl/5.8
/usr/lib/perl5/vendor_perl/5.8/cygwin
/usr/lib/perl5/vendor_perl/5.8 .) at
/usr/lib/perl5/site_perl/5.8/Spreadsheet/Read.pm line 57.
Compilation failed in require at ./test.pl line 3.
BEGIN failed--compilation aborted at ./test.pl line 3.
(NOTE: I reformatted the output, so it wouldn't be 1000+ characters long, and it's easier to see the #INC path).
The module is in /usr/lib/perl5/site_perl/5.8/Spreadsheet/XLSX.pm.
Oh, take a look at this too:
$ pwd
/usr/lib/perl5/site_perl/5.8/Spreadsheet
$ ls -la
total 152
drwxr-xr-x+ 4 phalder Domain Users 0 Nov 1 21:51 .
drwxrwxrw-+ 11 twinborne Users 0 Nov 1 22:28 ..
drwxr-xr-x+ 3 phalder Domain Users 0 Nov 1 20:48 ParseExcel
-rwxr-xr-x 1 phalder Domain Users 107773 Apr 6 2011 ParseExcel.pm
-rwxrwxrwx 1 phalder Domain Users 29142 Nov 2 12:53 Read.pm
drwxr-xr-x+ 2 phalder Domain Users 0 Nov 1 21:51 XLSX
-rwxr-xr-x 1 phalder Domain Users 8411 May 16 2010 XLSX.pm
$ ls -la XLSX
total 48
drwxr-xr-x+ 2 phalder Domain Users 0 Nov 1 21:51 .
drwxr-xr-x+ 4 phalder Domain Users 0 Nov 1 21:51 ..
-rwxr-xr-x 1 phalder Domain Users 5487 May 16 2010 Fmt2007.pm
-rwxr-xr-x 1 phalder Domain Users 37046 May 16 2010 Utility2007.pm
The permissions seem okay.
Another Addendum:
When I did a CPAN reinstall, I got this:
Result: PASS
/usr/bin/make test -- OK
Running make install
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ERROR: Can't create '/usr/lib/perl5/site_perl/5.8/cygwin/auto/Spreadsheet/Read'
Do not have write permissions on
'/usr/lib/perl5/site_perl/5.8/cygwin/auto/Spreadsheet/Read'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
at -e line 1
Installing /usr/lib/perl5/site_perl/5.8/Spreadsheet/Read.pm
Installing /usr/share/man/man3/Spreadsheet.Read.3pm
make: *** [pure_site_install] Error 255
/usr/bin/make install -- NOT OK
Oops! I didn't check the permission of the /usr/lib/perl5/site_perl/5.8/cygwin directory tree.
Did a chmod -R a+rx * on the whole /usr/lib/perl5 directory. We'll see if it works again.
Found the Problem
I took a slightly different tact. I modified Spreadsheet::Read to print out $# after the eval. That way, I could see what error it was getting. Here's the results:
$ ./test.pl
DEBUG: ""DEBUG: "Can't locate Spreadsheet/ReadSXC.pm in #INC
(#INC contains:
/usr/lib/perl5/5.8/cygwin
/usr/lib/perl5/5.8
/usr/lib/perl5/site_perl/5.8/cygwin
/usr/lib/perl5/site_perl/5.8
/usr/lib/perl5/site_perl/5.8/cygwin
/usr/lib/perl5/site_perl/5.8
/usr/lib/perl5/vendor_perl/5.8/cygwin
/usr/lib/perl5/vendor_perl/5.8
/usr/lib/perl5/vendor_perl/5.8/cygwin
/usr/lib/perl5/vendor_perl/5.8 .) at (eval 8) line 1.
"DEBUG: "Can't locate Spreadsheet/ReadSXC.pm in #INC
(#INC contains: /usr/lib/perl5/5.8/cygwin [...]) at (eval 9) line 1.
"DEBUG: ""DEBUG: "Can't locate Compress/Raw/Zlib.pm in #INC
(#INC contains: /usr/lib/perl5/5.8/cygwin [...]) at (eval 15) line 1.
"DEBUG: "Can't locate Spreadsheet/Perl.pm in #INC
(#INC contains: /usr/lib/perl5/5.8/cygwin [...]) at (eval 18) line 1.
Did you see that? The problem isn't Spreadsheet::XLSX, but Compress::Raw::Zlib. I set the entire permissions on /usr/lib/perl to 777, and then installed Compress::Raw::Zlib and Spreadsheet::ReadSXC.
This must have been a problem when these modules were initially installed. I wasn't the one doing the cpan install, but helping the person over the phone, so I didn't get a chance to see these errors if they popped up. CPAN tends to be really, really noisy, and I've learned to catch the random error message as CPAN runs by.
The problem may have been /usr/lib/perl5/site_perl/5.8/cygwin not having the correct permissions all along.
The program now works.
Thanks for all of your help. Somehow, it lead me down the right trail.

how do I check if a domain name is available (in bulk)?

I am looking to do a bulk domain name lookup to see if some domain names are available for purchase. I couldn't find a perl module, but it seems like there should be a way to do this in perl. I am looking for something free. thx!
From here: http://www.webhostingtalk.com/showthread.php?t=625723
Here’s a quick perl script that requires Net :: DNS (fairly common module).
#!/usr/bin/perl
# Domains Available
# Josh Skidmore <josh#vorcado.com>
# 05 August 2007 | 11:40p EST
# Requirements
use Net::DNS;
# Variables
%VAR = (
db => './domains.txt',
);
# Open file
open (DB,$VAR{'db'});
my (#domains) = <DB>;
close (DB);
# Test domains
foreach my $domain (#domains)
{
chomp($domain);
my ($available) = &check_domain(domain => $domain);
if ($available)
{
print "$domain is available.<br />\n";
}
else
{
print "$domain is NOT available<br />\n";
}
}
sub check_domain {
# Test domain for existance
# Josh Skidmore <josh#vorcado.com>
# 05 August 2007 | 11:42p EST
# Variables
my (%DATA) = #_ ;
my ($available) = 0;
# Start Net::DNS
my $res = Net::DNS::Resolver->new;
$res->udp_timeout(2);
$res->tcp_timeout(2);
my ($domain) = $res->search($DATA{'domain'});
if ($domain)
{
($available) = 1;
}
# Output
return ($available);
}
There are plenty of whois-like modules on CPAN. Net::Whois::Parser looks promising, for one.
Barring that, the whois command is available in Linux and other Unix-y systems (including Cygwin for windows). There's also a whois script in Perl on CPAN. Running those programs is the easy part. The tricky part, which Perl can definitely help with, is parsing the output from those programs.