1

i am using Wininet to download images and save them to memory stream but for more management reason i want to allow only gif images and jpg to be downloaded i tried to add check for FURL but extract file extension from url is bad step for me here is my wininet function

function DownloadToStream: Boolean;
var
  hSession     : HINTERNET;
  hService     : HINTERNET;
  lpBuffer     : array[0..1023] of Byte;
  dwBytesRead  : DWORD;
  dwBytesAvail : DWORD;
  dwTimeOut    : DWORD;
  Sessionname : String;
  Setsession : Pwidechar;
begin
  Result := False;
  Sessionname := nameofsession;
  Setsession := pwidechar(Sessionname);
  hSession := InternetOpen(Setsession, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if not Assigned(hSession) then Exit;
  try
    hService := InternetOpenUrl(hSession, PChar(FUrl), nil, 0, 0, 0);
    if hService = nil then
      Exit;
    try
      dwTimeOut := 60000;
      InternetSetOption(hService, INTERNET_OPTION_RECEIVE_TIMEOUT, @dwTimeOut, SizeOf(dwTimeOut));
      if InternetQueryDataAvailable(hService, dwBytesAvail, 0, 0) then
      repeat
        if not InternetReadFile(hService, @lpBuffer[0], SizeOf(lpBuffer), dwBytesRead) then
          Break;
        if dwBytesRead <> 0 then
          FMs.WriteBuffer(lpBuffer[0], dwBytesRead);
      until dwBytesRead = 0;
      Result := FMS.Size > 0;
    finally
      InternetCloseHandle(hService);
    end;
  finally
    InternetCloseHandle(hSession);
  end;
end;
mjn
  • 36,362
  • 28
  • 176
  • 378
MartinLoanel
  • 184
  • 3
  • 17
  • 1
    Sounds like you need to parse the URI like so: http://stackoverflow.com/a/16703210/988445 Then you can extract the file extension from the "Path" property. – Jerry Dodge Aug 27 '15 at 23:38
  • problem i wil stuck in that some url could be like this : https://i.stack.imgur.com/j0w2S.jpg?s=64&g=1 and some url could be like this - : https://i.stack.imgur.com/j0w2S.jpg or url also could be .html or php – MartinLoanel Aug 28 '15 at 00:14
  • Yes, that's why parsing the URL will extract `j0w2S.jpg` directly out by itself, so that you can detect `.jpg`. – Jerry Dodge Aug 28 '15 at 00:18
  • 1
    If you can't use your URI to filter the items then you need to look at the data to see if you can find the JPG or GIF headers. This question has some code to check the stream for the type of image: http://stackoverflow.com/questions/959160/load-jpg-gif-bitmap-and-convert-to-bitmap Look at the method called `DetectImage` in the first answer. – Graymatter Aug 28 '15 at 00:19
  • @JerryDodge I can't see how that would work. The web server will stream back the data without any header information directly from the URL. – Graymatter Aug 28 '15 at 00:20
  • @Graymatter They way I understand it, OP wants to stop this procedure from continuing before it even connects. "i tried to add check for FURL but extract file extension from url is bad step for me" I translate to "How do I extract `.jpg` or `.gif` out of `FURL`?" – Jerry Dodge Aug 28 '15 at 00:21
  • @JerryDodge That's impossible to do because you can't tell the type of data that would be returned by the web server. You can minimize the traffic by reading a small chunk of data and checking the first 3 bytes. That's about the only option. I can see what you mean though because of the way the question is worded. – Graymatter Aug 28 '15 at 00:23
  • @Graymatter Yes, that is the case, but OP mentions nothing about receiving the data. Just that they tried to check `FURL` but thought it was a bad idea. If that's not the case, then you would have to check the response if it returned a content type. Or read the file headers. If it were me, I would block such requests in the first place. But yes, it's good to have checks both before requesting and after receiving header info (hate to download the file only to dispose of it). And not all web servers return either content type or header info. – Jerry Dodge Aug 28 '15 at 00:24

2 Answers2

4

You can send a HTTP HEAD request and look at the content-type response header. If it is image/gif then it is safe to assume that the resource is a gif image. Of course this requires a properly configured HTTP server.

As a (Delphi) starting point, see: https://stackoverflow.com/a/9166393/80901

Community
  • 1
  • 1
mjn
  • 36,362
  • 28
  • 176
  • 378
3

This is something that would have to be managed from many different angles. There's no one place in this process where you can make a check to ensure you're only downloading a .gif file.

Consider...

  • A URL like http://somesite.com/Logo with no extension
  • A web server responding with an error page
  • A web server responding with an unexpected file format
  • A web server responding with the right image but image is a different format
  • A web server which does not support returning content type

What you will have to consider implementing is...

Each of these is an entirely different solution, depending on your requirements, and you might need to use only one, two or all three.

Community
  • 1
  • 1
Jerry Dodge
  • 26,858
  • 31
  • 155
  • 327
  • Thank you jerry i am starting to following the directions – MartinLoanel Aug 28 '15 at 11:01
  • Checking the actual downloaded file data for a GIF header is the best option, since all other options can either send non-GIF data with the proper type reported, or can *lie* and claim that a GIF is being requested/sent when it really is not. Don't take the chance. Validate the downloaded data before you use it. – Remy Lebeau Aug 29 '15 at 02:45
  • @Remy Well yes, it wasn't really clear in what ways OP wanted to protect from other formats, so I thought I'd offer a collection of possible implementation to accommodate for their precise needs. – Jerry Dodge Aug 29 '15 at 04:48