Discussion:
HTTP PUT to IIS
(too old to reply)
MartinF
2008-05-12 16:06:20 UTC
Permalink
Hello All,

I need to programmatically upload a file to an IIS server. For this I wrote
a small proof of concept app that uses WinInet.lib that runs on my Vista
machine and connects to a server that runs IIS 7.0 The app appears to work
just fine, but at the end of the HttpQueryInfo() call with the
HTTP_QUERY_STATUS_CODE I get a 404 response. Analyzing the log on the IIS
server reveals the following:

#Date: 2008-05-09 23:43:40
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port
cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status
time-taken
2008-05-09 23:43:40 192.168.1.253 GET /Upload/ - 80 - 192.168.1.253
Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506)
200 0 0 50
2008-05-09 23:44:02 192.168.1.253 PUT /Upload/Test.txt - 80 - 192.168.1.185
HttpSend 404 0 2 200
2008-05-09 23:47:12 192.168.1.253 GET / - 80 - 192.168.1.253
Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506)
200 0 0 100
2008-05-09 23:48:44 192.168.1.253 PUT /Upload/Test.txt - 80 - 192.168.1.185
HttpSend 404 0 64 110
2008-05-09 23:58:16 192.168.1.253 PUT /Upload/Test.txt - 80 - 192.168.1.185
HttpSend 404 0 64 150

I abbreviate the code here for the sake of brevety:

1.- Calling my class as follows:
int _tmain(int argc, _TCHAR* argv[])
{
CHttpSend Http;

if ( Http.Init( TEXT("http://192.168.1.253/Upload/Test.txt") ) == true )
{
Http.SendFile( TEXT("c:\\Develop\\Test.txt") );
}

return 0;
}

2.- Abbreviated CHttpSend::Init() is as follows:


m_hInternet = InternetOpen( TEXT("HttpSend"),
INTERNET_OPEN_TYPE_PRECONFIG,
0, 0, 0) ;

URL_COMPONENTS urlComp = { 0 };
TCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH] = { 0 };
TCHAR szPath[INTERNET_MAX_PATH_LENGTH] = { 0 };
TCHAR szExtra[INTERNET_MAX_PATH_LENGTH] = { 0 };

urlComp.dwStructSize = sizeof(urlComp);
urlComp.lpszHostName = szHostName;
urlComp.dwHostNameLength = sizeof(szHostName) - 1;
urlComp.lpszUrlPath = szPath;
urlComp.dwUrlPathLength = sizeof(szPath) - 1;
urlComp.lpszExtraInfo = szExtra;
urlComp.dwExtraInfoLength= sizeof(szExtra) - 1;

InternetCrackUrl( pszUrl, 0, ICU_ESCAPE, &urlComp);

// At this point szHostName contains "192.168.1.253"
// At this point urlComp.nPort is 80. I made sure it doesn't conflict with
default website.

m_hHttp = InternetConnect( m_hInternet, szHostName, urlComp.nPort,
0, 0, INTERNET_SERVICE_HTTP, 0, 0);


3.- Abbreviated CHttpSend::SendFile() is as follows:


hRequest = HttpOpenRequest (
m_hHttp, TEXT("PUT"), m_pszUrl, NULL,
NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0
);

memset(&IBuff, 0, sizeof(IBuff));
IBuff.dwStructSize = sizeof(IBuff);
IBuff.dwBufferTotal = File.Length();
ulBytesToSend = IBuff.dwBufferTotal;

HttpSendRequestEx( hRequest, &IBuff, NULL, HSR_INITIATE, 0);

// Do a number of InternetWriteFile() calls as we are reading from
// the file to send.

InternetWriteFile( hRequest, pBuff, ulBytes, &ulWritten );

// Once all the file content was process
HttpEndRequest( hRequest, NULL, 0, 0 );

// And finally I do the HttpQueryInfo() which fails with a 404

if ( HttpQueryInfo( hRequest, HTTP_QUERY_STATUS_CODE, szBuff, &dwSize, &dw )
== TRUE )
{
UINT uRetCode = _wtol( szBuff );

if ( uRetCode < 400 )
bRet = true;
}

I suspect that there could be some IIS related configuration, but I think to
have it wide open from a security point of view. I am able to browse the
directory from a remote Internet Explorer.

Any help in this matter is greatly appreciated and thank you in advance.
Martin
Volodymyr M. Shcherbyna
2008-05-13 08:50:04 UTC
Permalink
I'd test this code at first on Apache, and if things goes fine you can play
with IIS configurations. Also, could you please make a trace from Wireshark,
and put it here?
--
V.
This posting is provided "AS IS" with no warranties, and confers no
rights.
Post by MartinF
Hello All,
I need to programmatically upload a file to an IIS server. For this I
wrote a small proof of concept app that uses WinInet.lib that runs on my
Vista machine and connects to a server that runs IIS 7.0 The app appears
to work just fine, but at the end of the HttpQueryInfo() call with the
HTTP_QUERY_STATUS_CODE I get a 404 response. Analyzing the log on the IIS
#Date: 2008-05-09 23:43:40
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port
cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status
time-taken
2008-05-09 23:43:40 192.168.1.253 GET /Upload/ - 80 - 192.168.1.253
Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506)
200 0 0 50
2008-05-09 23:44:02 192.168.1.253 PUT /Upload/Test.txt - 80 -
192.168.1.185 HttpSend 404 0 2 200
2008-05-09 23:47:12 192.168.1.253 GET / - 80 - 192.168.1.253
Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506)
200 0 0 100
2008-05-09 23:48:44 192.168.1.253 PUT /Upload/Test.txt - 80 -
192.168.1.185 HttpSend 404 0 64 110
2008-05-09 23:58:16 192.168.1.253 PUT /Upload/Test.txt - 80 -
192.168.1.185 HttpSend 404 0 64 150
int _tmain(int argc, _TCHAR* argv[])
{
CHttpSend Http;
if ( Http.Init( TEXT("http://192.168.1.253/Upload/Test.txt") ) == true )
{
Http.SendFile( TEXT("c:\\Develop\\Test.txt") );
}
return 0;
}
m_hInternet = InternetOpen( TEXT("HttpSend"),
INTERNET_OPEN_TYPE_PRECONFIG,
0, 0, 0) ;
URL_COMPONENTS urlComp = { 0 };
TCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH] = { 0 };
TCHAR szPath[INTERNET_MAX_PATH_LENGTH] = { 0 };
TCHAR szExtra[INTERNET_MAX_PATH_LENGTH] = { 0 };
urlComp.dwStructSize = sizeof(urlComp);
urlComp.lpszHostName = szHostName;
urlComp.dwHostNameLength = sizeof(szHostName) - 1;
urlComp.lpszUrlPath = szPath;
urlComp.dwUrlPathLength = sizeof(szPath) - 1;
urlComp.lpszExtraInfo = szExtra;
urlComp.dwExtraInfoLength= sizeof(szExtra) - 1;
InternetCrackUrl( pszUrl, 0, ICU_ESCAPE, &urlComp);
// At this point szHostName contains "192.168.1.253"
// At this point urlComp.nPort is 80. I made sure it doesn't conflict with
default website.
m_hHttp = InternetConnect( m_hInternet, szHostName, urlComp.nPort,
0, 0, INTERNET_SERVICE_HTTP, 0, 0);
hRequest = HttpOpenRequest (
m_hHttp, TEXT("PUT"), m_pszUrl, NULL,
NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0
);
memset(&IBuff, 0, sizeof(IBuff));
IBuff.dwStructSize = sizeof(IBuff);
IBuff.dwBufferTotal = File.Length();
ulBytesToSend = IBuff.dwBufferTotal;
HttpSendRequestEx( hRequest, &IBuff, NULL, HSR_INITIATE, 0);
// Do a number of InternetWriteFile() calls as we are reading from
// the file to send.
InternetWriteFile( hRequest, pBuff, ulBytes, &ulWritten );
// Once all the file content was process
HttpEndRequest( hRequest, NULL, 0, 0 );
// And finally I do the HttpQueryInfo() which fails with a 404
if ( HttpQueryInfo( hRequest, HTTP_QUERY_STATUS_CODE, szBuff, &dwSize,
&dw ) == TRUE )
{
UINT uRetCode = _wtol( szBuff );
if ( uRetCode < 400 )
bRet = true;
}
I suspect that there could be some IIS related configuration, but I think
to have it wide open from a security point of view. I am able to browse
the directory from a remote Internet Explorer.
Any help in this matter is greatly appreciated and thank you in advance.
Martin
MartinF
2008-05-14 16:49:41 UTC
Permalink
Confirmed that this code works with Apache. Please find attached the output
from Wireshark with filtering set to HTTP traffic on port 80.
The physical folder is also shared. Security settings are 'full control' to
all users including IIS_IUSRS

Thank you Volodymyr for your help.
Martin
Post by Volodymyr M. Shcherbyna
I'd test this code at first on Apache, and if things goes fine you can
play with IIS configurations. Also, could you please make a trace from
Wireshark, and put it here?
--
V.
This posting is provided "AS IS" with no warranties, and confers no
rights.
Post by MartinF
Hello All,
I need to programmatically upload a file to an IIS server. For this I
wrote a small proof of concept app that uses WinInet.lib that runs on my
Vista machine and connects to a server that runs IIS 7.0 The app appears
to work just fine, but at the end of the HttpQueryInfo() call with the
HTTP_QUERY_STATUS_CODE I get a 404 response. Analyzing the log on the IIS
#Date: 2008-05-09 23:43:40
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port
cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status
time-taken
2008-05-09 23:43:40 192.168.1.253 GET /Upload/ - 80 - 192.168.1.253
Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506)
200 0 0 50
2008-05-09 23:44:02 192.168.1.253 PUT /Upload/Test.txt - 80 -
192.168.1.185 HttpSend 404 0 2 200
2008-05-09 23:47:12 192.168.1.253 GET / - 80 - 192.168.1.253
Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506)
200 0 0 100
2008-05-09 23:48:44 192.168.1.253 PUT /Upload/Test.txt - 80 -
192.168.1.185 HttpSend 404 0 64 110
2008-05-09 23:58:16 192.168.1.253 PUT /Upload/Test.txt - 80 -
192.168.1.185 HttpSend 404 0 64 150
int _tmain(int argc, _TCHAR* argv[])
{
CHttpSend Http;
if ( Http.Init( TEXT("http://192.168.1.253/Upload/Test.txt") ) == true )
{
Http.SendFile( TEXT("c:\\Develop\\Test.txt") );
}
return 0;
}
m_hInternet = InternetOpen( TEXT("HttpSend"),
INTERNET_OPEN_TYPE_PRECONFIG,
0, 0, 0) ;
URL_COMPONENTS urlComp = { 0 };
TCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH] = { 0 };
TCHAR szPath[INTERNET_MAX_PATH_LENGTH] = { 0 };
TCHAR szExtra[INTERNET_MAX_PATH_LENGTH] = { 0 };
urlComp.dwStructSize = sizeof(urlComp);
urlComp.lpszHostName = szHostName;
urlComp.dwHostNameLength = sizeof(szHostName) - 1;
urlComp.lpszUrlPath = szPath;
urlComp.dwUrlPathLength = sizeof(szPath) - 1;
urlComp.lpszExtraInfo = szExtra;
urlComp.dwExtraInfoLength= sizeof(szExtra) - 1;
InternetCrackUrl( pszUrl, 0, ICU_ESCAPE, &urlComp);
// At this point szHostName contains "192.168.1.253"
// At this point urlComp.nPort is 80. I made sure it doesn't conflict
with default website.
m_hHttp = InternetConnect( m_hInternet, szHostName, urlComp.nPort,
0, 0, INTERNET_SERVICE_HTTP, 0, 0);
hRequest = HttpOpenRequest (
m_hHttp, TEXT("PUT"), m_pszUrl, NULL,
NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0
);
memset(&IBuff, 0, sizeof(IBuff));
IBuff.dwStructSize = sizeof(IBuff);
IBuff.dwBufferTotal = File.Length();
ulBytesToSend = IBuff.dwBufferTotal;
HttpSendRequestEx( hRequest, &IBuff, NULL, HSR_INITIATE, 0);
// Do a number of InternetWriteFile() calls as we are reading from
// the file to send.
InternetWriteFile( hRequest, pBuff, ulBytes, &ulWritten );
// Once all the file content was process
HttpEndRequest( hRequest, NULL, 0, 0 );
// And finally I do the HttpQueryInfo() which fails with a 404
if ( HttpQueryInfo( hRequest, HTTP_QUERY_STATUS_CODE, szBuff, &dwSize,
&dw ) == TRUE )
{
UINT uRetCode = _wtol( szBuff );
if ( uRetCode < 400 )
bRet = true;
}
I suspect that there could be some IIS related configuration, but I think
to have it wide open from a security point of view. I am able to browse
the directory from a remote Internet Explorer.
Any help in this matter is greatly appreciated and thank you in advance.
Martin
Volodymyr M. Shcherbyna
2008-06-03 14:04:39 UTC
Permalink
Sorry for delayed answer. I just looked at wireshark output. Sounds like IIS
behaves very strange. You can continue investigate the problem on IIS side,
ask here: microsoft.public.inetserver.iis.security
--
V.
This posting is provided "AS IS" with no warranties, and confers no
rights.
Post by MartinF
Confirmed that this code works with Apache. Please find attached the output
from Wireshark with filtering set to HTTP traffic on port 80.
The physical folder is also shared. Security settings are 'full control' to
all users including IIS_IUSRS
Thank you Volodymyr for your help.
Martin
Post by Volodymyr M. Shcherbyna
I'd test this code at first on Apache, and if things goes fine you can
play with IIS configurations. Also, could you please make a trace from
Wireshark, and put it here?
--
V.
This posting is provided "AS IS" with no warranties, and confers no
rights.
Post by MartinF
Hello All,
I need to programmatically upload a file to an IIS server. For this I
wrote a small proof of concept app that uses WinInet.lib that runs on my
Vista machine and connects to a server that runs IIS 7.0 The app appears
to work just fine, but at the end of the HttpQueryInfo() call with the
HTTP_QUERY_STATUS_CODE I get a 404 response. Analyzing the log on the IIS
#Date: 2008-05-09 23:43:40
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port
cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status
time-taken
2008-05-09 23:43:40 192.168.1.253 GET /Upload/ - 80 - 192.168.1.253
Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506)
200 0 0 50
2008-05-09 23:44:02 192.168.1.253 PUT /Upload/Test.txt - 80 -
192.168.1.185 HttpSend 404 0 2 200
2008-05-09 23:47:12 192.168.1.253 GET / - 80 - 192.168.1.253
Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.0;+SLCC1;+.NET+CLR+2.0.50727;+.NET+CLR+3.0.04506)
200 0 0 100
2008-05-09 23:48:44 192.168.1.253 PUT /Upload/Test.txt - 80 -
192.168.1.185 HttpSend 404 0 64 110
2008-05-09 23:58:16 192.168.1.253 PUT /Upload/Test.txt - 80 -
192.168.1.185 HttpSend 404 0 64 150
int _tmain(int argc, _TCHAR* argv[])
{
CHttpSend Http;
if ( Http.Init( TEXT("http://192.168.1.253/Upload/Test.txt") ) == true )
{
Http.SendFile( TEXT("c:\\Develop\\Test.txt") );
}
return 0;
}
m_hInternet = InternetOpen( TEXT("HttpSend"),
INTERNET_OPEN_TYPE_PRECONFIG,
0, 0, 0) ;
URL_COMPONENTS urlComp = { 0 };
TCHAR szHostName[INTERNET_MAX_HOST_NAME_LENGTH] = { 0 };
TCHAR szPath[INTERNET_MAX_PATH_LENGTH] = { 0 };
TCHAR szExtra[INTERNET_MAX_PATH_LENGTH] = { 0 };
urlComp.dwStructSize = sizeof(urlComp);
urlComp.lpszHostName = szHostName;
urlComp.dwHostNameLength = sizeof(szHostName) - 1;
urlComp.lpszUrlPath = szPath;
urlComp.dwUrlPathLength = sizeof(szPath) - 1;
urlComp.lpszExtraInfo = szExtra;
urlComp.dwExtraInfoLength= sizeof(szExtra) - 1;
InternetCrackUrl( pszUrl, 0, ICU_ESCAPE, &urlComp);
// At this point szHostName contains "192.168.1.253"
// At this point urlComp.nPort is 80. I made sure it doesn't conflict
with default website.
m_hHttp = InternetConnect( m_hInternet, szHostName, urlComp.nPort,
0, 0, INTERNET_SERVICE_HTTP, 0, 0);
hRequest = HttpOpenRequest (
m_hHttp, TEXT("PUT"), m_pszUrl, NULL,
NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0
);
memset(&IBuff, 0, sizeof(IBuff));
IBuff.dwStructSize = sizeof(IBuff);
IBuff.dwBufferTotal = File.Length();
ulBytesToSend = IBuff.dwBufferTotal;
HttpSendRequestEx( hRequest, &IBuff, NULL, HSR_INITIATE, 0);
// Do a number of InternetWriteFile() calls as we are reading from
// the file to send.
InternetWriteFile( hRequest, pBuff, ulBytes, &ulWritten );
// Once all the file content was process
HttpEndRequest( hRequest, NULL, 0, 0 );
// And finally I do the HttpQueryInfo() which fails with a 404
if ( HttpQueryInfo( hRequest, HTTP_QUERY_STATUS_CODE, szBuff, &dwSize,
&dw ) == TRUE )
{
UINT uRetCode = _wtol( szBuff );
if ( uRetCode < 400 )
bRet = true;
}
I suspect that there could be some IIS related configuration, but I think
to have it wide open from a security point of view. I am able to browse
the directory from a remote Internet Explorer.
Any help in this matter is greatly appreciated and thank you in advance.
Martin
Continue reading on narkive:
Loading...