Annotation of rat/map.pm, revision 1.2

1.1       albertel    1: # The LearningOnline Network with CAPA
                      2: # routines for modyfing .sequence and .page files
                      3: #
1.2     ! raeburn     4: # $Id: map.pm,v 1.1 2006/08/17 22:35:51 albertel Exp $
1.1       albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
                     28: 
                     29: package LONCAPA::map;
                     30: 
                     31: use HTML::TokeParser;
                     32: use Apache::lonnet;
                     33: use Apache::lonlocal;
                     34: use File::Copy;
                     35: use LONCAPA;
                     36: 
                     37: use vars qw(@order @resources @resparms @zombies);
                     38: 
                     39: # Mapread read maps into global arrays @links and @resources, determines status
                     40: # sets @order - pointer to resources in right order
                     41: # sets @resources - array with the resources with correct idx
                     42: #
                     43: sub mapread {
                     44:     my ($fn)= @_;
                     45: 
                     46:     my @links;
                     47: 
                     48:     @resources=('');
                     49:     @order=();
                     50:     @resparms=();
                     51:     @zombies=();
                     52: 
                     53:     my ($outtext,$errtext)=&loadmap($fn,'');
                     54:     if ($errtext) { return ($errtext,2); }
                     55: 
                     56: # -------------------------------------------------------------------- Read map
                     57:     foreach (split(/\<\&\>/,$outtext)) {
                     58: 	my ($command,$number,$content)=split(/\<\:\>/,$_);
                     59:         if ($command eq 'objcont') {
                     60: 	    my ($title,$src,$ext,$type)=split(/\:/,$content);
                     61: 	    if ($ext eq 'cond') { next; }
                     62: 	    if ($type ne 'zombie') {
                     63: 		$resources[$number]=$content;
                     64: 	    } else {
                     65: 		$zombies[$number]=$content;
                     66: 	    }
                     67:         }
                     68:         if ($command eq 'objlinks') {
                     69:             $links[$number]=$content;
                     70:         }
                     71:         if ($command eq 'objparms') {
                     72: 	    if ($resparms[$number]) {
                     73: 		$resparms[$number].='&&&'.$content;
                     74: 	    } else {
                     75: 		$resparms[$number]=$content;
                     76: 	    }
                     77:         }
                     78:     }
                     79: # ------------------------------------------------------- Is this a linear map?
                     80:     my @starters;
                     81:     my @endings;
                     82: 
                     83:     foreach (@links) {
                     84:         if (defined($_)) {
                     85: 	    my ($start,$end,$cond)=split(/\:/,$_);
                     86:             if ((defined($starters[$start])) || (defined($endings[$end]))) { 
                     87: 		return
                     88: 		    (&mt('Map has branchings. Use advanced editor.'),1);
                     89:             }
                     90: 	    $starters[$start]=1;
                     91: 	    $endings[$end]=1;
                     92: 	    if ($cond) {
                     93: 		return
                     94: 		    (&mt('Map has conditions. Use advanced editor.'),1);
                     95:             }
                     96: 	}
                     97:     }
                     98: 
                     99:     for (my $i=1; $i<=$#resources; $i++) {
                    100:         if (defined($resources[$i])) {
                    101: 	    unless (($starters[$i]) || ($endings[$i])) {
                    102:                 return
                    103: 		    (&mt('Map has unconnected resources. Use advanced editor.'),1);
                    104:             }
                    105:         }
                    106:     }
                    107: # ---------------------------------------------- Did we just read an empty map?
                    108:     if ($#resources<1) {
                    109:         undef $resources[0];
                    110: 	$resources[1]=':::start';
                    111:         $resources[2]=':::finish';
                    112:     }
                    113: # -------------------------------------------------- This is a linear map, sort
                    114: 
                    115:     my $startidx=0;
                    116:     my $endidx=0;
                    117:     for (my $i=0; $i<=$#resources; $i++) {
                    118:         if (defined($resources[$i])) {
                    119:             my ($title,$url,$ext,$type)=split(/\:/,$resources[$i]);
                    120: 	    if ($type eq 'start') { $startidx=$i; }
                    121:             if ($type eq 'finish') { $endidx=$i; }
                    122:         }
                    123:     }
                    124:     my $k=0;
                    125:     my $currentidx=$startidx;
                    126:     $order[$k]=$currentidx;
                    127:     for (my $i=0; $i<=$#resources; $i++) {
                    128:         foreach (@links) {
                    129: 	    my ($start,$end)=split(/\:/,$_);
                    130:             if ($start==$currentidx) {
                    131: 		$currentidx=$end;
                    132:                 $k++;
                    133:                 $order[$k]=$currentidx;
                    134:                 last;
                    135:             }
                    136:         }
                    137:         if ($currentidx==$endidx) { last; }
                    138:     }
                    139:     return $errtext;
                    140: }
                    141: 
                    142: # ---------------------------------------------- Read a map as well as possible
                    143: # Also used by the sequence handler
                    144: # Call lonsequence::attemptread to read from resource space
                    145: #
                    146: sub attemptread {
                    147:     my $fn=shift;
                    148: 
                    149:     my @links;
                    150:     my @theseres;
                    151: 
                    152:     my ($outtext,$errtext)=&loadmap($fn,'');
                    153:     if ($errtext) { return @theseres }
                    154: 
                    155: # -------------------------------------------------------------------- Read map
                    156:     foreach (split(/\<\&\>/,$outtext)) {
                    157: 	my ($command,$number,$content)=split(/\<\:\>/,$_);
                    158:         if ($command eq 'objcont') {
                    159: 	    my ($title,$src,$ext,$type)=split(/\:/,$content);
                    160: 	    unless ($type eq 'zombie') {
                    161: 		$theseres[$number]=$content;
                    162: 	    }
                    163:         }
                    164:         if ($command eq 'objlinks') {
                    165:             $links[$number]=$content;
                    166:         }
                    167:     }
                    168: 
                    169: # --------------------------------------------------------------- Sort, sort of
                    170: 
                    171:     my @objsort;
                    172: 
                    173:     for (my $k=1;$k<=$#theseres;$k++) {
                    174: 	if (defined($theseres[$k])) {
                    175: 	    $objsort[$#objsort+1]=$k;
                    176: 	}
                    177:     }
                    178: 
                    179:     for (my $k=1;$k<=$#links;$k++) {
                    180: 	if (defined($links[$k])) {
                    181: 	    my @data1=split(/\:/,$links[$k]);
                    182: 	    my $kj=-1;
                    183: 	    for (my $j=0;$j<=$#objsort;$j++) {
                    184: 		if ((split(/\:/,$objsort[$j]))[0]==$data1[0]) {
                    185: 		    $kj=$j;
                    186: 		}
                    187: 	    }
                    188: 	    if ($kj!=-1) { $objsort[$kj].=':'.$data1[1]; }
                    189: 	}
                    190:     }
                    191:     for (my $k=0;$k<=$#objsort;$k++) {
                    192: 	for (my $j=0;$j<=$#objsort;$j++) {
                    193: 	    if ($k!=$j) {
                    194: 		my @data1=split(/\:/,$objsort[$k]);
                    195: 		my @data2=split(/\:/,$objsort[$j]);
                    196: 		my $dol=$#data1+1;
                    197: 		my $dtl=$#data2+1;
                    198: 		if ($dol+$dtl<1000) {
                    199: 		    for (my $kj=1;$kj<$dol;$kj++) {
                    200: 			if ($data1[$kj]==$data2[0]) {
                    201: 			    for ($ij=1;$ij<$dtl;$ij++) {
                    202: 				$data1[$#data1+1]=$data2[$ij];
                    203: 			    }
                    204: 			}
                    205: 		    }
                    206: 		    for (my $kj=1;$kj<$dtl;$kj++) {
                    207: 			if ($data2[$kj]==$data1[0]) {
                    208: 			    for ($ij=1;$ij<$dol;$ij++) {
                    209: 				$data2[$#data2+1]=$data1[$ij];
                    210: 			    }
                    211: 			}
                    212: 		    }
                    213: 		    $objsort[$k]=join(':',@data1);
                    214: 		    $objsort[$j]=join(':',@data2);
                    215: 		}
                    216: 	    }
                    217: 	} 
                    218:     }
                    219: # ---------------------------------------------------------------- Now sort out
                    220: 
                    221:     @objsort=sort {
                    222: 	my @data1=split(/\:/,$a);
                    223: 	my @data2=split(/\:/,$b);
                    224: 	my $rvalue=0;
                    225: 	for (my $k=1;$k<=$#data1;$k++) {
                    226: 	    if ($data1[$k]==$data2[0]) { $rvalue--; }
                    227: 	}
                    228: 	for (my $k=1;$k<=$#data2;$k++) {
                    229: 	    if ($data2[$k]==$data1[0]) { $rvalue++; }
                    230: 	}
                    231: 	if ($rvalue==0) { $rvalue=$#data2-$#data1; }
                    232: 	$rvalue;
                    233:     } @objsort;
                    234: 
                    235:     my @outres;
                    236: 
                    237:     for ($k=0;$k<=$#objsort;$k++) {
                    238: 	$outres[$k]=$theseres[(split(/\:/,$objsort[$k]))[0]];
                    239:     }
                    240: 
                    241:     return @outres;
                    242: }
                    243: 
                    244: # ------------------------------------- Revive zombie idx or get unused number
                    245: 
                    246: sub getresidx {
                    247:     my $url=shift;
                    248:     my $max=1+($#resources>$#zombies?$#resources:$#zombies);
                    249:     unless ($url) { return $max; }
                    250:     for (my $i=0; $i<=$#zombies; $i++) {
                    251: 	my ($title,$src,$ext,$type)=split(/\:/,$zombies[$i]);
                    252: 	if ($src eq $url) {
                    253: 	    undef($zombies[$i]);
                    254: 	    return $i;
                    255: 	}
                    256:     }
                    257:     return $max;
                    258: }
                    259: 
                    260: # --------------------------------------------------------------- Make a zombie
                    261: 
                    262: sub makezombie {
                    263:     my $idx=shift;
                    264:     my ($name,$url,$ext)=split(/\:/,$resources[$idx]);
                    265:     my $now=time;
                    266:     $zombies[$idx]=$name.
                    267: 	' [('.$now.','.$env{'user.name'}.','.$env{'user.domain'}.')]:'.
                    268: 	$url.':'.$ext.':zombie';
                    269: }
                    270: 
                    271: # ----------------------------------------------------------- Paste into target
                    272: # modifies @order, @resources
                    273: 
                    274: sub pastetarget {
                    275:     my ($after,@which)=@_;
                    276:     my @insertorder=();
                    277:     foreach (@which) {
                    278:         if (defined($_)) {
                    279: 	    my ($name,$url)=split(/\=/,$_);
                    280:             $name=&unescape($name);
                    281:             $url=&unescape($url);
                    282:             if ($url) {
                    283: 		my $idx=&getresidx($url);
                    284: 		$insertorder[$#insertorder+1]=$idx;
                    285: 		my $ext='false';
                    286: 		if ($url=~/^http\:\/\//) { $ext='true'; }
                    287: 		$url=~s/\:/\&colon;/g;
                    288: 		$name=~s/\:/\&colon;/g;
                    289: 		$resources[$idx]=$name.':'.$url.':'.$ext.':normal:res';
                    290: 	    }
                    291:         }
                    292:     }
                    293:     my @oldorder=splice(@order,$after);
                    294:     @order=(@order,@insertorder,@oldorder);
                    295: }
                    296: 
                    297: # ------------------------------------------------ Get start and finish correct
                    298: # modifies @resources
                    299: 
                    300: sub startfinish {
                    301: # Remove all start and finish
                    302:     foreach (@order) {
                    303: 	my ($name,$url,$ext)=split(/\:/,$resources[$_]);
                    304:         if ($url=~/http\&colon\:\/\//) { $ext='true'; }
                    305:         $resources[$_]=$name.':'.$url.':'.$ext.':normal:res';
                    306:     }
                    307: # Garbage collection
                    308:     my $stillchange=1;
                    309:     while (($#order>1) && ($stillchange)) {
                    310: 	$stillchange=0;
                    311: 	for (my $i=0;$i<=$#order;$i++) {
                    312: 	    my ($name,$url,$ext)=split(/\:/,$resources[$order[$i]]);
                    313: 	    unless ($url) {
                    314: # Take out empty resource
                    315: 		for (my $j=$i+1;$j<=$#order;$j++) {
                    316: 		    $order[$j-1]=$order[$j];
                    317: 		}
                    318: 		$#order--;
                    319: 		$stillchange=1;
                    320: 		last;
                    321: 	    }
                    322: 	}
                    323:     }
                    324: # Put in a start resource
                    325:     my ($name,$url,$ext)=split(/\:/,$resources[$order[0]]);
                    326:     $resources[$order[0]]=$name.':'.$url.':'.$ext.':start:res';
                    327: # Make sure this has at least start and finish
                    328:     if ($#order==0) {
                    329: 	$resources[&getresidx()]='::false';
                    330: 	$order[1]=$#resources;
                    331:     }
                    332: # Make the last one a finish resource
                    333:     ($name,$url,$ext)=split(/\:/,$resources[$order[$#order]]);
                    334:     $resources[$order[$#order]]=$name.':'.$url.':'.$ext.':finish:res';
                    335: }
                    336: 
                    337: # ------------------------------------------------------------------- Store map
                    338: 
                    339: sub storemap {
                    340:     my $realfn=shift;
                    341:     my $fn=$realfn;
                    342: # unless this is forced to work from the original file, use a temporary file
                    343: # instead
                    344:     unless (shift) {
                    345: 	$fn=$realfn.'.tmp';
                    346: 	unless (-e $fn) {
                    347: 	    copy($realfn,$fn);
                    348: 	}
                    349:     }
                    350: # store data either into tmp or real file
                    351:     &startfinish();
                    352:     my $output='graphdef<:>no';
                    353:     my $k=1;
                    354:     for (my $i=0; $i<=$#order; $i++) {
                    355:         if (defined($resources[$order[$i]])) {
                    356: 	    $output.='<&>objcont<:>'.$order[$i].'<:>'.$resources[$order[$i]];
                    357:         }
                    358: 	if (defined($resparms[$order[$i]])) {
                    359: 	    foreach (split('&&&',$resparms[$order[$i]])) {
                    360: 		if ($_) {
                    361: 		    $output.='<&>objparms<:>'.$order[$i].'<:>'.$_;
                    362: 		}
                    363: 	    }
                    364: 	}
                    365:         if (defined($order[$i+1])) {
                    366: 	    if (defined($resources[$order[$i+1]])) {
                    367: 		$output.='<&>objlinks<:>'.$k.'<:>'.
                    368: 		    $order[$i].':'.$order[$i+1].':0';
                    369: 		$k++;
                    370:             }
                    371:         }
                    372:     }
                    373:     for (my $i=0; $i<=$#zombies; $i++) {
                    374:         if (defined($zombies[$i])) {
                    375: 	    $output.='<&>objcont<:>'.$i.'<:>'.$zombies[$i];
                    376:         }
                    377:     }
                    378:     $output=~s/http\&colon\;\/\///g;
                    379:     $env{'form.output'}=$output;
                    380:     return &loadmap($fn,&savemap($fn,''));
                    381: }
                    382: 
                    383: # ------------------------------------------ Store and get parameters in global
                    384: 
                    385: sub storeparameter {
                    386:     my ($to,$name,$value,$ptype)=@_;
                    387:     my $newentry='';
                    388:     my $nametype='';
                    389:     foreach (split('&&&',$resparms[$to])) {
                    390: 	my ($thistype,$thisname,$thisvalue)=split('___',$_);
                    391: 	if ($thisname) {
                    392: 	    unless ($thisname eq $name) {
                    393: 		$newentry.=$_.'&&&';
                    394: 	    } else {
                    395: 		$nametype=$thistype;
                    396: 	    }
                    397: 	}
                    398:     }
                    399:     unless ($ptype) { $ptype=$nametype; }
                    400:     unless ($ptype) { $ptype='string'; }
                    401:     $newentry.=$ptype.'___'.$name.'___'.$value;
                    402:     $resparms[$to]=$newentry;
                    403: }
                    404: 
                    405: sub delparameter {
                    406:     my ($to,$name)=@_;
                    407:     my $newentry='';
                    408:     my $nametype='';
                    409:     foreach (split('&&&',$resparms[$to])) {
                    410: 	my ($thistype,$thisname,$thisvalue)=split('___',$_);
                    411: 	if ($thisname) {
                    412: 	    unless ($thisname eq $name) {
                    413: 		$newentry.=$_.'&&&';
                    414: 	    }
                    415: 	}
                    416:     }
                    417:     $resparms[$to]=$newentry;
                    418: }
                    419: 
                    420: sub getparameter {
                    421:     my ($to,$name)=@_;
                    422:     my $value=undef;
                    423:     my $ptype=undef;
                    424:     foreach (split('&&&',$resparms[$to])) {
                    425: 	my ($thistype,$thisname,$thisvalue)=split('___',$_);
                    426: 	if ($thisname eq $name) {
                    427: 	    $value=$thisvalue;
                    428: 	    $ptype=$thistype;
                    429: 	}
                    430:     }
                    431:     return ($value,$ptype);
                    432: }
                    433: 
                    434: # ------------------------------------------------------------- From RAT to XML
                    435: 
                    436: sub qtescape {
                    437:     my $str=shift;
                    438:     $str=~s/\&colon;/\:/g;
                    439:     $str=~s/\&\#58\;/\:/g;
                    440:     $str=~s/\&\#39\;/\'/g;
                    441:     $str=~s/\&\#44\;/\,/g;
                    442:     $str=~s/\"/\&\#34\;/g;
                    443:     return $str;
                    444: }
                    445: 
                    446: # ------------------------------------------------------------- From XML to RAT
                    447: 
                    448: sub qtunescape {
                    449:     my $str=shift;
                    450:     $str=~s/\:/\&colon\;/g;
                    451:     $str=~s/\'/\&\#39\;/g;
                    452:     $str=~s/\,/\&\#44\;/g;
                    453:     $str=~s/\"/\&\#34\;/g;
                    454:     return $str;
                    455: }
                    456: 
                    457: # --------------------------------------------------------- Loads map from disk
                    458: 
                    459: sub loadmap {
                    460:     my ($fn,$errtext,$infotext)=@_;
                    461:     if ($errtext) { return('',$errtext); }
                    462:     my $outstr='';
                    463:     my @obj=();
                    464:     my @links=();
                    465:     my $instr='';
                    466:     if ($fn=~/^\/*uploaded\//) {
                    467:         $instr=&Apache::lonnet::getfile($fn);
                    468:     } elsif (-e $fn) {
                    469:         my @content=();
                    470:         {
                    471: 	    open(my $fh,"<$fn");
                    472:             @content=<$fh>;
                    473:         }
                    474:         $instr=join('',@content);
                    475:     }
                    476:     if ($instr eq -2) {
                    477:         $errtext.='Map not loaded: An error occured while trying to load the map.';
1.2     ! raeburn   478:     } elsif ($instr eq '-1') {
        !           479:         $errtext.=&mt('Map not loaded: The file [_1] does not exist.',$fn);
1.1       albertel  480:     } elsif ($instr) {
                    481:         my $parser = HTML::TokeParser->new(\$instr);
                    482:         my $token;
                    483:         my $graphmode=0;
                    484: 
                    485:         $fn=~/\.(\w+)$/;
                    486:         $outstr="mode<:>$1";
                    487: 
                    488:         while ($token = $parser->get_token) {
                    489: 	    if ($token->[0] eq 'S') {
                    490:                 if ($token->[1] eq 'map') {
                    491: 		    $graphmode=($token->[2]->{'mode'} eq 'rat/graphical');
                    492:                 } elsif ($token->[1] eq 'resource') {
                    493: # -------------------------------------------------------------------- Resource
                    494:                     $outstr.='<&>objcont';
                    495:                     if (defined($token->[2]->{'id'})) {
                    496: 			$outstr.='<:>'.$token->[2]->{'id'};
                    497:                         if ($obj[$token->[2]->{'id'}]==1) {
                    498: 			    $errtext.='Error: multiple use of ID '.
                    499: 				$token->[2]->{'id'}.'. ';
                    500:                         }
                    501:                         $obj[$token->[2]->{'id'}]=1; 
                    502:                     } else {
                    503:                         my $i=1;
                    504:                         while (($i<=$#obj) && ($obj[$i]!=0)) { $i++; }
                    505:                         $outstr.='<:>'.$i;
                    506:                         $obj[$i]=1;
                    507:                     }
                    508:                     $outstr.='<:>';
                    509:                     $outstr.=qtunescape($token->[2]->{'title'}).":";
                    510:                     $outstr.=qtunescape($token->[2]->{'src'}).":";
                    511:                     if ($token->[2]->{'external'} eq 'true') {
                    512:                         $outstr.='true:';
                    513:                     } else {
                    514:                         $outstr.='false:';
                    515:                     }
                    516:                     if (defined($token->[2]->{'type'})) {
                    517: 			$outstr.=$token->[2]->{'type'}.':';
                    518:                     }  else {
                    519:                         $outstr.='normal:';
                    520:                     }
                    521: 		    if ($token->[2]->{'type'} ne 'zombie') {
                    522: 			$outstr.='res';
                    523: 		    } else {
                    524:                         $outstr.='zombie';
                    525: 		    }
                    526:                 } elsif ($token->[1] eq 'condition') {
                    527: # ------------------------------------------------------------------- Condition
                    528:                     $outstr.='<&>objcont';
                    529:                     if (defined($token->[2]->{'id'})) {
                    530: 			$outstr.='<:>'.$token->[2]->{'id'};
                    531:                         if ($obj[$token->[2]->{'id'}]==1) {
                    532: 			    $errtext.='Error: multiple use of ID '.
                    533: 				$token->[2]->{'id'}.'. ';
                    534:                         }
                    535:                         $obj[$token->[2]->{'id'}]=1; 
                    536:                     } else {
                    537:                         my $i=1;
                    538:                         while (($i<=$#obj) && ($obj[$i]!=0)) { $i++; }
                    539:                         $outstr.='<:>'.$i;
                    540:                         $obj[$i]=1;
                    541:                     }
                    542:                     $outstr.='<:>';
                    543:                     $outstr.=qtunescape($token->[2]->{'value'}).':';
                    544:                     if (defined($token->[2]->{'type'})) {
                    545: 			$outstr.=$token->[2]->{'type'}.':';
                    546:                     } else {
                    547:                         $outstr.='normal:';
                    548:                     }
                    549:                     $outstr.='cond';
                    550:                 } elsif ($token->[1] eq 'link') {
                    551: # ----------------------------------------------------------------------- Links
                    552:                     $outstr.='<&>objlinks';
                    553: 		    
                    554: 		    if (defined($token->[2]->{'index'})) {
                    555: 			if ($links[$token->[2]->{'index'}]) {
                    556: 			    $errtext.='Error: multiple use of link index '.
                    557: 				$token->[2]->{'index'}.'. ';
                    558: 			}
                    559: 			$outstr.='<:>'.$token->[2]->{'index'};
                    560: 			$links[$token->[2]->{'index'}]=1;
                    561: 		    } else {
                    562: 			my $i=1;
                    563: 			while (($i<=$#links) && ($links[$i]==1)) { $i++; }
                    564: 			$outstr.='<:>'.$i;
                    565: 			$links[$i]=1;
                    566: 		    }
                    567: 		    
                    568:                     $outstr.='<:>'.$token->[2]->{'from'}.
                    569: 			':'.$token->[2]->{'to'};
                    570:                     if (defined($token->[2]->{'condition'})) {
                    571: 			$outstr.=':'.$token->[2]->{'condition'};
                    572:                     } else {
                    573:  			$outstr.=':0';
                    574:                     }
                    575: # ------------------------------------------------------------------- Parameter
                    576:                 } elsif ($token->[1] eq 'param') {
                    577:                     $outstr.='<&>objparms<:>'.$token->[2]->{'to'}.'<:>'.
                    578: 			$token->[2]->{'type'}.'___'.$token->[2]->{'name'}.
                    579: 			'___'.$token->[2]->{'value'};
                    580:                 } elsif ($graphmode) {
                    581: # --------------------------------------------- All other tags (graphical only)
                    582:                     $outstr.='<&>'.$token->[1];
                    583:                     if (defined($token->[2]->{'index'})) {
                    584: 			$outstr.='<:>'.$token->[2]->{'index'};
                    585:                         if ($token->[1] eq 'obj') {
                    586: 			    $obj[$token->[2]->{'index'}]=2;
                    587:                         }
                    588:                     }
                    589:                     $outstr.='<:>'.$token->[2]->{'value'};
                    590:                 }
                    591:             }
                    592:         }
                    593: 
                    594:     } else {
                    595:         $errtext.='Map not loaded: The file does not exist. ';
                    596:     }
                    597:     return($outstr,$errtext,$infotext);
                    598: }
                    599: 
                    600: 
                    601: # ----------------------------------------------------------- Saves map to disk
                    602: 
                    603: sub savemap {
                    604:     my ($fn,$errtext)=@_;
                    605:     my $infotext='';
                    606:     my %alltypes;
                    607:     my %allvalues;
                    608:     if (($fn=~/\.sequence(\.tmp)*$/) ||
                    609:         ($fn=~/\.page(\.tmp)*$/)) {
                    610: 	
                    611: # ------------------------------------------------------------- Deal with input
                    612:         my @tags=split(/<&>/,$env{'form.output'});
                    613:         my $outstr='';
                    614:         my $graphdef=0;
                    615:         if ($tags[0] eq 'graphdef<:>yes') {
                    616: 	    $outstr='<map mode="rat/graphical">'."\n";
                    617:             $graphdef=1;
                    618:         } else {
                    619:             $outstr="<map>\n";
                    620:         }
                    621:         foreach (@tags) {
                    622: 	    my @parts=split(/<:>/,$_);
                    623: 	    if ($parts[0] eq 'objcont') {
                    624: 		my @comp=split(/:/,$parts[$#parts]);
                    625: # --------------------------------------------------------------- Logical input
                    626: 		if (($comp[$#comp] eq 'res') || ($comp[$#comp] eq 'zombie')) {
                    627: 		    $comp[0]=qtescape($comp[0]);
                    628: 		    $comp[1]=qtescape($comp[1]);
                    629: 		    if ($comp[2] eq 'true') {
                    630: 			if ($comp[1]!~/^http\:\/\//) {
                    631: 			    $comp[1]='http://'.$comp[1];
                    632: 			}
                    633: 			$comp[1].='" external="true';
                    634: 		    } else {
                    635: 			if ($comp[1]=~/^http\:\/\//) {
                    636: 			    $comp[1]=~s/^http\:\/\/[^\/]*\//\//;
                    637: 			}
                    638: 		    }
                    639: 		    $outstr.='<resource id="'.$parts[1].'" src="'
                    640: 			.$comp[1].'"';
                    641: 		    
                    642: 		    if (($comp[3] ne '') && ($comp[3] ne 'normal')) {
                    643: 			$outstr.=' type="'.$comp[3].'"';
                    644: 		    }
                    645: 		    if ($comp[0] ne '') {
                    646: 			$outstr.=' title="'.$comp[0].'"';
                    647: 		    }
                    648: 		    $outstr.=" />\n";
                    649: 		} elsif ($comp[$#comp] eq 'cond') {
                    650: 		    $outstr.='<condition id="'.$parts[1].'"';
                    651: 		    if (($comp[1] ne '') && ($comp[1] ne 'normal')) {
                    652: 			$outstr.=' type="'.$comp[1].'"';
                    653: 		    }
                    654: 		    $outstr.=' value="'.qtescape($comp[0]).'"';
                    655: 		    $outstr.=" />\n";
                    656: 		}
                    657: 	    } elsif ($parts[0] eq 'objlinks') {
                    658: 		my @comp=split(/:/,$parts[$#parts]);
                    659: 		$outstr.='<link';
                    660: 		$outstr.=' from="'.$comp[0].'"';
                    661: 		$outstr.=' to="'.$comp[1].'"';
                    662: 		if (($comp[2] ne '') && ($comp[2]!=0)) {
                    663: 		    $outstr.=' condition="'.$comp[2].'"';
                    664: 		}
                    665: 		$outstr.=' index="'.$parts[1].'"';
                    666: 		$outstr.=" />\n";
                    667: 	    } elsif ($parts[0] eq 'objparms') {
                    668: 		undef %alltypes;
                    669: 		undef %allvalues;
                    670: 		foreach (split(/:/,$parts[$#parts])) {
                    671: 		    my ($type,$name,$value)=split(/\_\_\_/,$_);
                    672: 		    $alltypes{$name}=$type;
                    673: 		    $allvalues{$name}=$value;
                    674: 		}
                    675: 		foreach (keys %allvalues) {
                    676: 		    if ($allvalues{$_} ne '') {
                    677: 			$outstr.='<param to="'.$parts[1].'" type="'
                    678: 			    .$alltypes{$_}.'" name="'.$_
                    679: 			    .'" value="'.$allvalues{$_}.'" />'
                    680: 			    ."\n";
                    681: 		    }
                    682: 		}
                    683: 	    } elsif (($parts[0] ne '') && ($graphdef)) {
                    684: # ------------------------------------------------------------- Graphical input
                    685: 		$outstr.='<'.$parts[0];
                    686: 		if ($#parts==2) {
                    687: 		    $outstr.=' index="'.$parts[1].'"';
                    688: 		}
                    689: 		$outstr.=' value="'.qtescape($parts[$#parts]).'" />'."\n";
                    690: 	    }
                    691:         }
                    692:         $outstr.="</map>\n";
                    693: 	if ($fn=~/^\/*uploaded\/(\w+)\/(\w+)\/(.*)$/) {
                    694: 	    $env{'form.output'}=$outstr;
                    695:             my $result=&Apache::lonnet::finishuserfileupload($2,$1,
                    696: 							     'output',$3);
                    697: 	    if ($result != m|^/uploaded/|) {
                    698: 		$errtext.='Map not saved: A network error occured when trying to save the map. ';
                    699: 	    }
                    700:         } else {
                    701: 	    if (open(my $fh,">$fn")) {
                    702: 		print $fh $outstr;
                    703: 		$infotext.="Map saved as $fn. ";
                    704: 	    } else {
                    705: 		$errtext.='Could not write file '.$fn.'.  Map not saved. ';
                    706: 	    }
                    707:         }
                    708:     } else {
                    709: # -------------------------------------------- Cannot write to that file, error
                    710:         $errtext.='Map not saved: The specified path does not exist. ';
                    711:     }
                    712:     return ($errtext,$infotext);
                    713: }
                    714: 
                    715: 1;
                    716: __END__

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.