sourcecode
davis
<code>
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use Net::LDAP;
use Net::LDAPS;
use Template;
my $template_input = '\documentclass[10pt,a4paper]{article}
\usepackage{times}
\usepackage{xtab}
\usepackage{colortbl}
\setlength\textheight{290mm}
\setlength{\voffset}{-15mm}
\begin{document}
\begin{center}
\begin{xtabular}{lllll}
\textbf{Name} & \textbf{Title} & \textbf{Ext.} & \textbf{Mobile} & \textbf{SPD} \\\\
\hline
[% FOREACH buildings %]
\hline
\multicolumn{5}{c}{[% buildingname %]}\\\\
\hline
[% FOREACH staff %]
[%- IF loop.index % 2 -%]\rowcolor[gray]{0.91}[%- END -%][%name%] & \\tiny{[%title%]} & [%extension%] & [%mobile%] & [%mobile_speed_dial%]\\\\
[% END %]
[% END %]
\end{xtabular}
\end{center}
\end{document}';
##There'll be some customization necessary here
my $ldap = Net::LDAPS->new("domain.controller") or die "$@";
my $message
= $ldap->bind( "cn=Some User,ou=Service Accounts,dc=company,dc=com",
password => 'Secret' );
$message = $ldap->search(
base => "ou=Employees,dc=company,dc=com",
filter => "(& (cn=*) (objectClass=user))",
);
$message->code && die $message->error;
my @skip_names = (
#A list of names to be skipped (service/admin accounts etc)
);
my %staff;
foreach my $employee ( $message->all_entries ) {
my $name = $employee->get_value("cn");
next if ( grep /^\Q$name\E$/, @skip_names );
my $title = $employee->get_value("title") || "";
my $extension = $employee->get_value("telephoneNumber") || "";
my $mobile = $employee->get_value("mobile") || "";
my $mobile_speed_dial = $employee->get_value("pager") || "";
my $building = $employee->get_value("physicalDeliveryOfficeName") || "";
my $useraccount_control = $employee->get_value("userAccountControl")
|| "";
next if ( account_disabled($useraccount_control) ); # Skip disabled accounts
push @{ $staff{$building} },
{
name => $name,
title => $title,
extension => $extension,
mobile => $mobile,
mobile_speed_dial => $mobile_speed_dial
};
}
my @buildings;
foreach my $building ( sort keys(%staff) ) {
my @staff = sort { $a->{name} cmp $b->{name} } @{ $staff{$building} };
push @buildings, { buildingname => $building, staff => \@staff };
}
my $template = Template->new();
my $output;
$template->process( \$template_input, { buildings => \@buildings }, \$output )
or die $template->e->error(), "\n";
open( my $fh, ">", "phone_list.tex" )
or die "Couldn't open phone_list.tex for writing: $!\n";
print $fh $output;
close($fh);
sub account_disabled {
my $flags = shift;
my %check = calculate_flags($flags);
return 1 if ( $check{ACCOUNTDISABLE} );
return 0;
}
sub calculate_flags {
my $flags_to_check = shift;
my %table = (
SCRIPT => 0x0001,
ACCOUNTDISABLE => 0x0002,
HOMEDIR_REQUIRED => 0x0008,
LOCKOUT => 0x0010,
PASSWD_NOTREQD => 0x0020,
PASSWD_CANT_CHANGE => 0x0040,
ENCRYPTED_TEXT_PWD_ALLOWED => 0x0080,
TEMP_DUPLICATE_ACCOUNT => 0x0100,
NORMAL_ACCOUNT => 0x0200,
INTERDOMAIN_TRUST_ACCOUNT => 0x0800,
WORKSTATION_TRUST_ACCOUNT => 0x1000,
SERVER_TRUST_ACCOUNT => 0x2000,
DONT_EXPIRE_PASSWORD => 0x10000,
MNS_LOGON_ACCOUNT => 0x20000,
SMARTCARD_REQUIRED => 0x40000,
TRUSTED_FOR_DELEGATION => 0x80000,
NOT_DELEGATED => 0x100000,
USE_DES_KEY_ONLY => 0x200000,
DONT_REQ_PREAUTH => 0x400000,
PASSWORD_EXPIRED => 0x800000,
TRUSTED_TO_AUTH_FOR_DELEGATION => 0x1000000,
);
my %results;
foreach my $flag ( keys %table ) {
$results{$flag} = 1 if ( $flags_to_check & $table{$flag} );
}
return %results;
}
</code>
<p>
Here's a script to extract telephone entries from a Windows AD via Net::LDAP (thanks [g0n]!) and output them to a LaTeX file to be process with pdflatex. The results aren't too terrible.
</p>
<p>
You'll probably need to customize it; we, for example, store "Mobile speed dial" numbers in the "Pager" field. We also deliberately separate based on the physical building — YMMV.
</p>
<p>
I'd recommend separating the template into a separate file, I included here inline because it's easier to download.
</p>
NT Admin
/msg davis