Unsuccessful upload to a ftp server on Linux using Qt![File zero size at destination] - qt

I am trying to upload a file to a FTP server, which is a local server created by vsftpd. I have set necessary parameters needed for connecting and transferring files in the vsftpd.conf file. My requirement is to upload a file to this server. When i logged statechanged messages, HostLookup, Connecting, Connected, Logged in, closing, and Unconnected messages were emitted by my ftp object. But when i check in the destination directory the file is there but of 0 size...What could be wrong? following is the code I used...
QImage img("./Sample.jpg");
QBuffer* buf = new QBuffer();
buf->open(QBuffer::ReadWrite);
buf->seek(0);
img.save(buf, "jpg");
connection = new QFtp();
connection->connectToHost("localhost");
connection->login();
connection->cd("ftpshare/");
connection->put(buf, "Sample.jpg", QFtp::Binary);
qDebug(QString::number(connection->error()).toLatin1());
qDebug(connection->errorString().toLatin1());
connect(connection,SIGNAL(stateChanged(int)),this,SLOT(ftpstatechanged(int)));
connection->close();

Are you sure the first line of finds the Sample.jpg in the folder it is looking in? Maybe the working directory is not what you think it is. Otherwise this should work just fine.

The problem was with usage of buffer. It got solved when I used QByteArray instead.
QImage img("./Sample.png");
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
img.save(&buffer, "PNG");
connection = new QFtp();
connection->connectToHost("localhost");
connection->login();
connection->cd("ftpshare/");
connection->put(ba, "Sample.png", QFtp::Binary);

Related

Exception getting while migration of alfresco content, Too many open files

I am getting this error while migrating content from one alfresco repository to other.
And I am getting this error on live production server logs.
And also Server is getting down while migration is running.
Can anyone please help me to resolve this issue or any suggestion is there to avoid this issue.
Any help or comments will be appreciated.
Thanks in Advance.
I have written below code snippet
ContentStream contentStream = new ContentStreamImpl("content." + FilenameUtils.getExtension(fileName),
BigInteger.valueOf(fileName.length()), new MimetypesFileTypeMap().getContentType(newfile), doc.getContentStream().getStream());
I have 2 repositorys,Using above code I am reading content stream from source and creating new file in target repository and adding the content stream. But I didn't found any way to to close the content stream.
Please find below error log for more details.
java.net.SocketException: Too many open files
at java.net.PlainSocketImpl.socketAccept(Native Method)
If you are using the DotCMIS method GetContentStream on the client side, make sure you always close the stream - even if you are not reading it. Otherwise, the socket to the server stays open. Depending on your application the client and/or the server can run out of sockets.
Closing the stream works like this:
IContentStream contentStream = document.GetContentStream();
Stream stream = contentStream.Stream;
... do something with the stream ...
stream.Close();

Qt login to steam with QNetworkAccessManager

I'm using QT 5.0.2 prebuilt and QT creator 2.7.0 and my goal is to login to steam network programmatically using uname, password and steamguard code. Or to be more precise: get QNetworkAccessManager from its initial uninitialized state to the state where it could retrieve any data from steam related sites as if it was logged in as some user.
So the login happens in 4 steps (4 request-response combos):
NOTE: Steam site javascript uses post in all requests, but it seems that get also works.
Assume username "hyper"
1. Initial request:
post https://store.steampowered.com/login/getrsakey/?username=hyper
Here is my function:
void http::steam_auth(const QString &uname, const QString &pwd)
{
QString encrypted_password, sg, pkey_exp, pkey_mod, timestamp, emailsteamid;
QJsonDocument json_buffer;
QByteArray buffer;
QUrl rsa(steam_getrsa), login(steam_dologin); //steam login urls
QUrlQuery urlquery;
Here we send our request:
urlquery.addQueryItem("username", uname); //first step
urlquery.addQueryItem("l", "english"); //set communication language
rsa.setQuery(urlquery);
QNetworkRequest first(rsa);
QNetworkReply *reply = this->get(first);
buffer = reply->readAll();
As a response we get:
{"success":true,"publickey_mod":"AC41A964789638B6A3B3BD5ADD9F3680FA45881C70FD2032B10A3BB6D2ACF021C2B3D564DC44DE3054E3BF78A1753399223C794A0DED03A76CD1F1DFE851E30F0D6F14484C258EB6053676A47D20A68E11ECCD783F343594DDA3817AA5DCCE75FAF5C68BB197DA1FF12F22F9FCD83624D00A23CC57A367563ADBBCEDF5C8742A57B12A4BD04DC02A55C80F4F6984B1E2D5A99081510326E1C6BAB2C2723560487E8F7EA1A2CB55AEFC5594C9FBB71CAD553CB2D866214BC41156259FEC55362D38DCDBE8FADFB577FE0736CE3E37AF6D2CDDF28FA218C1E477E29B17713BFC48A227455B6B0DE09884CC0820CE40CD4877D93704D00E20A235FCF55D100A01C1","publickey_exp":"010001","timestamp":"284691100000"}
Which means everything is ok.
Now we need to encrypt our password before sending it
json_buffer = QJsonDocument::fromJson(buffer);
pkey_exp = json_buffer.object().value("publickey_exp").toString();
pkey_mod = json_buffer.object().value("publickey_mod").toString();
timestamp = json_buffer.object().value("timestamp").toString();
delete reply;
urlquery.clear();
encrypted_password = app::core::get_encrypted_password(pwd, pkey_exp, pkey_mod);
2. Send encrypted password:
urlquery.addQueryItem("username", uname);
urlquery.addQueryItem("password", encrypted_password);
urlquery.addQueryItem("emailauth", "");
urlquery.addQueryItem("captchagid", "");
urlquery.addQueryItem("captcha_text", "");
urlquery.addQueryItem("emailsteamid", "");
urlquery.addQueryItem("rsatimestamp", timestamp);
urlquery.addQueryItem("remember_login", "false");
login.setQuery(urlquery);
QNetworkRequest second(login);
second.setUrl(login);
reply = this->get(second);
buffer = reply->readAll();
We get a request string as follows:
post https://store.steampowered.com/login/dologin/?username=solidbeetle2&password=YmhTKVkRXyiCYe6wx+ZJ8PIhzj4A4BLWgJFOE5ge7nbIAM6m1G9qHh+Iqx30ZLdB0wW0xdWDNCgHBNPHKLA+P2pYhPF0DeL9v8UQsers6NCNNPZ0SFN4HhNlu6Gwh8QAjrNykev7N5FADXwJnFjPBvmvthATmrktVEtFYF54lckaPnijXYSDIpfEjmG8+bCDKT/GLaUiftA2QauUY9ap8WHSEoykiTmfL344ghzjhCA33UKx0NIgBrDdI1RLfHVcmAcU/c9NEhoHLOT93n8hqWY+YVx9VbOcKqqZPrbCiQoU2BZrqK6N7aj+K6kH0VWHH7+LD2KJx4BUJgHOmNqVDg%3D%3D&emailauth=&captchagid=&captcha_text=&emailsteamid=&rsatimestamp=50693150000&remember_login=false
It is perfectly valid as far as I can tell, JS on steam site sends ajax with the same, but...
Here is the problem
When I get a response with this it says message:Invalid login in json... But if I save the full query string from my request to file and then paste it either in browser or in HTTP Request builder inside HTTP Analyzer, it works fine displaying message:SteamGuard
What could be wrong? Is there something I'm missing? Does QNetworkAccessManager break this somehow?:c
Sorry if something is not clear, I'll try my best to explain again if needed.
Thanks in advance!
P.S. Is there any solid way to examine requests my app is sending?
P.S.S. my qt creator seems to crash when debugging projects with qml option, idk why...
I have inspected all this stuff and finally was able to achieve my goal.
In short the problem was in qt's web-oriented classes. It seemed obvious that qurlquery should encode characters such as / or = in their %-encoded form.. but it is NOT the case, therefore I had to replace them manually in QString. If someone needs a working routine, it can be found here (Its not pretty :c)

copy file from local to remote server

I'm dynamically creating html files on my local system (using HTMLTEXTWRITER, then save them using streamwriter to local file system). I want to copy this file to my remote server withour user interaction, so that my users can read file. I use C#
for instance I want to copy from d:\myfile.html to mysite.com\myfile.html, how can I do it?
I have used this and it worked. may be useful
for holding path of local
rPath = "\\" & Request.UserHostAddress & "\c$\temp\"
for output file
rOutput = Session.SessionID & "_" & Format(Date.Now(), "ddMMyyhhmmss") & ".pdf"
now: report will be created at localhost\c\temp
You can't use the System.IO classes for this (unless you have access to the remote server as a network drive), but you can programmatically POST the file from the client to the remote server over HTTP using System.Net.
Here's a snippet using the WebRequest class:
WebRequest request = WebRequest.Create( url );
request.Timeout = 1000; // some appropriate value
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = 0; // set a length here
using( StreamWriter requestStream = new StreamWriter( request.GetRequestStream(), System.Text.Encoding.UTF8) ) {
// write to the stream here using requestStream.Write();
requestStream.Close();
}
More info for HTTP: http://msdn.microsoft.com/en-us/library/debx8sh9.aspx
Alternatively, you could use a protocol designed for transferring files like FTP (or something more secure) which isn't that hard to do in code.
FTP options: http://msdn.microsoft.com/en-us/library/ms229718
Is you remote server based on Windows and in the same workgroup or domain with you working machine ? If so, you can turn on the Windows File Sharing on the server. Then you can copy your file with cmd like this:
copy c:\test.txt \\mysite.com
The path "\\mysite.com" is also valid used by File.Copy in C#.
Otherwise, you need to set up a FTP environment on you server and use the FTP related API in C#.
You could set-up an FTP server and copy the files programmatically via FTP.
An example would be found here or here.
There are three ways by which you can copy the file to remote server.
Using normal file copy mode. Here you need to have access to the the webserver shared path. If the webserver is in same network as your application, then you can share the webroot and provide write access to the user who is running the application. He can then use File.Copy("source.txt", "\\Servername\SharedFolderName\target.txt").
The second approach is to use FTP to copy the file to the remote server. This MSDN example would help you on how to do this. This will work with most of the shared hosting providers.
You can use HTTP POST as noted by Tim. But this would let any user to perform the post. You may have to take care of user provisioning, authentication and authorization. IMO, keep this as last option as provisioning user and providing rights to certain path, may become cumbersome.

iis7 website accessed externally downloads files to server instead of local machine

I've a site set up in IIS. It's allows users to download files from a remote cloud to their own local desktop. HOWEVER, the context seems to be mixed up, because when I access the website externally via the IP, and execute the download, it saves the file to the server hosting the site, and not locally. What's going on??
My relevant lines code:
using (var sw2 = new FileStream(filePath,FileMode.Create))
{
try
{
var request = new RestRequest("drives/{chunk}");
RestResponse resp2 = client.Execute(request);
sw2.Write(resp2.RawBytes, 0, resp2.RawBytes.Length);
}
}
Your code is writing a file to the local filesystem of the server. If you want to send the file to the client, you need to do something like
Response.BinaryWrite(resp2.RawBytes);
The Response object is what you use to send data back to the client who made the request to your page.
I imagine that code snippet you posted is running in some sort of code-behind somewhere. That is running on the server - it's not going to be running on the client. You will need to write those bytes in the Response object and specify what content-type, etc. and allow the user to Save the file himself.

Response.TransmitFile() with UNC share (ASP.NET)

In the comments of this page:
http://msdn.microsoft.com/en-us/library/12s31dhy%28v=VS.90%29.aspx
..it says that TransmitFile() cannot be used with UNC shares. As far as I can tell, this is the case; I get this error in Event Log when I attempt it:
TransmitFile failed. File Name: \\myshare1\e$\file.zip, Impersonation Enabled: 0, Token Valid: 1, HRESULT: 0x8007052e
The suggested alternative is to use WriteFile(), however, this is problematic because it loads the file into memory. In my application, the files are >200MB, so this is not going to scale.
Is there a method in ASP.NET for streaming files to users that's:
scalable (doesn't read entire file into RAM or occupy ASP.NET threads)
works with UNC shares
Mapping a network drive as a virtual directory is not an option for us. I would like to avoid copying the file to the local web server as well.
Thanks
Have you tried setting up an IIS vroot using the remote UNC path as its home directory? If it works, this may be the easiest solution. You can still enforce authentication barriers on the files (e.g. via an HttpModule, or perhaps even via the out-of-box forms auth module) but you can rely on IIS to efficiently stream the content once your auth filters give the go-ahead.
A caveat: the last time I configured IIS in a UNC scenario was a long time ago (1998!!!) and I ran into intermittent problems with files being locked on the remote machine, making updating files sometimes problematic. Dealing with recovery after a UNC server reboot was also interesting. I assume in the 11 years since then those problems have been ironed out, but you can never be sure!
Another approach may be to install a web server on the UNC machine, and then install a reverse proxy server on your web server, like the new IIS7 Application Request Routing module.
If you're willing to tie up a server thread, you can use the approach recommended in KB812406 which deals with issues around RAM consumption, timeouts, client disconnection, etc. Make sure to turn off Response Buffering!
The ideal maximum-control solution would be a "streaming HttpHandler" where, instead of having to send the output all at once, you could return a stream to ASP.NET and let ASP.NET deal with the details about chunking results to the client, dealing with disconnects, etc. But I was unable to find a good way to do this. :-(
Something you could try is opening the network file using a FileStream, and using a loop to read a chunk of the file, transmit the chunk (using Response.Write(Char[], Int32, Int32)), dispose of the chunk, and repeat until the file has been completely read.
You could write the file to a local directory, and have a robocopy job monitoring the directory to do the copy.
Since you want to avoid writing to the local server, though, you may want to investigate putting a server (HTTP or FTP, e.g.) on the target server, and writing the file to that service.
could you set up another IIS website which points to the UNC, then redirect them to the file on that other website?
Response.Redirect("http://files.somewhere.com/some/file.blah");
That way it will be running in a separate worker process and have no effect on your current site, and the files will be served directly by IIS, which is clearly best.
The actual error you got back was a logon failure to the file share (which isn't massively surprising considering the user IIS is likely to be running as, as well as you trying to access an administrative share). Have you tried setting up a share which has no access restrictions at all just to check if that is the issue rather than any specific limit in TransmitFile.
If that fixes it then you need to login to that share one way or another as the current user, or impersonate a user which does have permissions.
It is also worth pointing out that after abit of looking around with reflector TransmitFile can potentially end up reading the file into memory anyway, and that WriteFile has another version which takes a boolean value which decides whether to read the file into memory or not (in fact the default WriteFile passes false for this parameter). Might be worth you poking around in the code.
I would recommend the second site approach and implement a token-based authentication mechanism. Encode an authentication cookie in the URL passed to the client via Redirect. This could be an opaque value that is shared behind-the-scenes, or it could be something as simple as a hash of a secret password and the current date, for example.
One project I did used the hashing. One server generated a hash of a shared secret password and an extension number. The second server (which was on a different network) took the same password and extension and hashed them to confirm the user was allowed to place a call from that extension to the desired phone number.
The code for TransmitFile is very simple, why not modify it to do what you need?
public void TransmitFile(string filename, long offset, long length)
{
if (filename == null)
{
throw new ArgumentNullException("filename");
}
if (offset < 0L)
{
throw new ArgumentException(SR.GetString("Invalid_range"), "offset");
}
if (length < -1L)
{
throw new ArgumentException(SR.GetString("Invalid_range"), "length");
}
filename = this.GetNormalizedFilename(filename);
using (FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
long num = stream.Length;
if (length == -1L)
{
length = num - offset;
}
if (num < offset)
{
throw new ArgumentException(SR.GetString("Invalid_range"), "offset");
}
if ((num - offset) < length)
{
throw new ArgumentException(SR.GetString("Invalid_range"), "length");
}
if (!this.UsingHttpWriter)
{
this.WriteStreamAsText(stream, offset, length);
return;
}
}
if (length > 0L)
{
bool supportsLongTransmitFile = (this._wr != null) && this._wr.SupportsLongTransmitFile;
this._httpWriter.TransmitFile(filename, offset, length, this._context.IsClientImpersonationConfigured || HttpRuntime.IsOnUNCShareInternal, supportsLongTransmitFile);
}
}
private void WriteStreamAsText(Stream f, long offset, long size)
{
if (size < 0L)
{
size = f.Length - offset;
}
if (size > 0L)
{
if (offset > 0L)
{
f.Seek(offset, SeekOrigin.Begin);
}
byte[] buffer = new byte[(int) size];
int count = f.Read(buffer, 0, (int) size);
this._writer.Write(Encoding.Default.GetChars(buffer, 0, count));
}
}
internal void TransmitFile(string filename, long offset, long size, bool isImpersonating, bool supportsLongTransmitFile)
{
if (this._charBufferLength != this._charBufferFree)
{
this.FlushCharBuffer(true);
}
this._lastBuffer = null;
this._buffers.Add(new HttpFileResponseElement(filename, offset, size, isImpersonating, supportsLongTransmitFile));
if (!this._responseBufferingOn)
{
this._response.Flush();
}
}
Thanks,
Phil.

Resources