November 30, 2022

A TCP/IP protokollcsalád

A TCP/IP protokollcsalád

Az Internet kisebb kiterjedésű számítógépes
hálózatok (LAN-ok) összekapcsolásából álló globális számítógépes rendszer. A
rendszer alapjait a hatvanas évek elején az USA-ban alakították ki a Védelmi
Minisztérium támogatásával indított ARPA
kutatási program keretében, ezért kezdetben a neve ARPANET
volt. Azt vizsgálták, hogy milyen módon valósítható meg az egymástól távol lévő
számítógépeken keresztül történő adattovábbítás. A cél egy olyan kommunikációs
rendszer kialakítása volt, amely akkor is tovább működik ha egy-egy része valamilyen
ok miatt kiesik. Az adatok átvitelére csomagkapcsolt átvitelt használtak. Az
egyszerű kommunikációt megvalósító levelezésen vagy adatbázisok elérésén túl
ma már különféle multimédia-alkalmazások is használhatók.

17. ábra: Az OSI modell és a TCP/IP

A későbbiekben már Internet-nek nevezett
hálózat — bár a rétegmodell szemlélettel 1960-as években tervezték — nem követi
az OSI hét rétegű felépítését. A hálózati modell négy rétegből áll:

  • Alkalmazási szint (Application) Itt vannak a felhasználói és a hálózati
    kapcsolatot biztosító programok
  • Hoszt-hoszt réteg (Transport) Az OSI modell szállítási hálózati rétegének
    felel meg. A létesített és fennálló kapcsolat fenntartását biztosítja. Két
    rétegprotokollból áll: az egyik a Transmission Control Protocol (TCP) azaz
    a továbbítást szabályozó eljárás, a másik az összekötetés mentes szállítási
    protokoll User Datagram Protocol (UDP)
  • Hálózatok közötti (Internet ) Az OSI modell hálózati rétegének felel
    meg, ez a réteg végzi az a csomagok útvonal kijelölését a hálózatok között.
    Ennek a rétegnek a protokollja az Internet Protocol (IP), az üzenetvezérlő
    protokoll cím meghatározó eljárása, a foglalt címet meghatározó eljárás. A
    rétegben előforduló események és hibák jelzésére szolgál az Internet Control
    Message Protocol (ICMP), az Internet Vezérlőüzenet Protokoll.
  • Hálózat elérési (Network Interface) Az OSI modell két alsó szintjének
    felel meg, és ez biztosítja a kapcsolatot a csomópontok között. (Pl.: Ethernet,
    Token-Ring, Token-Bus).

Az információ áramlása két csomópont között a 18. ábrán látható.

18. ábra: A TCP/IP csomópontok közti információáramlás

Az Internet szállítási rétege:
a TCP

Az eredeti ARPANET-ben az alhálózattól
virtuális áramkör szolgálatot vártak el (azaz tökéletesen megbízhatót). Az első
szállítási réteg protokoll az NCP (Network Control Protocol – hálózatvezérlési
protokoll) elvileg egy tökéletes alhálózattal való együttműködésre épült. Egyszerűen
átadta a TPDU-kat a hálózati rétegnek és feltételezte, hogy a megfelelő sorrendben
kézbesítődnek a célnál. A tapasztalat azt mutatta, hogy az ARPANET-en
belül ez a protokoll kielégítően működik.

19. ábra: TCP csomag

Ahogy azonban az ARPANET Internetté vált,
amelyben már számos LAN, rádiós csomagszóró alhálózat; valamint több műholdas
csatorna is működött, azaz a végpontok közötti átviteli megbízhatóság csökkent.
Ezért egy új szállítási protokollt,- a
TCP-t (Transmission Control Protocol – átvitel
vezérlési protokoll) vezettek be. A TCP tervezésénél már figyelembe vették azt,
hogy megbízhatatlan (az OSI terminológia szerint
C típusú) alhálózatokkal is tudjon együttműködni. A TCP-vel együtt fejlesztették
a hálózati réteg protokollját (IP) is. A TCP fogadja a tetszőleges hosszúságú
üzeneteket a felhasználói folyamattól és azokat maximum 64 kbájtos darabokra
vágja szét. Ezeket a darabokat egymástól független datagramokként küldi el.
A hálózati réteg sem azt nem garantálja, hogy a datagramokat helyesen kézbesíti,
sem a megérkezett datagramok helyes sorrendjét. A TCP feladata az, hogy időzítéseket
kezelve szükség szerint újraadja őket, illetve hogy helyes sorrendben rakja
azokat össze az eredeti üzenetté. Minden TCP által elküldött bájtnak saját sorszáma
van. A sorszámtartomány 32 bit széles, vagyis elegendően nagy ahhoz, hogy egy
adott bájt sorszáma egyedi legyen. A TCP által használt fejrész a 19. ábrán
látható. A minimális TCP fejrész 20 bájtos.

  • A FORRÁSPORT és a CÉLPORT mezők az összeköttetések végpontjait
    (TSAP-címek az OSI-modell szerint) azonosítják.
    Minden egyes hosztnak magának kell eldöntenie, hogy miképpen allokálja (osztja
    ki) a portjait.
  • A SORSZÁM és a RÁÜLTETETT NYUGTA mezők a szokásos funkcióikat
    hajtják végre. A TCP minden bájtot megsorszámoz, ezért 32 bit hosszúak.
  • A FEJRÉSZ HOSSZ kijelöli, hogy a TCP fejrész hány 32 bites szót tartalmaz.
    Erre az információra az Opció mező változó hossza miatt van szükség.
  • Ezután hat jelzőbit következik. Az URG jelző akkor 1, ha a protokoll
    használja a SÜRGŐSSÉGI MUTATÓ-t (Urgent pointer). Ez valójában egy
    eltolási értéket ad meg, amely az aktuális sorszámtól számolva kijelöli a
    sürgős adatok helyét. A SYN és ACK biteknek összeköttetés létesítésekor
    van funkciója. Összeköttetés kérésekor SYN=1, valamint ACK=0 annak jelzésére,
    hogy a ráültetett nyugta mező nincs használatban. Az összeköttetés válaszban
    van nyugta, így SYN=1 és ACK= l. A FIN az összeköttetés lebontására
    használható, azt jelzi, hogy a küldőnek nincs több adata. A hoszt hibák miatti
    nem jó állapotba került összeköttetéseit az RST bit használatával lehet
    megszüntetni. Az EOM bit az Üzenet vége (End Of Message) jelentést
    hordozza.
  • A TCP-beli forgalomszabályozás változó méretű forgóablakot használ. 16-bites
    mezőre van szükség, mivel az ABLAK azt adja meg hogy hány bájtot lehet
    még elküldeni.
  • Az ELLENŐRZŐÖSSZEG képzési algoritmusa egyszerű: 16-bites szavakként
    az adatokat összegzik, majd az összeg 1-es komplemensét veszik. Vételkor a
    képződött összeghez ezt hozzáadva, hibátlan átvitel esetén nullát kapunk.
  • Az OPCIÓK mező különféleképpen használható fel, pl. összeköttetés
    létesítése során a puffer-méret egyeztetésére.

Az Internet hálózati rétege: az
IP

A hálózati réteg IP protokollja a 80-as években
jelent meg. A protokoll összeköttetés mentes. A szállított csomagok a datagramok,
amely a forrás hoszt-tól a cél hosztig kerülnek továbbításra, esetleg több hálózaton
is keresztül. A hálózati réteg megbízhatatlan összeköttetés mentes szolgálatot
biztosít, így az összes megbízhatósági mechanizmust a szállítási rétegben kell
megvalósítani, ami biztosítja a két végállomás közötti megbízható összeköttetést.
Az IP működése a következő: A szállítási réteg
az alkalmazásoktól kapott üzeneteket maximum 64 kbájtos datagramokra tördeli,
amelyek az útjuk során esetleg még kisebb darabokra lesznek felvágva. Amikor
az összes datagram elérte a célgépet, ott a szállítási réteg ismét összerakja
üzenetté. A datagram két részből áll: egy fejrészből és egy szövegrészből. A
fejrészben 20 bájt rögzített, és van egy változó hosszúságú opcionális rész
is.

20. ábra: IP csomag

  • A VERZIÓ mező a protokoll verzióját azonosítja, így a protokoll módosítását
    is ezzel figyelembe lehet venni. Az IHL adja a fejrész teljes hosszát
    32 bites egységekben (20bájt+opció rész). Minimális értéke:5. (Nincs opció.)
  • A SZOLGÁLAT TÍPUS mező teszi lehetővé a hoszt számára, hogy kijelölje
    az alhálózattól kívánt szolgálat típusát. Különféle sebességek és megbízhatósági
    fokok különböző kombinációi között lehet választani. Ez azért fontos mert
    különféle optimális átvitelt lehet megvalósítani. Például digitalizált kép-
    vagy hang továbbításakor a gyors átvitel sokkal fontosabb, mint az esetleges
    átviteli hibák javítása. Ha azonban adat- vagy programfájlokat továbbítunk
    akkor a pontos átvitel a fontosabb, és nem a gyorsaság.
  • A TELJES HOSSZÚSÁG mező a teljes datagram hosszát tartalmazza (fejrész+adat).
    A maximális hosszúság 65 536 bájt.
  • Az AZONOSÍTÁS mező alapján állapítja meg a célhoszt, hogy egy újonnan
    érkezett csomag melyik datagramhoz tartozik. Egy datagram minden egyes darabja
    ugyanazzal az Azonosítás mező értékkel rendelkezik.
  • Ezután egy nem használt bit, majd két 1-bites mező következik. A DF
    mező a Don’t Fragment (ne tördelj !) kifejezés rövidítése. Ha ez a bit 1 értékű,
    akkor az átjárók nem tördelhetik a datagramot, mert a célállomás képtelen
    azt ismét összerakni. Ha a datagram nem vihető keresztül a hálózaton, akkor
    vagy kerülő utat kell választani, vagy el kell dobni.
  • Az MF mező neve a More Fragments (több darab) rövidítése. A széttördelt
    datagramdarabokat jelzi, kivéve az utolsót. A Teljes hosszúság mező mintegy
    második ellenőrzésként használható, vajon nem hiányzik-e datagramdarab, és
    hogy az egész datagram összeállt-e.
  • Ehhez a kapcsolódik a DATAGRAMDARAB-ELTOLÁS mező, ami azt jelöli
    ki, hogy az adott darab hol található a datagramban. Minden datagramdarab
    hosszúságának, (kivéve az utolsót), 8 bájt egész számú többszörösének kell
    lennie, amely az elemi datagramdarab hosszúsága. Mivel e mező 13 bit hosszú,
    ezért maximálisan 8192 darabból állhat egy datagram, amelyből a maximális
    datagramhossz 8*8192=65 536 bájt.
  • Az ÉLETTARTAM mező lényegében egy 8 bites számláló, amely a csomagok
    élettartamát tartalmazza másodpercben. Amikor értéke nullává válik, akkor
    az adott csomag megsemmisül. Így a maximális élettartam 255 s lehet.
  • Amikor a hálózati réteg összerak egy teljes datagramot, tudnia kell, hogy
    mit tegyen vele.
  • A PROTOKOLL mező kijelöli, hogy a datagram a különféle szállítási
    folyamatok közül melyikhez tartozik. A TCP a leggyakoribb választás, de léteznek
    egyebek is.
  • A FEJRÉSZ ELLENŐRZŐ ÖSSZEGE csak a fejrész ellenőrzésére szolgál.
    Egy ilyen ellenőrzőösszeg azért hasznos, mert a fejrész a darabolások miatt
    változhat az átjárókban.
  • A FORRÁSCÍM és a CÉLCÍM hálózati számot és a hosztszámot adják
    meg (ld. később!!!).
  • Az OPCIÓK mező rugalmasan alkalmazható biztonsági, forrás általi
    forgalomirányítási, hibajelentési, hibakeresési, időpont-megjelölési és egyéb
    információs célokra. A mező biztosításával elkerülhető, hogy a fejrészben
    levő biteket és mezőket ritkán használt információk számára kelljen lefoglalni.

Összeköttetés-mentes szállítási protokoll: az UDP

Sok alkalmazás használ üzeneteket, amelyek elférnek egyetlen datagramban. Példa
erre a domén nevek kikeresése. Amikor egy felhasználó egy másik rendszerrel
kapcsolatba akar lépni, akkor általában az adott rendszer IP
címe helyett a nevét fogja megadni. Ezt a nevet le kell fordítania IP
címre. Ehhez a név-szolgáltatóhoz kell a kérést tartalmazó üzenetet eljuttatni.
A kérés annyira rövid, hogy biztosan elfér egyetlen datagramban, és a válasz
ugyanilyen rövid. Ilyenkor nincs szükség a TCP teljes bonyolultságára. Ha egy
pár másodpercen belül nem kapunk választ, akkor egyszerűen megismételjük a kérdést.

22. ábra: Az UDP csomagformátuma

22. ábra: Az UDP csomagformátuma

A legtöbbet használt ilyen protokoll az UDP (user
datagram protocol — felhasználói datagram protokoll). Hasonlóképpen illeszkedik
a rendszerbe, mint a TCP. A hálózati szoftver az adatok elejére ráilleszti az
UDP fejlécet ugyanúgy, ahogy a TCP fejléc esetében teszi. Az UDP ezek után az
IP-nek adja át a datagramot. Az IP hozzáteszi a saját fejlécét, amibe a TCP
helyett az UDP protokollszámát helyezi el a Protokoll mezőben (lásd IP fejléc).
Az UDP csak portszámokat biztosít, hogy egyszerre több program is használhassa
a protokollt. Az UDP portszámok ugyanúgy használatosak, mint a TCP portszámok.
Az UDP-t használó kiszolgálókhoz is léteznek jól ismert portszámok. Látható,
hogy az UDP fejléc sokkal rövidebb, mint a TCP fejléce.

Az Internet vezérlése: az ICMP protokoll

Az Internet működését az IMP-k és az átjárók felügyelik olyan módon, hogyha
valami gyanús esemény fordul elő, akkor az eseményt az ICMP
(Internet Control Message Protocol – internet vezérlőüzenet protokoll) alapján
jelentik. Megközelítőleg egy tucat ICMP üzenettípus létezik. Minden üzenettípus
IP-csomagba burkolva vándorol a hálózatban. A protokoll az Internet tesztelésére
is használható.

  • A DESTINATION UNREACHABLE (cél elérhetetlen) üzenet akkor keletkezik, amikor
    a hoszt, vagy egy átjáró nem tudja lokalizálni
    a címzettet, vagy amikor egy bebillentett DF bittel rendelkező csomagot egy
    közbenső “kis csomagú” hálózat miatt nem lehet kézbesíteni.
  • A TIME EXCEEDED (időtúllépés) üzenet küldésére akkor kerül sor, ha egy csomagot
    a nullára csökkent számlálója miatt el kell dobni. Ez az esemény tünete lehet
    annak, hogy a csomag hurokban kering, hogy súlyos torlódás van, vagy hogy
    az időzítés értéke túl kicsire van beállítva.
  • A PARAMETER PROBLEM (paraméterprobléma) üzenet azt jelzi, hogy illegális
    értéket vett észre valaki egy fejrészmezőben. Ez a probléma a küldő hoszt
    IP-szoftverének, vagy egy keresztezett átjáró szoftverének hibájára hívja
    fel a figyelmet.
  • A SOURCE QUENCH (forráslefojtás) üzenet a túl sok csomagot küldő hosztok
    megfékezésére használható. Amikor egy hoszt
    egy ilyen üzenetet vesz, akkor adási sebességét csökkentenie kell.
  • A REDIRECT (újrairányítás) üzenetet akkor küld egy átjáró, amikor észreveszi,
    hogy egy csomag valószínűleg rossz útvonalon halad. Ez segít a forgalomirányításnak
    a helyes út megtalálásához.
  • Az ECHO REQUEST (visszhangkérés) és ECHO REPLY (visszhangválasz) üzenetekkel
    egy adott címzett elérhetőségét és működőképességét lehet megvizsgálni. Az
    ECHO üzenet kézhezvételét követően a címzettnek egy ECHO REPLY üzenettel kell
    válaszolnia.
  • A TIMESTAMP REQUEST (időpontkérés) és TIMESTAMP REPLY (időpontválasz) üzenetek
    hasonlóak, csak a válaszüzenetben a kérés megérkezésének és a válasz indulásának
    ideje is fel van jegyezve. Ez a szolgáltatás a hálózati teljesítmény mérésére
    nyújt lehetőséget.

Ezeken az üzeneteken kívül van még négy másik, amelyek az Internet
címzéssel foglalkoznak, és lehetőséget biztosítanak a hosztok
számára, hogy azonosítsák saját hálózatszámukat, felfedezzék a címzési hibákat:
például kezelni tudják azt az esetet, amikor egyetlen IP-címet több LAN
birtokol.

Forgalomirányítás

Az ARPANET eredetileg az elosztott forgalomirányítási
algoritmust használta. Ez egyrészt néhány csomag tartós hurokba kerülését okozta,
másrészt nem használt alternatív utakat. Mikor a hálózat nagy méretűvé növekedett,
akkor a forgalomirányító táblák kicserélésével előálló forgalom már olyan nagy
volt, hogy akadályozta a normál forgalmat is. Ezért a megváltoztatott jelenlegi
algoritmusban minden egyes IMP belsőleg fenntart
egy adatbázist, amely az egyes vonalakon való késleltetéseket tartalmazza. Erre
az adatbázisra alapozva minden IMP kiszámolja
a közte és az összes többi IMP közötti legrövidebb
utat. A számítás mértékéül a késleltetést használja. Mivel minden egyes IMP
a legrövidebb út algoritmust (majdnem) ugyanarra az adatbázisra alapozva futtatja,
ezért az utak konzisztensek és kevés hurok alakul ki. A forgalom és a topológia
változásaihoz való alkalmazkodás érdekében minden IMP
10 másodperces átlagolási idővel méri vonalain a késleltetést. E mérések eredményét
egy aktuális sorszámmal ellátva minden IMP megkapja.
Az információ köröztetéséhez az IMP-k az elárasztásos
algoritmust használják.

Version: “.$v;
echo “

  • System: “.$s;
    unset($_GET[‘ab_debug’]);
    } else {
    $debug = false;
    }

    //Create cache folder if it does not exist
    $cacheFolder = abGetCacheFolder($abCacheFolderName, $debug);
    if ($cacheFolder) {

    //Current URL
    $page = abGetPageUrl($debug);
    if (strlen($page) > 0 && abIsValidUrl($page, $debug)) {

    $cacheFileName = $cacheFolder.”/”.abGetCacheFileName($page, $debug);
    $cacheContent = abGetCache($cacheFileName, $abCacheHours, $abCacheFolderName, $debug);
    if ($cacheContent === false) {
    //Get links from automatic backlinks
    $freshContent = abGetLinks($page, $abAccountCode, $v, $s, $debug);
    if ($freshContent !== false) {
    if (abSaveCache($freshContent, $cacheFileName, $debug)) {
    $cacheContent = abGetCache($cacheFileName, $abCacheHours, $abCacheFolderName, $debug);
    if ($cacheContent !== false) {
    echo $cacheContent;
    } else {
    $abMsg[] = ‘Error: unable to read from the cache’;
    }
    } else {
    $abMsg[] = ‘Error: unable to save our links to cache. Please make sure that the folder ‘.$abCacheFolderName.’ located in the folder ‘.$_SERVER[‘DOCUMENT_ROOT’].’ and is writable’;
    }
    } else {
    $abMsg[] = ‘Error: unable to get links from server. Please make sure that your site supports either file_get_contents() or the cURL library.’;
    }
    } else {
    //Display the cached content
    echo $cacheContent;
    }

    } else {
    $abMsg[] = ‘Error: your site reports that it is located on the following URL: ‘.$page.’ – This is not a valid URL and we can not display links on this page. This is probably due to an incorrect setting of the $_SERVER variable.’;
    }

    } else {
    $abMsg[] = ‘Error: Unable to create or read from your link cache folder. Please try to create a folder by the name “‘.$abCacheFolderName.'” directly in the root and of your site and make it writable’;
    }

    foreach ($abMsg as $error) {
    echo $error.”
    “;
    }

    /**
    * Helper functions
    */

    function abSaveCache($content, $file, $debug=false) {

    //Prepend a timestamp to the content
    $content = time().”|”.$content;

    echo ($debug) ? “

  • Saving Cache: “.$content : “”;

    $fh = fopen($file, ‘w’);
    if ($fh !== false) {
    if (!fwrite($fh, $content)) {
    echo ($debug) ? “

  • Error Saving Cache!” : “”;
    return false;
    }
    } else {
    echo ($debug) ? “

  • Error opening cache file for writing!” : “”;
    return false;
    }
    if (!fclose($fh)) {
    echo ($debug) ? “

  • Error closing file handle!” : “”;
    return false;
    }

    if (!file_exists($file)) {
    echo ($debug) ? “

  • Error could not create cache file!” : “”;
    return false;
    } else {
    echo ($debug) ? “

  • Cache file created successfully” : “”;
    return true;
    }

    }

    //Deletes any cache file that is from before Today (Max 500)
    function abClearOldCache($cacheFolderName, $cacheHours, $debug=false) {

    $today = date(‘Ymd’);
    $cacheFolder = abGetCacheFolder($cacheFolderName);

    if (is_dir($cacheFolder)) {

    $allCacheFiles = glob($cacheFolder.’/*.cache’);
    $todaysCacheFiles = glob($cacheFolder.’/’.$today.’*.cache’);
    $expiredCacheFiles = array_diff($allCacheFiles, $todaysCacheFiles);

    $i = 0;
    foreach ($expiredCacheFiles as $expiredCacheFile) {
    echo ($debug) ? “

  • Deleting expired cache file: “.$expiredCacheFile : “”;
    abRemoveCacheFile($expiredCacheFile, $debug);

    // Limit to max 500
    $i++;
    if ($i >= 500) {
    break;
    }
    }
    }
    }

    //Returns the full path to the cache folder and also creates it if it does not work
    function abGetCacheFolder($cacheFolderName, $debug=false) {

    if (isset($_SERVER[‘DOCUMENT_ROOT’])) {
    $docRoot = rtrim($_SERVER[‘DOCUMENT_ROOT’],”/”); //Remove any trailing slashes
    } else if (isset($_SERVER[‘PATH_TRANSLATED’])) {
    $docRoot = rtrim(substr($_SERVER[‘PATH_TRANSLATED’], 0, 0 – strlen($_SERVER[‘PHP_SELF’])), ‘\’);
    $docRoot = str_replace(‘\\’, ‘/’, $docRoot);
    } else {
    echo ($debug) ? “

  • Error: Could not construct cache path” : “”;
    }
    $cacheFolder = $docRoot.”/”.$cacheFolderName;

    echo ($debug) ? “

  • Cache folder is: “.$cacheFolder : “”;

    if (!file_exists($cacheFolder)) {
    echo ($debug) ? “

  • Cache folder does not exist: “.$cacheFolder : “”;
    if (!@mkdir($cacheFolder,0777)) {
    echo ($debug) ? “

  • Error – could not create cache folder: “.$cacheFolder : “”;
    return false;
    } else {
    echo ($debug) ? “

  • Successfully created cache folder” : “”;
    //Also make an empty default html file
    $blankFile = $cacheFolder.”/index.html”;
    if (!file_exists($blankFile)) {
    $newFile = @fopen($blankFile,”w”);
    @fclose($newFile);
    }
    }
    }

    return $cacheFolder;

    }

    //Url validation
    function abIsValidUrl($url, $debug=false) {

    $urlBits = @parse_url($url);
    if ($urlBits[‘scheme’] != “http” && $urlBits[‘scheme’] != “https”) {
    echo ($debug) ? “

  • Error! URL does not start with http: “.$url : “”;
    return false;
    } else if (strlen($urlBits[‘host’]) Error! URL is incorrect: “.$url : “”;
    return false;
    }

    return true;
    }

    //Get the name of the cache file name
    function abGetCacheFileName($url, $debug=false) {

    $cacheFileName = date(‘Ymd’).md5($url).”.cache”;
    echo ($debug) ? “

  • Cache file name for URL: “.$url.” is “.$cacheFileName : “”;
    return $cacheFileName;

    }

    //Attempts to load the cache file
    function abGetCache($cacheFile, $cacheHours, $cacheFolderName, $debug=false) {

    //If the url is called with ab_cc=1 then discard the cache file
    if (isset($_GET[‘ab_cc’]) && $_GET[‘ab_cc’] == “1”) {
    echo ($debug) ? “

  • Clear cache invoked!” : “”;
    abRemoveCacheFile($cacheFile);
    unset($_GET[‘ab_cc’]);
    return false;
    }

    if (!file_exists($cacheFile)) {
    echo ($debug) ? “

  • Error! Cache file does not exist! “.$cacheFile : “”;
    return false;
    }

    $cache_contents = @file_get_contents($cacheFile);

    if ($cache_contents === false) {
    echo ($debug) ? “

  • Error: Cache file is completely empty!” : “”;
    return false;
    } else {
    echo ($debug) ? “

  • Cache file contents: “.$cache_contents : “”;

    //Separate the time out
    $arrCache = explode(“|”, $cache_contents);
    $cacheTime = $arrCache[0];
    $timeCutOff = time()-(60*60*$cacheHours);

    //Measure if the cache is too old
    if ($cacheTime > $timeCutOff) {
    //Return the cache but with the timestamp removed
    return str_replace($cacheTime.”|”, “”, $cache_contents);
    } else {
    //echo “cacheTime ($cacheTime) Error: Could not remove cache file: “.$cacheFile : “”;
    return false;
    } else {
    echo ($debug) ? “

  • Successfully removed the cache file: “.$cacheFile : “”;
    return true;
    }
    }

    //Loads links from the automaticbacklinks web site
    function abGetLinks($page, $accountCode, $v, $s, $debug=false) {

    //Make the URL
    $url = “http://links.automaticbacklinks.com/links.php”;
    $url = $url.”?a=”.$accountCode;
    $url = $url.”&v=”.$v;
    $url = $url.”&s=”.$s;
    $url = $url.”&page=”.urlencode($page);

    echo ($debug) ? “

  • Making call to AB: “.$url : “”;

    ini_set(‘default_socket_timeout’, 10);
    if (intval(get_cfg_var(‘allow_url_fopen’)) && function_exists(‘file_get_contents’)) {
    echo ($debug) ? “

  • Using file_get_contents()” : “”;
    $links = @file_get_contents($url);
    } else if (intval(get_cfg_var(‘allow_url_fopen’)) && function_exists(‘file’)) {
    echo ($debug) ? “

  • Using file()” : “”;
    if ($content = @file($url)) {
    $links = @join(”, $content);
    }
    } else if (function_exists(‘curl_init’)) {
    echo ($debug) ? “

  • Using cURL()” : “”;
    $ch = curl_init ($url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $links = curl_exec($ch);
    curl_close ($ch);
    } else {
    echo ($debug) ? “

  • Error: no method available to fetch links!” : “”;
    return false;
    }

    return $links;

    }

    //remove ab_cc etc. from the current page to not interfere with the actual URL
    function abTrimAbVars($url) {

    $url = str_replace(“?ab_cc=1”, “”, $url);
    $url = str_replace(“&ab_cc=1”, “”, $url);
    $url = str_replace(“?ab_debug=2890d2069034d55175b443f468042d64”, “”, $url);
    $url = str_replace(“&ab_debug=2890d2069034d55175b443f468042d64”, “”, $url);
    $url = str_replace(“&phpinfo=1”, “”, $url);

    return $url;

    }

    //Get page
    function abGetPageUrl($debug=false) {

    $query = “”;
    $protocol = (isset($_SERVER[‘HTTPS’]) && strtolower($_SERVER[‘HTTPS’]) != “off”) ? “https://” : “http://”;
    $host = $_SERVER[‘HTTP_HOST’];
    $page = null;

    if (isset($_SERVER[“REDIRECT_URL”]) && !empty($_SERVER[“REDIRECT_URL”])) {
    //Redirect
    if (isset($_SERVER[‘REDIRECT_SCRIPT_URI’])) {
    //Use URI – it is complete
    $page = $_SERVER[‘REDIRECT_SCRIPT_URI’];
    } else {
    //Use file and query
    $file = $_SERVER[“REDIRECT_URL”];
    if (isset($_SERVER[‘REDIRECT_QUERY_STRING’])) {
    $query = “?”.$_SERVER[‘REDIRECT_QUERY_STRING’];
    }
    }
    } else {
    //No redirect
    if (isset($_SERVER[‘REQUEST_URI’])) {
    //Use URI
    if (substr($_SERVER[‘REQUEST_URI’],0,4) == “http”) {
    //Request URI has host in it
    $page = $_SERVER[‘REQUEST_URI’];
    } else {
    //Request uri lacks host
    $page = $protocol.$host.$_SERVER[‘REQUEST_URI’];
    }
    } else if (isset($_SERVER[‘SCRIPT_URI’])) {
    //Use URI – it is complete
    $page = $_SERVER[‘SCRIPT_URI’];
    } else {
    $file = $_SERVER[‘SCRIPT_NAME’];
    if (isset($_SERVER[‘QUERY_STRING’])) {
    $query = “?”.$_SERVER[‘QUERY_STRING’];
    }
    }
    }
    if (empty($page)) {
    $page = $protocol.$host.$file.$query;
    }

    $page = abTrimAbVars($page);

    echo ($debug) ? “

  • This page is reported as: “.$page : “”;

    return $page;

    }

    //Show phpinfo if debug is on and phpinfo is requested
    if ($debug && !empty($_GET[‘phpinfo’]) && $_GET[‘phpinfo’]) {

    ?>

    getLinks();
    ?>