Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > IdHTTP -> передача параметров скрипту


Автор: inside 12.7.2006, 13:02
Привет! Я отправляю HTTP запрос из приложения на Delphi, которое является клиентом на cgi -скрипт на Perl. Запрос имеет аргументы name - имя файла и login - имя пользователя. Нужно, чтобы скрипт переместил файл name в папку ../login/ которая уже была создана. 

Для перемещения файлов я использую функцию move модуля File::Copн: 

move("../Papka/$in{name}", "../$in{login}/$in{name}"; 

print "Content-type: text/html\n\n"; 


#------------------------------------------------------------------------------- 

Проблема в том, что файл не копируется! Если в строке браузера вызвать скрипт - всё ок! Но если вызывать из Delphi (используется компонент Indy), то файл ПРОСТО не копируется, хотя АБСОЛЮТНО совпадают как запросы, так и функции move. 

Привожу выдержку из лог-файла: 

83.237.63.58 - - [11/Jul/2006:23:42:34 +0400] "GET /cgi-bin/move.cgi?name=power.mp3&login=hitman HTTP/1.1" 200 5 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"  - из браузера 

83.237.63.58 - - [11/Jul/2006:23:43:04 +0400] "GET /cgi-bin/move.cgi?name=power.mp3&login=hitman HTTP/1.1" 200 5 "-" "Mozilla/3.0 (compatible; Indy Library)"  - из Делфи 

как видно, запросы одинковы, но в первом случае файл копируется, во втором - нет. Очень прошу Помочь. Заранее спасибо! 

Код на Делфи такой: 

Код

var 
  LoginInfo: TStrings; 
  Response: TStringStream; 
  resp: string; 
begin 
  LoginInfo := TStringList.Create; 
  Response := TStringStream.Create(''); 
  LoginInfo.Clear; 
  LoginInfo.Add('name=filename'); 
  LoginInfo.Add('login=nickname'); 
  IdHTTP1.Request.ContentType:='application/x-www-form-urlencoded'; 
  IdHTTP1.Post('http://adres/cgi-bin/move.cgi',LoginInfo,Response); 
  resp:=Response.DataString; 
  Response.Free; 
  LoginInfo.Free; 


Очень прошу помочь!   

Автор: Snowy 12.7.2006, 13:12
Код
var 
  LoginInfo: TStringList; 
  resp: string; 
begin 
  LoginInfo := TStringList.Create;
  LoginInfo.Add('name=filename');
  LoginInfo.Add('login=nickname');
  try
    resp := IdHTTP1.Post('http://adres/cgi-bin/move.cgi',LoginInfo);
  finally
    LoginInfo.Free; 
  end;
end;
Ты определись: ты отправляешь GET или POST запрос?

Добавлено @ 13:13 
Не может быть одинаковых GET запросов, если ты из браузера отправляешь GET, а из дельфи POST  

Автор: inside 12.7.2006, 13:23
Из Делфи отправляю с помощью Post. В логах был Get - потому что пробовал и Get-ом и Post-ом. Всё равно НЕ РАБОТАЕТ. 

Snowy - resp := IdHTTP1.Post('http://adres/cgi-bin/move.cgi',LoginInfo,Response);
а Response - забыл вставить в список переменных?

Как быть? 


ЗЫ: Точнее Reponse там вообще не нужен =) 

Автор: Snowy 12.7.2006, 13:41
Цитата(inside @  12.7.2006,  13:23 Найти цитируемый пост)
Точнее Reponse там вообще не нужен
Угу. Забыл убрать.

Попробуй так:
Код

function SendMove(name, login: string): string;
var
  http: TIdHTTP;
begin
  http := TIdHTTP.Create(nil);
  try
    try
      result := http.Get('http://adres/cgi-bin/move.cgi?name=' + name + '&login=' + login);
    except
      on E: Error do result := E.Message;
    end;
  finally
    http.Free;
  end;
end;
  

Автор: inside 12.7.2006, 13:56
 smile  Неа... не копирует. Может проблема в кодировке - move("../Papka/$in{name}", "../$in{login}/$in{name}"; 
- я там их такой функцией копирую. Уже всё перепробовал. 

Автор: Snowy 12.7.2006, 14:06
Причем тут кодировка, если ты не используешь ни русских символов, ни пробела.
Попробуй логировать в файл то, что получает cgi скрипт и сравнить разницу.
И какую строку ты пишешь в браузере, что у тебя всё проходит? 

Автор: inside 12.7.2006, 16:06
В файл писал лог - сохранял запрос - они в точности одинаковы, если отправлять из Делфи или из браузера. Из браузера я просто пишу http://www.adress.ru/cgi-bin/move.cgi?name=filename&login=nickname

И всё копирует. Уже была мысль вызвать браузер из проги, а выходным данным скрипта послать комманду закрытия окна, так что оно будет открыаться и сразу закрываться. Но это конечно криво. Надо разобраться почему не копирует.  

Автор: Snowy 12.7.2006, 16:19
Ну, если запросы идентичны, значит дело не в дельфи, а в скрипте.
Может там проверка на клиента идет...
Попробуй прописать строку клиента, как у IE. 

Автор: inside 12.7.2006, 16:41
 smile  По нулям... Изменил UserAgent. Вот логи:


83.237.63.56 - - [12/Jul/2006:17:37:15 +0400] "GET /cgi-bin/move.cgi?name=demon.mp3&login=miracle HTTP/1.1" 200 5 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
(из программы - файл не копируется)

83.237.63.56 - - [12/Jul/2006:17:37:34 +0400] "GET /cgi-bin/move.cgi?name=demon.mp3&login=miracle HTTP/1.1" 200 5 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
(из браузера - файл копируется удачно)

 smile   smile   smile   smile    Может проблема в правах доступа - может из Делфи права другие, чем из браузера. На папку, куда надо копировать установлены 700. Хотя пробовал и 755 и 777 - всё ровно НЕ ИДЁТ...

Люди, выручайте - что делать?  smile 
 

Автор: Snowy 12.7.2006, 16:47
Права тут не при чем.
Запрос он и есть запрос.
Разве что у тебя к скрипту не напрямую обращается...
Тогда поставь HandleRedirect в true. 

Автор: inside 12.7.2006, 16:56
Изменил - ноль....  smile  

Автор: Snowy 12.7.2006, 17:05
Код
function SendMove(name, login: string): string;
var
  http: TIdHTTP;
begin
  http := TIdHTTP.Create(nil);
  http.HandleRedirect := true;
  try
    try
      result := http.Get('http://adres/cgi-bin/move.cgi?name=' + name + '&login=' + login);
    except
      on E: Error do result := E.Message;
    end;
  finally
    http.Free;
  end;
end;

Код
move("../Papka/$in{name}", "../$in{login}/$in{name}"); 
print "../$in{login}/$in{name}\n\n"; 
Что на выходе у функции?     

Автор: inside 12.7.2006, 17:20
Вот так сделал =) 

Код

print "Content-type: text/html\n\n";
if (move("../Crazzzy/$in{name}", "../$in{login}/$in{name}")) {print "ok"} else {print "shit!"}


Опять же - если браузер - вижу ok, если прога - shit!  smile 

Хм... уже что-то....

хотя сама функция вот такая: 
Код

sub move {
    croak("Usage: move(FROM, TO) ") unless @_ == 2;

    my($from,$to) = @_;

    my($fromsz,$tosz1,$tomt1,$tosz2,$tomt2,$sts,$ossts);

    if (-d $to && ! -d $from) {
    $to = _catname($from, $to);
    }

    ($tosz1,$tomt1) = (stat($to))[7,9];
    $fromsz = -s $from;
    if ($^O eq 'os2' and defined $tosz1 and defined $fromsz) {
      # will not rename with overwrite
      unlink $to;
    }
    return 1 if rename $from, $to;

    # Did rename return an error even though it succeeded, because $to
    # is on a remote NFS file system, and NFS lost the server's ack?
    return 1 if defined($fromsz) && !-e $from &&           # $from disappeared
                (($tosz2,$tomt2) = (stat($to))[7,9]) &&    # $to's there
                ($tosz1 != $tosz2 or $tomt1 != $tomt2) &&  #   and changed
                $tosz2 == $fromsz;                         # it's all there

    ($tosz1,$tomt1) = (stat($to))[7,9];  # just in case rename did something

    {
        local $@;
        eval {
            local $SIG{__DIE__};
            copy($from,$to) or die;
            my($atime, $mtime) = (stat($from))[8,9];
            utime($atime, $mtime, $to);
            unlink($from)   or die;
        };
        return 1 unless $@;
    }
    ($sts,$ossts) = ($! + 0, $^E + 0);

    ($tosz2,$tomt2) = ((stat($to))[7,9],0,0) if defined $tomt1;
    unlink($to) if !defined($tomt1) or $tomt1 != $tomt2 or $tosz1 != $tosz2;
    ($!,$^E) = ($sts,$ossts);
    return 0;
}

*cp = \©
*mv = \&move;


if ($^O eq 'MacOS') {
    *_protect = sub { MacPerl::MakeFSSpec($_[0]) };
} else {
    *_protect = sub { "./$_[0]" };
}

# &syscopy is an XSUB under OS/2
unless (defined &syscopy) {
    if ($^O eq 'VMS') {
    *syscopy = \&rmscopy;
    } elsif ($^O eq 'mpeix') {
    *syscopy = sub {
        return 0 unless @_ == 2;
        # Use the MPE cp program in order to
        # preserve MPE file attributes.
        return system('/bin/cp', '-f', $_[0], $_[1]) == 0;
    };
    } elsif ($^O eq 'MSWin32') {
    *syscopy = sub {
        return 0 unless @_ == 2;
        return Win32::CopyFile(@_, 1);
    };
    } elsif ($macfiles) {
    *syscopy = sub {
        my($from, $to) = @_;
        my($dir, $toname);

        return 0 unless -e $from;

        if ($to =~ /(.*:)([^:]+):?$/) {
        ($dir, $toname) = ($1, $2);
        } else {
        ($dir, $toname) = (":", $to);
        }

        unlink($to);
        Mac::MoreFiles::FSpFileCopy($from, $dir, $toname, 1);
    };
    } else {
    $Syscopy_is_copy = 1;
    *syscopy = \©
    }
}


Пойди разберись, где именно она ноль вернула  smile   

Автор: Snowy 12.7.2006, 17:35
нет, пусть вернёт именно "../$in{login}/$in{name}\n\n"
Может именно тут разница зарыта.

Добавлено @ 17:36 
И сниферни или пропусти через мапер весь заголовок запроса, а не только GET 

Автор: inside 12.7.2006, 17:53
Цитата

нет, пусть вернёт именно "../$in{login}/$in{name}\n\n"


это я уже проверял - сохранял в лог, как выглядят функции move при подстановке значений переменных - абсолютно одинаково.

Цитата

И сниферни или пропусти через мапер весь заголовок запроса, а не только GET 


Как это сделать - я не знаю - объясни - обязательно займусь

 

Автор: Snowy 12.7.2006, 18:06
Вот код маппера.
http://forum.vingrad.ru/index.php?showtopic=89811&view=findpost&p=689298
Настрой его на подключение к серверу. Хост - adres, порт 80.
В браузере и программе настрой прокси: хост - localhost, порт - порт мапера.
В указанный файл будет сброшен весь траффик.
Если и есть разница в запросах - увидишь её в файле. 

Автор: inside 12.7.2006, 18:13
вот здесь выдается 0... Для меня только этот код сложноват. Кто-нибудь понимает - где именно ошибка? (точнее не ошибка - это move из File::Copy, а почему не получается скопировать?)

Код

    my($from,$to) = @_;

    my($fromsz,$tosz1,$tomt1,$tosz2,$tomt2,$sts,$ossts);

    if (-d $to && ! -d $from) {
    $to = _catname($from, $to);
    }

    ($tosz1,$tomt1) = (stat($to))[7,9];
    $fromsz = -s $from;
    if ($^O eq 'os2' and defined $tosz1 and defined $fromsz) {
      # will not rename with overwrite
      unlink $to;
    }
    return 1 if rename $from, $to;

    # Did rename return an error even though it succeeded, because $to
    # is on a remote NFS file system, and NFS lost the server's ack?
    return 1 if defined($fromsz) && !-e $from &&           # $from disappeared
                (($tosz2,$tomt2) = (stat($to))[7,9]) &&    # $to's there
                ($tosz1 != $tosz2 or $tomt1 != $tomt2) &&  #   and changed
                $tosz2 == $fromsz;                         # it's all there

    ($tosz1,$tomt1) = (stat($to))[7,9];  # just in case rename did something

    {
        local $@;
        eval {
            local $SIG{__DIE__};
            copy($from,$to) or die;
            my($atime, $mtime) = (stat($from))[8,9];
            utime($atime, $mtime, $to);
            unlink($from)   or die;
        };
        return 1 unless $@;
    }
    ($sts,$ossts) = ($! + 0, $^E + 0);

    ($tosz2,$tomt2) = ((stat($to))[7,9],0,0) if defined $tomt1;
    unlink($to) if !defined($tomt1) or $tomt1 != $tomt2 or $tosz1 != $tosz2;
    ($!,$^E) = ($sts,$ossts);
    return 0;

   

Автор: inside 12.7.2006, 18:36
Snowy, в Мапере поставил - хост - Айпи сервера, порт -80
В Браузере И Программе - хост- localhost, порт - 80.
всё правильно?

Браузер вообще ничего не отображает - ошибка 501. Программа вроде подключается, но логи не пишет. Где я накосячил? 

Автор: inside 12.7.2006, 20:26
 smile   smile   smile  Snowy, ты не поверишь - я засунул отправку запроса в обработку EndWork IdFTP.... Знаю, поступок героический, но понял, что косяк в этом после того, как досконально перепробовал все остальные варианты. Спасибо тебе большое =) 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)