?

Log in

No account? Create an account
ummm. hello. - LiveJournal Client Discussions [entries|archive|friends|userinfo]
LiveJournal Client Discussions

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

ummm. hello. [Feb. 5th, 2002|07:16 pm]
LiveJournal Client Discussions

lj_clients

[meirion]
and a question ;-)

i've finally got around to starting to write the lj client i've been talking about writing for the past six months or so. i note that there's a wxpython client just recently started development; mine is being written in wxwindows which is the original c++ version. i also note that the wxpython client is being primarily developed under windows, and i'll be primarily (to start with) developing under unix then cross-compiling and checking the results under winxp.

my question (extremely stupid, but i haven't solved it after a couple of hours' debugging -- all i can afford this week -- and another programmer has given it the quick once-over and can't see what i'm doing wrong):

i can't manage to login ! i send to www.livejournal.com port 80 the following string:

POST /interface/flat HTTP/1.0\r\nHost: www.livejournal.com\r\nContent-type: application/x-www-form-urlencoded\r\nContent-length: 34\r\n\r\nmode=login
&user=test&password=test\r\n

(changing the content length to 35 doesn't change anything).

the socket connection is successful, but the reply i get ends in:

errmsg
Client error: No mode specified.
success
FAIL

what (moronic, presumably) thing am i doing here ?

-m-
linkReply

Comments:
From: evan
2002-02-05 12:45 pm (UTC)

that isn't what you're sending.

I just cut'n'pasted what you put up there into telnet:


trout:~% telnet www.livejournal.com 80
Trying 66.150.15.150...
Connected to livejournal.com.
Escape character is '^]'.
POST /interface/flat HTTP/1.0
Host: www.livejournal.com
Content-type: application/x-www-form-urlencoded
Content-length: 34

mode=login&user=test&password=test


And got a successful login.

HTTP/1.1 200 OK
Date: Tue, 05 Feb 2002 20:43:37 GMT
Server: Apache/1.3.22 (Unix) Debian GNU/Linux mod_fastcgi/2.2.12
Content-length: 490
Connection: close
Content-Type: text/plain

[...]
name
PK Test
success
OK

(Reply) (Thread)
From: evan
2002-02-05 12:48 pm (UTC)

Re: that isn't what you're sending.

If you pasted that string from what your code is actually doing (by maybe printing the string to stdout), then my first guess is that you're not actually sending \r\n, maybe \n\r or just \n.


However, when all is said and done you *should not* be writing your own HTTP client. There are a number of HTTP libraries that will do it correctly. This has been discussed a number of times before on lj_clients...
(Reply) (Parent) (Thread)
From: evan
2002-02-05 01:20 pm (UTC)

had enough comments yet? :)

Though now that I think about it, cross-platform HTTP support will be a bit of a hassle.

If you want to properly support proxies (etc.) on Win32, you should be using the HTTP libraries provided by the OS, but then on Unix, you'll be stuck...
Heh. Maybe you're better off doing it yourself. :)
(Reply) (Parent) (Thread)
[User Picture]From: meirion
2002-02-05 01:32 pm (UTC)

Re: had enough comments yet? :)

never enough comments ;-)

but, yes, this was basically the reason i was doing it myself to start with -- the thought of the horrors associated with other platforms.

-m-
(Reply) (Parent) (Thread)
[User Picture]From: meirion
2002-02-05 01:24 pm (UTC)

Re: that isn't what you're sending.

umm, yes. i did that yesterday as part of my debugging. well, more precisely, i cout-ed what i'd fed into wxwin, and c&p-ed that into telnet. and it worked fine. hence my stumpedness.

i'll go back and read the relevant bits on lj_clients about http libraries to use; any chance of giving me a hint to what month it might have appeared in (i read the last month and the first month or so and no hint there ....)

i guess you'd suggest curl ? does that work cross-platform enough to support unix/ms/macos/os2 ? as that's where wxwin is looking to be heading ...

-m-
(Reply) (Parent) (Thread)
From: evan
2002-02-05 01:38 pm (UTC)

Re: that isn't what you're sending.

Ah, yeah, see my other comment--
telnet automatically does \r\n at the end of lines, and you can't see (using cout) if you're sending them from wxwin.

Basically, at some point, some part of the LJ system changed so that we were a bit more strict about the HTTP spec (before, we were accepting HTTP headers that ended with \n instead of \r\n). Suddenly, a bunch of clients (who had tried to implement HTTP themselves) stopped working.

At another point, the people who weren't including the Host: header were getting refused connections due to another change which didn't affect anyone who was using a full HTTP implementation.

I'd like to say that if it works now, it'll work forever, but you can never be too sure... Curl is what I've used. It's not great, but it is the only option for Unix, really, and it's been ported to a lot of different platforms.

Maybe you could do some sort of factory pattern to hide it across platforms? You're using C++, right? :)

class LJRequest {
  ...
  virtual ErrorStatus run() = 0;
};
class LJCurlRequest : public LJRequest {
  ...
  virtual ErrorStatus run() {
    // actually run it, using libcurl
  }
};

LJRequest* newLJRequest() {
  if (PLATFORM == PLATFORM_UNIX)
     return new LJCurlRequest;
  else if (PLATFORM == PLATFORM_WINDOWS)
     return new LJWindowsRequest;
}
-- evan, who always designs things well in theory but never in practice
(Reply) (Parent) (Thread)
[User Picture]From: meirion
2002-02-05 02:50 pm (UTC)

Re: that isn't what you're sending.

right, i'll check tomorrow. i did notice that if i removed the odd \r it failed in a more clearly "failing" fashion (hung until timeout and then printed "failed" from my debugging message).

far too tired to think any more about this tonight ;-)

-m-
(Reply) (Parent) (Thread)
[User Picture]From: meirion
2002-02-06 03:14 am (UTC)

the plot thickens ...

if i c&p that string *exactly* as i pasted it above into telnet (i.e. without sending it to stdout, and pasting it all as one long line with \r\n rather than hitting the enter key) i then need to hit the enter key twice to get the server to realise i've sent it anything, at which point it spouts the same error message as i posted yesterday.

i guess i might have to look at using curl on unix, something else on windows, something else on macos and something else on os/2 (if necessary). this didn't sound like a neat solution (it's the kind of thing wxwindows in general tries to avoid doing wherever possible, and i've somewhat bought into that philosophy after using it for 2.5 years, which is the longest i've managed to use a gui toolkit for without getting fed up of it) so i was hoping for something more generic.

hohum. perhaps i should test it on windows, although i'm rather loath to net-enable winxp ;-)

thanks for your comments and suggestions, they're helping !

-m-
(Reply) (Parent) (Thread)
From: evan
2002-02-06 12:35 pm (UTC)

Re: the plot thickens ...

Er... you can't paste it verbatim, \r and \n are control characters... ?
I must be misunderstanding something...

And I don't know what happens if you copy'n'paste something with line breaks, whether they're interpreted as \n or \r\n or which program even decides it.

Maybe you could paste some of your code here so I can look at it?
(Reply) (Parent) (Thread)
[User Picture]From: meirion
2002-02-06 01:19 pm (UTC)

Re: the plot thickens ...

perhaps i'm being exceptionally stupid then (wouldn't surprise me in the slightest, to be honest).

my OnConnect method is as follows:

void LivejournalLoginWindow::OnConnect(wxCommandEvent& WXUNUSED(event))
{
const char *header;
header="POST /interface/flat HTTP/1.0\r\nHost: www.livejournal.com\r\nContent-type: application/x-www-form-urlencoded\r\nContent-length:34\r\n\r\nmode=login &user=test&password=test\r\n";
char *answer;
unsigned char len;
len = wxStrlen(header) + 1;
answer = new char[1024];
wxSocketClient *sockclient = new wxSocketClient();
sockclient->SetNotify(wxSOCKET_CONNECTION_FLAG |
wxSOCKET_INPUT_FLAG |
wxSOCKET_LOST_FLAG);
sockclient->Notify(TRUE);
wxIPV4address addr;

wxString hostname = wxString("www.livejournal.com");
addr.Hostname(hostname);
addr.Service(80);
if (sockclient->Connect(addr, TRUE)) {
cout << header << endl;
sockclient->Write(&len, 1);
sockclient->Write(header, len);
if (sockclient->Error()) cout << "failed" << endl;
else {
sockclient->Read(answer,600);
if (sockclient->Error()) {
cout << "failed" << endl;
cout << sockclient->LastError() << endl;
}
else {
cout << answer << endl;
}
}
sockclient->Close();
} else {
sockclient->Close();
wxMessageBox(_("Can't connect to the specified host"), _("Alert !"));
}

}

-m- (would it be easier to mail me or IM me or talk on IRC or something ?)
(Reply) (Parent) (Thread)
From: evan
2002-02-06 01:26 pm (UTC)

i think i found it:

sockclient->Write(&len, 1);

What is that for? Maybe you're thinking of a different protocol? :P


Mail works well for me, too. evan@livejournal.com.
(Reply) (Parent) (Thread)
[User Picture]From: sprote
2002-02-16 04:31 pm (UTC)

Re: that isn't what you're sending.

curl definitely works on Mac OS X ... the curl command-line tool ships with 10.1, and I'm not sure whether libcurl is included but it is at least downloadable.

Don't bother with supporting Mac OS 9. It's too damn hard to code for (and I say this as a 15-year veteran of Mac programming.) Just use Cocoa and be happy.
(Reply) (Parent) (Thread)
[User Picture]From: mart
2002-02-08 05:49 am (UTC)

This almost definitely isn't what's causing your problem, but you don't need the newline at the end of the entity body. If you don't include it in the content-length, then it should just be ignored. If you do, then the password will be evaluated with a newline on the end of it, which will obviously fail.

(Reply) (Thread)