how can I tell if a remote file is an image

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • ebobnar

    how can I tell if a remote file is an image

    I've written a link aliasing script that allows users to rewrite urls
    on their web pages. The crux of the script is the following:

    if(getimagesize ($redirect_to) == 0)
    header("Locatio n: $redirect_to");
    else
    include("$redir ect_to");

    Which uses getimagesize() to determine if the link specified in
    $redirect_to points to an image (i.e img src) in which case it should
    include the image in the page, or if the link points to another
    website (i.e. a href), in which case I use the header method to
    redirect to that page when the link alias is called.

    So far this script has been working great, but I recently had a
    customer run it under php4.2.2 and the getimagesize is taking approx.
    160 seconds to execute.

    Can anyone think of a different way to tell if a remote file is an
    image? And also, has anyone else experienced this kind of behavior
    with getimagesize when running php4.2.2?

    Assistance is really appreciated.

    Thanks,

    Esoos
  • Dennis Biletsky

    #2
    Re: how can I tell if a remote file is an image

    Try to look on extension of $redirect_to. If it will image extension (.jpg,
    ..gif, .png, etc), so that is picture, otherwise other file type

    "ebobnar" <ebobnar74@yaho o.com> ???????/???????? ? ???????? ?????????:
    news:c903769f.0 404020053.3eadb fea@posting.goo gle.com...[color=blue]
    > I've written a link aliasing script that allows users to rewrite urls
    > on their web pages. The crux of the script is the following:
    >
    > if(getimagesize ($redirect_to) == 0)
    > header("Locatio n: $redirect_to");
    > else
    > include("$redir ect_to");
    >
    > Which uses getimagesize() to determine if the link specified in
    > $redirect_to points to an image (i.e img src) in which case it should
    > include the image in the page, or if the link points to another
    > website (i.e. a href), in which case I use the header method to
    > redirect to that page when the link alias is called.
    >
    > So far this script has been working great, but I recently had a
    > customer run it under php4.2.2 and the getimagesize is taking approx.
    > 160 seconds to execute.
    >
    > Can anyone think of a different way to tell if a remote file is an
    > image? And also, has anyone else experienced this kind of behavior
    > with getimagesize when running php4.2.2?
    >
    > Assistance is really appreciated.
    >
    > Thanks,
    >
    > Esoos[/color]


    Comment

    • Ian.H

      #3
      Re: how can I tell if a remote file is an image

      Please learn to post correctly...

      [ http://tk.digiserv.net/tofu.txt ]


      On Fri, 02 Apr 2004 12:03:30 +0300, Dennis Biletsky wrote:
      [color=blue]
      > Try to look on extension of $redirect_to. If it will image extension (.jpg,
      > .gif, .png, etc), so that is picture, otherwise other file type[/color]


      LOL!

      This is m$ "thinking". . and most certainly _not_ how it _really_ works.

      fopen() / fread() / fclose() would work a _lot_ more effectively than this
      proposed solution.. although I cna only guess that this is pretty much
      what getimagesize() does too.. although it may be faster to jkust read the
      header compared to whatever other tests getimagesize() performs too.



      Regards,

      Ian

      --
      Ian.H
      digiServ Network
      London, UK


      Comment

      • Dennis Biletsky

        #4
        Re: how can I tell if a remote file is an image


        "ebobnar" <ebobnar74@yaho o.com> ???????/???????? ? ???????? ?????????:
        news:c903769f.0 404020053.3eadb fea@posting.goo gle.com...[color=blue]
        > I've written a link aliasing script that allows users to rewrite urls
        > on their web pages. The crux of the script is the following:
        >
        > if(getimagesize ($redirect_to) == 0)
        > header("Locatio n: $redirect_to");
        > else
        > include("$redir ect_to");
        >
        > Which uses getimagesize() to determine if the link specified in
        > $redirect_to points to an image (i.e img src) in which case it should
        > include the image in the page, or if the link points to another
        > website (i.e. a href), in which case I use the header method to
        > redirect to that page when the link alias is called.
        >
        > So far this script has been working great, but I recently had a
        > customer run it under php4.2.2 and the getimagesize is taking approx.
        > 160 seconds to execute.
        >
        > Can anyone think of a different way to tell if a remote file is an
        > image? And also, has anyone else experienced this kind of behavior
        > with getimagesize when running php4.2.2?
        >
        > Assistance is really appreciated.
        >
        > Thanks,
        >
        > Esoos[/color]

        Perhaps, this function will work better.



        Comment

        • Ian.H

          #5
          Re: how can I tell if a remote file is an image

          On Fri, 02 Apr 2004 16:50:07 +0300, Dennis Biletsky wrote:


          [ snip ]

          [color=blue][color=green]
          >> Can anyone think of a different way to tell if a remote file is an
          >> image? And also, has anyone else experienced this kind of behavior
          >> with getimagesize when running php4.2.2?
          >>
          >> Assistance is really appreciated.
          >>
          >> Thanks,
          >>
          >> Esoos[/color]
          >
          > Perhaps, this function will work better.
          > http://www.php.net/manual/en/functio...-imagetype.php[/color]


          If the image hasn't been optiomised (ie: had the thumbnail (exif image)
          removed).



          Regards,

          Ian

          --
          Ian.H
          digiServ Network
          London, UK


          Comment

          • Dennis Biletsky

            #6
            Re: how can I tell if a remote file is an image

            "Ian.H" <ian@WINDOZEdig iserv.net> ???????/???????? ? ???????? ?????????:
            news:pan.2004.0 4.02.13.02.05.4 68000@bubbleboy .digiserv.net.. .[color=blue]
            > Please learn to post correctly...
            >
            > [ http://tk.digiserv.net/tofu.txt ]
            >
            >
            > On Fri, 02 Apr 2004 12:03:30 +0300, Dennis Biletsky wrote:
            >[color=green]
            > > Try to look on extension of $redirect_to. If it will image extension[/color][/color]
            (.jpg,[color=blue][color=green]
            > > .gif, .png, etc), so that is picture, otherwise other file type[/color]
            >
            >
            > LOL!
            >
            > This is m$ "thinking". . and most certainly _not_ how it _really_ works.
            >
            > fopen() / fread() / fclose() would work a _lot_ more effectively than this
            > proposed solution.. although I cna only guess that this is pretty much
            > what getimagesize() does too.. although it may be faster to jkust read the
            > header compared to whatever other tests getimagesize() performs too.
            >
            >
            >
            > Regards,
            >
            > Ian
            >
            > --
            > Ian.H
            > digiServ Network
            > London, UK
            > http://digiserv.net/
            >[/color]

            fread() is way that works in any case, but you will need analyze file
            signature to identify what type of that file and you should now how to do
            that. You should know file structure of various pictures' formats.


            Comment

            • Ian.H

              #7
              Re: how can I tell if a remote file is an image

              On Fri, 02 Apr 2004 17:45:05 +0300, Dennis Biletsky wrote:
              [color=blue]
              > "Ian.H" <ian@WINDOZEdig iserv.net> ???????/???????? ? ???????? ?????????:
              > news:pan.2004.0 4.02.13.02.05.4 68000@bubbleboy .digiserv.net.. .[color=green]
              >> Please learn to post correctly...
              >>
              >> [ http://tk.digiserv.net/tofu.txt ]
              >>
              >>
              >> On Fri, 02 Apr 2004 12:03:30 +0300, Dennis Biletsky wrote:
              >>[color=darkred]
              >> > Try to look on extension of $redirect_to. If it will image extension[/color][/color]
              > (.jpg,[color=green][color=darkred]
              >> > .gif, .png, etc), so that is picture, otherwise other file type[/color]
              >>
              >>
              >> LOL!
              >>
              >> This is m$ "thinking". . and most certainly _not_ how it _really_ works.
              >>
              >> fopen() / fread() / fclose() would work a _lot_ more effectively than this
              >> proposed solution.. although I cna only guess that this is pretty much
              >> what getimagesize() does too.. although it may be faster to jkust read the
              >> header compared to whatever other tests getimagesize() performs too.[/color][/color]

              [color=blue]
              > fread() is way that works in any case, but you will need analyze file
              > signature to identify what type of that file and you should now how to do
              > that. You should know file structure of various pictures' formats.[/color]


              Like.. the first 4 bytes of the file (in most cases)? Don't really need to
              know much about the actual structure of the rest of the data.. just the
              header.

              $fp = @fopen('foo.jpg 'm 'rb');
              if ($fp) {
              $fh = @fread($fp, 4);
              @fclose($fp);
              }

              switch ($fh) {
              'JPEG': /* File is a JPEG image */; break;
              'GIF.': /* File is a GIF image */; break;
              [...]
              default: /* File == unknown / invalid type */
              }



              This example is _very_ crude and I haven't double checked to see exactly
              how many bytes of the header would need to be read in (I think it
              differs between 2 and 4.. but maybe wrong).. but should work just fine and
              possible quicker than getimagesize(). . although I haven't tested any of
              this =)



              Regards,

              Ian

              --
              Ian.H
              digiServ Network
              London, UK


              Comment

              • Dennis Biletsky

                #8
                Re: how can I tell if a remote file is an image


                "Ian.H" <ian@WINDOZEdig iserv.net> ???????/???????? ? ???????? ?????????:
                news:pan.2004.0 4.02.15.43.49.4 69000@bubbleboy .digiserv.net.. .[color=blue]
                > On Fri, 02 Apr 2004 17:45:05 +0300, Dennis Biletsky wrote:
                >[color=green]
                > > "Ian.H" <ian@WINDOZEdig iserv.net> ???????/???????? ? ???????? ?????????:
                > > news:pan.2004.0 4.02.13.02.05.4 68000@bubbleboy .digiserv.net.. .[color=darkred]
                > >> Please learn to post correctly...
                > >>
                > >> [ http://tk.digiserv.net/tofu.txt ]
                > >>
                > >>
                > >> On Fri, 02 Apr 2004 12:03:30 +0300, Dennis Biletsky wrote:
                > >>
                > >> > Try to look on extension of $redirect_to. If it will image extension[/color]
                > > (.jpg,[color=darkred]
                > >> > .gif, .png, etc), so that is picture, otherwise other file type
                > >>
                > >>
                > >> LOL!
                > >>
                > >> This is m$ "thinking". . and most certainly _not_ how it _really_ works.
                > >>
                > >> fopen() / fread() / fclose() would work a _lot_ more effectively than[/color][/color][/color]
                this[color=blue][color=green][color=darkred]
                > >> proposed solution.. although I cna only guess that this is pretty much
                > >> what getimagesize() does too.. although it may be faster to jkust read[/color][/color][/color]
                the[color=blue][color=green][color=darkred]
                > >> header compared to whatever other tests getimagesize() performs too.[/color][/color]
                >
                >[color=green]
                > > fread() is way that works in any case, but you will need analyze file
                > > signature to identify what type of that file and you should now how to[/color][/color]
                do[color=blue][color=green]
                > > that. You should know file structure of various pictures' formats.[/color]
                >
                >
                > Like.. the first 4 bytes of the file (in most cases)? Don't really need to
                > know much about the actual structure of the rest of the data.. just the
                > header.
                >
                > $fp = @fopen('foo.jpg 'm 'rb');
                > if ($fp) {
                > $fh = @fread($fp, 4);
                > @fclose($fp);
                > }
                >
                > switch ($fh) {
                > 'JPEG': /* File is a JPEG image */; break;
                > 'GIF.': /* File is a GIF image */; break;
                > [...]
                > default: /* File == unknown / invalid type */
                > }
                >
                >
                >
                > This example is _very_ crude and I haven't double checked to see exactly
                > how many bytes of the header would need to be read in (I think it
                > differs between 2 and 4.. but maybe wrong).. but should work just fine and
                > possible quicker than getimagesize(). . although I haven't tested any of
                > this =)
                >
                >
                >
                > Regards,
                >
                > Ian
                >
                > --
                > Ian.H
                > digiServ Network
                > London, UK
                > http://digiserv.net/
                >[/color]

                Yes, in common, first several bytes, but you should analyze it. By, the way,
                JPEG some time has JFIF signature :). Anyway, I agree that your version will
                work in any case.

                Regards,
                Dennis


                Comment

                • David Precious

                  #9
                  Re: how can I tell if a remote file is an image

                  ebobnar wrote:
                  [color=blue]
                  > Can anyone think of a different way to tell if a remote file is an
                  > image? And also, has anyone else experienced this kind of behavior
                  > with getimagesize when running php4.2.2?[/color]

                  If you're willing to trust the remote server to correctly report the
                  Content-Type, it'd be a lot more efficient than retrieving the whole thing
                  just to check it out.

                  Perhaps something along the general lines of:

                  $fh = fsockopen($host ,80);
                  if ($fh)
                  {
                  fputs($fh,"HEAD $url HTTP/1.0\n\n");
                  $resp = fgets($fh,2048) ;
                  if (preg_match("/Content-Type:(.+)/",$resp,$match) )
                  {
                  print "Content type is : " . $match[1];
                  }
                  fclose($fh);
                  }

                  Of course you'd have to parse the URL they've entered to get the hostname
                  and path correct, but that shouldn't be too hard.

                  Cheers

                  Dave P


                  --
                  David Precious


                  Comment

                  • Andy Hassall

                    #10
                    Re: how can I tell if a remote file is an image

                    On Fri, 02 Apr 2004 14:00:25 GMT, "Ian.H" <ian@WINDOZEdig iserv.net> wrote:
                    [color=blue]
                    >On Fri, 02 Apr 2004 16:50:07 +0300, Dennis Biletsky wrote:
                    >[color=green][color=darkred]
                    >>> Can anyone think of a different way to tell if a remote file is an
                    >>> image? And also, has anyone else experienced this kind of behavior
                    >>> with getimagesize when running php4.2.2?[/color]
                    >>
                    >> Perhaps, this function will work better.
                    >> http://www.php.net/manual/en/functio...-imagetype.php[/color]
                    >
                    >
                    >If the image hasn't been optiomised (ie: had the thumbnail (exif image)
                    >removed).[/color]

                    Actually, despite being a part of the EXIF extension, this function doesn't
                    actually have anything to do with EXIF. If you look at the source, it's just a
                    wrapper that calls back into php_getimagetyp e in standard/image.c, which does a
                    read of the first few bytes pretty much as you posted elsewhere in this thread.

                    The php_getimagetyp e C function is also used by the PHP function getimagesize.

                    --
                    Andy Hassall <andy@andyh.co. uk> / Space: disk usage analysis tool
                    http://www.andyh.co.uk / http://www.andyhsoftware.co.uk/space

                    Comment

                    • ebobnar

                      #11
                      Re: how can I tell if a remote file is an image

                      Thank you to everyone who replied to my question.

                      I haven't solved it yet. Apparently exif_imagetype only works on php[color=blue]
                      >= php 4.3.0, and I am working with php 4.2.2. I tried the reading the[/color]
                      header for image identifiers, like so:

                      $fp = @fopen("$redire ct_to", 'rb');
                      if ($fp) {
                      $fh = @fread($fp, 12);
                      @fclose($fp);
                      }

                      if (preg_match("/GIF87|GIF88|GIF 89|JFIF|hsi1|MM |II|IIN1|PNG|BM |P1|P4|P2|P5|P3 |P6/i",
                      $fh)) {
                      include("$redir ect_to");
                      } else {
                      header("Locatio n: $redirect_to");
                      }

                      This improved things somewhat, execution time dropped from about 160
                      sec to about 80 sec, but still takes much too long to be practical.

                      I appreciate everyones feedback, and I am continuing to look for a way
                      to solve this problem.

                      Thanks,

                      Esoos

                      Comment

                      • Chung Leong

                        #12
                        Re: how can I tell if a remote file is an image

                        "David Precious" <pinkmeat@presh web.co.uk> wrote in message
                        news:1080942326 .74016.0@iris.u k.clara.net...[color=blue]
                        > If you're willing to trust the remote server to correctly report the
                        > Content-Type, it'd be a lot more efficient than retrieving the whole thing
                        > just to check it out.[/color]

                        getimagesize() at most reads 12 bytes from the stream, so I don't think file
                        size is an issue here. The problem, it appears, is that the PHP isn't timing
                        out quickly when the server doesn't respond or if the domain name is
                        invalid.

                        Reduce default_socket_ time so that getimagesize fails quickly, instead of
                        160 seconds that this customer has set:

                        $dst = ini_set('defaul t_socket_timeou t', 5);
                        getimagesize($r edirect_to);
                        ini_set('defaul t_socket_timeou t', $dst);


                        Comment

                        • Chung Leong

                          #13
                          Re: how can I tell if a remote file is an image

                          "ebobnar" <ebobnar74@yaho o.com> wrote in message
                          news:c903769f.0 404020053.3eadb fea@posting.goo gle.com...[color=blue]
                          > I've written a link aliasing script that allows users to rewrite urls
                          > on their web pages. The crux of the script is the following:
                          >
                          > if(getimagesize ($redirect_to) == 0)
                          > header("Locatio n: $redirect_to");
                          > else
                          > include("$redir ect_to");[/color]

                          BTW: You've actually written a script that allows users to take over your
                          server. Use readfile(), not include(), to print the content of a remote
                          page.


                          Comment

                          • ebobnar

                            #14
                            Re: how can I tell if a remote file is an image

                            Thanks again to everyone who responded.

                            I have tried everyones suggestions, but still have not been completely
                            sucessful.
                            [color=blue]
                            >If you're willing to trust the remote server to correctly report the
                            >Content-Type, it'd be a lot more efficient than retrieving the whole[/color]
                            thing[color=blue]
                            >just to check it out.[/color]

                            I wrote a function, similar to the one in this post:

                            function display_content _type($hostname , $file) {

                            $ip = gethostbyname($ hostname);
                            $fp = fsockopen($ip, 80, &$errno, &$errstr);

                            if ($fp)
                            {
                            fputs($fp, "GET " . $file . " HTTP/1.0\r\n" .
                            "Host: $hostname\r\n" .
                            "Accept: text/html\r\n" .
                            "Accept: text/plain\r\n\r\n" );

                            $src = '';
                            while (!feof ($fp)) {
                            $src .= fgets($fp, 4096);
                            if (preg_match("/Content-Type:(.+)/", $src, $match))
                            {
                            print "Content type is : " . $match[1];
                            fclose ($fp);
                            exit;
                            }
                            }
                            }
                            }

                            This works well with when called with arguments like:

                            display_content _type("http://www.yahoo.com", "/index.html");

                            but fails completely when called like:

                            display_content _type("http://www.qksrv.net",
                            "/click-1469122-7154067");

                            Also, runs extremely slow under php 4.2.2.
                            [color=blue]
                            >getimagesize () at most reads 12 bytes from the stream, so I don't[/color]
                            think file[color=blue]
                            >size is an issue here. The problem, it appears, is that the PHP isn't[/color]
                            timing[color=blue]
                            >out quickly when the server doesn't respond or if the domain name is
                            >invalid.[/color]

                            I profiled the code very closely, and was able to tell that it was
                            precisely the getimagesize() function that was taking 180 seconds to
                            complete. I don't think that the program is failing to retrieve the
                            images, because if I wait 180 seconds for getimagesize() to complete,
                            then the images are downloaded and displayed normally.

                            I also tried just using:

                            header("Locatio n: $redirect_to");

                            for both images and web pages, and it works pretty well, but fails
                            when the link to the image is redirected to another site (I imagine
                            for server load balancing, but I digress...)

                            I am thinking that the problem is php 4.2.2. It seems that any file
                            manipulation functions that access remote files run really slow. I'm
                            not sure if this is the case but that's my guess.

                            The question now stands: if I just use the header("Locatio n:
                            $redirect_to");
                            statement, is there a way to determine if the link is being redirected
                            (that would run quickly on php 4.2.2?) Does php have a function that
                            does this?

                            I would like to do something like the following pseudocode:

                            header("Locatio n: $redirect_to");
                            if ($status_code == "3.x.x") {
                            header("Locatio n: $redirect_to_wh ateverpage_is specified in the
                            redirect header");
                            }


                            also, thanks to Chung Leong for the security heads up.

                            Comment

                            Working...