<?php
error_reporting(E_ALL); // nastavení varování při ladění
require_once('Common.php'); // Společné funkce
require_once('TemplateEngine.php'); // Stroj pro práci s templejty
require_once('DirMetadata.php'); // Modul pro načítání informace o adresářích
define('WRAP', 70, true); // Lámání řetězcových hodnot
// Stavová informace
// -----------------
//
// Tento skript používá pro přenesení stavu ke kliemtovi a zpět dvě stavové
// proměnné prostřednictvím odkazu (zpracová ModRewrite, definováno v konfiguraci webu).
// Jsou to:
//
// lang - zde je kód jazyka, chybějící kód se přesměruje na angličtinu
//
// path - zde se uvádí cesta vůči DOCUMENT_ROOT webu, neplatná cesta se přesměruje
// na root
//
// Vyzvedni si parametry z URL
// ---------------------------
// Vyzvedni jazyk z předaného parametru
$Lang = (is_string($_GET['lang'])) ? $_GET['lang'] : $Lang = 'en';
$Params['lang'] = $Lang;
//print "Lang:{$Lang}<br>";
// Převezmi cestu, a odstraň lomítko na konci (na začátku lomítko je)
$Path = (is_string($_GET['path'])) ? $_GET['path'] : $Path = '';
$Path = '/'.ltrim(rtrim($Path, '/'), '/');
// Decode entities ?
// $LinkFull=htmlspecialchars_decode($LinkFull);
// Ulož
$Params['path'] = $Path;
//print "Path:{$Path}<br>";
// Načti metadata pro sekci (první adresář)
// Nikdy nevěř tomu, co přijde od klienta
$SectionDirInfo = new DirMetadata();
$SectionDirInfo->LoadDirInfo('/'.GetSection($Path).'/'.DIRINFO, $Lang);
if($Path!='/')
{
if(!$SectionDirInfo->GetValid())
Redirect('', $Lang); // Neexistující sekci přesměruj na root
}
// Pokus se načíst informace jako by cesta vedla do adresáře
$ThisDirInfo = new DirMetadata();
$ThisDirInfo->LoadDirInfo($Path.'/'.DIRINFO, $Lang);
if($ThisDirInfo->GetValid())
{
// Založ objekt templejtu a načti jej
$Template = new TemplateEngine();
$error = $Template->LoadTemplate($_SERVER['DOCUMENT_ROOT'].'/'.TEMPLATE_LISTDIR, $Lang);
if ($error!='')
Error($error);
// Generuj dynamický obsah do proměnných objektu Template
ListDir($SectionDirInfo, $ThisDirInfo, $Template, $Params);
// Odešli výsledek klientovi
echo $Template->GetPage();
return;
}
// Pokus se načíst informace jako by cesta vedla do projektu
$ThisDirInfo->LoadDirInfo($Path.'/'.PRJINFO, $Lang);
if($ThisDirInfo->GetValid())
{
// Založ objekt templejtu a načti jej
$Template = new TemplateEngine();
$error = $Template->LoadTemplate($_SERVER['DOCUMENT_ROOT'].'/'.TEMPLATE_LISTPRJ, $Lang);
if ($error!='')
Error($error);
// Generuj dynamický obsah do proměnných objektu Template
ListPrj($SectionDirInfo, $ThisDirInfo, $Template, $Params);
// Odešli výsledek klientovi
echo $Template->GetPage();
return;
}
// Neplatná cesta (ani adresář, ani projekt)
Redirect('/', $Lang);
return;
function CreateListLinkHTML($Params, $DirName='', $Title='')
{
// Spoj cestu a (volitelné) jméno adresáře
if ($DirName!='')
$Params['path'] = $Params['path'].'/'.$DirName;
// Odvoď jméno z názvu adresáře
$DirName = basename($Params['path']);
if ($DirName == '')
{
$DirName = '(root)';
}
// Jméno skriptu (statické jméno je pomocí mod_rewrite přesměrováno na tento skript)
$ScriptName = '/' . LISTSCRIPT;
$ScriptName .= ($Params['lang'] !== '') ? '.'.$Params['lang'] : '';
$ScriptName .= '.html';
// Sestav odkaz
$Link = "<a href=\"{$Params['path']}{$ScriptName}\"";
if ($Title!='')
$Link .= "\n".' title="'.htmlspecialchars($Title).'"';
$Link .= ">$DirName</a>";
return $Link;
}
function CreateListLinkPathHTML($Params, $Title)
// Vstupem je cesta (začínající /) od DOCUMENT_ROOT
// Výsledkem je řádka odkazů na jednotlivé adresáře cesty
// Odkazy jsou odkazy na skript (obsahuje cestu i jazyk)
{
// Rozděl cestu na kousky
$Parts = explode('/', $Params['path']);
if ($Parts[0]=='')
array_shift($Parts); // vyhoď případnou prázdnou položku
// Začínáme od rootu
$TempPath = '';
// Odkaz na root (je vždy)
$Params['path'] = $TempPath;
$Link = CreateListLinkHTML($Params, '', $Title);
// Je něco víc než root?
if (isset($Parts[0]) && $Parts[0]!='')
{
// Odkaz na všechny další adresáře cesty
foreach($Parts as $Key => $Value)
{
// Přidej adresář
$TempPath .= '/'.$Value;
// Vyrob odkaz
$Link .= " /\n";
$Params['path'] = $TempPath;
$Link .= CreateListLinkHTML($Params, '', $Title);
}
}
// Vrať výsledek
return $Link;
}
function ListDir($SectionDirInfo, $ThisDirInfo, $Template, $Params)
// Tato funkce vkládá informace do objektu Template pro výpis seznamu
// položek v adresáři (seznam projektů a sekcí v zadaném adresáři)
{
// Lokálně používané parametry pěkně při ruce
$Path = $Params['path'];
$Lang = $Params['lang'];
// HTML hlavička - doplň sekci
$Template->SetVariable('InfoSection', GetSection($Path));
// Zkopíruj informace z DIRINFO (z adresáře sekce a pak z aktuálního adresáře)
// do proměnných templejtu
foreach($SectionDirInfo->DirData as $Key => $Value)
{
$Template->SetVariable($Key, $Value, WRAP);
}
foreach($ThisDirInfo->DirData as $Key => $Value)
{
$Template->SetVariable($Key, $Value, WRAP);
}
// Klikací řádka s cestou
$Template->SetVariable('InfoPath',
CreateListLinkPathHTML($Params, $Template->GetString('InfoPathTitle')));
// Permalink
$Template->SetVariable('InfoPermaLink', PermaLinkCreateLink($Path));
// Procházej adresář
// -----------------
// Odstraň lomítko u prázdné cesty aby se nezdvojovalo
if ($Params['path']=='/')
$Params['path'] = '';
// Objekt pro načítání informací o adresářích a projektech
$DirInfo = new DirMetadata();
// Abych nešahal pořád do objektu, použiju proměnnou
$Glue = $Template->GetVariable('InfoGlue');
// Sem se střádá mezivýsledek
// Zvlášť adresáře a projekty aby byly oddělené ve výsledku
$LinesDir = ''; // Adresáře
$LinesPrj = ''; // Projekty
// Procházení adresářem
$Dir = glob($_SERVER['DOCUMENT_ROOT'].$Path.'/*', GLOB_ONLYDIR);
// Vezmi jen jméno adresáře a vytvoř asociativní pole s klíči
foreach ($Dir as $Key => $DirName)
{
$DirName = basename($DirName);
$NewDir[$DirName] = $DirName;
}
$Dir = $NewDir;
unset($NewDir);
// Setřídění adresářů podle preferovaného třídění ze [SortPreferences]
$NewDir = array();
$Sort = $ThisDirInfo->GetVariable('SortPreferences'); // vzorové třídění
if ($Sort!='')
{
$Sort = explode("\n", $Sort);
// Najdi a přendej nalezené položky
foreach ($Sort as $Value)
{
$Value = trim($Value);
if (isset($Dir[$Value]))
{
// Zařaď do nového pole
$NewDir[] = $Value;
// Vyhoď ze starého
unset($Dir[$Value]);
}
}
// Přendej zbylé položky
foreach ($Dir as $Value)
{
$NewDir[] = $Value;
}
$Dir = $NewDir;
unset($NewDir);
}
// Zpracování položek
foreach ($Dir as $DirName)
{
// Načti informace o (každém) adresáři
$DirInfoValid = $DirInfo->LoadDirInfo($Path.'/'.$DirName.'/'.DIRINFO, $Lang);
// Pokud to není adresář, tak načti informace o projektu
if (!$DirInfoValid)
{
$ProjectInfoValid = $DirInfo->LoadDirInfo($Path.'/'.$DirName.'/'.PRJINFO, $Lang)
or
// Heuristika pro projekty, které ještě nemají popis
$ProjectInfoValid = is_dir($_SERVER['DOCUMENT_ROOT'].$Path.'/'.$DirName.'/DOC')
or
$ProjectInfoValid = is_dir($_SERVER['DOCUMENT_ROOT'].$Path.'/'.$DirName.'/SCH');
}
// Zkontroluj, zda jsme v platné sekci
if ($DirInfoValid || $ProjectInfoValid)
{
// Připrav si proměnné
unset($Variables);
foreach($DirInfo->DirData as $Key => $Value)
{
$Variables[$Key] = $DirInfo->GetString($Key, WRAP);
}
$Variables['InfoName'] = ($DirInfoValid or $ProjectInfoValid) ? CreateListLinkHTML($Params, $DirName, $DirInfo->GetString('InfoLongDescription'))
: $DirName;
$Variables['InfoPicture'] = CreatePicturesLink($Params['path'].'/'.$DirName, $Glue, 'Ilustrative Picture', '/'.TEMPLATE_PATH.'/'.$Template->GetVariable('InfoNoPicture'), 150);
$Variables['InfoDescripion'] = $DirInfo->GetString('InfoShortDescription', WRAP);
$Variables['InfoWebSVN'] = CreateSVNLink($Params['path'].'/'.$DirName, $Params['lang'], $Template->GetString('InfoSVNTitle'));
if (!$DirInfoValid)
{
$Variables['InfoWIKI'] = CreateWikiLink($DirName, $Params['lang'], $Template->GetString('InfoWikiTitle'));
}
$Variables['InfoHTML'] = CreateFilesLink($Params['path'].'/'.$DirName.'/DOC/HTML/*.[hH][tT][mM][lL]', $Glue);
$Variables['InfoPDF'] = CreateFilesLink($Params['path'].'/'.$DirName.'/DOC/*.[pP][dD][fF]', $Glue);
$Variables['InfoSCH'] = CreateFilesLink($Params['path'].'/'.$DirName.'/SCH/*.[pP][dD][fF]', $Glue);
// Vlož info o dostupnosti na UST
if($DirInfo->GetString('InfoBuyUST')!= '')
{
$Variables['InfoBuy'] = CreateLink($DirInfo->GetString('InfoBuyUST'),'UST');
}
// Poukni proměnné do vzoru a střádej si výsledek
if ($DirInfoValid)
$LinesDir .= $Template->Substitute($Variables, $Template->GetVariable('InfoLine'));
else
$LinesPrj .= $Template->Substitute($Variables, $Template->GetVariable('InfoLine'));
}
}
// Slož k sobě obě části (adresář / separátor / projekt)
if ($LinesDir!='' and $LinesPrj!='')
$Lines = $LinesDir.$Template->GetString('InfoSeparator').$LinesPrj;
else
$Lines = $LinesDir.$LinesPrj;
// Teď sestavené položky ulož do proměnné "InfoLine" objektu
$Template->SetVariable('InfoLine', $Lines);
}
function ListPrj($SectionDirInfo, $ThisDirInfo, $Template, $Params)
// Tato funkce vkládá informace do objektu Template pro výpis informací
// o projektu (náhled, informace, odkazy na dokuemntaci etc.)
{
// Lokálně používané parametry pěkně při ruce
$Path = $Params['path'];
$Lang = $Params['lang'];
// Abych nešahal pořád do objektu, použiju proměnnou
$Glue = $Template->GetVariable('InfoGlue');
// HTML hlavička - doplň sekci
$Template->SetVariable('InfoSection', GetSection($Path));
// Zkopíruj informace z DIRINFO (z adresáře sekce a pak z aktuálního adresáře)
// do proměnných templejtu
foreach($SectionDirInfo->DirData as $Key => $Value)
{
$Template->SetVariable($Key, $Value, WRAP);
}
foreach($ThisDirInfo->DirData as $Key => $Value)
{
$Template->SetVariable($Key, $Value, WRAP);
}
// Klikací řádka s cestou
$Template->SetVariable('InfoPath',
CreateListLinkPathHTML($Params, $Template->GetString('InfoPathTitle')));
// Permalink
$Template->SetVariable('InfoPermaLink', PermaLinkCreateLink($Path));
// Zpracuj informace o projektu
// ----------------------------
unset($Variables);
// Převezmi data z popisu projektu
foreach($ThisDirInfo->DirData as $Key => $Value)
{
$Variables[$Key] = $ThisDirInfo->GetString($Key, WRAP);
}
$Template->SetVariable('InfoVariables', $Variables);
// Odkaz na obrázky k projektu
$Template->SetVariable('InfoPictures', CreatePicturesLink($Path, $Template->GetString('InfoPicturesGlue'), 'Ilustrative Picture', '', 200));
// Data do tabulky
$Template->SetVariable('InfoText', CreateFilesLink($Path.'/DOC/{HTML/*.[hH][tT][mM][lL],*.[pP][dD][fF]}', $Glue));
$Template->SetVariable('InfoWebSVN', CreateSVNLink($Path, $Lang, $Template->GetString('InfoSVNTitle')));
$Variables['InfoName'] = basename($Path);
/* $Variables['InfoName'] = ($DirInfoValid or $ProjectInfoValid) ? CreateListLinkHTML($Params, $DirName, $DirInfo->GetString('InfoLongDescription'))
: $DirName;
$Variables['InfoPicture'] = CreatePicturesLink($Params['path'].'/'.$DirName, $Glue, 'Ilustrative Picture', '/'.TEMPLATE_PATH.'/'.$Template->GetVariable('InfoNoPicture'), 150);
$Variables['InfoDescripion'] = $DirInfo->GetString('InfoShortDescription', WRAP);
$Variables['InfoWebSVN'] = CreateSVNLink($Params['path'].'/'.$DirName, $Params['lang'], $Template->GetString('InfoSVNTitle'));
if (!$DirInfoValid)
{
$Variables['InfoWIKI'] = CreateWikiLink($DirName, $Params['lang'], $Template->GetString('InfoWikiTitle'));
}
$Variables['InfoHTML'] = CreateFilesLink($Params['path'].'/'.$DirName.'/DOC/HTML/*.[hH][tT][mM][lL]', $Glue);
$Variables['InfoPDF'] = CreateFilesLink($Params['path'].'/'.$DirName.'/DOC/*.[pP][dD][fF]', $Glue);
$Variables['InfoSCH'] = CreateFilesLink($Params['path'].'/'.$DirName.'/SCH/*.[pP][dD][fF]', $Glue);
// Vlož info o dostupnosti na UST
if($DirInfo->GetString('InfoBuyUST')!= '')
{
$Variables['InfoBuy'] = CreateLink($DirInfo->GetString('InfoBuyUST'),'UST');
}
*/
// Poukni proměnné do vzoru a střádej si výsledek
$LinesPrj = $Template->Substitute($Variables, $Template->GetVariable('InfoLine'));
$Template->SetVariable('InfoLine', $LinesPrj);
/*
// Objekt pro načítání informací o adresářích a projektech
$DirInfo = new DirMetadata();
// Abych nešahal pořád do objektu, použiju proměnnou
$Glue = $Template->GetVariable('InfoGlue');
// Sem se střádá mezivýsledek
// Zvlášť adresáře a projekty aby byly oddělené ve výsledku
$LinesDir = ''; // Adresáře
$LinesPrj = ''; // Projekty
// Procházení adresářem
$Dir = glob($_SERVER['DOCUMENT_ROOT'].$Path.'/*', GLOB_ONLYDIR);
// Vezmi jen jméno adresáře a vytvoř asociativní pole s klíči
foreach ($Dir as $Key => $DirName)
{
$DirName = basename($DirName);
$NewDir[$DirName] = $DirName;
}
$Dir = $NewDir;
unset($NewDir);
// Setřídění adresářů podle preferovaného třídění ze [SortPreferences]
$NewDir = array();
$Sort = $ThisDirInfo->GetVariable('SortPreferences'); // vzorové třídění
if ($Sort!='')
{
$Sort = explode("\n", $Sort);
// Najdi a přendej nalezené položky
foreach ($Sort as $Value)
{
$Value = trim($Value);
if (isset($Dir[$Value]))
{
// Zařaď do nového pole
$NewDir[] = $Value;
// Vyhoď ze starého
unset($Dir[$Value]);
}
}
// Přendej zbylé položky
foreach ($Dir as $Value)
{
$NewDir[] = $Value;
}
$Dir = $NewDir;
unset($NewDir);
}
// Zpracování položek
foreach ($Dir as $DirName)
{
// Načti informace o (každém) adresáři
$DirInfoValid = $DirInfo->LoadDirInfo($Path.'/'.$DirName.'/'.DIRINFO, $Lang);
// Pokud to není adresář, tak načti informace o projektu
if (!$DirInfoValid)
{
$ProjectInfoValid = $DirInfo->LoadDirInfo($Path.'/'.$DirName.'/'.PRJINFO, $Lang)
or
// Heuristika pro projekty, které ještě nemají popis
$ProjectInfoValid = is_dir($_SERVER['DOCUMENT_ROOT'].$Path.'/'.$DirName.'/DOC')
or
$ProjectInfoValid = is_dir($_SERVER['DOCUMENT_ROOT'].$Path.'/'.$DirName.'/SCH');
}
// Zkontroluj, zda jsme v platné sekci
if ($DirInfoValid || $ProjectInfoValid)
{
// Připrav si proměnné
unset($Variables);
foreach($DirInfo->DirData as $Key => $Value)
{
$Variables[$Key] = $DirInfo->GetString($Key, WRAP);
}
$Variables['InfoName'] = ($DirInfoValid or $ProjectInfoValid) ? CreateListLinkHTML($Params, $DirName, $DirInfo->GetString('InfoLongDescription'))
: $DirName;
$Variables['InfoPicture'] = CreatePicturesLink($Params['path'].'/'.$DirName, $Glue, 'Ilustrative Picture', '/'.TEMPLATE_PATH.'/'.$Template->GetVariable('InfoNoPicture'), 150);
$Variables['InfoDescripion'] = $DirInfo->GetString('InfoShortDescription', WRAP);
$Variables['InfoWebSVN'] = CreateSVNLink($Params['path'].'/'.$DirName, $Params['lang'], $Template->GetString('InfoSVNTitle'));
if (!$DirInfoValid)
{
$Variables['InfoWIKI'] = CreateWikiLink($DirName, $Params['lang'], $Template->GetString('InfoWikiTitle'));
}
$Variables['InfoHTML'] = CreateFilesLink($Params['path'].'/'.$DirName.'/DOC/HTML/*.[hH][tT][mM][lL]', $Glue);
$Variables['InfoPDF'] = CreateFilesLink($Params['path'].'/'.$DirName.'/DOC/*.[pP][dD][fF]', $Glue);
$Variables['InfoSCH'] = CreateFilesLink($Params['path'].'/'.$DirName.'/SCH/*.[pP][dD][fF]', $Glue);
// Vlož info o dostupnosti na UST
if($DirInfo->GetString('InfoBuyUST')!= '')
{
$Variables['InfoBuy'] = CreateLink($DirInfo->GetString('InfoBuyUST'),'UST');
}
// Poukni proměnné do vzoru a střádej si výsledek
if ($DirInfoValid)
$LinesDir .= $Template->Substitute($Variables, $Template->GetVariable('InfoLine'));
else
$LinesPrj .= $Template->Substitute($Variables, $Template->GetVariable('InfoLine'));
}
}
// Slož k sobě obě části (adresář / separátor / projekt)
if ($LinesDir!='' and $LinesPrj!='')
$Lines = $LinesDir.$Template->GetString('InfoSeparator').$LinesPrj;
else
$Lines = $LinesDir.$LinesPrj;
// Teď sestavené položky ulož do proměnné "InfoLine" objektu
$Template->SetVariable('InfoLine', $Lines);
*/
}
// *************************************
function WrapString($String, $Wrap=0)
// Provede odstranění nadbytečných bílých znaků
// a volitleně (pokud je $Wrap nenulové) provede zálámání na zadaný počet znaků
{
// Odstaň bílé znaky
$String = preg_replace('/\s+/su', ' ', $String);
// Volitelné nalámání
if ($Wrap!=0)
$String = wordwrap($String, $Wrap);
return $String;
}
function xxxCheckWebPath($Path)
// Zadaná cesta se chápe jako cesta uvnitř webu (vzhledem k document root).
// Případné relativní části (/../..) převede na absolutní a zkontroluje
// výsledek, zda nevybočuje mimo web.
// Na začátku nechá lomítko, na konci ho odstraní.
// Pokud je výsledná cesta neplatná, vrátí prázdný řetězec. Kontroluje, zda
// zadaný adresář existuje.
{
// Převeď cestu na opravdovou, odstraň relativní odkazy
$Path = realpath($_SERVER['DOCUMENT_ROOT'].$Path);
// Zkontroluj, zda jsme nevybočili z webu
if ( 0 == strncmp($Path, $_SERVER['DOCUMENT_ROOT'], strlen($_SERVER['DOCUMENT_ROOT']) ) )
{
// Shoda - odstraň DOCUMENT_ROOT část cesty
return substr( $Path, strlen($_SERVER['DOCUMENT_ROOT']) );
}
else
{
// Vybočili jsme z webu
return '';
}
}
function GetSection($Path)
// Vrátí první část cesty (to je to, co nazýváme sekce)
{
// Ignoruj lomítko na začátku
$Path = ltrim($Path, '/');
// Vykousni první slovo až po lomítko
$Section = substr($Path, 0, strpos($Path.'/', '/'));
// Ošetři root
if ($Section=='')
$Section = "(root)";
// Vrať výsledek
return $Section;
}
function CreateLink($InternetWebPath, $Title='')
// Vstupem je cesta do jiného webu.
// a volitelně title (zobrazí se při najetí myši na odkaz).
// Vrací řetězec s odkazem
{
$Link = '<a href="'.$InternetWebPath.'"';
if ($Title != '')
$Link .= "\n".' title="'.$Title.'"';
$Link .= '>';
$Link .= $Title;
$Link .= '</a>';
return $Link;
}
function CreateScriptLink($Params, $DirName='', $Title='')
// Vytvoř odkaz na skript s parametry skriptu. Parametry jsou předány jako
// pole s jmény položek a hodnotami. Volitelná položka $DirName se přidá k cestě
// v položce $Params. Pokud je zadaná cesta prázdná nebo / zobrazí se slovo root
{
// Připoj volitelné jméno adresáře
if ($DirName!='')
$Params['path'] = $Params['path'].'/'.$DirName;
// Odvoď jméno z názvu adresáře
$DirName = basename($Params['path']);
if ($DirName == '')
{
$DirName = '(root)';
$Params['path'] = '/';
}
// Zpracuj pole parametrů
$ParamsLine = '';
$LocalGlue = '';
foreach($Params as $Key => $Value)
{
$ParamsLine .= $LocalGlue.$Key.'='.urlencode($Value);
$LocalGlue = '&';
}
unset($LocalGlue);
// Sestav odkaz
$Link = '<a href="'.$_SERVER['SCRIPT_NAME'].'?'.$ParamsLine.'"';
if ($Title!='')
$Link .= "\n".' title="'.htmlspecialchars($Title).'"';
$Link .= ">$DirName</a>";
return $Link;
}
function CreateScriptLinkPath($Params, $Title)
// Vstupem je cesta (začínající /) od DOCUMENT_ROOT
// Výsledkem je řádka odkazů na jednotlivé adresáře cesty
// Odkazy jsou odkazy na skript s parametrem cesty a jazyka
// Vstupem je pole parametrů ze kterých použijeme parametr 'path',
// ostatní jen umístíme do odkazů.
{
// Rozděl cestu na kousky
$Parts = explode('/', $Params['path']);
if ($Parts[0]=='')
array_shift($Parts); // vyhoď případnou prázdnou položku
// Začínáme od rootu
$TempPath = '';
// Odkaz na root (je vždy)
$Params['path'] = $TempPath;
$Link = CreateScriptLink($Params, '', $Title);
// Je něco víc než root?
if (isset($Parts[0]) && $Parts[0]!='')
{
// Odkaz na všechny další adresáře cesty
foreach($Parts as $Key => $Value)
{
// Přidej adresář
$TempPath .= '/'.$Value;
// Vyrob odkaz
$Link .= " /\n";
$Params['path'] = $TempPath;
$Link .= CreateScriptLink($Params, '', $Title);
}
}
// Vrať výsledek
return $Link;
}
?>