| 1 | #!/usr/bin/perl |
|---|
| 2 | # |
|---|
| 3 | # ICQ99a contact list converter, version 2 |
|---|
| 4 | # (tested with builds 1547, 1677, 1700 and 1800) |
|---|
| 5 | # |
|---|
| 6 | # (c)1999 Erwin Aitenbichler <eait@gmx.at> |
|---|
| 7 | # This program is released under the terms of the GPL. |
|---|
| 8 | # |
|---|
| 9 | |
|---|
| 10 | $path=(getpwuid($<))[7]."/.licq/"; |
|---|
| 11 | $pathUsers=$path."users/"; |
|---|
| 12 | $fnOwner=$path."owner.uin"; |
|---|
| 13 | $fnUsers=$path."users.conf"; |
|---|
| 14 | $verbose=1; |
|---|
| 15 | $|=1; |
|---|
| 16 | |
|---|
| 17 | foreach $arg (@ARGV) |
|---|
| 18 | { |
|---|
| 19 | if ($arg eq "-q") |
|---|
| 20 | { $verbose=0; } |
|---|
| 21 | elsif ($arg eq "-v") |
|---|
| 22 | { $verbose=2; } |
|---|
| 23 | elsif ($arg eq "-vv") |
|---|
| 24 | { $verbose=3; } |
|---|
| 25 | else |
|---|
| 26 | { $fn=$arg; } |
|---|
| 27 | } |
|---|
| 28 | |
|---|
| 29 | if (!defined($fn)) |
|---|
| 30 | { |
|---|
| 31 | print STDERR "\nsyntax: licq.winconvert99a [options] <your_uin>.dat\n"; |
|---|
| 32 | print STDERR "Extracts all UINs out of an ICQ99a database and creates licq .uin files.\n"; |
|---|
| 33 | print STDERR "(tested with builds 1547, 1677, 1700 and 1800)\n"; |
|---|
| 34 | print STDERR "\nThe .dat-file is usually located in: <your_win_drive>/Program Files/icq/NewDB/\n"; |
|---|
| 35 | print STDERR "\noptions:\n"; |
|---|
| 36 | print STDERR " -q quiet\n"; |
|---|
| 37 | print STDERR " -v verbose\n"; |
|---|
| 38 | print STDERR " -vv verbose more\n"; |
|---|
| 39 | print STDERR "\n"; |
|---|
| 40 | exit 0; |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | # get owner uin |
|---|
| 44 | |
|---|
| 45 | open(INFH, "<$fnOwner") || die "can't open '$fnOwner'.\n"; |
|---|
| 46 | while(<INFH>) |
|---|
| 47 | { |
|---|
| 48 | if ($_=~/Uin = (\d+)/) |
|---|
| 49 | { |
|---|
| 50 | $own_uin=$1; |
|---|
| 51 | } |
|---|
| 52 | } |
|---|
| 53 | close(INFH); |
|---|
| 54 | die "canŽt determine owner uin.\n" if (!defined($own_uin)); |
|---|
| 55 | print "owner uin: $own_uin\n\n" if $verbose>=2; |
|---|
| 56 | |
|---|
| 57 | # read users from users.conf |
|---|
| 58 | |
|---|
| 59 | %uins=(); |
|---|
| 60 | if (open(INFH, "<$fnUsers")) |
|---|
| 61 | { |
|---|
| 62 | while (<INFH>) |
|---|
| 63 | { |
|---|
| 64 | $uins{$1}=1 if ($_=~/User\d+ = (\d+)/); |
|---|
| 65 | } |
|---|
| 66 | close(INFH); |
|---|
| 67 | } |
|---|
| 68 | else |
|---|
| 69 | { |
|---|
| 70 | print "Ž$fnUsersŽ not found - will create a new one.\n" if $verbose>=1; |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | # import users |
|---|
| 74 | |
|---|
| 75 | $count=0; |
|---|
| 76 | readFile($fn); |
|---|
| 77 | |
|---|
| 78 | # write new users.conf |
|---|
| 79 | |
|---|
| 80 | open(OUTFH, ">$fnUsers") || die "canŽt open Ž$fnUsersŽ for writing.\n"; |
|---|
| 81 | @list=sort {$a <=> $b} (keys %uins); |
|---|
| 82 | print OUTFH "[users]\nNumOfUsers = ", $#list+1, "\n"; |
|---|
| 83 | $i=1; |
|---|
| 84 | foreach $key (@list) |
|---|
| 85 | { |
|---|
| 86 | print OUTFH "User", $i++, " = ", $key, "\n"; |
|---|
| 87 | } |
|---|
| 88 | close(OUTFH); |
|---|
| 89 | |
|---|
| 90 | print "$count users add.\n" if $verbose>=1; |
|---|
| 91 | |
|---|
| 92 | if ($verbose>=1) |
|---|
| 93 | { |
|---|
| 94 | print "NOTE: This script doesn't support all user information fields.\n"; |
|---|
| 95 | print "Select 'Users/Update All Users' in licq to get full user information.\n"; |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | sub readFile() |
|---|
| 99 | { |
|---|
| 100 | my $fn=shift; |
|---|
| 101 | open(INFH, "<$fn") || die "can't open file '$fn'\n"; |
|---|
| 102 | binmode INFH; # for M$... |
|---|
| 103 | my @buf; |
|---|
| 104 | for ($pos=0; $pos<7; $pos++) |
|---|
| 105 | { |
|---|
| 106 | $buf[$pos]=ord(getc(INFH)); |
|---|
| 107 | } |
|---|
| 108 | print "reading" if $verbose==1; |
|---|
| 109 | while (!eof(INFH)) |
|---|
| 110 | { |
|---|
| 111 | # find pattern: 00 id 00 n 00 00 00 |
|---|
| 112 | if ($buf[0]==0 && |
|---|
| 113 | $buf[1]!=0 && |
|---|
| 114 | $buf[2]==0 && |
|---|
| 115 | $buf[3]!=0 && |
|---|
| 116 | $buf[4]==0 && |
|---|
| 117 | $buf[5]==0 && |
|---|
| 118 | $buf[6]==0) |
|---|
| 119 | { |
|---|
| 120 | readRecord (1, $buf[3]); |
|---|
| 121 | seek INFH, $pos, 0; |
|---|
| 122 | readRecord (2, $buf[3]); |
|---|
| 123 | seek INFH, $pos, 0; |
|---|
| 124 | } |
|---|
| 125 | shift (@buf); |
|---|
| 126 | push (@buf, ord(getc(INFH))); |
|---|
| 127 | $pos++; |
|---|
| 128 | print "." if ($pos%10000==0 && $verbose==1); |
|---|
| 129 | } |
|---|
| 130 | close(INFH); |
|---|
| 131 | print "\n" if $verbose==1; |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | sub readRecord() |
|---|
| 135 | { |
|---|
| 136 | my $version=shift; |
|---|
| 137 | my $n=shift; |
|---|
| 138 | if ($version==1) |
|---|
| 139 | { |
|---|
| 140 | for ($i=0; $i<$n; $i++) |
|---|
| 141 | { |
|---|
| 142 | last if !readField1(); |
|---|
| 143 | } |
|---|
| 144 | } |
|---|
| 145 | else |
|---|
| 146 | { |
|---|
| 147 | for ($i=0; $i<$n; $i++) |
|---|
| 148 | { |
|---|
| 149 | last if !readField2(); |
|---|
| 150 | } |
|---|
| 151 | } |
|---|
| 152 | return if ($i<$n); |
|---|
| 153 | return if !readString(); # display name |
|---|
| 154 | my $displayName=$str; |
|---|
| 155 | return if !readString(); # nick name |
|---|
| 156 | return if $str eq ""; |
|---|
| 157 | my $nickName=$str; |
|---|
| 158 | return if !readString(); # first name |
|---|
| 159 | my $firstName=$str; |
|---|
| 160 | return if !readString(); # last name |
|---|
| 161 | my $lastName=$str; |
|---|
| 162 | return if !readString(); # email |
|---|
| 163 | my $email=$str; |
|---|
| 164 | read(INFH, $buffer, 4); |
|---|
| 165 | $uin=unpack("V", $buffer); |
|---|
| 166 | return if ($uin==$own_uin); |
|---|
| 167 | $count++ if (!$uins{$uin}); |
|---|
| 168 | $uins{$uin}=1; |
|---|
| 169 | |
|---|
| 170 | my $fnUIN=$pathUsers.$uin.".uin"; |
|---|
| 171 | if (!-f $fnUIN) |
|---|
| 172 | { |
|---|
| 173 | open(OUTFH, ">$fnUIN") || die "can't open '$fnUIN' for writing.\n"; |
|---|
| 174 | print OUTFH "[user]\n"; |
|---|
| 175 | print OUTFH "Alias = ", $displayName ne "" ? $displayName : $nickName; |
|---|
| 176 | print OUTFH "\nFirstName = $firstName\n"; |
|---|
| 177 | print OUTFH "LastName = $lastName\n"; |
|---|
| 178 | print OUTFH "EMail = $email\n"; |
|---|
| 179 | print OUTFH "History = default\n"; |
|---|
| 180 | print OUTFH "Authorization =\n"; |
|---|
| 181 | print OUTFH "OnlineNotify =\n"; |
|---|
| 182 | print OUTFH "NewUser =\n"; |
|---|
| 183 | print OUTFH "NewMessages =\n"; |
|---|
| 184 | print OUTFH "Group =\n"; |
|---|
| 185 | print OUTFH "City =\n"; |
|---|
| 186 | print OUTFH "State =\n"; |
|---|
| 187 | print OUTFH "Homepage =\n"; |
|---|
| 188 | print OUTFH "Age =\n"; |
|---|
| 189 | print OUTFH "Sex =\n"; |
|---|
| 190 | print OUTFH "About =\n"; |
|---|
| 191 | print OUTFH "PhoneNumber =\n"; |
|---|
| 192 | print OUTFH "Country =\n"; |
|---|
| 193 | print OUTFH "VisibleList =\n"; |
|---|
| 194 | print OUTFH "InvisibleList =\n"; |
|---|
| 195 | close(OUTFH); |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | if ($verbose>=2) |
|---|
| 199 | { |
|---|
| 200 | print "display name : $displayName\n"; |
|---|
| 201 | print "nick name : $nickName\n"; |
|---|
| 202 | print "first name : $firstName\n"; |
|---|
| 203 | print "last name : $lastName\n"; |
|---|
| 204 | print "email : $email\n"; |
|---|
| 205 | print "uin : $uin\n\n"; |
|---|
| 206 | } |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | # read Žold styleŽ fields |
|---|
| 210 | sub readField1() |
|---|
| 211 | { |
|---|
| 212 | if (readString()) |
|---|
| 213 | { |
|---|
| 214 | if ($str ne "") |
|---|
| 215 | { |
|---|
| 216 | print "$str\n" if $verbose>=3; |
|---|
| 217 | my $n=2; |
|---|
| 218 | $n=5 if ($str eq "ClientFeatures" || |
|---|
| 219 | $str eq "Picture Update Date"); |
|---|
| 220 | $n=3 if ($str eq "UserHomepageDescription" || |
|---|
| 221 | $str eq "UserHomepageCategory"); |
|---|
| 222 | read(INFH, $buffer, $n); |
|---|
| 223 | return 1; |
|---|
| 224 | } |
|---|
| 225 | } |
|---|
| 226 | return 0; |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | # read Žnew styleŽ fields |
|---|
| 230 | sub readField2() |
|---|
| 231 | { |
|---|
| 232 | if (readString()) |
|---|
| 233 | { |
|---|
| 234 | if ($str ne "") |
|---|
| 235 | { |
|---|
| 236 | print "$str\n" if $verbose>=3; |
|---|
| 237 | my $c=getc(INFH); |
|---|
| 238 | my $n=-1; |
|---|
| 239 | $n=1 if $c eq "e"; |
|---|
| 240 | $n=2 if $c eq "f"; |
|---|
| 241 | $n=4 if ($c eq "i" || $c eq "h"); |
|---|
| 242 | if ($c eq "k") |
|---|
| 243 | { |
|---|
| 244 | $n=get(); |
|---|
| 245 | get(); |
|---|
| 246 | } |
|---|
| 247 | return 0 if $n==-1; |
|---|
| 248 | read(INFH, $buffer, $n) if $n>0; |
|---|
| 249 | return 1; |
|---|
| 250 | } |
|---|
| 251 | } |
|---|
| 252 | return 0; |
|---|
| 253 | } |
|---|
| 254 | |
|---|
| 255 | sub readString() |
|---|
| 256 | { |
|---|
| 257 | $str=""; |
|---|
| 258 | my $len=get(); |
|---|
| 259 | return 0 if get()!=0; |
|---|
| 260 | return 1 if ($len==0); |
|---|
| 261 | my $i, $c; |
|---|
| 262 | for ($i=0; $i<$len-1; $i++) |
|---|
| 263 | { |
|---|
| 264 | $c=getc(INFH); |
|---|
| 265 | return 0 if (ord($c)==0); |
|---|
| 266 | $str.=$c; |
|---|
| 267 | } |
|---|
| 268 | return 0 if get()!=0; |
|---|
| 269 | return 1; |
|---|
| 270 | } |
|---|
| 271 | |
|---|
| 272 | sub get() |
|---|
| 273 | { |
|---|
| 274 | my $c=getc(INFH); |
|---|
| 275 | return $c if !defined($c); |
|---|
| 276 | $c=ord($c); |
|---|
| 277 | return $c; |
|---|
| 278 | } |
|---|