3
# $Id: asn1c.cgi,v 1.20 2005/04/28 02:55:35 vlm Exp $
6
############################################################################
7
# The following preferences may be modified to match the local environment #
8
############################################################################
10
# Directory with the users data.
11
$TMPDIR = '/tmp/asn1c-cgi-jail/';
12
$SUIDHelper = './asn1c-suid-helper';
13
$SkeletonsDir = '/usr/local/share/asn1c'; # Will be needed only once
14
$CompilerLocation = '/usr/local/bin/asn1c'; # asn1c binary location
15
$HelpDBFile = $TMPDIR . '/var/db/Help-DB'; # Help requests database
16
$HashProgramPath = 'md5'; # Program to hash the input
17
$DM = 0750; # Directory mode for all mkdirs
18
$MaxHistoryItems = 5; # Number of items in History
19
$DynamicHistory = 'yes'; # Full/Short history
20
$safeFilenameRE = '[a-zA-Z0-9_]+[.a-zA-Z0-9_-]{0,200}'; # Safe filename regex
21
$safeTimeRE = '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}';
22
$ASN1C_Page = 'http://lionet.info/asn1c';
23
$HelpEmail = 'asn1c@lionet.info';
24
$defaultUserEmail = 'your@email-for-reply';
25
$DataERR = 65; # EX_DATAERR from <sysexits.h>
27
$warn = '<CENTER><FONT SIZE=+1><B>';
28
$unwarn = '</B></FONT></CENTER>';
30
$OpEnvFailed = 'Failed to create the operations\' environment:';
31
$RandFailed = 'No source of randomness';
32
$SandBoxInitFailed = 'User playground initialization failed';
34
$myName = $ENV{SCRIPT_NAME}; # URL of this particular script (without args)
36
$homePath = "<FONT FACE=Courier SIZE=-1>"
37
. "<A HREF=http://lionet.info>Home</A>"
38
. " >> <A HREF=$ASN1C_Page>asn1c</A>"
39
. " >> <A HREF=$ASN1C_Page/asn1c.cgi>Free Online ASN.1 Compiler</A>"
42
###################################################
43
# The code below rarely requires any modification #
44
###################################################
46
use CGI qw/param cookie header upload escapeHTML/;
48
$|=1; # Enable AutoFlush (for older versions of Perl)
50
my %binaryDecoders = (
52
type => 'X.509 Certificate',
53
typeExt => 'X.509 Certificate',
59
tap0311 => { order => 2,
61
typeExt => 'GSM TAP3-11 data',
67
tap0310 => { order => 3,
69
typeExt => 'GSM TAP3-10 data',
75
tap0309 => { order => 4,
77
typeExt => 'GSM TAP3-09 data',
83
mheg5 => { order => 5,
85
typeExt => 'ISO MHEG-5 data',
93
typeExt => 'BER encoded data',
96
msg => "<!-- Use 'enber' to convert it back into BER -->\n"
100
my $redirect = ''; # No redirection by default
101
my $redirect_bottom = ''; # No redirection text by default
102
my $content = ''; # Default content is empty
104
sub IssueRedirect() {
105
$redirect = "<META HTTP-EQUIV=\"Refresh\" "
106
. "CONTENT=\"5; URL=$myName\">";
107
$redirect_bottom = "<P><CENTER>This page will <A HREF=$myName>disappear</A> in 5 seconds.</CENTER>"
110
# If something goes wrong, this function is invoked to display the error message
112
local $_ = join("<BR>\n", @_);
113
$content = $warn . $_ . $unwarn;
117
# Make the directory name containing session files for the given Session ID
118
sub makeSessionDirName($$) {
119
my $pfx = shift; # Prefix is the name of the top-level directory
120
my $sid = shift; # Session identifier (md5)
121
$pfx . '/sessions/' . $sid . '/';
124
# Create ISO 8601 time string: "YYYY-MM-DDThh:mm:ss"
127
return $cachedTime if $cachedTime;
128
my @tm = localtime(time);
133
# Insert leading zeros
134
for(my $i = 0; $i < 5; $i++) {
135
$tm[$i] =~ s/^(.)$/0$1/;
138
$cachedTime = "$tm[5]-$tm[4]-$tm[3]T$tm[2]:$tm[1]:$tm[0]";
141
# Create the necessary environment for chrooting into.
142
sub prepareChrootEnvironment() {
143
return 1 if(-d $TMPDIR); # Envuronment already exists
144
mkdir $TMPDIR, $DM, or bark($OpEnvFailed, $!); # Global directory
145
mkdir $TMPDIR . 'sessions', $DM or bark($OpEnvFailed, $!); # sessions
146
mkdir $TMPDIR . 'bin', $DM or bark($OpEnvFailed, $!); # asn1c location
147
mkdir $TMPDIR . 'skeletons', $DM or bark($OpEnvFailed, $!); # asn1c data
148
mkdir $TMPDIR . 'var', $DM or bark($OpEnvFailed, $!);
149
mkdir $TMPDIR . 'var/db', $DM or bark($OpEnvFailed, $!);
151
# Merge in dynamic libc
152
mkdir $TMPDIR . 'lib', $DM or bark($OpEnvFailed, $!);
153
system("cd $TMPDIR/lib && "
155
. " /lib/ld-linux.*" # Linux ELF loader
156
. " /lib/libc.*" # Standard C library
157
. " /lib/libm.*" # Math library
158
. '; do ln $i; done');
159
} elsif(-d '/usr/lib') {
160
# There's no /lib on MacOS
161
mkdir $TMPDIR . 'usr', $DM or bark($OpEnvFailed, $!);
162
mkdir $TMPDIR . 'usr/lib', $DM or bark($OpEnvFailed, $!);
163
mkdir $TMPDIR . 'usr/lib/system', $DM or bark($OpEnvFailed, $!);
164
system("cd $TMPDIR/usr/lib && "
167
. " /usr/lib/libSystem.*"
168
. " /usr/lib/system/libmath*"
170
. '; do ln $i; done');
172
if(-d '/usr/libexec') {
174
mkdir $TMPDIR . 'usr', $DM;
175
mkdir $TMPDIR . 'usr/libexec',$DM or bark($OpEnvFailed, $!);
176
system("cd $TMPDIR/usr/libexec && "
177
. 'for i in /usr/libexec/ld-elf.*; do ln $i; done');
179
system("cp $CompilerLocation $TMPDIR/bin 2>/dev/null") == 0
180
or bark($OpEnvFailed, $!);
181
system("cp -r $SkeletonsDir/* $TMPDIR/skeletons >/dev/null 2>&1") == 0
182
or bark($OpEnvFailed, $!);
186
sub makeArchive($$) {
189
my $archName = $sandbox . '/+Archive.tgz';
192
system("cd $sandbox && "
193
. "for i in ./*.[ch]; do if [ -L \$i ]; then"
194
. " cp $TMPDIR/skeletons/\$i \$i.-;"
196
. " fi done && tar --dereference --ignore-failed-read --owner nobody --group nobody -zcf +tmp." . $$ . " *.[ch] Makefile* +Compiler.Log *.asn *.asn1"
197
. " && rm -f ./*.[ch] ./Makefile*"
198
. " && mv ./+tmp." . $$ . " $archName"
199
. " || rm -f ./+tmp." . $$);
200
undef unless -f $archName;
206
my $EnvironmentSetOK = prepareChrootEnvironment();
209
# Record user's email.
211
$userEmail = cookie('userEmail');
212
$userEmail = $defaultUserEmail unless defined($userEmail);
213
$tmpEmail = param('email');
214
if(defined($tmpEmail)) {
215
unless($tmpEmail =~ /^\s*([a-z0-9._+-]+@[a-z0-9.+-]+)\s*$/i) {
216
bark("Invalid email address: "
217
. "<B><FONT COLOR=darkred>$tmpEmail</FONT></B>");
219
my $previousEmail = $userEmail;
221
if($userEmail eq $defaultUserEmail) {
223
bark("Please enter <FONT COLOR=red>your own</FONT> "
224
. "valid email address, "
225
. "instead of default \"<FONT COLOR=darkred>$defaultUserEmail</FONT>\"");
227
if($userEmail ne $previousEmail) {
228
# Refresh cookie contents.
229
my $ck = cookie(-name=>'userEmail',
231
-path=>'/', -expires=>'+1d');
232
print "Set-Cookie: " . $ck . "\n";
237
# Check if full history requested.
239
$HistoryShow = cookie('HistoryShow');
240
$HistoryShow = '' unless $HistoryShow;
241
$tmpHSParam = param('history'); # Control cookie setting
242
if (defined($tmpHSParam)
243
&& $tmpHSParam ne $HistoryShow
244
&& $tmpHSParam =~ /^(full|short)$/) {
245
$HistoryShow = $tmpHSParam;
246
my $ck = cookie(-name=>'HistoryShow',
247
-value=>$HistoryShow,
248
-path=>'/', -expires=>'+1h');
249
print "Set-Cookie: " . $ck . "\n";
253
# Prepare the session and create the session directory.
254
# If session exists, perfom arguments checking and execute historic views.
256
$session = cookie('SessionID');
259
open(R, '/dev/urandom')
260
or open(R, '/dev/random')
261
or bark($RandFailed);
262
read(R, $session, 16) == 16 or bark("Not enough randomness");
263
if($ENV{HTTP_USER_AGENT}) {
264
$session .= $ENV{HTTP_USER_AGENT}; # Add randomness
266
my $pid = open(R, "-|");
267
if($pid == 0) { # Child
268
open(W, "| $HashProgramPath") or die;
273
$session =~ s/[^a-f0-9]//ig;
274
bark("md5 program is rotten here") if(length($session) != 32);
275
$sessionDir = makeSessionDirName($TMPDIR, $session);
276
mkdir($sessionDir, $DM) or bark($SandBoxInitFailed);
277
my $ck = cookie(-name=>'SessionID', -value=>$session,
278
-path=>'/', -expires=>'+1y');
279
print "Set-Cookie: " . $ck . "\n";
281
$session =~ s/[^a-f0-9]//ig;
282
bark("Nope, try again") if(length($session) != 32); # cool hacker?
284
# Make sure the session directory exists
285
$sessionDir = makeSessionDirName($TMPDIR, $session);
286
mkdir($sessionDir, $DM) or bark($SandBoxInitFailed)
287
unless(-d $sessionDir);
289
my $t = param('time');
290
my $file = param('file');
291
my $fetch = param('fetch');
292
my $show = param('show');
293
my $remove = param('remove');
295
unless(defined($t) && defined($file)
296
&& $t =~ /^${safeTimeRE}$/
297
&& $file =~ /^${safeFilenameRE}$/
298
&& ($fetch eq '' or $fetch =~ /^${safeFilenameRE}$/)
305
if($fetch ne '' or $show =~ /^(log|unber|tgz)$/ or $remove ne '') {
306
my $sandbox = $sessionDir . '/' . $t . '--' . $file;
310
my $tarball = makeArchive($TMPDIR, $sandbox);
312
or bark("Cannot create archive [$sandbox]");
314
printf("Content-Type: application/x-tar\n");
315
printf("Content-Encoding: gzip\n\n");
316
exec("cat $tarball");
318
} elsif($show eq 'unber') {
319
$targetFile = $sandbox . '/+UNBER';
320
} elsif($show eq 'log') {
321
$targetFile = $sandbox . '/+Compiler.Log';
322
} elsif($remove ne '') {
323
print "Status: 303 See Other\n";
324
print "Location: $myName\n";
327
$sessionDir . '/' . $t . '-R--' . $file);
330
$targetFile = $sandbox . '/' . $fetch;
332
if($targetFile ne '') {
333
open(I, '< ' . $targetFile)
334
or bark("Invalid or outdated request $!");
335
printf "Content-Type: text/plain\n\n";
343
# Check if transaction help is requested.
345
$transHelp = param('transHelp');
346
if(defined($transHelp)
347
&& $transHelp =~ /^([0-9]+)--($safeTimeRE)--($safeFilenameRE)$/) {
348
open(S, "| sendmail -it")
349
or bark("Cannot perform help request, "
350
. "please email to the address below");
351
print S "From: $userEmail\n";
352
print S "To: $HelpEmail\n";
353
print S "Subject: asn1c help requested for $3 ($1) by $userEmail\n";
356
print S "User $userEmail requested help with\n";
357
print S "$session/$2--$3 ($1)\n";
360
open(S, '>> ' . $sessionDir . '/' . $2 . '--' . $3 . '/+HelpReq')
361
or bark("Cannot perform help request, "
362
. "please email to the address below");
363
print S "$userEmail\n";
366
open(S, '>> ' . $HelpDBFile); # Susceptible to race condition.
367
print S "$session/$2--$1--$3\n";
370
$content = '<CENTER>Transaction '
371
. "$1 ($3) is marked for manual processing.<BR>"
372
. "Results will be mailed to "
373
. "<FONT COLOR=darkgreen>$userEmail</FONT> shortly."
379
open(LOG, ">> $sessionDir/+logfile") or bark("Sandbox error: $!");
380
print LOG isoTime() . "\tIP=$ENV{REMOTE_ADDR}";
381
print LOG "\tEMAIL=$userEmail" if($userEmail ne $defaultUserEmail);
384
@gotNames = param('file');
385
if($#gotNames != -1 && $gotNames[0] ne "") {
386
$gotFile = param('file');
387
@gotFiles = upload('file');
394
my $asnText = param('text');
396
if($#gotNames == -1) {
397
push(@gotNames, 'module.asn1') if $asnText;
400
# Make safe filenames
401
foreach my $fname (@gotNames) {
403
s/.*\///g; # Strip directory components
404
s/.*\\//g; # Strip directory components (DOS version)
405
s/^[.-]/_/g; # Don't allow filenames starting with a dot or a dash
406
s/[^._a-zA-Z0-9-]/_/g;
409
bark("Too strange filename: \"$fname\"");
411
$_ .= '.asn1' unless(/asn[1]{0,1}$/i);
412
@gotSafeNames = (@gotSafeNames, $_);
417
# Save the files and start compilation process.
419
if($#gotSafeNames >= 0) {
420
$transactionDir = isoTime() . '--' . join("-", @gotSafeNames);
421
print LOG "\tDST=$transactionDir";
423
my $sandbox = $sessionDir . '/' . $transactionDir;
424
mkdir($sandbox, $DM) or bark($SandBoxInitFailed);
426
open(O, '> ' . $sandbox . '/+Names');
427
print O join("\n", @gotNames);
428
open(O, '> ' . $sandbox . '/+safeNames');
429
print O join("\n", @gotSafeNames);
430
for(my $i = 0; $i <= $#gotSafeNames; $i++) {
431
my $name = $gotSafeNames[$i];
432
open(O, '> ' . $sandbox . '/'. $name);
433
if($#gotFiles == -1) {
434
print O $asnText; # param(text)
435
unlink $sessionDir . '/lastText';
436
symlink $transactionDir . '/' . $name,
437
$sessionDir . '/lastText';
439
# Save the uploaded data into specified file
440
print O while <$gotFile>;
445
my $inChDir = makeSessionDirName("/", $session) . $transactionDir;
447
my $optDebugL = param('optDebugL');
448
my $optE = param('optE');
449
my $optEF = param('optEF');
450
my $optNT = param('optNT');
451
my $optCN = param('optCN');
452
$options .= " -Wdebug-lexer"
453
if(defined($optDebugL) && $optDebugL eq "on");
454
$options .= " -E" if(defined($optE) && $optE eq "on");
455
$options .= " -EF" if(defined($optEF) && $optEF eq "on");
456
$options .= " -fnative-types" if(defined($optNT) && $optNT eq "on");
457
$options .= " -fcompound-names" if(defined($optCN) && $optNT eq "on");
458
my $CompileASN = "$TMPDIR/bin/asn1c -v | sed -e 's/^/-- /'"
459
. " > $sandbox/+Compiler.Log 2>&1"
460
. "; $SUIDHelper $TMPDIR $inChDir asn1c $options @gotSafeNames "
461
. " >> $sandbox/+Compiler.Log 2>&1"
462
. "; ec=\$?; echo \$ec > $sandbox/+ExitCode"
465
my $fType = param('fileType');
466
$fType = 'auto' unless $fType;
468
# Compile as ASN.1 text
469
if($fType eq 'auto' || $fType eq 'asn1') {
470
my $ec = system($CompileASN);
471
bark("Failed to initiate compilation process: $!")
472
if(!-r $sandbox . '/+ExitCode');
473
if($ec != (256 * $DataERR)) {
474
makeArchive($TMPDIR, $sandbox) unless $ec;
475
goto REGET; # Issue a clean GET request.
479
# Unrecognized ASN.1 module format.
480
# Try out several BER decoders.
481
foreach my $t (sort { $binaryDecoders{$a} cmp $binaryDecoders{$b} }
482
keys %binaryDecoders) {
483
next unless ($fType eq 'auto' or $fType eq $t);
484
my %dec = %{$binaryDecoders{$t}};
485
my $ec = system("$SUIDHelper $TMPDIR $inChDir $dec{exe} $dec{cmdopts} @gotSafeNames > $TMPDIR/$inChDir/+UNBER.tmp 2>&1");
486
next if ($ec != 0 and $t ne $fType
487
and (-s "$TMPDIR/$inChDir/+UNBER.tmp" < 1000));
488
last unless open(U, "> $TMPDIR/$inChDir/+UNBER");
489
my $fnames = escapeHTML(join(", ", @gotNames));
490
print U "<!-- $dec{type} structure of $fnames; "
491
. "decoded by '$dec{exe}' "
492
. "(c) Lev Walkin <vlm\@lionet.info> -->\n"
494
open(T, "< $TMPDIR/$inChDir/+UNBER.tmp");
498
open(U, "> $TMPDIR/$inChDir/+UNBER.TYPE");
499
print U $dec{typeExt};
502
# Indicate unclean exit.
503
open(U, "> $TMPDIR/$inChDir/+UNBER.EXIT");
509
unlink("$TMPDIR/$inChDir/+UNBER.tmp");
513
if($ENV{REQUEST_METHOD} ne 'GET') {
514
print "Status: 303 See Other\n";
515
print "Location: $myName\n";
520
if(-f $sessionDir . '/lastText') {
521
if(param('resetText')) {
522
unlink $sessionDir . '/lastText';
524
$rtt = "<BR> [<A HREF=$myName?resetText=ok>refill with sample ASN.1 module text</A>]";
529
"<FORM METHOD=POST ACTION=$myName ENCTYPE=\"multipart/form-data\">"
530
. "<TABLE BORDER=0><TR><TD> </TD><TD COLSPAN=2>"
531
. "Pick the ASN.1 module or binary encoded data file:\n"
532
. "</TD></TR><TD VALIGN=top><FONT COLOR=green>⇒</FONT></TD><TD>"
533
. "<SELECT NAME=fileType>"
534
. "<OPTION VALUE=auto>Autodetect type of file ..."
535
. "<OPTION VALUE=asn1>ASN.1 module text..."
536
. "<OPTION VALUE=ber>BER/DER/CER data ..."
537
. "<OPTION VALUE=tap0311>GSM TAP3-11 data ..."
538
. "<OPTION VALUE=tap0310>GSM TAP3-10 data ..."
539
. "<OPTION VALUE=tap0309>GSM TAP3-09 data ..."
540
. "<OPTION VALUE=mheg5>ISO MHEG-5 data ..."
541
. "<OPTION VALUE=x509>X.509 in DER (not PEM!)..."
543
. "</TD><TD ALIGN=right>"
544
. "<INPUT TYPE=file NAME=file SIZE=13>"
545
. "</TD></TR><TR><TD> </TD><TD COLSPAN=2>"
546
. "Or paste the ASN.1 text into the following area:$rtt\n"
547
. "</TD></TR><TD VALIGN=top><FONT COLOR=green>⇒</FONT></TD><TD COLSPAN=2>"
548
. "<TEXTAREA NAME=text ROWS=16 COLS=60>\n"
550
if(open(T, '< ' . $sessionDir . '/lastText')) {
551
$form .= escapeHTML($_) while <T>;
556
. " * This ASN.1 specification is given for illustrative purposes.\n"
557
. " * Your own ASN.1 module must be properly formed too!\n"
558
. " * (Make sure it has BEGIN/END statements, etc.)\n"
560
. "TestModule DEFINITIONS ::= \n"
563
. " TestType ::= SEQUENCE {\n"
564
. " num [PRIVATE 1] INTEGER,\n"
565
. " str UTF8String (SIZE(1..20)) OPTIONAL\n"
572
$form .= "</TEXTAREA>\n"
573
. "</TD></TR><TD COLSPAN=3 ID=extrasmall"
574
. " STYLE=\"border-left: dashed 1px rgb(200, 200, 200);\">\n"
575
. "These options may be used to control the compiler's behavior:<BR>\n"
576
. "<INPUT TYPE=checkbox NAME=optDebugL> Debug lexer (<I>-Wdebug-lexer</I>)<BR>\n"
577
. "<INPUT TYPE=checkbox NAME=optE> Just parse and dump (do not verify) (<I>-E</I>)<BR>\n"
578
. "<INPUT TYPE=checkbox NAME=optEF> Parse, verify validity, and dump (<I>-E -F</I>)<BR>\n"
579
. "<INPUT TYPE=checkbox NAME=optNT CHECKED=on> Use native machine types (e.g. <b>double</b> instead of <b>REAL_t</b>) (<I>-fnative-types</I>)<BR>\n"
580
. "<INPUT TYPE=checkbox NAME=optCN> Prevent name clashes in compiled output (<I>-fcompound-names</I>)<BR>\n"
581
. "<I>... the command line ASN.1 compiler, <A HREF=$ASN1C_Page>asn1c</A>, supports many other parameters</I>."
583
. "</TD></TR><TD VALIGN=top><FONT COLOR=green>⇒</FONT></TD><TD COLSPAN=2>"
584
. "<INPUT TYPE=submit VALUE=\"Proceed with ASN.1 compilation\">"
585
. " (<A HREF=$ASN1C_Page>What is ASN.1?</A>)"
586
. "</FORM></TD></TR></TABLE>";
589
# Gather previous transactions to generate the history page.
590
# The history page contains a list of several last ASN.1 files
591
# which were uploaded for compilation into the system
592
# by this particular browser (cookie-tracked).
594
opendir(SD, $sessionDir) or bark("Cannot open sandbox: $!");
595
my @transactions = sort { $b cmp $a }
596
(grep {/^${safeTimeRE}(-R)?--${safeFilenameRE}?$/}
598
my $CountHistoryItems = 0;
599
my $CountGlobalItems = 0;
600
my $CountShownItems = 0;
601
my $fullresp = param("fullresp");
602
foreach my $trans (sort { $b cmp $a } @transactions) {
604
next unless($trans =~ /^($safeTimeRE)--($safeFilenameRE)$/);
605
$CountHistoryItems++;
606
next if($CountHistoryItems > $MaxHistoryItems
607
&& $HistoryShow ne 'full');
610
my ($t, $f) = ($1, $2);
612
$t =~ s/T/ /; # "1999-01-02T13:53:12" => "1999-01-02 13:53:12"
614
# Global transaction number
615
my $tNum = 2 + $#transactions - $CountGlobalItems;
617
# Open the list of file names under which these files are known
618
# at the remote system.
619
open(I, '< ' . $sessionDir . '/' . $trans . '/+Names');
622
# Open the list of "safe" file names under which these files
623
# are known to our file system.
624
open(I, '< ' . $sessionDir . '/' . $trans . '/+safeNames');
627
# Create a list of real file names whith appropriate links to the
628
# "safe" file names for subsequent file fetching.
629
my @markedNames = ();
630
for(my $i = 0; $i <= $#Names; $i++) {
631
local $_ = "<A HREF=\"$myName?time="
632
. escapeHTML($origTime)
634
. "&fetch=$safeNames[$i]\" ID=modrefs>"
635
. escapeHTML($Names[$i])
637
@markedNames = (@markedNames, $_);
641
open(I, '< ' . $sessionDir . '/' . $trans . '/+ExitCode')
645
my $resText = "Show compiler log";
648
$results = "<FONT COLOR=darkgreen><B>"
649
. "Compiled OK</B></FONT><BR>\n";
650
} elsif(open(U, $sessionDir . '/' . $trans . '/+UNBER.TYPE')) {
651
my $type = <U>; close(U);
654
$msg = 'Treating input as ' . $type;
656
$msg = 'This looks like ' . $type;
658
$results = "<FONT COLOR=darkgreen><B>$msg</B></FONT><BR>\n";
659
if(-f $sessionDir . '/' . $trans . '/+UNBER.EXIT') {
660
$results = "<FONT COLOR=darkred SIZE=-1>"
661
. "<NOBR>$type:</NOBR> "
662
. "Broken encoding</FONT><BR>\n";
663
$ec = 'broken-input';
664
$resText = "Show $type decoding attempt";
667
$resText = "Show $type contents";
672
$why = "<NOBR>Broken input file</NOBR>" if $ec == $DataERR;
673
$results = "<FONT COLOR=darkred SIZE=-1>"
674
. "<NOBR>ASN.1 compiler error:</NOBR> "
675
. "$why</FONT><BR>\n";
678
$allowFetchResults = $ec eq "0"
679
&& (-f $sessionDir . '/' . $trans . '/+Archive.tgz'
680
|| -f $sessionDir . '/' . $trans . '/Makefile.am.sample');
683
. ($allowFetchResults ? '1. ' : '')
684
. "<A HREF=\"$myName/$f-$tNum.$resCode?time="
685
. escapeHTML($origTime)
687
. "&show=$resCode\">"
689
. ($ec ? ' ←' : '')
691
$results .= "<BR>\n<NOBR>"
692
. "2. <A HREF=\"$myName/$f-$tNum.tgz?time="
693
. escapeHTML($origTime)
696
. "Fetch compiled C sources (.tgz)</A> ←</NOBR>"
697
if $allowFetchResults;
700
open(H, '< ' . $sessionDir . '/' . $trans . '/+HelpResp')
702
open(H, '< ' . $sessionDir . '/' . $trans . '/+HelpReq')
703
and chomp($eml = <H>);
705
shift(@resp) while($resp[0] =~ /^$/);
706
if($fullresp eq $tNum) {
707
my $r = join("<BR>", @resp);
709
$results .= "<P><B>Analysis:</B>";
710
$results .= "<BR>(<A HREF=\"$myName\">Hide full explanation</A>)";
711
$results .= "<BLOCKQUOTE>";
713
$results .= "</BLOCKQUOTE>";
714
$results .= "(<A HREF=\"$myName\">Hide full explanation</A>)";
716
$results .= "<P><B>Analysis:</B> $resp[0]<BR>";
717
$results .= "(<A HREF=\"$myName?fullresp=$tNum\">Show full explanation</A>)";
720
$results .= "<P><FONT COLOR=darkred Family=Serif><B>"
721
. "Status: manual help requested<BR>"
722
. " by <FONT COLOR=black>$eml</FONT>,<BR>"
723
. "expect results in a few hours.<B></FONT>";
726
. "To get free help, leave a return address:<BR>"
727
. "<INPUT TYPE=text NAME=email VALUE=\"$userEmail\"><BR>"
728
. "<INPUT TYPE=hidden NAME=transHelp VALUE=\"$tNum--$trans\">"
729
. '<INPUT TYPE=Submit VALUE="Help me fix it!">'
731
$atLeastOneError = 1;
735
$trColor = ' BGCOLOR=#f8f8f8';
736
$trColor = ' BGCOLOR=#d0ffe0' if $CountHistoryItems == 1;
738
$history .= "<TR $trColor>"
739
. "<TH ALIGN=center ID=num>$tNum"
740
. "<BR><FONT FACE=serif>[<A ID=modrefs "
741
. "HREF=\"$myName?time="
742
. escapeHTML($origTime)
743
. "&file=$f&remove=$tNum\""
744
. ">×</A>]</FONT>"
746
. "<TD ALIGN=center>"
747
. join(", ", @markedNames)
749
. "<FORM METHOD=POST ACTION=$myName><TD ID=extrasmall>"
756
if($DynamicHistory eq 'yes') {
757
# [Un-]limit number of history items
758
$HistoryItemsHidden = $CountHistoryItems - $CountShownItems;
759
if($HistoryItemsHidden > 0) {
760
# Propose to expand the list.
762
$HistoryItemsHidden == 1 or $item = 'items';
763
$history .= "<TR BGCOLOR=white><TD COLSPAN=3 ALIGN=center>"
764
. "<A HREF=\"$myName?history=full\">"
765
. "Show full history</A> "
766
. "($HistoryItemsHidden hidden $item)"
768
} elsif($HistoryShow eq "full" && $#transactions >= $MaxHistoryItems) {
769
# Propose to shorten the list.
771
$MaxHistoryItems == 1 or $item = 'items';
772
$history .= "<TR BGCOLOR=white><TD COLSPAN=3 ALIGN=center>"
773
. "<A HREF=\"$myName?history=short\">"
774
. "Short history</A> ($MaxHistoryItems $item)"
780
$history = "<H3>History</H3>"
781
. "<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0 BGCOLOR=#404040 WIDTH=100%><TR><TD>"
782
. "<TABLE BORDER=0 CELLPADDING=5 CELLSPACING=1 WIDTH=100%>\n"
783
. "<TR BGCOLOR=#e0f0d0>"
784
. "<TH WIDTH=1%>N</TH><TH>Files processed</TH><TH>Result</TH>\n"
786
. $history . "</TABLE></TD></TR></TABLE><BR>\n";
788
if($atLeastOneError) {
789
$history .= "<FONT COLOR=#404040>"
790
. "<FONT COLOR=darkred><B>Bottom line:</B> ASN.1 compiler was unable to process some of the input.</FONT><BR>"
791
. "This is typically caused by syntax errors in the input files.\n"
792
. "Such errors are normally fixed by removing or adding a couple of characters in the ASN.1 module.<BR>\n"
793
. "<BR><B><FONT COLOR=darkred>⇒ Please consider clicking on the appropriate "<I>Help me fix it!</I>" button above.</FONT></B><BR>\n"
794
. "An email will be sent to a live person who will fix the ASN.1 module for you. (The typical turn-around time is less than 24 hours.)\n"
795
. "<BR>This is <B>free</B>, and highly advisable.\n"
796
. "<BR>Your request will help us make a better compiler!\n"
803
$history = "<FONT SIZE=+2 COLOR=#a0a0a0>"
804
. "[compiled results will appear here]</FONT>";
805
$histValign = 'center';
811
"<TABLE WIDTH=100% BORDER=0 CELLSPACING=5 CELLPADDING=5><TR><TD ID=inputbox VALIGN=top ROWSPAN=2 WIDTH=40%>\n"
812
. "<H3 ALIGN=center>ASN.1 Input</H3>\n"
814
. "</TD><TD WIDTH=60% HEIGHT=50% ALIGN=center VALIGN=$histValign>$history \n"
815
. "</TD></TR><TR><TD HEIGHT=50% VALIGN=bottom>"
816
. "<B>Privacy Note:</B> this page is tailored "
817
. "to your browser. "
818
. "<I>Other users will see their own (different) data.</I> "
819
. "(<A HREF=asn1c-privacy.html>Read more...</A>)"
820
. "</TD></TR></TABLE>";
822
$ua = $ENV{HTTP_USER_AGENT};
825
print LOG "\tUA=\"$ua\"";
826
print LOG "\n"; # Finalize logging record
830
print header(-expires=>'-1y');
832
# If environment has never been set up completely, remove it.
833
if($EnvironmentSetOK != 1 && $TMPDIR ne "/") {
834
system("rm -rf $TMPDIR/ >/dev/null 2>&1");
840
<TITLE>Free Online ASN.1 Compiler</TITLE>
841
<META NAME="Description" CONTENT="Free Online ASN.1 Compiler">
843
<STYLE TYPE="text/css">
847
font-family: monospace;
851
font-family: sans-serif;
855
font-family: sans-serif;
858
border-right: dashed 1px rgb(200, 200, 200);
862
font-family: sans-serif;
866
text-decoration: none;
869
text-decoration: underline;
885
<CENTER><ADDRESS><FONT SIZE=-1 FACE=Courier COLOR=#404040>
886
<A HREF=$ASN1C_Page>The ASN.1 Compiler</A>
887
Copyright © 2003, 2004, 2005
888
Lev Walkin <<A HREF=mailto:vlm@lionet.info?Subject=asn1c>vlm@lionet.info</A>>
889
</FONT></ADDRESS></CENTER>