Page 1 of 2 12 LastLast
Results 1 to 10 of 17

Thread: Great Mirror Code -- Not question, just sharing

  1. #1
    Join Date
    Mar 2006
    Location
    Illinois, USA
    Posts
    12,164
    Thanks
    265
    Thanked 690 Times in 678 Posts

    Default Great Mirror Code -- Not question, just sharing

    Well... I run a theater as part of my site that hosts independant films, and we're going to be hosting a film soon that will get thousands of downloads ("Ideality", you may have heard of it if you're into CG/filmmaking/etc.), and it'll be a big file.

    As such, I decided we needed mirrors. But then I thought about the downsides.
    Really... who clicks the mirror links? No one... they want to download the "real file" from the "real host"... it doesn't really save much bandwidth for the "real host".

    So... the obvious option then is to only give them one option to click... a random link from the list of mirrors...
    Then I realized that didn't quite work because all they'd have to do is refresh, and they might download the file twice accidentally or something, making it better, but, again, not a great solution.


    So... here's a perfect answer to this:


    I'll write this in a tutorial style, so you can follow along with how to add it to the page, rather than just an example:

    Put the following php at the top of your page:
    PHP Code:
    <?php
    $ip 
    $_SERVER['REMOTE_ADDR']; //grabs IP address
    $md5 md5($ip); //randomizes it a bit, to be sure similar IPs are mixed up
    $char $md5[31]; //grabs the last digit of the md5 string
    //(yes, it's 32 long, but since it starts at 0, the 32nd number is really 31)
    $ascii ord($char); //turn the character into it's ascii code. Ex: "c" = 99.
    $n $ascii 10//the % (mobius) gets the remainder from division.
    //this will give you the last digit of a number. Ex: (from above) 99/10= 9r9, so... $n=9.
    ...
    ?>
    Now you've got your random number setup. It's almost totally random which number an IP will get. The only way it can change is if the IP changes... so, basically, you're guaranteed, at least for a single visit, that that person will only get one number.
    Note: the number will be a single digit, from 0-9.

    After this, you need to setup a set of ifs (or a switch statement), like this:
    PHP Code:
    <?php
    ...
    if (
    $n == 0$url "http:/...URL0";
    if (
    $n == 1$url "http:/...URL1";
    if (
    $n == 2$url "http:/...URL2";
    if (
    $n == 3$url "http:/...URL3";
    if (
    $n == 4$url "http:/...URL4";
    if (
    $n == 5$url "http:/...URL5";
    if (
    $n == 6$url "http:/...URL6";
    if (
    $n == 7$url "http:/...URL7";
    if (
    $n == 8$url "http:/...URL8";
    if (
    $n == 9$url "http:/...URL9";
    ...
    ?>
    Then you've got your mirror list setup.

    Just do your page as is, then do this:

    PHP Code:
    <!--HTML ABOVE THIS... etc... -->
    <a href="<?php echo $url?>">This is the mirrored link!</a>
    <!--HTML below this... and no one is the wiser... looks like the "real" link... -->

    There are probably others uses than just mirroring, but most of them probably relate to sorting in some way.
    You could have it relate to another number than 10 URLs, too, btw... just assign multiple numbers to the same URL, or divide by 100 with the % command, and you'll have 0-99 as possible outputs, and that will be enough


    Here's a working example.... at the moment, it just does the first part of the code, outputting the pseudorandom number that's generated.
    http://ci-pro.com/misc/phptest/ipnum.php


    Anyway, just thought this could be helpful to people.

    Thoughts?




    For fun, post your number... just out of curiosity
    I'm 9, like I used in the example.


    btw, just a note-- I'm not logging IPs or anything if you're worried... its the exact code you see above.

  2. #2
    Join Date
    Jun 2005
    Location
    英国
    Posts
    11,876
    Thanks
    1
    Thanked 180 Times in 172 Posts
    Blog Entries
    2

    Default

    4.
    Quote Originally Posted by djr33
    I'm not logging IPs or anything if you're worried... its the exact code you see above.
    Why would anyone be worried?
    This could fail if a user were using an anonymising proxy.
    Code:
    <?php
    ...
    if ($n == 0) $url = "http:/...URL0";
    if ($n == 1) $url = "http:/...URL1";
    if ($n == 2) $url = "http:/...URL2";
    if ($n == 3) $url = "http:/...URL3";
    if ($n == 4) $url = "http:/...URL4";
    if ($n == 5) $url = "http:/...URL5";
    if ($n == 6) $url = "http:/...URL6";
    if ($n == 7) $url = "http:/...URL7";
    if ($n == 8) $url = "http:/...URL8";
    if ($n == 9) $url = "http:/...URL9";
    ...
    ?>
    Better to use:
    Code:
    $url = array(
      "http:/...URL0",
      "http:/...URL1",
      "http:/...URL2"
    );
    $url = $url[$n];
    Twey | I understand English | 日本語が分かります | mi jimpe fi le jbobau | mi esperanton komprenas | je comprends français | entiendo español | tôi ít hiểu tiếng Việt | ich verstehe ein bisschen Deutsch | beware XHTML | common coding mistakes | tutorials | various stuff | argh PHP!

  3. #3
    Join Date
    Mar 2006
    Location
    Illinois, USA
    Posts
    12,164
    Thanks
    265
    Thanked 690 Times in 678 Posts

    Default

    Umm.... why would that work better?
    Wouldn't it have the exact same result?
    (I'm not saying it would, but I can't see a difference myself...)

    Or, you could just have if 0, elseif 1, elseif 2,... else 9. That would mean it would at least go with the default...



    As for IPs... some people don't like IP being logged.... or, maybe here, people don't care. Whatever... just figured I'd note that.

  4. #4
    Join Date
    Jun 2005
    Location
    英国
    Posts
    11,876
    Thanks
    1
    Thanked 180 Times in 172 Posts
    Blog Entries
    2

    Default

    Wouldn't it have the exact same result?
    Yes, but it's less code and easier to read, and, I believe, more efficient, especially with a lot of cases.
    Twey | I understand English | 日本語が分かります | mi jimpe fi le jbobau | mi esperanton komprenas | je comprends français | entiendo español | tôi ít hiểu tiếng Việt | ich verstehe ein bisschen Deutsch | beware XHTML | common coding mistakes | tutorials | various stuff | argh PHP!

  5. #5
    Join Date
    Mar 2006
    Location
    Illinois, USA
    Posts
    12,164
    Thanks
    265
    Thanked 690 Times in 678 Posts

    Default

    This could fail if a user were using an anonymising proxy.
    I thought you substitute code was related to that sentence... nevermind.

    And... I don't know if I agree with it failing. The beauty of md5 is that even with no input, it still generates a 32 character string. md5("") will give you a result... so even if they have "no IP", they'll still get a number... yeah?
    Plus... even if its a fake/masked/whatever IP, it'll still have some type of IP sent to the server, yes?

  6. #6
    Join Date
    Jun 2005
    Location
    英国
    Posts
    11,876
    Thanks
    1
    Thanked 180 Times in 172 Posts
    Blog Entries
    2

    Default

    Yes, but it won't have your consistency and so on.
    Something else you might want to do is check that the hosts actually exist before sending the user to them:
    Code:
    function checkAlive($host) {
      $port; $a; $f;
      if(strpos($host, "://")) {  // We're dealing with an URL
        $a = explode($host, "://");
        $protocol = $a[0];
        $a = $a[1];
        $a = substr($a, 0, strpos($a, "/"));
        if(strpos($a, ":")) {  // We've been given a port
          $port = substr($a, strpos($a, ":") + 1) + 0;
          $a = substr($a, 0, strpos($a, ":"));
        } else
          switch($protocol) {
            case "http":
              $port = 80;
              break;
            case "ftp":
              $port = 21;
              break;
            case default:
              $port = 80;
          }
      }
      if(!$f=fsockopen($a, $port)) return false;
      else fclose($f);
      return true;
    }
    Then:
    Code:
    for($i=$n;;$i++)
      if(checkAlive($url[$i])) {
        $url = $url[$i];
        break;
      } else if($i == $n - 1)
        $url = "sorryNoMirrors.php";
      else if($i == count($url) - 1)
        $i = 0;
    That should (untested) skip to the next mirror if the chosen one is dead.
    Last edited by Twey; 04-17-2006 at 10:56 AM.
    Twey | I understand English | 日本語が分かります | mi jimpe fi le jbobau | mi esperanton komprenas | je comprends français | entiendo español | tôi ít hiểu tiếng Việt | ich verstehe ein bisschen Deutsch | beware XHTML | common coding mistakes | tutorials | various stuff | argh PHP!

  7. #7
    Join Date
    Mar 2006
    Location
    Illinois, USA
    Posts
    12,164
    Thanks
    265
    Thanked 690 Times in 678 Posts

    Default

    Hmm.... kinda confusing. I get it.... but I'm just not used to a lot of that stuff... totally unfamiliar with ports, for example, but that's what learning is for


    Seems like I could just assume the hosts will work... check them every day or so, or something... not as 'perfect', though.

  8. #8
    Join Date
    Mar 2006
    Location
    Illinois, USA
    Posts
    12,164
    Thanks
    265
    Thanked 690 Times in 678 Posts

    Default

    Ok, Twey. Here's a much simpler code... this work?


    Full code:
    PHP Code:
    <?php

    $ip 
    $_SERVER['REMOTE_ADDR'];
    $md5 md5($ip);
    $char $md5[31];
    $ascii ord($char);
    $n $ascii 10;

    $url = array(
      
    "http:/...URL0",
      
    "http:/...URL1",
      
    "http:/...URL2",
      
    "....."
    );
    $mirrorsdown 0;
    for (
    $url $url[$n]; !file_exists($url[$n]); $n++) {
         
    $check++;
         if (
    $check == 11) {
              
    $mirrorsdown 1;
              break;
              }
         if (
    $n == 9$n 0;
         }
    if (
    $mirrorsdown == 1) {
         
    $link "Sorry, but all mirrors are down!";
         }
    else {
         
    $link "<a href=\"$url[$n]\" alt=\"file\">Download!</a>"
         
    }
    ....
    ....
    echo 
    "...".$link."...";
    ?>

    edit: escaped a quote
    Last edited by djr33; 04-16-2006 at 09:29 AM.

  9. #9
    Join Date
    Jun 2005
    Location
    英国
    Posts
    11,876
    Thanks
    1
    Thanked 180 Times in 172 Posts
    Blog Entries
    2

    Default

    You put an alt on an anchor?

    It may work, but not if allow_url_fopen isn't set in php.ini.
    One problem with it is that you're never going to reach 11, as every time it gets to 9 it will be sent down to 0 again, so if all the mirrors are up, you're going to be in an infinite loop. Also, you've further mired yourself in that maximum of ten mirrors your original MD5-based mirror selection flung you into. It's certainly not as portable, and I think my code was actually simpler.

    Another thing: possible values from your bit of code at the top are:
    0 (0), 1 (1), 2 (2), 3 (3), 4 (4), 5 (5), 6 (6), 7 (7), 8 (8), 9 (9), 1 (a), 2 (b), 3 (c), 4 (d), 5 (e), 6 (f)
    As you can see, the chances of it being 0-6 are twice those of it being 7-9. A better idea would be to use the last character of the MD5 string directly; this would allow you 16 mirrors and a fair chance on each.
    Twey | I understand English | 日本語が分かります | mi jimpe fi le jbobau | mi esperanton komprenas | je comprends français | entiendo español | tôi ít hiểu tiếng Việt | ich verstehe ein bisschen Deutsch | beware XHTML | common coding mistakes | tutorials | various stuff | argh PHP!

  10. #10
    Join Date
    Mar 2006
    Location
    Illinois, USA
    Posts
    12,164
    Thanks
    265
    Thanked 690 Times in 678 Posts

    Default

    You put an alt on an anchor?
    No... hmm? That's a link with an alt tag. Ignore it if you want.

    Code:
         $check++;
         if ($check == 11) {
              $mirrorsdown = 1;
              break;
              }
    ...this will reach 11. It's just a count. It'll loop 0,1,2,....,9,0 and that second 0 will be the eleventh time its run through the loop. Then the break will exit it out of the while, so it won't be endless... it'll stop right then, with "$mirrorsdown" set to 1, meaning it'll give an error, not a link.


    I'm kinda lost in the last paragraph. From what I've seen, md5 doesn't just do those characters, but all letters, plus caps. I might be imagining this, though, in which case, yeah, you're right...

    btw, I've used the file commands before, so I'm assuming that allow_url_fopen is working... so.... yeah.

    Your code didn't really make sense to me 'cause a lot of it was complex commands I'm unfamiliar with... might be simpler to you, though. Plus, it was longer

    Also... the only reason mine is too complex is that it does the loop to move to the next one if it's an error..... I don't really need that. Heh.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •