Indy IdIRC - does not Join a Chat Room - indy

I want to join an IRC room, using TIdIRC + Lazarus. I am familair with this discussion.
This is my code :
procedure TForm1.Button4Click(Sender: TObject);
begin
if Edit3.Text = '' then
begin
log('ERROR : Nick unknown, specify a Nick (look for the textbox saying ''Nick'' and replace it)', Memo3);
log('ERROR : Also provide Real Name and Alt Nic', Memo3);
Edit3.Text:= 'Nick';
Edit6.Text:= 'Real Name';
end
else
if Edit6.Text = '' then
begin
log('ERROR : Real Name unknown, provide Real Name', Memo3);
end
else
begin
IdIRC1.Host:=Edit1.Text;
IdIRC1.Port:=StrToInt(Edit5.Text);
IdIRC1.Nickname:=Edit4.Text;
IdIRC1.Username:=Edit4.Text;
IdIRC1.RealName:=Edit6.Text;
IdIRC1.AltNickname:=Edit7.Text;
log('Attempting to connect .. ', Memo1);
IdIRC1.Connect;
if IdIRC1.Connected then
begin
log('Connected ! ' , Memo1);
{Trying to join a channel .. }
if Edit4.Text = '' then
begin
IdIRC1.Join(Edit2.Text);
// IdIRC1.OnJoin:=;
log('channel joined', Memo1);
end
else
begin
IdIRC1.Join(Edit2.Text, Edit4.Text);
log('channel joined with password', Memo1);
end;
end
else
begin
end;
end;
begin
end;
end;
The log message "Connected !" is printed. Since this will happen after IdIRC1.Connect() is exited, and IdIRC1.Connected is found to be true, I am assuming that connection was established.
However, IdIRC1.Join() is not connecting.
Edit2.Text is set to '#Orcan'; while Edit4.Text is set to '' (an empty string).
I am recieving an error message:
Project has raised Exception class EIdConnClosedGracefully with the message :
Connection Closed gracefully
I am at the same time, from the same computer, logged in to irc.freenode.net , where the program is supposed to connect to, using konversations. In the user list the program, using the preset nick name, does not show up.
What am I doing wrong?

Related

Using TIdHTTPServer thread safe in D2005

This question has been asked very often and I've spent hours reading, trying, testing with no result.
I guess it has to do with my older 2005 version.
Below is the code I tried after reading a post in the Embarcadero forum answered by Remy Lebeau:
Thread: How to handle multiple HTTP sessions with Indy10 TIdHTTPServer
procedure TMainForm.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
Msg : String;
begin
if ARequestInfo.QueryParams <> '' then
begin
Msg := DateTimeToStr(Now) + ': ReqParam "' + ARequestInfo.QueryParams + '"';
TThread.Queue(nil,
procedure
begin
Memo1.Lines.Add(Msg);
end
);
AResponseInfo.ContentText := '<HTML><BODY>Query Params found.</BODY></HTML>';
end
else
begin
AResponseInfo.ContentText := '<HTML><BODY>Error: No Query Params.</BODY></HTML>';
Msg := DateTimeToStr(Now) + ': Error: No Query Params';
TThread.Queue(nil,
procedure
begin
Memo1.Lines.Add(Msg);
end
);
end;
end;
What I'm aiming for is accessing a memo or log file entry in a thread safe manner. Somehow using TThread.Synchronize() or TThread.Queue() doesn’t compile.
When adding the TThread.Queue() line as suggested by Remy, the error I get is:
E2029 Expression expected but procedure found
Does somebody have an alternative that I can use in Delphi 2005?
Edit: this is what I see from code completion:

How to display time in Real-time in Virtual Pascal

I've been making a stock-keeping program for my school (In Virtual Pascal) and as part of that, I want to be able to display today's date along with the current time at the main menu of the program. Now, I've been able to display the correct date as that was pretty simple.
But when I use this code for displaying Time, it only displays the time at which the program is compiled, and does not refresh to display the current time.
Procedure getTheTime;
VAR
Hour, Minute, Second, Sec100 : WORD;
BEGIN
GetTime( Hour, Minute, Second, Sec100 );
TEXTCOLOR(lightgreen);
whereY;
whereX;
WRITE;WRITE(' ');
WRITE( Hour, ':', Minute, ':', Second, '.', Sec100);
END;
Basically, it displays this: 19:8:41.75
And I want the time to refresh as time goes by.
Any help would be appreciated.
The procedure where I call the getTheTime procedure.
Procedure mainMenu;
BEGIN
REPEAT
CLRSCR;
getTheDate;
getTheTime;
TEXTCOLOR(15);
GOTOXY(18,2);
WRITELN('Welcome To RAK Academy''s School Shop');
TEXTCOLOR(11);
GOTOXY(18,3);
WRITELN('------------------------------------');
WRITELN;
WRITE('A ':25);
TEXTCOLOR(15);
WRITELN(': Customers');
WRITELN;
TEXTCOLOR(11);
WRITE('B ':25);
TEXTCOLOR(15);
WRITELN(': Products');
WRITELN;
TEXTCOLOR(11);
WRITE('C ':25);
TEXTCOLOR(15);
WRITELN(': Orders');
WRITELN;
TEXTCOLOR(11);
WRITE('X ':25);
TEXTCOLOR(15);
WRITELN(': Exit');
WRITELN;
GOTOXY(0,3);
WRITE('Enter Choice: ':23);
MenuChoice:=UPCASE(READKEY);
sndPlaySound('F:\School\IB 1\HL subjects\Computer Science\Pascal programs\InternalAssessment\sound files\beep.wav', snd_Async or snd_NoDefault );
TEXTCOLOR(11);;
WRITELN(MenuChoice);
TEXTCOLOR(15);
DELAY(200);
CASE MenuChoice OF
'A' : CustomersMenu;
'B' : ProductsMenu;
'C' : OrdersMenu;
'X' : BEGIN
sndPlaySound('F:\School\IB 1\HL subjects\Computer Science\Pascal programs\InternalAssessment\sound files\end.wav', snd_Async or snd_NoDefault );
WRITELN;
WRITELN('Program Is Shutting Down');
GOTOXY(25,15);
DELAY(750);
WRITE('.');
DELAY(750);
WRITE('.');
DELAY(750);
WRITE('.');
DELAY(750);
END
ELSE
BEGIN
WRITELN;
TEXTCOLOR(12);
WRITELN('ERROR - Only Enter A-B Or X To Exit. Please Try Again.');
TEXTCOLOR(11);
READKEY;
END;
END;
UNTIL menuChoice='X';
END;
It is not the time at which the program is compiled, but the time at which the program is run.
The code between BEGIN-END runs once and then updates the time.
If you want the time to update you need to add a timer that updates the time when the OnTimer event triggers.
From memory, to give you an idea how to do this:
var updatecounter : integer;
mustexit : Boolean;
updatecounter:=10; mustexit:=false;
repeat //eventloop start.
if keypressed then
begin
c:=readkey;
if c=#0 then
c2:=readkey; // C=#0 is functionkey, read second value
mustexit:=processkey(c,c2); // process whatever key is pressed
end
else
begin
sleep(10); // windows/winprocs unit? Don't know VP that well.
// pauses 10ms
dec(updatecounter);
if updatecounter=0 then // every 10*10ms update time
begin
updatetime; // update the time.
updatecounter:=10;
end;
end;
until mustexit;
You can implement the various procedures and play with constants to get the responsivenes you want.

Using oracle DBMS_LDAP to validate user credentials against Microsoft Active Directory

We are trying to authenticate our Application users using dbms_ldap against Microsoft AD and we have no means of testing it in our offshore environment
We have three specific questions
1)How to verify the user exists in Microsoft Active directory
We use the below code to get the Distinguished name of the Application user
DBMS_LDAP.USE_EXCEPTION := FALSE;
retval := DBMS_LDAP.search_s(ld => ldapSession,
base => LDAP_BASE,
scope => DBMS_LDAP.SCOPE_SUBTREE,
filter => '(&(objectclass=USER)(SAMAccountName=' ||
p_username || '))',
attrs => attrList,
attronly => 0,
res => ldapMessage);
-- get the DN
if retval <> DBMS_LDAP_UTL.SUCCESS THEN
RAISE l_ldap_exception;
END IF;
userDN := DBMS_LDAP.get_dn(ldapSession, ldapMessage);
So the first question is what will be the value of
userDN and ldapMessage
if the user doesn't exist in Microsoft AD
2)Suppose the user exists and has entered the wrong password in that case what will be the return value of retval
if p_password is null then
raise_application_error(-20000, 'Invalid Null password');
else
retval := DBMS_LDAP.simple_bind_s(ldapSession,userDN, p_password);
end if;
if retval <> DBMS_LDAP_UTL.SUCCESS THEN
RAISE l_ldap_exception;
and if;
3)My third question is suppose the user has logged in the system and ldapsession is still not unbind what will be the way to identify duplicate session
WARNING WARNING WARNING
This is less an answer and more a warning to anyone who uses the following code to validate a user.
retval := DBMS_LDAP.simple_bind_s(ldapSession, userDN, p_password);
By design (LDAP Design) this function call will always return success if the password is null. This was done to allow anonymous LDAP queries. This might be disabled on your specific server but not always.
So, if you want to use this function then make sure you wrap it with an if block that ensures the user provided password is not null. e.g.
if p_password is null then
raise_application_error(-20000, 'Invalid Null password');
else
retval := DBMS_LDAP.simple_bind_s(ldapSession,userDN, p_password);
end if;
For more details see: http://www.inside-oracle-apex.com/dbms_ldapsimple_bind_s-apex_ldapauthenticate-and-null-password/
First, read the docs. It has almost everything you need to answer your questions: http://docs.oracle.com/cd/E23943_01/oid.1111/e10186/dbmsldap_ref.htm
1) Either NULL or get_dn_exception will be raised, I'm not sure. Anyway, another method to check is to count the search results, where you only need to check if the count is >0:
DBMS_LDAP.count_entries(ld => ldapSession, msg => ldapMessage)
2) retval can only be DMBS_LDAP.SUCCESS, an exception is raised on any error
3) If you have session id, call any procedure that requires a valid LDAP session, e.g. simple_bind_s and check if invalid_session is raised. If you don't have a session id, I'm not aware of a method to determine if there are any LDAP sessions open.
In my application I do it like this:
ld := DBMS_LDAP.INIT(LDAP_SERVER, 389);
retval := DBMS_LDAP.SIMPLE_BIND_S(ld, LDAP_USER, LDAP_PASSWORD);
DBMS_LDAP.USE_EXCEPTION := FALSE;
retval := DBMS_LDAP.SEARCH_S(
ld => ld,
base => LDAP_BASE,
SCOPE => DBMS_LDAP.SCOPE_SUBTREE,
FILTER => '&(objectCategory=user)(sAMAccountName='||username ||')',
attrs => attrs,
attronly => 0,
res => ldapMessage);
retval := DBMS_LDAP.COUNT_ENTRIES(ld, ldapMessage);
ldapEntry := DBMS_LDAP.FIRST_ENTRY(ld, ldapMessage);
IF ldapEntry IS NULL THEN
retval := DBMS_LDAP.MSGFREE(ldapMessage);
retval := DBMS_LDAP.UNBIND_S(ld);
RAISE_APPLICATION_ERROR(-20001, 'User does not exist');
ELSE
userDN := DBMS_LDAP.GET_DN(ld, ldapEntry);
END IF;
retval := DBMS_LDAP.MSGFREE(ldapMessage);
IF p_password IS NULL THEN
retval := DBMS_LDAP.UNBIND_S(ld);
RAISE_APPLICATION_ERROR(-20000, 'Invalid Null password');
ELSE
retval := DBMS_LDAP.SIMPLE_BIND_S(ldapSession, userDN, p_password);
IF retval <> DBMS_LDAP_UTL.SUCCESS THEN
retval := DBMS_LDAP.UNBIND_S(ld);
RAISE_APPLICATION_ERROR(-20001, 'Wrong password');
END IF;
END IF;
retval := DBMS_LDAP.UNBIND_S(ld);
Regarding your questions:
1) How to verify the user exists in Microsoft Active directory
See my code
So the first question is what will be the value of userDN and ldapMessage
userDN will be NULL, ldapMessage I don't care.
2) Suppose the user exists and has entered the wrong password in that case what will be the return value of retval
For valid password: DBMS_LDAP.SUCCESS (0)
For wrong paasword: DBMS_LDAP.INVALID_CREDENTIALS (49)
Note, you get DBMS_LDAP.INVALID_CREDENTIALS only when you set DBMS_LDAP.USE_EXCEPTION := FALSE;, otherwise you get an exception if the password is wrong.
3) My third question is suppose the user has logged in the system and ldapsession is still not unbind what will be the way to identify duplicate session
Ensure proper calling of DBMS_LDAP.UNBIND_S(ld); in your code.
Another warning:
When you provide wrong password at DBMS_LDAP.SIMPLE_BIND_S(ldapSession, userDN, p_password); then the badPwdCount property in Active Directory is not incremented! Thus you can do infinite attempts to enter (or brute force) a password.

Pascal comparison error

I have a problem with my very simple Pascal code. (I just started to learn Pascal.)
So it's about an age comparison code then rest can be seen through the code.
program Test;
uses crt;
var
age : real;
Begin
writeln('Enter your age: ');
readln(age);
if age>18 then
if age<100 then
Begin
clrscr;
textcolor(lightgreen);
writeln('Access Granted');
end
else
if age<18 then
Begin
clrscr;
textcolor(lightred);
writeln('ACCESS DENIED');
writeln('Reason:You are way to young');
end
else
Begin
clrscr;
textcolor(lightred);
writeln('ACCESS DENIED');
writeln('Reason:You are way to old');
end;
readln;
end.
When I enter a value below 18 as the age, I expect the program to respond:
ACCESS DENIED
Reason:You are way to young
but I don't get any output. Why?
Sometimes text indentation helps you to see the issue. Here's your code with indentation added:
program Test;
uses crt;
var
age : real;
Begin
writeln('Enter your age: ');
readln(age);
if age>18 then
if age<100 then
Begin
clrscr;
textcolor(lightgreen);
writeln('Access Granted');
end
else
if age<18 then
Begin
clrscr;
textcolor(lightred);
writeln('ACCESS DENIED');
writeln('Reason:You are way to young');
end
else
Begin
clrscr;
textcolor(lightred);
writeln('ACCESS DENIED');
writeln('Reason:You are way to old');
end;
readln;
end.
And to make the implemented logic more obvious, I will now represent the nested ifs without the code that they execute:
if age>18 then
if age<100 then
... // Access Granted
else
if age<18 then
... // You are way too young
else
... // You are way too old
;
It is easy to see now that the branch marked as You are way too young is never reached. It is supposed to be executed when age is less than 18, but that if statement is nested into another if which will call it only when age is greater than 18. So, age should first qualify as greater than 18, then less than 18 in order for that branch to execute – you can see now why you do not get the expected result!
The intended logic could possibly be implemented this way:
if age>18 then
if age<100 then
... // Access Granted
else // i.e. "if age >= 100"
... // You are way too old
else // now this "else" belongs to the first "if"
... // You are way too young
;
I believe you should be able to fill in the missing code blocks correctly.
Just one last note: you might want to change age>18 to age>=18, so that 18 proper does not qualify as "too young".

Action on closing Windows console

I'm writing a Windows console program that takes no console input. The user closes it by clicking the close button. Is there any way to recognize that it's being closed to perform one last action?
Yes, there is. You set a console contrl handler function (a callback) which gets informed about a few events. Here's an example in Delphi. You should get the idea if you need it for another language.
function MyConsoleEventHandler( dwCtrlType : DWORD) : BOOL; stdcall;
// note: will be called from another thread!
begin
result := TRUE;
try
case dwCtrlType of
CTRL_C_EVENT : Writeln('Ctrl+C');
CTRL_BREAK_EVENT : Writeln('Ctrl+Break');
CTRL_CLOSE_EVENT : Writeln('CloseTask-Signal');
CTRL_LOGOFF_EVENT : Writeln('LogOff-Signal');
CTRL_SHUTDOWN_EVENT : Writeln('Shutdown-Signal');
else
Writeln('Console-Event ',dwCtrlType,' received');
end;
if g_StopServer <> nil then begin
Writeln( 'Stopping the Server ...');
g_StopServer.SetEvent;
end;
except
// catch all
end;
end;
class procedure TMyServer.Run;
begin
SetConsoleCtrlHandler( #MyConsoleEventHandler, TRUE);
Writeln('Server listening at port '+IntToStr(PORT_SOAP));
Writeln('Press Ctrl+C to stop the server.');
Writeln;
g_StopServer.WaitFor( INFINITE);
end;

Resources