From c548ae72a8642349d8a642d15ecb8a406405fca5 Mon Sep 17 00:00:00 2001 From: Abdelmajid El-oualy Date: Mon, 10 Jun 2024 19:00:17 +0100 Subject: [PATCH 01/56] push one --- irc_server.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/irc_server.cpp b/irc_server.cpp index 174f96a..0d6fbcf 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -60,6 +60,8 @@ while (1) fds.push_back(client_pfd); clients.push_back(client(client_pfd, argv[2])); + + } } else From a0f5c85a06ea53e23b7182d7f369db39cf43a44b Mon Sep 17 00:00:00 2001 From: Abdelmajid El-oualy Date: Wed, 12 Jun 2024 12:49:27 +0100 Subject: [PATCH 02/56] push one --- FT_IRC | Bin 89600 -> 129236 bytes client.cpp | 72 ++++++++++++++++++++++++++++++++++--------------- client.hpp | 7 +++-- irc_server.cpp | 10 ++++--- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/FT_IRC b/FT_IRC index a25a2f6f9658ad7204fb5f37a224460773cef7a9..94710bc7e460d809152ca23cc559b8e904fbafa6 100755 GIT binary patch literal 129236 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 delta 24198 zcmbuH34B!5+5gYISqKow5Vo*p*n?~nAOU1?0t^hB1leRW2_Z3&1jZyRE^!7zlyL|S z-r`tnHEtD`)~OLmQFK5GXkFsc8mqN~wZ1p6)=powf}(kU&pFRcAo_m(|Ieq>-gD0P zInQ~{de1rcg0PNA=pcAPB_qKm6ma!e4xEvT>fKDfRvuZ1CNhNb#@a%1H{+D z!Oz+4z{j&v=iaTPPf!$obMH1LYO_*fh7y0s;+SFV)@Jp7?Vu7jl2!bOb>qRr0Y*%- z57~2{iY@0v#FzebW0yXm_gBAATFG%Lj#$}<>hUx0g)lE~ZqACFyg5s+UcN%=)TB9Ptc)Mid+IaFMiMI$$I12x$M^F_ID>kQ1gl zli8p3bw%-}@$1I-}7Lmxib010h@ho34r2Iw873mW!u19`O-!pl1TY-Jmp; zN|(^sD#Sepmi07(2^qG&+M=N2gPFgseRJQzhQ}X>8D|rw>dtP4o_Jdi_xnQFk!&=Q z+whbaH|psP;Y3F#Biy^Y{?Xk=q_@Mn2ZP96mvx~|2s4b~<@TQeo<=K{C?Y`JJ(~&(NNsJ?$cy^!7c*BYkG31};%eqO^yMFZ)dBcPAP4*Pg%7 z+G-h!p-AT2#`L~}z3-^l*d?)cO8Xh){u9Sq@pA``Q?&mL^Eu?~ul?N84agt_FjsS& zTvYT+Dr;co%Rwq~R`EWx%s*>n38Gdy$SC^+x{r}Nsu}~`{}v25QE-3V47g}4S;w0&x|FeN6O9Mb278+*zeA9^ z19cR3PdkxPGZ+Q}wI<5%KaG^K{_{x3UwgK#%mEordC8qvb55(dAX4_cgQ=lovJ{mp za!E1@2dF=He%ES8`Cb5<=NC~+Hd<hZSpewlqG@$7xz(n2cIphtsj0yQ9lc_XYDUpE$|sX0!rNZG#$nYasUiB9iHAQR$DZ3e~R7my+U2{ewZ ztiNtAHSLwCEXEOq# z2Td~eCmxjkx++TAOZ8}pl`>FEVibfV)3uaZAEq%bGL2_hj+az}JHxTyL)|d9IZtaD=K1dn7SKx5-$y6^m3s zq(U@_%w`qsOur=l?zVpQw5}+EX4+qKs9Kn`DKD(Ge*R z94A%tcv+iV>YI(#EI3^&`?+Nj=H(wxAW7ePk$Rt{+_Dr}Xo)j;=TN7H+tCtVA`*qo zXfII~tyQQCiOhE?1^TlsIxy3(Qm?1fM^x%GE4r;6Nn%c^7G6qiv!apdBeDp`No4L+ z#*?h*jvd~J7XZnH6^}wu*mPpt@ryn4q8~b#E^1Ml3{{%*=i8Qvtf^TlKa!c9Remum zUfPh3%DE<@p(W5CEypezm4k7Sq=_pZqDjw73*RXq;6w_p@`M})Eq!=6| zEx$#Gl&-Yq`VX2^s3asd@4JLSeRa(GERx1<}%HZw-~3>7k8~9nLmEGx%?JmkbR&2;LQzB+J|Yn=O&|R$bD&h z={@l0Cbe{vFT}PO%r=`3>@;eIj@0%VPYfLgw|VHbdSpk##9>Rdaoe_|2DE9Bm2=lY zdn1V;5iJwjBcrv+>0Ee0_15kvt(Mb=_uJg0`Mmy}2Q8 z!cblRYe_>*=D0Zh!(!u^$sg)J6dA#+4SMe)`}Wvh2>ZRY0`HB8FB z8U_lCnyJgt`0q`<0d<-%v8^1x+tmXN+|IL%(UQ(K}~C+Lddh4bwgC zbjt0Wku7XQ&D1r<`W&DB(6z=#IsNo)*FJn9N7Mi7TI0LfNAxSMZFpu*iI!NgN*2sF zX|=J#wL(9!vf*{ty}JJHI^%lx^u-@t15=3nx;EW!~o5U7rsRm+So+@tiOYmB}N)_3l^jKm2iuWPt!hPC!@tVPQ_3F5q+;!U`Fn`#b z=C(>zhgK{wE?(2W_q@v|hd_0sIc2^vX8A><@7(T2){5bJ95VDPVM?AqR{|n z&BdP>`s|rnwUNJSUpMhFEuPyf%D7|o=H55_6S0`4FoDF- zfTr2M+6KMq;C~C7=Vm!LGK5gy-yc~D`1LD%^ z81?6i@^y(B8`f>oJ~K|P%SqcwUkd)}W*T-BydID0h@c* z$(_c$^|zP$WG+zhyP{@gJ2acO6O=~exCv})c5A1lG5@wEb5XnAS@XKf^v<^HMa*F` zYMU&p;hoo4iyBKdtkJV)8HYFQ)W`nC7<%1m)b{4<_6$}9Uy7OKO%&ynTDD5>Ie)Bdt@c&!im?riTMlX6 zU%UblKe5Vn@d&l*N4{?BRp9h_fantoP# zn5M@;{qkwLHyNO5`rRRNn*RMzIZf{vLgIv>6O6K(&gp*{(y;XAUb=o$x>2-jhVkI7 zp7hOw+eZx6DZJmgNtgthVXM(xJJ@hk_s`gP1U--_U`fuAR^^+_C4<^4A2vU0sHlEJ z)Bk&*G21(@_X_O7FxQ^NTx)mx-*fvhyqv}_y=mp65W_ZHh>qmSsn``ZyLX6CbF}NQ z`8D#kQeYn;r>N68CE|2WDav#L2HwPE*<_{s-p<=Z@>12xYxYn0i1cH`%q{h_n+NsKF37DJD?A`8k2U7 z)aDp#cU@6H>k+TY@56*u$0)aod8&hODovzMcMzg^&zOfg2$M)y+t0YTE3FgS=Zsn0 z&ls?KLMLg#(a%`6yN_|#ZkwLe&vigwEJ6If4tv%{s;Na zVlS4GjtRnOy1KXi^E9Jx&3L^u&6p2wTAHz=#_sjdXz*jT!Vq=Wxv(G{&yZ`w8S{zn zX=<${ywhFkJBP2#w`#t{S0){}op!ZqXI%8nBw7*@@bw=ET0R;;&7Df)&wd_Jz>Pm^Fb4LUpLa zD@JQeouEv1s!W2%U=rmxLPE--33Bcc*+8fd4vn@2sY6fqk(r%G7g(7E%_kw0)Pg;b znj*sfB~N)<{vLM;V%cvrceSa$(jhKr7PZCw8gW0_=p}YE`U%9UMpv)9RY(t-bUqZU zHuw4u#%QScYfX4&fRfc^4TlCAokVDKR)~_q4N~E_T!jNiSb<`wQH~?hsxjLA2x*ze zaNG;?&CuaEncDmXq-m&$YD7WwF^BgCxuw!)q$tkaE+VW}}PGw#cvb%|77$33-h)~ z$KL-}^EW}kYJR`>U_@4^wvpMuaW~yc22rEzwHAxOq zU)ubnWzIs0(fo&@V>Q2&+f_}_{^;+iRHVxWe?8^4OXcQ(onxJ;qXI`rPI>(aQOaIh z^V4A-sZ#U5(o^Po?%hc>jZ5^rIuGG9rZ}w$+G!?_#WYWvK)ErhZG=j|aw6j#Z zbPnu_D6rr;5ifGH`BJJ7ce+~XcrJp&0h(&*4+)5Q6fv?LhH)cSht2+wS;r+oYW^c3 zTCL^^&L#0qZz6!Am0M4?T>Wy?we}fd){! zV4M{gTldZwo{2I_6IhYu1|YB`vcMlPpYB0&O#Rq18{Uk;#*&QWzH^{FnTuX?3hPL* zT1bL-^-r8%3Je;NyOzb(obecagXtTJq>bvcSnV6lH?TlZ&#AiAVO#VZNor2z^A@t% zzvNxCL)5$U(Ka)=obZ(IltvwxJrIY^EFq3J8Ik~A9Wi{Z5tW5$88-Y_X)Y>~}I^C1x0Ba8xL zpJJ8lteFbARkC}{@XuOX+YYe;3BMai1yNfGH(EumsdC>KGe01Ma!3V`hgnP+(MMtp zo#YgcPchzmxQ{Vtf6sLK(<7A=u~Bn^0#sO?hK))wmhN9a;9to~C*{SMS=U{L&yzLt z_U9JOMl7I*-?{wdGODx~95Gq|~aDFA z>6Yqwssg5ihsnn%GEU4(H-Zl*js~~AqZszG(&lef_nCZXhYo!y-bf#deaZ_xyvQ1z zyfW$@jl;DiO_x`K8ti<_>(UU~wXKvWFbX~0)s#}l)itH&!%8!HXVTs!*xLVpB=NR* zxR}!97`$&dLd6hr*R4Eb?x*4Ccj5S=I@aE_DldHKsXmqGP%E3vawylFZ&y==$NNKr z4kpN~E7np>Q>kiX`jS08xd-~QySJv=L{fZ{3iBc*@w*~CLR}GnI!s8#Oao}NVldXx zKKR5{D_RqdCNa#K%qP@qgn7gjO?fei`rrSid4Fdr3LT6APn&;K*&LR}&=0P|WQ~i4 zH~L5Y?@(i(&PdQ-HPulR7y}4XBb8XRWRpP}<#ddKE;Y+g49s9M0~`qXT^CzuP{`F+ zP8D>t(TY+9TuB!(jvUC;STwqyR$^=`p4iWh{LcHgeTD3(%;y6LqWEUHQSazwJn~R4 zqq%rR@1Ib(shhlN3Iwx3)|XbiMbf+Scy-&&zwXi z*l)p%-*t+c<`j*apPj%~eD9Lh4sCQLHPS{b3~eipJOZJE;4zFrGwm~Wvs7~pF@+N^$~Zopl^Dwd^Ke6wT^fW%XsUEM(G}t?hDd= zQMwW7o|Nt>>7JJES?Rti-Pff1hIE^x`?hr7mF}OU+brEbOZP*s^gfbqRJtEa_Y>)U zDqT~$|1I6mrTc|+W77Q}>3${Me@pkgbibAEMd|(^U4gw@>j+)C@zPBkj9p#ph$IPJ zq?;_=?$WhMH&wd5q}xZjY0~X4-GR~_EM2>Fhe~(2bVo`zL%LT;cdT^BOV=?NyZY7< z6D3TRZnku3m)SbvO6ks!?kwp#r8^t05R2;usPw^_0lvC(K z3N=vZZ3;yxbe2N#G+JJy&~Od;w>(S19VC2$LVuu8J%t9*F8Lk`-AJK*6gokn-4sg0 zxNe~@ffD)?bITSAJxifY6r$}z%UTLe#9GyoOCkC~Y?())=P5LULf&sEIFW+%=iinL z3ay~fU<&P^P%jGIMWHSf3R6f>=v4~+8*gX{T?}aXoI-RvsO4h{4Wdx9lu_N^pim~s zPElwfg^vB;MQ{xT>C>R3m_omzP!)xKK_Ned?xxT$DYTbDPf_SL3O!GuDhjO}}R((p(Kc zPijchq>18W+&uCof3AtgwB&C!QKPT?hpsitBxqEO()-3~!}=yy3rEs@ns6okMiXn3 z@X51rtPuM(pZ2h>?Qhp6{e7CYTN9@+%1&whzthFvv~K=5aZ#K5o$eJ)dh(-j!qht> z;_kQ+`?_k+#ScQbIo{TqAij!Ui0~T;DfcJhC?y%;y@_L>^GqkwdAF18yCf0oL^`h~ zr5x%k{+>iSdpeWO)16;JmS1$~jPN&IhPU0@YQ1le)?46wcS^VQUBz6qMN#J(P1|DJ z@!psvJ+v+reV)f(+_dX(03s_a>)b=@mY%*sn>8Evy|k_?G!@l)UpFmjO2SfY#`rdE zDa*Cps^!lxHorf}u)kw(*!%u!E$!+Ba~6p%V&!tzHR2jq&f=?cmbfSb;F+f>xF9)bE9xY-3icP27~?{Nwdg>Of#WAK}> zOG>*Jj8%Coe6d)F74Y+y3bBWHr4aYR&s~KA!ndu)r8oHXYq9jf_vPV&+|N;vjY143 zzYurZ;D<}loQo02Erl`oHf$(;@O_miC46U<5Rbr*ZO0gbAK8f;cJS+O79!&i4D3R| z;X8K=(G0(-7V+@&_rlhFc>K_V@7pKD4Dy4>3%>mTS_FO^b!W0zElM=BKYroPLJM~h zdZY_{G=C&TXmpn@nkuwNUnEQuS}+YY=qI$M0myiu(4v@|J?Ze%!FI@p!XGBI7`n$d z66r@F(@{dpy#fWq6B#44{0ZZAHeFoHgcW+9X5DE$mDx+XdknHwiQ zs$A^YEHvL{6tfH_%2D1*p?T0oVjG_ANQL(C-6S;oEyxOw^H!lbQOBqkehqS{fkpVf zJ(vd`OiW2J!iisd(=f(l^?#=PF6{SWpSqdiX?T!7nB^Jl*Q25&kD;~6k1$g&5DSc3 z@~Jn-pUCNEDBmmQu^^ZIwd`+Ve+&CN+276nKKAcnzn=Xk*pK2xkOjb7O1|?B<LH^a8V4CvrhDb&G6!!5#kX~et@NU*rtWvLEZC)0=0zk>Z+m7gtcXF-ttL+n4o z{%_cCWd9`j7&3q8megaI$R9sDzwbf2c15SjgZBXd8A}u*IqLVf#wQy^>r=X&U z;+Id#D@Puor}sl+U9mPa-dAGbp<=Cjf0_T)%c~~k@Pi^>Bus+MFku)g;1vP-IJ;< z)Aquh8(QQ+)h{AZ=$0F`&Y`PQ5ju6FW(z%pQ0KXsuI-e|Vd&1W6=1*Iy);dZ5}l8UW6 zWM$)0$#P{?LE+}S!jjE-#Ra8h6wyc#1%-u0m@|P9!i^YT1ZN2f%eGb)5j7DNR}>W$ zY}!;&x}|t437biHeNmMq^O7)1!m`rJs-i7~CSiF|d0`1gJVv^O6A41k6Sne#(k)_K$kt!$HD&bLtHnf&TM;Md?~ZZm4H3&1sX+GjqQa`J6$`S( zdr8^i?ye%Cta5?4M-Tn0SX-TXJT6n5jBD5VOG3y#K+BE4tEbRICwgOSILfpkdShJZ zxBt?{g#LOAgLcC87_VEpYeQ$>*E23YHcr6FLdKbeB?T3ERTTxLRh0`0UE=ZhDS2~? z3d+j1Vq_G}L7=EY{4(Lkudeq;uWp`ru%}4KR`Uc&)AI5*ZN-Q!D|2DKYfgxZkFJA)Z#~R~mX&DzzVO>ND9!oQxB36a$q!Rswbnhp{n7soh!b7sioYgjiVMk8 z@Xq8FZ>mJuKj;>EeTe3cdnY+F)HFnMdEZZt7eRbV#0%dMvNaJ(|462J>`TPdLl!Th z&mkr*lit)k8t_F`h<>=6Lpy z`XVGg*fX?dxVBjTWoqb)0&QX9!>JYM@KD}xZJzh>RAhz^IhdDjOuF@S=aj0LC*De> zs;Q>W^T_IbpDOeU%&C}^DvCC_Hi~ajFNx2lDW!OmsOgD%N@PE1LGcJ9O>@LO4yP3nxXPINn6VS3`&ubf| zGPs8Yxy+r=l%(KeUcg+>T*Mq^-p?FiKF4h1gM|tB3M6~E%y%gE3J(jStWeLqc%VuU zVLr*+#QY_5jJY@ZmNF3hRaMHI&wM|#kNJ7Y=zlsMpmcP2N(MY56_3LADsesYT;?X` zLT37IrS!*`@eM2ab7l|oNPPE_y%_T{V)_1Ms02G$!N%Ok>}0;c9Auth=K@;knWM}v zG1EVEqXM2|rgISDoRzpDVy%S&Gq;LRC@e$@Pn4`?YF_mnNE0!pJWa*f5RMQ zE*#-i25kHVydPtM4ARjM8F-P|$NUL%nE48f1*y+p&RdwB%*UAXnLlUtF^}|OFvuF< zpo218%xq(>V|FsX!5n1nfxf2n^;UZ3DD%&l1=a$x{~R-&rx1Hh7SO-aB*9pW1vv&X z6&Hgkg9!7>%u(hG%wnR_pMgH)ap>By9{Cv!dXG3FSv4P$}qd+l?S!8=%x%lsmk<^d1$4;&w6&OzT&eEnRN zzM470d>l*})Vox?j=m>uVxFtmD`G6z%L=x6D#7c_9%dRFWWdL~nK{f%V?$=Z{5^Aw zIR|}D@wWNO{&aLrcY6PVEVxbzFp8O}uc?MH<`+0V*R2d(WcDyS(N&Z|J#&zm{we^m z_<=chf#Nwi(5Lm^!-Bme00)_0WezhBn62WY%r`RI7Ak`$neB@dC!njyo|Abtb1t(1 zmg~QV1zpg0vIfjKU}}LT<`vBJcMaGT*R#H7iDLR!FQjj~TJhgGK9@NIT}|=Mr7C`t zi`V}M3m%686(Gv|-^}z+|0%;<^d-gHnQvxxGQY%}&zy{|qYQn_i@}sWf0?p(V7^xg zf-LwGD@2&n(08&x%= zSz_jgm}AVpXLhbo1{2X$q#t9xhME5K1hLr7>}2*n%z|7N{2okAmd~uAugPG9IfpsQ zT+3`A_cF&6dxiCJ8M{^`c%2n&YZO~wuMTGG>ou3z`gRO6 zTOXhKYgPKb7<_V2ZcuD()18vh|JFV|pB1cqdX(Avwu>>#eLHGozfKvnw(Sn)wofzW zwofx=Yg->CM*hOu*NZ%5aE4tqnT>e|b1w5s%pT@*%syt?*UK@$Y;EJi`O3bvjc)?W z?+toE; zzTUP;>06)Y4rc3XIG@@28ul<-U&9e*>uXqeiuWfd+4>sxFk4^4K4$A{ zxSrWM0SPl(Cmv1A)`5pt6srPQCmwcY>%=3-Y@K+7nXMC!D6@6K5o5MaIBeG|`_=(R zF7v=N*+pLAV?o=A1#{bp1+#TxVJlGv+YT(4+YT(4+YT(4t@D8}vpOF@|JzEHLF<6P z!K@Alu;?&b=L0cj>wLg|gGz6m59BgiyIdc$wacz&mRmA<|C(4}ZL`H@WzgCc+nB9g zG5)$ON3pdHcQRXhx_oA9OBZCez9YiSw55~le{PvFXl)|%nXPSgklET+N0_Z`b(GoK zR*Q0F&)QYnn5|tk{Yjo)L+q;6_kWND*0ws#Y;CKXn5}JfjM>^&+qNi!)~?siY;8h4 z%+_}V{t6%qpwB@6%hibmyekzk=C)1gR+XS_Q_9@7DP^|y^--^6U~a&0#%1J*9r!EEhvbD6DOu7_FeaN*`vsi5CP9x0QxqwZ~e_)O=4_T>Nz`jq}D`$2x|Cu?TdB`fI@AIh# zs{|hAeCB%Q511p&tFW7vZ_$2b?;&P8v$a3)I$20Ot^I-hE|r0` zKX5Wz`vVWNwLkDN^Zo!A>sVlI5TeYyK@hf}%D~zmIGL^W+{bL4_eYtn8<6Q z?zB;ttK}U1A7O#Dp2wK2_1u29O7JN)VZ6F(NCwU`m))b{yW#_c;-6w3%uH7hNk5aB zt|Ai8CH5jgd`JmavjW{sB!wH8>5d|CH8b5+BtF2riTP1xy1Pj6zhkC5jKr@q(^W>| zb6_u(nC>)^;A>W(yN$%1@d-uobjOi+5HsC%B+g`}JCDRJ=CRCcm{%~DGw)&EwU*X@ zWI&f9$-qHYc#7F-a=Ii*@sD#nU6v$%ftfB%62HkzmnVs>E}%=4#2<4!-K8Y{dM)~& z3P6`CNszQoF`3WEQuY=blH;FDj;3DB%aIhbor8a6*FDJBraj5%b3LHz1OM? z=~gBQtQyhnOyXNO0o~Fh-ftOXevp}NZBqQR%yfH`_zd$V=06j6#-aB!D&DI@DFvEM z>y=<2GyO*w$v`%#T*@{^dpx3cwYZMV}W(=b7G>(z`FlwFw?zes?pz=t!to* zJ1KoJO~w0}t!trYnXT)gE0UBx?oF$||3AV4>%M3=j8Lkfb#L@7X6wFauP!Ryx;J_U zGu>~d0-lp>LrC%0k}*cQDgF)&J&XiufBd?3l>$mDf4KNg3T^z04*YTlKG%W2>%hH| zFSl1Va@7o_{0!4W9FO zF5tnxw-Mjr>4mu7c>3V!izf|FKRo^M48SuG5B*!M!FbZ~*zsIMI$Aq^z|)Fn7-T|6 z`)dg3c;fKH<4M4ih^G^t;dn;iNy5_^PZvBR@r=fE1)ec@#^M==hyHEi1UwErbWwCN zo-91sc&6Z?|MK!QJXhkGj%Nm*nY8}S!gCcKC!QQUv+>Nq(-Y4SJVWt}!jpj~6VD_( zbMc`0{^Qp3{%6hiAGhAx|E&4Y0{>U**^l0kr~O7dI=MjmR1e*@N!uLCD$<6ebhyzP z%1p$iPh6EB)&26Dt)XA<*V5^R{JJjx?!nJBlmtNm^*`7Hv{!!yYX=rR}b) zy4Zen^A>HaPB+pogl6^828V8})V>X!+OF+N&nhg#HG9_$;z!rP=^qI!2-WYz72yZS z8Gn;@Tj+T>U2t<+-k>h`9G!Ht_S99O#?#u&F74F|E!(5b4t@JP68-j=Hb&bR+I39p z71}UB>ynVWXnA&CsJ>a7d-Sn0TDE3eoavyO;1zlF?+6wYmeZx=UZLP$wan0}J=)Ar z+3#_oKJ<##*R`n7g{zn-*5Yh+e|u%Yw4yBq8_SCFN{bgr1wdcR5T^A}jqg{3MlV)w7 zcC_kC&Cq*gi}`cr`>0Xwc#0A(|!~+HS@=!?9hqx8m@Ta_rC`0 B0CoTX diff --git a/client.cpp b/client.cpp index 9866f9e..2b2dd25 100644 --- a/client.cpp +++ b/client.cpp @@ -1,5 +1,6 @@ #include "client.hpp" + client::client(pollfd client_pfd, std::string password) { this->client_pfd = client_pfd; @@ -29,39 +30,58 @@ void client::set_realname(std::string realname) { this->realname = realname; } +std::vector buffer_to_line(std::string buffer, std::string siparator) +{ + std::vector lines; + std::string line; + std::istringstream stm(buffer); + while (std::getline(stm, line)) + { + size_t found = line.find_first_of(siparator); + + if (found != std::string::npos) + { + line = line.substr(0, found); + } + lines.push_back(line); + } + return lines; +} + + + + bool client::set_authenticated() { std::string line; - if (this->is_registered == true) + if (this->is_authenticated == true) { + std::cout << this->nickname << " is authenticated" << std::endl; return (true); }else { - if (this->massage.find("NICK") != std::string::npos) - { - line = this->massage.substr(this->massage.find("NICK"), this->massage.find("\n")); - this->nickname = line.substr(5, line.find("\n")); - } - if (this->massage.find("USER") != std::string::npos) - { - line = this->massage.substr(this->massage.find("USER"), this->massage.find("\n")); - this->username = line.substr(5, line.find("\n")); - } - if (this->massage.find("REALNAME") != std::string::npos) - { - line = this->massage.substr(this->massage.find("REALNAME"), this->massage.find("\n")); - this->realname = line.substr(9, line.find("\n")); - } - if (this->nickname != "" && this->username != "" && this->realname != "") - { - this->is_registered = true; - return (true); - }else + std::vector lines = buffer_to_line(this->massage, "\r\n"); + std::cout << this->massage << std::endl; + this->nickname = "dddddd"; + + std::cout << "---------------vvv--------------------" << std::endl; + std::cout << "the size of lines : " << lines.size() << std::endl; + for (unsigned int i = 0; i < lines.size(); i++) { - return (false); + std::cout << lines[i] << std::endl; + } + std::cout << "---------------vvv--------------------" << std::endl; + + + + + + + + } return (false); @@ -96,5 +116,13 @@ void client::print_massage() std::cout << this->massage << std::endl; } +void client::print_client() +{ + std::cout << "nickname : " << this->nickname << std::endl; + std::cout << "username : " << this->username << std::endl; + std::cout << "realname : " << this->realname << std::endl; + std::cout << "password sabmited : " << this->sabmit_password << std::endl; +} + diff --git a/client.hpp b/client.hpp index 1791310..54b8bc3 100644 --- a/client.hpp +++ b/client.hpp @@ -3,7 +3,8 @@ #include #include - +#include +#include class client { private : @@ -13,6 +14,7 @@ class client std::string username; std::string realname; std::string password; + std::string sabmit_password; bool is_authenticated; bool is_registered; @@ -30,10 +32,11 @@ class client void set_client_pfd(pollfd client_pfd); void set_massage(std::string massage); void print_massage(); + void print_client(); }; - +std::vector buffer_to_line(std::string buffer); #endif diff --git a/irc_server.cpp b/irc_server.cpp index 0d6fbcf..eecaed0 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -60,8 +60,6 @@ while (1) fds.push_back(client_pfd); clients.push_back(client(client_pfd, argv[2])); - - } } else @@ -91,9 +89,13 @@ while (1) buffer[0] = '\0'; }else { + // std::cout << "---------------------------------" << std::endl; + // std::cout << "client : " << l << std::endl; + // clients[l].print_massage(); + // std::cout << "---------------------------------" << std::endl; + std::cout << "---------------------------------" << std::endl; - std::cout << "client : " << l << std::endl; - clients[l].print_massage(); + clients[l].print_client(); std::cout << "---------------------------------" << std::endl; } } From d83c2fe53ab37dc7669fac1f5c80893d502c76e7 Mon Sep 17 00:00:00 2001 From: Abdelmajid El-oualy Date: Sat, 15 Jun 2024 20:20:37 +0100 Subject: [PATCH 03/56] push one --- FT_IRC | Bin 129236 -> 123828 bytes client.cpp | 50 ++++++++++++++++++++++++++++++++++++------------- client.hpp | 1 + irc_server.cpp | 32 ++++++++++++++++--------------- 4 files changed, 55 insertions(+), 28 deletions(-) diff --git a/FT_IRC b/FT_IRC index 94710bc7e460d809152ca23cc559b8e904fbafa6..f499cf3327fa4a345d66ce0462342ab315f38749 100755 GIT binary patch delta 27138 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 diff --git a/client.cpp b/client.cpp index 2b2dd25..561e1a9 100644 --- a/client.cpp +++ b/client.cpp @@ -7,6 +7,7 @@ client::client(pollfd client_pfd, std::string password) this->is_authenticated = false; this->is_registered = false; this->password = password; + this->index = 0; } @@ -60,20 +61,40 @@ bool client::set_authenticated() std::cout << this->nickname << " is authenticated" << std::endl; return (true); }else - { - std::vector lines = buffer_to_line(this->massage, "\r\n"); + { std::cout << this->massage << std::endl; - this->nickname = "dddddd"; + // std::vector lines = buffer_to_line(this->massage, "\r\n"); + - std::cout << "---------------vvv--------------------" << std::endl; - std::cout << "the size of lines : " << lines.size() << std::endl; - for (unsigned int i = 0; i < lines.size(); i++) - { - std::cout << lines[i] << std::endl; - - } + // std::cout << "---------------vvv--------------------" << std::endl; + // std::cout << "the size of lines : " << lines.size() << std::endl; + // for (unsigned int i = 0; i < lines.size(); i++) + // { + // std::cout << lines[i] << std::endl; + // if (lines[i].find("NICK") != std::string::npos) + // { + // std::string nickname = lines[i].substr(5, lines[i].size()); + // this->set_nickname(nickname); + // } + // if (lines[i].find("USER") != std::string::npos) + // { + // std::string username = lines[i].substr(5, lines[i].size()); + // this->set_username(username); + // } + + // if (lines[i].find("PASS") != std::string::npos) + // { + // std::string password = lines[i].substr(5, lines[i].size()); + // this->sabmit_password = password; + // if (this->password == password) + // { + // this->is_authenticated = true; + // this->password = ""; + // } + // } + // } - std::cout << "---------------vvv--------------------" << std::endl; + // std::cout << "---------------vvv--------------------" << std::endl; @@ -108,12 +129,15 @@ void client::set_client_pfd(pollfd client_pfd) void client::set_massage(std::string massage) { - this->massage = this->massage + massage; + this->massage = massage; } void client::print_massage() { - std::cout << this->massage << std::endl; + this->index++; + std::cout << "--------------" << "the cleint " << this->client_pfd.fd << " : " << this->index << " : print massage method start ----------------" << std::endl; + std::cout << this->massage; + std::cout << "--------------print massage method end----------------" << std::endl; } void client::print_client() diff --git a/client.hpp b/client.hpp index 54b8bc3..28e3fb7 100644 --- a/client.hpp +++ b/client.hpp @@ -19,6 +19,7 @@ class client bool is_authenticated; bool is_registered; std::string massage; + int index; public : client(pollfd client_pfd, std::string password); diff --git a/irc_server.cpp b/irc_server.cpp index eecaed0..8fb1079 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -77,27 +77,29 @@ while (1) { if ((clients[l].get_client_pfd().fd == fds[i].fd)) { - if (clients[l].set_authenticated() == true) - { - std::cout << "client : " << l << " authenticated" << std::endl; - } + // std::cout << buffer << std::endl; + // if (clients[l].set_authenticated() == true) + // { + // std::cout << "client : " << l << " authenticated" << std::endl; + // } - if (buffer[0] != ':') - { - // std::cout << "client found" << std::endl; + // if (buffer[0] != ':') + // { + // // std::cout << "client found" << std::endl; clients[l].set_massage(buffer); - buffer[0] = '\0'; - }else - { + // memset(buffer, 0, sizeof(buffer)); + // buffer[0] = '\0'; + // }else + // { // std::cout << "---------------------------------" << std::endl; // std::cout << "client : " << l << std::endl; - // clients[l].print_massage(); + clients[l].print_massage(); // std::cout << "---------------------------------" << std::endl; - std::cout << "---------------------------------" << std::endl; - clients[l].print_client(); - std::cout << "---------------------------------" << std::endl; - } + // std::cout << "---------------------------------" << std::endl; + // clients[l].print_client(); + // std::cout << "---------------------------------" << std::endl; + // } } From b714465a4e327684bae3b48f659145d616febde7 Mon Sep 17 00:00:00 2001 From: Abdelmajid El-oualy Date: Tue, 2 Jul 2024 13:08:10 +0100 Subject: [PATCH 04/56] update --- FT_IRC | Bin 130476 -> 130436 bytes irc_server.cpp | 2 +- irc_server.o | Bin 69968 -> 69884 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/FT_IRC b/FT_IRC index c61370e8bfbf1239ac4c677616f5750e9dca27ae..5ea40285c2bac7eb9ed2cfff8b8956445adc1c70 100755 GIT binary patch delta 17149 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 GO8h@CC#)p^ delta 17304 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 diff --git a/irc_server.cpp b/irc_server.cpp index 95f1ed0..ee430ef 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -83,7 +83,7 @@ while (1) if (clients[l].set_authenticated() == true) { std::cout << clients[l].get_client_pfd().fd << " is authenticated" << std::endl; - send(clients[l].get_client_pfd().fd, "NOTICE * :*** Looking up your hostname...\r\n", 45, 0); + clients[l].print_client(); } else { diff --git a/irc_server.o b/irc_server.o index 64209569ef74c72d6470960e52e58b0f4a4e8ffb..83dde32c68d8d8a59b64a0e112e7d6b69c6a49ec 100644 GIT binary patch delta 16854 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 delta 15882 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 From 37a310b2d2e276b5bc2470b63d9a840b33bc2736 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Tue, 2 Jul 2024 16:15:50 +0100 Subject: [PATCH 05/56] first push from aet-tass just for setting the work space --- FT_IRC | Bin 130436 -> 0 bytes client.o | Bin 86292 -> 0 bytes irc_server.hpp | 3 ++- irc_server.o | Bin 69884 -> 0 bytes server.o | Bin 43864 -> 0 bytes 5 files changed, 2 insertions(+), 1 deletion(-) delete mode 100755 FT_IRC delete mode 100644 client.o delete mode 100644 irc_server.o delete mode 100644 server.o diff --git a/FT_IRC b/FT_IRC deleted file mode 100755 index 5ea40285c2bac7eb9ed2cfff8b8956445adc1c70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130436 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 WM`FZa`p_H<8{^J@99T@rpZ^DAy4HaJ diff --git a/client.o b/client.o deleted file mode 100644 index 3f6287509579d52675ad43743a2e508f1855c6da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86292 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�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 o))8Pt5_^W5{eF1b?w%h2kN^Mx diff --git a/irc_server.hpp b/irc_server.hpp index 4d1d513..f689ba1 100644 --- a/irc_server.hpp +++ b/irc_server.hpp @@ -3,4 +3,5 @@ #include "server.hpp" -#endif \ No newline at end of file +#endif + diff --git a/irc_server.o b/irc_server.o deleted file mode 100644 index 83dde32c68d8d8a59b64a0e112e7d6b69c6a49ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69884 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 diff --git a/server.o b/server.o deleted file mode 100644 index 23354837c0ea88b87dd024f85719349cfc229595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43864 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∓S7=wX_jLS1>Leh(r}p%Yp)CSnPl zki~Km#pGOk1`X7#i(oC3vq;GX;HF4xYy%V3;7Wm=n3lt#c8yR(Zcn$W_?}`E{fcy( zK%Mb4u;eswLFX z(HW!U+lm=ErgWCwFG1xh_~VMD_4Q_b2mR{f?(kA6uQQ6&-rCubD{!LAq($9fEE8LE z4f)=L@W48(`SRv|x#-K)L@kHBB0u9dHe+Xy6D_{Q91CzmYf96^#UlC@(&0P-R=6!f z6Zk#PEMCQ1&V1ywVW1JF-xHmuUg^m!PXH@0kt~!aK}CLbDLDgX?}$aWv}|0P*MU=- z+iS4O2;~YY!NrTzT5PR&S~fPVGSvVCa%Jap(OPVwwSPgPgmY+o0-F};PwZ*Ss<>Qo zVCL1B!2FwEb0TA%SGUOG{_5PG*f?4Od9-4I{$AI!vOSYx>nRi6u`+2_BVK!#ANI%k9Yjw=l_Vri4yiEox*B55yTAiUuDF&}rPNe_R>M9VcpG*G zLebXjVrCUiG#6s)-h(AxpeDAZD;!u^XX2l|PbKK0UqK=(tXRIX=6w|CD-=l0clE?f zIz$Y$V26!!%G-Ow9W7zq)J*Hc{0z0qT;+v5R@RzL`5OBcSz82kNJ%!fZe|w`w!`HW zE30$5Jpmy;ug!T#PSeV&99c!0&Z$FwAjgoGY9$OJL?e|?kZp> zkGm5sUM>Hi+vf}4j?=T4DPk`Yu_=&Uc_M}yuUqLgG2`NaNI=8nD_|1ORMv*qM>=p6 z5^LE2;o_D&8&NmfLOAZB=O(80$i*W)ox9=syljRy;cNr%Hqim1}l5#HQ| zXD0Z&IJQiDO7pKcMvTM)?Je(F6b$x$Nb%)LY3mkGFY=BPu*xr%Oj;#9@4zLL<{*+6SJ2ix!pCD0M;j?&|b4WaIA zJN06AtTi#_N}{!vku&Eqb7j4`V&&DR=o1vOStF6d(Hcs62rU9~%<_J8W|g^evDKGS ztZZY?>H5m0CjPC!k1ZM+YLNchPHkNz#FRdzS0hTT1qDnPi>&YI>=9!Z3q?BcAOw%! zkt5|lA)L2)$XjYvUoe+=i#;v&+81N=xR`Qpjzr)4CXqLpSi)nq(pBto?SNZwhtQE4?Xi!i961XsDs& zU}GuZaI!@1Qd=ZGI{zVS=Cm?l8Pb?JGD=t{qiM0Fv6--xTD)(u)$(D<(-mqJ-=yg5 ziD72dg(aoOqNmYn&q50g7(;H}$aAb^Zy?u3+9&UM?pFA;oGi|!QYiqNSbVjkzP&xr z(gvHfBNf}a*FgP?bz)w@>@1&rX7@==aFKDjmm`u38R;u6_3c=8Vcvs`JTcYy){vH3 z+8T!stl{c3f!KO9fgN0RZ8x69U}N5i#Wzx)$anbEwIw^5;Lk>qC!J~&*(Xi!L5L5t zoAtzs+{|Hxa_Xv9V=+{kJ@hKzI~Rr4D*YLVjM^MqYhwXQ6j^-boUP`LTEk*G*Fr3G zuB&IKU4isucO8f6BDXnvezOVCDy#CY{UG)|wk`6at!-Zo$FDm4z|JAy^IA7M5hy-; zZ;Mz@Ev*BzWVOpKeF!PPizRjTz^g#oMCQU0k%jYNA+H{uTHLD`6 z_JOd(<=roBHf`$;G+jdzDOL}5sU?IKeYK3%mL@#IY>7l$dfM)dFqlM?ub8X zDqwG@_{ypH@dnKjTMk09On?U;qFB From 16eb4287a9e074e59ba443d161beb092a9e68a15 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Tue, 2 Jul 2024 16:22:07 +0100 Subject: [PATCH 06/56] channels.hpp implimented with the bisics requrements till now --- channels.hpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 channels.hpp diff --git a/channels.hpp b/channels.hpp new file mode 100644 index 0000000..69c6c31 --- /dev/null +++ b/channels.hpp @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* channels.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: aet-tass +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/02 16:18:46 by aet-tass #+# #+# */ +/* Updated: 2024/07/02 16:20:12 by aet-tass ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef CHANNEL_HPP +#define CHANNEL_HPP + +#include +#include + +class Channel { +private: + std::string name; + std::vector members; + std::vector operators; + std::string topic; + bool inviteOnly; + bool topicRestricted; + std::string password; + +public: + Channel(std::string name); + void join(std::string nickname); + void leave(std::string nickname); + void kick(std::string operatorNickname, std::string targetNickname); + void invite(std::string operatorNickname, std::string targetNickname); + void setTopic(std::string operatorNickname, std::string newTopic); + void setMode(std::string operatorNickname, char mode, bool value); +}; + +#endif From 2ca4e975258a63d7665dad7052d1e85f32f0263e Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Tue, 2 Jul 2024 18:29:00 +0100 Subject: [PATCH 07/56] done --- FT_IRC | Bin 0 -> 130436 bytes channels.hpp | 20 -------------------- client.o | Bin 0 -> 86292 bytes irc_server.cpp | 12 +++++++++++- irc_server.o | Bin 0 -> 69868 bytes server.o | Bin 0 -> 43864 bytes 6 files changed, 11 insertions(+), 21 deletions(-) create mode 100755 FT_IRC create mode 100644 client.o create mode 100644 irc_server.o create mode 100644 server.o diff --git a/FT_IRC b/FT_IRC new file mode 100755 index 0000000000000000000000000000000000000000..b5e1dd6799a8c7bf34a2d3b431ecc49860074aee GIT binary patch literal 130436 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 literal 0 HcmV?d00001 diff --git a/channels.hpp b/channels.hpp index 69c6c31..f688ff5 100644 --- a/channels.hpp +++ b/channels.hpp @@ -1,14 +1,3 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* channels.hpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: aet-tass +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/07/02 16:18:46 by aet-tass #+# #+# */ -/* Updated: 2024/07/02 16:20:12 by aet-tass ### ########.fr */ -/* */ -/* ************************************************************************** */ #ifndef CHANNEL_HPP #define CHANNEL_HPP @@ -25,15 +14,6 @@ class Channel { bool inviteOnly; bool topicRestricted; std::string password; - -public: - Channel(std::string name); - void join(std::string nickname); - void leave(std::string nickname); - void kick(std::string operatorNickname, std::string targetNickname); - void invite(std::string operatorNickname, std::string targetNickname); - void setTopic(std::string operatorNickname, std::string newTopic); - void setMode(std::string operatorNickname, char mode, bool value); }; #endif diff --git a/client.o b/client.o new file mode 100644 index 0000000000000000000000000000000000000000..3f6287509579d52675ad43743a2e508f1855c6da GIT binary patch literal 86292 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�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 o))8Pt5_^W5{eF1b?w%h2kN^Mx literal 0 HcmV?d00001 diff --git a/irc_server.cpp b/irc_server.cpp index ee430ef..cce7f84 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -83,7 +83,17 @@ while (1) if (clients[l].set_authenticated() == true) { std::cout << clients[l].get_client_pfd().fd << " is authenticated" << std::endl; + + // work starts here baby + // ft_comands_hamdler(){ + // if (m = "/join") + // join(); + // else if (m == "/kick") + // kick(); clients[l].print_client(); + + } + } else { @@ -97,7 +107,7 @@ while (1) } i++; } -} + return (0); } diff --git a/irc_server.o b/irc_server.o new file mode 100644 index 0000000000000000000000000000000000000000..778f7a857839b6dda05a32eff5a5b0d2c94a47d2 GIT binary patch literal 69868 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

    F_yHo_ZhXm)O75 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 bep_gbCyz5fXLf#8Reo0GtO9v>|JwfnmPv75 literal 0 HcmV?d00001 diff --git a/server.o b/server.o new file mode 100644 index 0000000000000000000000000000000000000000..23354837c0ea88b87dd024f85719349cfc229595 GIT binary patch literal 43864 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∓S7=wX_jLS1>Leh(r}p%Yp)CSnPl zki~Km#pGOk1`X7#i(oC3vq;GX;HF4xYy%V3;7Wm=n3lt#c8yR(Zcn$W_?}`E{fcy( zK%Mb4u;eswLFX z(HW!U+lm=ErgWCwFG1xh_~VMD_4Q_b2mR{f?(kA6uQQ6&-rCubD{!LAq($9fEE8LE z4f)=L@W48(`SRv|x#-K)L@kHBB0u9dHe+Xy6D_{Q91CzmYf96^#UlC@(&0P-R=6!f z6Zk#PEMCQ1&V1ywVW1JF-xHmuUg^m!PXH@0kt~!aK}CLbDLDgX?}$aWv}|0P*MU=- z+iS4O2;~YY!NrTzT5PR&S~fPVGSvVCa%Jap(OPVwwSPgPgmY+o0-F};PwZ*Ss<>Qo zVCL1B!2FwEb0TA%SGUOG{_5PG*f?4Od9-4I{$AI!vOSYx>nRi6u`+2_BVK!#ANI%k9Yjw=l_Vri4yiEox*B55yTAiUuDF&}rPNe_R>M9VcpG*G zLebXjVrCUiG#6s)-h(AxpeDAZD;!u^XX2l|PbKK0UqK=(tXRIX=6w|CD-=l0clE?f zIz$Y$V26!!%G-Ow9W7zq)J*Hc{0z0qT;+v5R@RzL`5OBcSz82kNJ%!fZe|w`w!`HW zE30$5Jpmy;ug!T#PSeV&99c!0&Z$FwAjgoGY9$OJL?e|?kZp> zkGm5sUM>Hi+vf}4j?=T4DPk`Yu_=&Uc_M}yuUqLgG2`NaNI=8nD_|1ORMv*qM>=p6 z5^LE2;o_D&8&NmfLOAZB=O(80$i*W)ox9=syljRy;cNr%Hqim1}l5#HQ| zXD0Z&IJQiDO7pKcMvTM)?Je(F6b$x$Nb%)LY3mkGFY=BPu*xr%Oj;#9@4zLL<{*+6SJ2ix!pCD0M;j?&|b4WaIA zJN06AtTi#_N}{!vku&Eqb7j4`V&&DR=o1vOStF6d(Hcs62rU9~%<_J8W|g^evDKGS ztZZY?>H5m0CjPC!k1ZM+YLNchPHkNz#FRdzS0hTT1qDnPi>&YI>=9!Z3q?BcAOw%! zkt5|lA)L2)$XjYvUoe+=i#;v&+81N=xR`Qpjzr)4CXqLpSi)nq(pBto?SNZwhtQE4?Xi!i961XsDs& zU}GuZaI!@1Qd=ZGI{zVS=Cm?l8Pb?JGD=t{qiM0Fv6--xTD)(u)$(D<(-mqJ-=yg5 ziD72dg(aoOqNmYn&q50g7(;H}$aAb^Zy?u3+9&UM?pFA;oGi|!QYiqNSbVjkzP&xr z(gvHfBNf}a*FgP?bz)w@>@1&rX7@==aFKDjmm`u38R;u6_3c=8Vcvs`JTcYy){vH3 z+8T!stl{c3f!KO9fgN0RZ8x69U}N5i#Wzx)$anbEwIw^5;Lk>qC!J~&*(Xi!L5L5t zoAtzs+{|Hxa_Xv9V=+{kJ@hKzI~Rr4D*YLVjM^MqYhwXQ6j^-boUP`LTEk*G*Fr3G zuB&IKU4isucO8f6BDXnvezOVCDy#CY{UG)|wk`6at!-Zo$FDm4z|JAy^IA7M5hy-; zZ;Mz@Ev*BzWVOpKeF!PPizRjTz^g#oMCQU0k%jYNA+H{uTHLD`6 z_JOd(<=roBHf`$;G+jdzDOL}5sU?IKeYK3%mL@#IY>7l$dfM)dFqlM?ub8X zDqwG@_{ypH@dnKjTMk09On?U;qFB literal 0 HcmV?d00001 From ba01ab62b106c30abcb1ebd265c510931be10b85 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Tue, 2 Jul 2024 18:49:20 +0100 Subject: [PATCH 08/56] branch problem fixed --- FT_IRC | Bin 130436 -> 0 bytes client.o | Bin 86292 -> 0 bytes irc_server.cpp | 12 +----------- irc_server.hpp | 3 +-- irc_server.o | Bin 69868 -> 0 bytes server.o | Bin 43864 -> 0 bytes 6 files changed, 2 insertions(+), 13 deletions(-) delete mode 100755 FT_IRC delete mode 100644 client.o delete mode 100644 irc_server.o delete mode 100644 server.o diff --git a/FT_IRC b/FT_IRC deleted file mode 100755 index b5e1dd6799a8c7bf34a2d3b431ecc49860074aee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130436 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 diff --git a/client.o b/client.o deleted file mode 100644 index 3f6287509579d52675ad43743a2e508f1855c6da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86292 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�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 o))8Pt5_^W5{eF1b?w%h2kN^Mx diff --git a/irc_server.cpp b/irc_server.cpp index cce7f84..ee430ef 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -83,17 +83,7 @@ while (1) if (clients[l].set_authenticated() == true) { std::cout << clients[l].get_client_pfd().fd << " is authenticated" << std::endl; - - // work starts here baby - // ft_comands_hamdler(){ - // if (m = "/join") - // join(); - // else if (m == "/kick") - // kick(); clients[l].print_client(); - - } - } else { @@ -107,7 +97,7 @@ while (1) } i++; } - +} return (0); } diff --git a/irc_server.hpp b/irc_server.hpp index f689ba1..4d1d513 100644 --- a/irc_server.hpp +++ b/irc_server.hpp @@ -3,5 +3,4 @@ #include "server.hpp" -#endif - +#endif \ No newline at end of file diff --git a/irc_server.o b/irc_server.o deleted file mode 100644 index 778f7a857839b6dda05a32eff5a5b0d2c94a47d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69868 zcmeHw3w&HvwfC8(Eh#M~yo48v7o;1B+d#lPia@W+jRxK6{rAtGq5 z!A+8|j>_OtX~;C_-#E&|6$-^8>*DgWOfU5>Uz$y;PZK{RKao7rC2*f%TuHLW8VN~} ze?y^Fjg6tmy2eN>9*Q@t2!(RxO=39*Sg(zBhQS}LV$9E>P-92DJ=(g8bL{d;>m}ib zOix^678M`tvLUanCDzaw4|TS#jkY$0LUjwRC5Bj@`)rvT3>pUY!SY88;{s{#9Fd_= zWOZm|dqYb^^4s+rX_omz7f6h?NqK$WmHj%=Fjh;7{96f_jDMo4vSST{{^6oZDStD{ zT@7OCF2i`E)-X`sfQsUJ3xDaK8~=_6Pc`sRuVsPcn}H4ceejV$N;pX%WdxG`kzL)d z{r%uU5|`XQginFw@+a#>fVd?lLMv1r{oT{a3I;6Hd~nzp96Dtly&_Eqk>uO zov~S2B9Q8)&t=aA#&`YJ)%BiHw()EFVttlk^f^V&O+J(Cy$4C|y&lDt>ZaUOFJ;Wx zUDo|DM$NA7H_(c5w1SIrp^d6gpto}`#sqPtwo@)MBosrcn?5GHGvMgjPJiJO3rL{p z6BV^tpIE2LWqpFOluyJIdEZ!Qml9Hw-9wPN5`hHZB1OqzF$^eM6qJ6D5`6HYX~>5q zDa-^?v2qkBw{bo$SbDd6h_m-z8@YEo4Mz(fG}3Wi7OpKBsD+bOyRVMRTq9C1usHg^xZbcO-i!p>18;>90}t=~<{F(AZ6> z7dMV03Gj?kqTx!3Pr|>2U6Q@aAw$YeiO<5ne~YPxS;@c6n1&7sX6xThpOs#LY<@R= z2CIQeQ@!Hvy)?j*zu^8(_Aa!PtWhOX-IN_j^-|7US6TO?!f!}-5%a8ScvK;X+)JgT zv8)~XxX4d!Csu2|;Lm1g+BwavAhn%7ivm5}7pUyJ#mA|xvhVNidJnq(Pu9A2lTB7- z5H#tt5C!{`XY<8pWMz<*dYu09kW;*+CU0-m^L`qU+bK(t4GWq28Dz>*rlwD zvr}7aChE5@Cqw}#?Zb!^yk!#u$z6fuy#q>3&g~QHude;>KoZNNWan^zmPsi>|1k3Q ziejA^*|ZeWsm@Fw`MgYb?R4M#!pe)w&fZ8`7-eVs43<}Jm3MI2aG+~v`OPnsovrAy zK2et+^_2!vwR;1u-6(}xcRfpMP*vq{*|WpyGgS2Np!h6@lp^ zfgK|yWKy#~J=y*wnV&3$BxJ$-Xhi3bv=X_-Tu<4?o2iw(!dHf#q9rzymkkAyzs!D4 zeH>E!gDQhuZ!nO2QKnIx3I3r#3O4C_9^Apwea8tC3Pe<^blO-m_W*hp-pbGMUayI2Sxdm z|H1QU0pB&^F6%y?>Zg!X0*_DnH}5M|8AyPDe;6?-DCYVp0CFp_DMRXQxD*QX1(NkW zf#kA;sG_I)4lF07+Nt&1?iR^~WzX)0j$2T?57K(-Qhv#ei6E9`7oQ<<0L>o|(#%$V zNa}>jF-%0fdX`#`F(CLvedZkIA57N2vTqjXw6GJYtU+mKE!9(2m4#_HuGCfogT`i= ztnVjKbv0DYRwq8eJ|o!0rcwCj7tGqSOt})(R1j8za^hjp@ddtg_c6328L+yjjGr6! z4?~xQJ-cN*$4(%*456Zas1Anc@&81Izux6agB){XO-2M-8+OaVPBW2zWZyC@6w%Zn zl-?Vd4%z-~6f&drLvY!Nc z{cuhUf$pH$-y8Vd(~X15OX zZYS?%g}Xf#F8T~BLJyja>T%@Kj2!4~?3;=|!jlro-rI?-cYTi#u@C!ntnrBvA1KVr z{FKP*9!Pf20I6)_*&qsiQzD~lFIGO&1m)92p>EhGLdQKMMfPe&_NwZST0s&0f!@mL zkLe((7LgyLk)}J#7ICjkp?dJo5JwrNx6lG7i3peMc2j9Ne#mEW3Y1!(5TeyMnG6oj z$gW??v-6=`FG+30DkpzDaePl*U1}XG1=kZaVx%lMNa~3`=)`_uhN07u2Q7!6b>oB7 z>{;~T`r)KtCyz|^P{E!bmOcAJu|5)OuLQE>`bEt*T~`=on+DV%&eJE^`3}U6q&nZx zv`)=mG{5x14!d52t=QGbrg`R&^OtvktY=wYD1A~_PtG-vx&CmQ_7;;9O#oto!9X1Y z5`xPw;UbxX!EoXAlDlV6N$BzanOa2xFgE|JnkJTzW__}M&G}Ld&AbL>?J3sIaH-TM zC!;3lMJri+#%j;nrkwa{S#K*f?CVo=eWv8^!Wk0zY3_R0-ahi}cj4k0DOVaRQ*?WI zwQlWS)kjH4rl!d`kDSf?oM#KPg{JT|Lb@cGP|(x&8oxcdGNi+|H3g@oO7J zAsQiB`v-kJ!_=f6|GOCYw6w*VM6DgnX(8#~EgDqzY$w>(?-r`}_;<-xsx8Ug{#|9y z4xpt$ZfPc2{~AdY?1GogvR)29o=KL;rLlE-u=qRQsNkkcH_01NS$=DKuo9zYm0_cN z@Y))wn~3qGH9i6& zz6>evmv*2vO0OE9sr8^9qX;-;Hg}3dzz()+7q!-07iPer!k}e?DIAsC3!}r&On=Fn zpVa=T*m#|Do+3kWFU3i6I@$;+bv)+yzz~83Ii}{FX9%Y#5Z_e)z&4PoItbB?R@~#^ zp_tUH?q>4`)IMTyG_(EG7gl=&a{7mj$u6Fwwi^1w$@={eE}NM%AY{~41470TtA;8* z1hf8-?RPZNJpG{-``L~=G9^?SZ8F7lM1G*AC&9`FepmABSZX#I0(W3i%Vg_itjI16a$1-5T{XWW-W+Ow7388 z){H&{nyjPGf+lP66JhpzM8*e-pZ`1m(fs#?Cq);%`<|Qyvq9nipZTyhZ$8|xYdPjS zgg4Bbe%+M#bdgh{?L5SspM(!~@|q-XMSOVkp^E=<{xD@@4p8$);rTK8HhIBQrTDWK z|I~T0xn<6s7qjz;s!ul`iS>}sbpqB;yh^5AW)BHZaoE=xm!&0OKK&4KC93nj!|AU|lh6O=?& zeV<@a_ZD}XI_#S*+MzU}8=R(kqBVRzFV5Gf^7>o`S##IUSnhcpue~hmsYC6bL*=*o z;|SYCY>zT3A-YQ?&=Qz5Y3}Mh)CM(Pd^!GsJqDUS5=j0~+>NW}u`GHMH-37t?M`)? z104NCXSbrScH^k4G?3gOD+QzcAQrh+|IgM(r#Iw_*x}O=XUY%g+^rl%t~Axr4SAoe zjL&jJlN430O0k~KKd`c`7h|Hm=6r@aRlvfXLar39nX@p%pimTeR6Pd9?y`;lA{~m` zX`VdcgWT!$qcvMp7xY74c(LpPnVIybmC&?kp1OgE#AZc-dglIjb0AqGt+Wn?uGvS& zpZU$jv?P2~^{>b5->kj&+K!a>2Ijn2cGm>iAmu}r^8o5)QxA-s-Jc;@;urgEn1 znLKa{5o$7l9e;KO=8Tlx$+sGzCT=ylMWev6182NA<`gcBCmOk93}S)=y2FvP8{_?v z{rn`WEA)ll)87y5c)vtEjKTYL)fP$L@%xfM3HJT7&Hb{+><<}_F@7)(roSE7@!ybx zG1j#{W0c)RcilwmX*A+~2<^z|>>?>2$t6=W8KmFhi4crGntg2Rk^KF&JGXvX*U2#~ zEt0o?&ed1O2efS&+WynPj`yHc{Sb5>!i`do)ET`7)o~*-g~vo}YOC9WbTCtb4#By* zeCC7CL-Xwo$0EO2mUHjL++R}ra`&@AvwdXOobyhxI#KQ|64G7a8#s1Ch;+S(PQ~Cb zPiRmx^`HxF$z9rj$|Q+gm|l&qa$ygWe{{}gOnq5b4o}coDNhHvIOSDi%yMr5<}hT3=O2xj z`r`iX^VvR>{wYPvLv)+{D1HbZ5aZ|w``g;dvR`+reoc0Af75WWIE7eAh>jkpO)`s! zCA=TVj<@30Ymy(ls?9j}vCf~4{VB@i@{_z_xHQFAIc{-(SMZtl(Kuj|PiL%;>rnVb zJd)4k$@xUt+KgQ%2(fcdDf^td`)unU(w97#-6Q}0UqIaC!QS9(YxFYDr_A;$dz4$- zNBW4dqdA{ZvhOhCZ?-=~8>sv;*k_rF3kbDX_TDv#Vp;EHkAG0z;iS_*atS=sNC#s| z8__!nWT^R8$bYWfWI@apfk-@ICra_$&R=IanaZLKvVJixat_^1)0Iuk#&$FQsr|%g z=U+^RD%O6m3e3@8#9WS_;vgQbqn_vE@Ah;Jl#8xccPG^N&Dytke^>qqKUqf6$I{Q?C?3z!kq-m|vDXJ9QlB%9$!$V@EIInlNCF>uf z>a&b2YyCEnrS8)7$W+erwbWnI{UIp=i+IXUIKQk>A4z8MB}t}7L*kFFi1S+i3=VnrhJ%te%V zH~_mANh-Iluf&emTzXTdvEp=l${Y$bQTt?hEM-tTYeVyh+EA)Y+lhr5FQ`?VD2-S%a8U^6ZKAP9eG{$DZ^6Dt*C(h5#&0g@HKK2!y#afM7aD8AYYo&X<1M`#c3pkw$lA1+* z3JZJMd88_9r|+)C+*gMsZnBaW`_h%@EC?P|c(E@xB)0WHw!h6a4kXAx%X1S+q_I98 z{h~}oSuh=2%bfpo_7-abwdNqB(*trFE2R6YYADvxJz4aEc_W_!NGBY@JS@QkpM9PH z_p{2?cnzf1=J$`4j=0MG4CSe=g7;5z>_LrG{YDj=yXD;T8sS6IAmTnHbgmx^%$;9e zwy|C|agb}K!-#9}gwhU}6PToNxm(dNoMn&_v&Fve6+WNk6CAZZ$hN=m_%i9L9kzI8 z(lz^$tUZd02c8^P<~4^ke&o#e@Rywa{O6qi$8Dir6hZhOv;t7`xy4@#_LqHpS;9uH zdz#NPQU487j1vKMwDm;Z{b8)dX)agaE|HU_HGWC|DSka0HvNNQiqPkZK=N`r8R*)D zppGeAEVt;iitcr*X&cM0t^v0gWL+m>^ylyluT1qM#L)H+u1w00<9b8}EVki!@sV`=MQ*WFPnt_5<)^NlVap-u zzB@oQ&k*;0G$(agPU;M63U;*U#|`1drbwwQi#1f13_m$sa-z-2l5t-xT(^i;S;L{} zZ$8uC#02qAc7AC0@Bdv7n~UVbTn~H1csAD#+4U<=oHU&u$@vq-FNzZ*!sYDyA4|N{ z%wH6r5X02mU+BE!u7=6wmueh4gPzKWZyx5bgOF-lrl5LR5Y=@!3*zq-AJiV{(D#A4(M? z)_|7%5!HG4`L}TI#3^I8Wq&2c zp5^?z`ojByvqVAt&e>d9mLD}&qJoQNTdqL^*rXLTA{oaNh(s4)I^7T7x`3j8Z z$$8`1G9OxK#=-j^aJl})WjunfAU@)nv}3IClZp_p!#y6HffnvBv8Y zCgJlt6DA@5TgRRQrr#g?D`NV=aVLJZ-1zlz-=IXgd=e-xlz*Cpec=S$EqDF&gp2v@ zSkUh>SLNvwULE6_{?#$Bk8$lEGvS>Q*TFHA(^GQ3VLVzg>8B;eQzdT0_*Ka`(0)@g zRTYNC58gk;b*k|qzQ+3EnCo6HF@9Mx;gxZ&Ov(SCz4%{T2k$@5ReH_@zw4qIhC%CW zTnFzz({-|e@1UN0cF4FA^{k$7m&k~fNsYbHfpH`-*Jdu)xX!YTuDCofp(y3v|L=Yl z#%L{jWQ_4SSJ@L|jPJY3elW&(%Qf-mV~p3vEPJuU^_>!Xop$}n{^jGQxlTUMq6hL8 zPg?EzXjZpn9Sy4@m%1;$B--8>>WH+jiL|@t#oF5AmjfC)I@Y$eH(hRcE*Ae8k@ohs zc6YSZ9cycDcCYMgZH!0TTC>>=jr2aeEWsV^a5r?uS4Udo(Z+^&q{*P1*0#7Ux1qVY z4fMA5c}p+9^iobmrgcO=9tp+Wt<&8Xv|iw*m+eKGI@~P{>!K~4E$)ua7%3WQauc7C zd)+ZXr01(#^*+9Y%r~x-1oUU_HOO>yJzaV9VWwZNp$Fw_>}b@`l~=xx>GWmVLiGMo z=z~nZPE+19Q4)0WgG|@ymtZ<=pmF8tpJw_N4LwM=B5{3FLSA{}I7xs9(v?T|FkPo# znCZIqC750^M#!Hp{^HNp56Mq`WfFDe`MqGLH zFw-&16r}etU1z@mreiiLSblhv@^0=}dao$1JpFu3pQoWGn6C4mG}FDB@)@S<>|ai| zwQ%X=dzj8)AYXr`e?W@KqX(IOjfS3Px>kRtpRFlxoGJ+yXy_iM>)ID&x=#P_DCHBQ zl<#BubyC0i5)7k!k^D3~iu`i=7CA1R|9hCO8=pa@a~RF*pD@!uC#x~_o67o$7vh4Z z^B)g8_C>OMzI>)*eMnaxy^rZvYv>uK>-x{&hJR91KEZUI|MoFm7k|=B*TsiHrq^of zceCO;|MD)PMP1YP^mOmCF>nf<$v`?s7Y-p4fh4>Em?h92aF3!5RYe`8Fi z8=|=K=zUDrwXdJ)I{OVUot~~NB!8Icy7*Dfis|b2FkM%_kLkMhg_)omAAL;M>DSNn zyJY*!{tI*e`M99YKVzfN(@fX3ub=6QZS}{M|F|VV*FGQ9b@4gIbgm}fKbWrTpZ-zk zgG@i(5Lcf3;Ze$$Pmu*bsVU#bbZz`#x~_i)nXZi=9C&s8<6*j2qhE~aI{Wo8T^m1` zZjT>5s{grR+cotMGF=-#cw*4T52o`laLH=2fBTrOYhORpb@m%zdbLJ>1KU};bpGjP zx~_g7({=R+nXYSJjOn`Zm1eq5zX7HvWi#eWFpLMe|AM@*)%j;)6na0?b@dN2{X@3; zw{iV$4h&lRF9^M#j($EK)u8R*Drn@!ejS5N7(cMg6 zsVU#bbY1_Xna<73Yu_N#n>F%%7fXV!eL<${*55Iv>-0-7U3Y%rxkT3gQ3+=Mj;Q`) zx^8^+GhH`+2AQtYFT?bZt^P@MGQ-CUD;`F9_Kh(;E!p$vos&^rX;M8 zFkgaUxVe90OxM}BkLkMp8({hsy835Hg08%W>AL<&FkLsk`Qe^n#jGg}gL{uN~U9$onwNzk<~%yeDv#mpuJqOxLw9!Sow6@-s}= zwa=I<3+nc-9;WNYPnhZJrI`5=@Vh$PpbXQs_4C2w=^FjrOxKn7Fu~F!0rt9Y4 zey0E3*1l#nzAuvmo&JMN*Y#h9=_hE~Z(J@3y7qaP&dabo{|Pf)*MEIX|Cual_TMIM zU(6@#-=xv6oJ;89Q;_Mp_J^6Si%-5QWyL!ChM69cY^MINu>J$1l+Q3-=U>JG=lb1D zKS^UB-zeq7OxMO2rt9Kwc%iIV=O2Ac*R7uhn67JoW)!;Nm-Vy#T{4yZ8)mw$|6@$Q zSQg1EpJw_;G<4%CNzm!+uF%JHoqdC&(8EmE%^w3y*V#A2blv%dyH@IduBQD#rY9ubY~MTFzCotz>K|sh zuK&)Eat+tVgLR7y*Shj!?jMV+^72W?l=h*wW*{*Y|1zJ$!#241KDtr*@2|;>`5!31 zYs`Y<#ma#J3Rte9U(yK8vdWUo!|b%y&Jr6_Q7> zImUc!=YsV<1HK;SV|x|kdjoulBKRi3e(RX;ItTq`fv>*^c{hP?3-dX(W1~f$>fb_k z*=muu#X-M4;Pd>e?6+?^@Eri(Hs(9Wfp6*?AALABzQH`F|o(I6!!}31pz_$~83Fe#Pz_;Hb?;Hodlg7e6EN_wn-#qZGV?JK* z6>M)4_+re*+pmIr_kd5em-(qK7X8k3;Cl^xo4MZe9r(tMgMTrfle`(=+roUO zImlaTkvGqQ?{@HQV|h+~jb|2(e&+K!$iwrD#%|_w>fd+3H&{fyXJC?0@_0Tk*l!EL zr}X1_yC7dP_*8#fNlmwru>o&0+b_{y1&_YnpA`vCYRGv8E=o|Hdz z0?zlC?`j9WI`9RU&&l3#@cEeUlMeD80N-Zja~gj;!Ixk@r+B>|e5;wyDbAgQ%3{n{ z>!9B}@G1SA#z7PKlzvX}>mG|dC;L4HzP?fHLjE-a&bN;F8o3>%6MwGtuSwwF#{7>t zw0jo#f)7eDYaIA)0^b(qa~dxj!Ix&fvmE4Y1>a`obF$AK@bxjDQ@;#|ckBc1ax8EX9*Nzz|-*jA7-d!xO z^v{D@zgYMlz&9|8eMrwq=v?Jrih;_YxkD`1$xbIhZie|T zV7Z0%BlEzwm-%$|r1;rnk>}(W_kd67=fw9I_y)ONr*-yg;M>i7PV&ZO?>%P(vFW-IuYvz|`lY7h9rMerQ}-)iP_(ldTy zR^Eq{p0o9OE(L#rwj39*~xFu zz~SI#=5w<5Lhz-F;A;lo7UrvWXzwQQ4Km*?8a^@q;gDzY7TJz<%vbuomkRn1@y`SQ zYUclw;=ivjKgFLjz(4H~Dehk8FEkG>1Yer@HaYM$gKzRTq&!_brFu7k&tN{cgS=u*alV8jNpPTud;=oPdo5p<24)tyXUyS*j?6MVn%b5>D zS6&6i%O3Crna`;m2f(M=yG0|9{3d=X)(0%_qs&*jc2_|^qyAe8{$b|V#TDYa9ejJ4 z&nZqk2)@iH?IAtSn2hxf^M#b2ufM3(^8n#m$s!M-O?wp!#}q0y7Z)gJI=ija2ze0!PC$seYoGs?HhX6oV{+2;Z9O=iCL zlzl$+g4RB_gMaTRa;ZHJf^V4l+$^`y_9s^JK!_ECDn3@k7wX!l+y222YCy@ zmu7h+T3iMEyBU0&nQxB+-zM+{A9c1j+2tAVEoVL_|9ZnB&xvmmZe9jhUdTbeS>Q`B zpOgJ=0^e%pyVybAM)1XoXvbEIJg0HL2Yg|c=hPnuz^ClD)kAuAZ7J0fjL*uxKD*Lwdzx6Dy^go}I83p`$ zA^3yL@1$olhymtv>X%L6^A#cQ8SvFGpDr%ZIC;Y&&xvo6JFA~=9Y*%q2tE(j`*)=2 zD*bo*4LV!}?9=211HJqMms7j%0pAGAb@HFbz?We@r*+_K;2SE!K4WpyRLQ##s*0;X zJ7$1yFUxcCp9jG=%zXSDno;`tc4>eDayNoM{T)em+COXs-{kK~KBxG;2YeppbF$+B zi#(_JJ{31x23el2|HS+UzTM0hVl$SWt8e%1;2#-9u9*M8H_Uu+WqB2_<166XTZFuK zz?We@r}fww=;Way(*X!hm8^M=mzKb3DcPsd|FyBWU`1XJ=Q$%|YfNzNT zoce9*dFWr})A>I{8Fk>>&3vD7&@T=?&ttNGo#xXAz_*;QfV7zciq(`z^#<@8OA(}4d8zLOcpG48rbe7CdW3E=NR z|1yyDz83f+;s?G7-0v6fn5p;`@Eb_K3M?^*0Qb>K4K8^Bsl&jPk0Jq_3b z{Odx)_#N<7;BSH70%m|4fWHAQ0R9X(7WgsXy9*5Z3Sz}R;C}#r4J7-#1bhwnB#`*F z0*UWh;J*Wp2a;ZYz0xrL4fs>w5b$Xr+4En3X{7H2ei?Wh@E5>aftXt>t_A)N@FE~$ zf5kb#p94<;P6WO`AFq@Gz6~UO-vq)}D*lc0pJjX)IEefn;F-YNfwuzZ0RImBvk!YL zU_X%h@nPWE(C;4LUy%MNung%S@Oa>5zzcvEGM>sfmhr7CB)tcCKKQO>tYDnL_~zx3 z{u1MDz_(Ff5cn2w3h>9k9hXTzco;}}d;v&$+yy)U`Ynt%1CK%eWx%tMUjcj>=mwqz zoCN%D;K)2_zdr(hi1cfm{t56*q(2LM3D^MK4Xgt00v->%8Ti+^c&i%l=RoSmCx8t| ze-nt~qKeM|w*hN`JAo$yUjY8~Qp0#2I0(D}H~`!M+zKTAdw~PM<-q5Fe#R=s$>;ygqycYN*@I>JEfqQ0S zJ_7Cnk{>?_{5z?s1FfLl@S1mJAY|6IxO4fqY@ zzX~j&_y*j9bOZ1a;1o`O%PaNj27Vp+oxq2H*8(2|P6vJsI39Q%@O2M<0|@vs@FT!y zIsJ7`e}U8YFy0LOD){CC$`2i5^E z0+Roq54-_*3Xtj>10*@`U5NWKz+V7~{}~|hZvv9MwLr4R$ABLNUJoRDECPNOcs%ff zz*1lza6by40{kVAq$dK;0{-PZ8J`~qeiG@=0@nkZfVTs^ zz)t|_^@kq^zB<(~ZUcS=xE4rz29h%mxDGgj^Ctt(M7j*P2Ke5&az5V=gy||?0CocJ z1;&9rzz*QYfD?f?bNULVS91D1#)Id`c=Z;L;=+FbM^NrX#>auTBE10^1J(mufMvio zUWdQU4b5@}C5L7#IiE16KnnF5CzteXrv598Ono+Rf?Hfz)qron{yx0{#d% z75Z%lzKir$U=8r&Kriwq1Kq%hz>6{8{1=Q!?a2VCJwF0o0{k}Pmw*A3?*U#7yaPA| zbQka{q+f@zXMg?NKXLH20n5U=3U@dfK|XdfwO>nPQ*M5 zd>Du+vtmB540t~9ufUUme*?aB0_+8R7)bW{Jdo^jEASHJe;9}mTrn3&{Y1~S%mD5@ zUaoVuGDd;Kw*W|dQ-H+x0U)NTig(KK2mfya65lt0#7EC85#IvfMZga*-Np2;KEVQ3Kf?FC!*XLK)7kIi7zHgiBQH0-}p6<^$2C6{i7@ zLwOevU01Q=Sn*E2imw1+;))co67)NP)cz+y)@Y ztp$?YQ-Eh6{XUeX^qWAcXAkf+Abkg74D$b#>8pVx>S7?tIfe7z9w+Cw&jbC)Zv_(H zA|T1D0@D0_V60645lHD@0b$~b=YeM;{WT!fcN-9IFhhg&TM>^5HwiNx=6}*@?in zfuzrG83%!1~@;>m|zSu`WW4e2IB|@Gs&U%_>r6pkmL_ArWq5AVMZUL zo6%s*ASj6PjA_OMW0=v$=w>t+GYBT4JR`kdk@1Hgg2`6s0~GoI zg*?VIV}fxVkoaRj;tzAakI~I&FlI1m3wexb#sp)S(Z}d!G#E3OOhtLdZ9vg~K+%7k zpI{6#`WW4e24e=3vXIA^W=t@K8GVdyMuRbf$(+g$0ZETRAn7r{`Dw-kW0=v$SOcVT z9w3!-bH2ft!6HHE$CzeJFoqd@jBZAQF@r^gD9@N?OfZHSeT;5KgE51}fhfqVVlzRi@aieWvJhKxNf0LtKWzC z%ygL!VqDO*0_!8J$BaHs(|d|3-OuUstGPU<&&K+P=<4?xPMRvy>h~G8BYqM+fpJaO zC#;u9UYOGxYmr7DsNco7`$DFZVQ|%O`_%iu z7hpX@cxpPPvJkJ9RWk;_@WdOz09EML73i{^jgSMO(iSjmUo=~}|_ z)%&rY!u%-s=Slhi);l77j!ai${X%K=dl66jISsw&`ZnSn(KDQmW4@s@tqbV7mi1A; z=g@w>q^sX=XbB*V{!zbMF@ktUlwNlr^$4f({a{c z{ocaqT>k*m={+-4zxrK^Rop)H{`@7(A7+1`b6nC-{r`eXo!lQmPA|Sx(i5DHV!cBA>h}a5VSB3I8K`4=IghvB zE|C1R&Znz|$D@bSTLPd%r>To1y_3fy?K9~5Hm4Juz6N?w{px-Czn&}8X{Nt1t*E0j5`TdzbG!#mAp*S`#Jqx zmZ#pY{wBwlez#yZzIhSrgMBq!Pji2SxqXc@Bt6FTkF&p|IsHW-=~wO+#f@XRyn1i@ zQl|Tue*JjKKgj6`+`r{hWclf;e>wet>R(PjsQQ=FuU;wTxzCa1&sY7+>0hyY^?vel z)xS*t3(qg*uoGRsWBt{8$G5Bg<#@UcJk(zGKJd?}{$=|4+`sC5+ix?!djIzyP%o8N z@7w+&$9FoMq^pzr*Ujmdu%07+AE*Dy_8;K%o!r0b{ns~f|El+0hq!;$`?t^J_C3h` z`!3Vf`?s%Q`RaY!mF(~8J=z1~SRbAbpSwz?)%&fxt7MuEed+q`e3@47ufC4sW0>g+ z*k9d<3v_)7?V|Ro_eInBB&F5+q2Kq(bOwG&*R3pHz5jUz%UADnz7z8@l~?b7Zp6GS zHX6rzj~kW0LKsY{@~Mj{!s4=-o*BD*GYYTKV6nr?+gCRixQZV|nVmzT??n)cbpT&`-iXumfFZvA??!m+1N<$Lj>_OjpZHuAkHI zsQ%*g>u9%-$La5}J$)?yrLmH(-amWil`>5?i|C@~QK-Cn|LqkVFTzZ3Wc}3pWhZmI zQSXa=2W6=|-Hf8^0%b2wU&8AP^?ug}u9o~^rhD05>OHW>aeSbgU366{|HU|`>uI+v zuil4xko}8pmeEzq<3HvTNnJ9AQ>OH4_ z@UZ@fTXg*$hZ;T?y9r z752}&&@V)%n~HR$PmpOJr=R2T;pX%t9v@*&Ph)=yFO=oK%l
      F_yHo_ZhXm)O75 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 bep_gbCyz5fXLf#8Reo0GtO9v>|JwfnmPv75 diff --git a/server.o b/server.o deleted file mode 100644 index 23354837c0ea88b87dd024f85719349cfc229595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43864 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∓S7=wX_jLS1>Leh(r}p%Yp)CSnPl zki~Km#pGOk1`X7#i(oC3vq;GX;HF4xYy%V3;7Wm=n3lt#c8yR(Zcn$W_?}`E{fcy( zK%Mb4u;eswLFX z(HW!U+lm=ErgWCwFG1xh_~VMD_4Q_b2mR{f?(kA6uQQ6&-rCubD{!LAq($9fEE8LE z4f)=L@W48(`SRv|x#-K)L@kHBB0u9dHe+Xy6D_{Q91CzmYf96^#UlC@(&0P-R=6!f z6Zk#PEMCQ1&V1ywVW1JF-xHmuUg^m!PXH@0kt~!aK}CLbDLDgX?}$aWv}|0P*MU=- z+iS4O2;~YY!NrTzT5PR&S~fPVGSvVCa%Jap(OPVwwSPgPgmY+o0-F};PwZ*Ss<>Qo zVCL1B!2FwEb0TA%SGUOG{_5PG*f?4Od9-4I{$AI!vOSYx>nRi6u`+2_BVK!#ANI%k9Yjw=l_Vri4yiEox*B55yTAiUuDF&}rPNe_R>M9VcpG*G zLebXjVrCUiG#6s)-h(AxpeDAZD;!u^XX2l|PbKK0UqK=(tXRIX=6w|CD-=l0clE?f zIz$Y$V26!!%G-Ow9W7zq)J*Hc{0z0qT;+v5R@RzL`5OBcSz82kNJ%!fZe|w`w!`HW zE30$5Jpmy;ug!T#PSeV&99c!0&Z$FwAjgoGY9$OJL?e|?kZp> zkGm5sUM>Hi+vf}4j?=T4DPk`Yu_=&Uc_M}yuUqLgG2`NaNI=8nD_|1ORMv*qM>=p6 z5^LE2;o_D&8&NmfLOAZB=O(80$i*W)ox9=syljRy;cNr%Hqim1}l5#HQ| zXD0Z&IJQiDO7pKcMvTM)?Je(F6b$x$Nb%)LY3mkGFY=BPu*xr%Oj;#9@4zLL<{*+6SJ2ix!pCD0M;j?&|b4WaIA zJN06AtTi#_N}{!vku&Eqb7j4`V&&DR=o1vOStF6d(Hcs62rU9~%<_J8W|g^evDKGS ztZZY?>H5m0CjPC!k1ZM+YLNchPHkNz#FRdzS0hTT1qDnPi>&YI>=9!Z3q?BcAOw%! zkt5|lA)L2)$XjYvUoe+=i#;v&+81N=xR`Qpjzr)4CXqLpSi)nq(pBto?SNZwhtQE4?Xi!i961XsDs& zU}GuZaI!@1Qd=ZGI{zVS=Cm?l8Pb?JGD=t{qiM0Fv6--xTD)(u)$(D<(-mqJ-=yg5 ziD72dg(aoOqNmYn&q50g7(;H}$aAb^Zy?u3+9&UM?pFA;oGi|!QYiqNSbVjkzP&xr z(gvHfBNf}a*FgP?bz)w@>@1&rX7@==aFKDjmm`u38R;u6_3c=8Vcvs`JTcYy){vH3 z+8T!stl{c3f!KO9fgN0RZ8x69U}N5i#Wzx)$anbEwIw^5;Lk>qC!J~&*(Xi!L5L5t zoAtzs+{|Hxa_Xv9V=+{kJ@hKzI~Rr4D*YLVjM^MqYhwXQ6j^-boUP`LTEk*G*Fr3G zuB&IKU4isucO8f6BDXnvezOVCDy#CY{UG)|wk`6at!-Zo$FDm4z|JAy^IA7M5hy-; zZ;Mz@Ev*BzWVOpKeF!PPizRjTz^g#oMCQU0k%jYNA+H{uTHLD`6 z_JOd(<=roBHf`$;G+jdzDOL}5sU?IKeYK3%mL@#IY>7l$dfM)dFqlM?ub8X zDqwG@_{ypH@dnKjTMk09On?U;qFB From 2033d5097f05d89b724b3c46db59c4d9bbe5b5e7 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Sun, 7 Jul 2024 17:31:29 +0100 Subject: [PATCH 09/56] Ya bissmilah, just stated by implimenting the Channel class with some basics --- .vscode/settings.json | 5 ++++- Channel.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ Channel.hpp | 30 ++++++++++++++++++++++++++++++ channels.hpp | 19 ------------------- irc_server.cpp | 1 - 5 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 Channel.cpp create mode 100644 Channel.hpp delete mode 100644 channels.hpp diff --git a/.vscode/settings.json b/.vscode/settings.json index a769c0e..88e8065 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "files.associations": { + "*.embeddedhtml": "html", "iostream": "cpp", "vector": "cpp", "ostream": "cpp", @@ -59,6 +60,8 @@ "type_traits": "cpp", "typeinfo": "cpp", "unordered_map": "cpp", - "utility": "cpp" + "utility": "cpp", + "__tree": "cpp", + "map": "cpp" } } \ No newline at end of file diff --git a/Channel.cpp b/Channel.cpp new file mode 100644 index 0000000..9d5115a --- /dev/null +++ b/Channel.cpp @@ -0,0 +1,42 @@ +#include "Channel.hpp" + +Channel::Channel() { + name = ""; + topic = ""; + chPassword = ""; + channelType = 0; + hasPassword = 0; +} +Channel::Channel(std::string channelName, int channelOperators , int channelType) { + name = channelName; + topic = ""; + chPassword = ""; + channelType = channelType; + hasPassword = 0; +} + +Channel::Channel(const Channel ©) { + name = copy.name; + topic = copy.topic; + clients = copy.clients; + operators = copy.operators; + chPassword = copy.chPassword; + channelType = copy.channelType; + hasPassword = copy.hasPassword; +} + +Channel &Channel::operator=(const Channel ©) { + if (this == ©) { + name = copy.name; + topic = copy.topic; + clients = copy.clients; + operators = copy.operators; + chPassword = copy.chPassword; + channelType = copy.channelType; + hasPassword = copy.hasPassword; + } + return *this; +} + +Channel::~Channel() { +} \ No newline at end of file diff --git a/Channel.hpp b/Channel.hpp new file mode 100644 index 0000000..e416ba8 --- /dev/null +++ b/Channel.hpp @@ -0,0 +1,30 @@ +#ifndef CHANNEL_HPP +#define CHANNEL_HPP + +#include +#include +#include +#include +#include "client.hpp" +class Channel { + private: + std::string name; + std::string topic; + std::map clients; + std::vector operators; + std::string chPassword; + int channelType; + int hasPassword; + + public: + Channel(); + Channel(std::string channelName, int channelOperators , int channelType); + Channel(const Channel ©); + Channel &operator=(const Channel ©); + ~Channel(); +} + + + + +#endif \ No newline at end of file diff --git a/channels.hpp b/channels.hpp deleted file mode 100644 index f688ff5..0000000 --- a/channels.hpp +++ /dev/null @@ -1,19 +0,0 @@ - -#ifndef CHANNEL_HPP -#define CHANNEL_HPP - -#include -#include - -class Channel { -private: - std::string name; - std::vector members; - std::vector operators; - std::string topic; - bool inviteOnly; - bool topicRestricted; - std::string password; -}; - -#endif diff --git a/irc_server.cpp b/irc_server.cpp index ee430ef..c9eef1c 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -98,6 +98,5 @@ while (1) i++; } } - return (0); } From f64b368b3a98ade18889b0cc73e208932b276329 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Sun, 7 Jul 2024 19:47:37 +0100 Subject: [PATCH 10/56] just setting up the setters and getters --- Channel.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++- Channel.hpp | 19 +++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/Channel.cpp b/Channel.cpp index 9d5115a..f561949 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -1,5 +1,8 @@ #include "Channel.hpp" +// canonical form : + + Channel::Channel() { name = ""; topic = ""; @@ -39,4 +42,67 @@ Channel &Channel::operator=(const Channel ©) { } Channel::~Channel() { -} \ No newline at end of file +} + +void Channel::setName(std::string channelName) { + name = channelName; +} + +// setters and getters : + +void Channel::setTopic(std::string channelTopic) { + topic = channelTopic; +} + +void Channel::setClients(std::map channelClients) { + clients = channelClients; +} + +void Channel::setOperators(std::vector channelOperators) { + operators = channelOperators; +} + +void Channel::setChPassword(std::string channelPassword) { + chPassword = channelPassword; +} + +void Channel::setChannelType(int channelType) { + channelType = channelType; +} + +void Channel::setHasPassword(int hasPassword) { + hasPassword = hasPassword; +} + +void Channel::setTopic(std::string channelTopic) { + topic = channelTopic; +} + +std::string Channel::getName() { + return name; +} + +std::string Channel::getTopic() { + return topic; +} + +std::map Channel::getClients() { + return clients; +} + +std::vector Channel::getOperators() { + return operators; +} + +std::string Channel::getChPassword() { + return chPassword; +} + +int Channel::getChannelType() { + return channelType; +} + +int Channel::getHasPassword() { + return hasPassword; +} + diff --git a/Channel.hpp b/Channel.hpp index e416ba8..a6cebfc 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -22,6 +22,25 @@ class Channel { Channel(const Channel ©); Channel &operator=(const Channel ©); ~Channel(); + + // setters : + void setName(std::string channelName); + void setTopic(std::string channelTopic); + void setClients(std::map channelClients); + void setOperators(std::vector channelOperators); + void setChPassword(std::string channelPassword); + void setChannelType(int channelType); + void setHasPassword(int hasPassword); + + // getters : + std::string getName(); + std::string getTopic(); + std::map getClients(); + std::vector getOperators(); + std::string getChPassword(); + int getChannelType(); + int getHasPassword(); + } From 2e41c4e4db4e62bd1a5e7a49c5169062b6b67fc7 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Mon, 8 Jul 2024 18:59:43 +0100 Subject: [PATCH 11/56] push from ayoub , nothing special added --- Channel.cpp | 14 +++++++------- Channel.hpp | 9 ++++++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index f561949..94b8f2a 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -86,11 +86,11 @@ std::string Channel::getTopic() { return topic; } -std::map Channel::getClients() { - return clients; -} +// std::map Channel::getClients() { +// return clients; +// } -std::vector Channel::getOperators() { +std::vector &Channel::getOperators() { return operators; } @@ -102,7 +102,7 @@ int Channel::getChannelType() { return channelType; } -int Channel::getHasPassword() { - return hasPassword; -} +// int Channel::getHasPassword() { +// return hasPassword; +// } diff --git a/Channel.hpp b/Channel.hpp index a6cebfc..4509d50 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -6,6 +6,7 @@ #include #include #include "client.hpp" + class Channel { private: std::string name; @@ -13,6 +14,7 @@ class Channel { std::map clients; std::vector operators; std::string chPassword; + std::map inviteList; int channelType; int hasPassword; @@ -35,11 +37,12 @@ class Channel { // getters : std::string getName(); std::string getTopic(); - std::map getClients(); - std::vector getOperators(); + std::vector &getOperators(); std::string getChPassword(); int getChannelType(); - int getHasPassword(); + int getClientID(const std::string &nickname) const; + int isClientInChannel(int fd); + } From dabeb5ea53e76f23d508e69b6314da200ab07950 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Mon, 8 Jul 2024 21:57:55 +0100 Subject: [PATCH 12/56] updating the Client class --- Channel.cpp | 26 ++++++++++++++++++++++++++ Channel.hpp | 2 ++ client.cpp | 5 +++++ client.hpp | 1 + 4 files changed, 34 insertions(+) diff --git a/Channel.cpp b/Channel.cpp index 94b8f2a..725f1f9 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -106,3 +106,29 @@ int Channel::getChannelType() { // return hasPassword; // } +std::map::const_iterator Channel::beginClientIter() const { + return clients.begin(); +} + +std::map::const_iterator Channel::endClientIter() const { + return clients.end(); +} + +int Channel::getClientID(const std::string &nickname) const { + for (const auto &client : clients) { + if (client.second.getNickname() == nickname) { + return client.first; + } + } + return -1; +} + +int Channel::isClientInChannel(int fd) { + std::map::iterator it; + it = clients.find(fd); + if (it != clients.end()) { + return 1; + } + return 0; +} + diff --git a/Channel.hpp b/Channel.hpp index 4509d50..41786c9 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -39,6 +39,8 @@ class Channel { std::string getTopic(); std::vector &getOperators(); std::string getChPassword(); + std::map::const_iterator beginClientIter() const; + std::map::const_iterator endClientIter() const; int getChannelType(); int getClientID(const std::string &nickname) const; int isClientInChannel(int fd); diff --git a/client.cpp b/client.cpp index 4bdc4f6..c38818e 100644 --- a/client.cpp +++ b/client.cpp @@ -31,6 +31,11 @@ void client::set_realname(std::string realname) { this->realname = realname; } + +std::string client::getNickname const() +{ + return this->nickname; +} std::vector buffer_to_line(std::string buffer, std::string siparator) { std::vector lines; diff --git a/client.hpp b/client.hpp index 28e3fb7..b832679 100644 --- a/client.hpp +++ b/client.hpp @@ -29,6 +29,7 @@ class client void set_realname(std::string realname); bool set_authenticated(); void set_registered(bool is_registered); + std::string getNickname() const; pollfd get_client_pfd(); void set_client_pfd(pollfd client_pfd); void set_massage(std::string massage); From 38c30831b3cb7bb4661954d33e73c4aa9d94a446 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Mon, 8 Jul 2024 22:54:30 +0100 Subject: [PATCH 13/56] settuping the channel --- Channel.cpp | 18 ++++++++++++++++++ Channel.hpp | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/Channel.cpp b/Channel.cpp index 725f1f9..bbed0aa 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -132,3 +132,21 @@ int Channel::isClientInChannel(int fd) { return 0; } +size_t Channel::getClientNb() const { + return clients.size(); +} + +void Channel::removeClient(int id) { + clients.erase(id); +} + +void Channel::removeInitedClient(int id) { + inviteList.erase(id); +} + +void Channel::removeOperator(int id) { + auto it = std::find(operators.begin(), operators.end(), id); + if (it != operators.end()) { + operators.erase(it); + } +} \ No newline at end of file diff --git a/Channel.hpp b/Channel.hpp index 41786c9..2fa7dac 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -44,6 +44,10 @@ class Channel { int getChannelType(); int getClientID(const std::string &nickname) const; int isClientInChannel(int fd); + size_t getClientNb() const; + void removeClient(int id); + void removeInitedClient(int id); + void removeOperator(int id); } From 2670c90587e79af81f5b5131a141ebc68960e34b Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Tue, 9 Jul 2024 21:53:22 +0100 Subject: [PATCH 14/56] push --- Channel.cpp | 25 ++++++++++++++++++++++++- Channel.hpp | 5 +++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Channel.cpp b/Channel.cpp index bbed0aa..6422fbd 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -78,6 +78,9 @@ void Channel::setTopic(std::string channelTopic) { topic = channelTopic; } +void Channel::setInvitedList(int id, client &c){ + inviteList[id] = c; +} std::string Channel::getName() { return name; } @@ -106,6 +109,10 @@ int Channel::getChannelType() { // return hasPassword; // } +int Channel::getHasPassword() const{ + return hasPassword; +} + std::map::const_iterator Channel::beginClientIter() const { return clients.begin(); } @@ -114,6 +121,11 @@ std::map::const_iterator Channel::endClientIter() const { return clients.end(); } +const std::map &Channel::getClientsFromChannel() const{ + return clients; + +} + int Channel::getClientID(const std::string &nickname) const { for (const auto &client : clients) { if (client.second.getNickname() == nickname) { @@ -136,6 +148,10 @@ size_t Channel::getClientNb() const { return clients.size(); } +int Channel::getHasPassword() const { + return hasPassword; +} + void Channel::removeClient(int id) { clients.erase(id); } @@ -149,4 +165,11 @@ void Channel::removeOperator(int id) { if (it != operators.end()) { operators.erase(it); } -} \ No newline at end of file +} + + +bool Channel::isClientInvited(int clientId) const{ + bool isInvited = (inviteList.count(clientId) > 0); + return isInvited; +} + diff --git a/Channel.hpp b/Channel.hpp index 2fa7dac..6f4c846 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -33,6 +33,7 @@ class Channel { void setChPassword(std::string channelPassword); void setChannelType(int channelType); void setHasPassword(int hasPassword); + void Channel::setInvitedList(int id, client &c); // getters : std::string getName(); @@ -44,7 +45,11 @@ class Channel { int getChannelType(); int getClientID(const std::string &nickname) const; int isClientInChannel(int fd); + int getHasPassword() const; size_t getClientNb() const; + bool isClientInvited(int clientId) const; + + const std::map &Channel::getClientsFromChannel() const; void removeClient(int id); void removeInitedClient(int id); void removeOperator(int id); From 25b406ef3860270cc334f65815fae68f5115ac8d Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Mon, 15 Jul 2024 21:55:54 +0100 Subject: [PATCH 15/56] just a test --- Channel.cpp | 16 ++++-- Channel.hpp | 9 ++- client.cpp | 15 ++++- client.hpp | 3 + cmd.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++++++++ irc_server.cpp | 6 ++ server.hpp | 13 +++++ 7 files changed, 206 insertions(+), 9 deletions(-) create mode 100644 cmd.cpp diff --git a/Channel.cpp b/Channel.cpp index 6422fbd..20caec9 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -54,12 +54,12 @@ void Channel::setTopic(std::string channelTopic) { topic = channelTopic; } -void Channel::setClients(std::map channelClients) { - clients = channelClients; +void Channel::setClients(int id, const std::string &userName) { + clients[id].set_nickname(userName); } -void Channel::setOperators(std::vector channelOperators) { - operators = channelOperators; +void Channel::setOperators(int operator) { + operators.push_back(operator); } void Channel::setChPassword(std::string channelPassword) { @@ -89,6 +89,8 @@ std::string Channel::getTopic() { return topic; } + + // std::map Channel::getClients() { // return clients; // } @@ -113,6 +115,12 @@ int Channel::getHasPassword() const{ return hasPassword; } + +std::map Channel::getInvitedList() const{ + return inviteList; + +} + std::map::const_iterator Channel::beginClientIter() const { return clients.begin(); } diff --git a/Channel.hpp b/Channel.hpp index 6f4c846..4184762 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -15,6 +15,7 @@ class Channel { std::vector operators; std::string chPassword; std::map inviteList; + // std::map channels; int channelType; int hasPassword; @@ -28,12 +29,13 @@ class Channel { // setters : void setName(std::string channelName); void setTopic(std::string channelTopic); - void setClients(std::map channelClients); - void setOperators(std::vector channelOperators); + // void setClients(std::map channelClients); + void setClients(int id, const std::string &userName); + void setOperators(int operator); void setChPassword(std::string channelPassword); void setChannelType(int channelType); void setHasPassword(int hasPassword); - void Channel::setInvitedList(int id, client &c); + void setInvitedList(int id, client &c); // getters : std::string getName(); @@ -47,6 +49,7 @@ class Channel { int isClientInChannel(int fd); int getHasPassword() const; size_t getClientNb() const; + std::map getInvitedList() const; bool isClientInvited(int clientId) const; const std::map &Channel::getClientsFromChannel() const; diff --git a/client.cpp b/client.cpp index c38818e..d66d597 100644 --- a/client.cpp +++ b/client.cpp @@ -32,10 +32,15 @@ void client::set_realname(std::string realname) this->realname = realname; } -std::string client::getNickname const() +std::string client::getNickname() const { return this->nickname; } + +std::string client::getUsername()const +{ + return this->username; +} std::vector buffer_to_line(std::string buffer, std::string siparator) { std::vector lines; @@ -148,9 +153,15 @@ void client::set_massage(std::string massage) this->massage = this->massage + massage; } +// get message +std::string client::get_massage() +{ + return this->massage; +} + void client::print_massage() { - this->index++; + this->index++;*/36250= std::cout << "--------------" << "the cleint " << this->client_pfd.fd << " : " << this->index << " : print massage method start ----------------" << std::endl; std::cout << this->massage; std::cout << "--------------print massage method end----------------" << std::endl; diff --git a/client.hpp b/client.hpp index b832679..bbf7939 100644 --- a/client.hpp +++ b/client.hpp @@ -30,11 +30,14 @@ class client bool set_authenticated(); void set_registered(bool is_registered); std::string getNickname() const; + std::string getUsername() const; pollfd get_client_pfd(); void set_client_pfd(pollfd client_pfd); void set_massage(std::string massage); void print_massage(); void print_client(); + std::string get_message(); + }; diff --git a/cmd.cpp b/cmd.cpp new file mode 100644 index 0000000..3e80ae9 --- /dev/null +++ b/cmd.cpp @@ -0,0 +1,153 @@ +#include "Server.hpp" +#include "Channel.hpp" +#include "client.hpp" + + + +void sendMessage(int fd, const std::string& msg) { + if (send(fd, msg.c_str(), msg.size(), 0) == -1) { + throw std::runtime_error("error: send() failed"); + } +} + +std::vector split(std::string line, char c) { + std::vector vec; + size_t pos; + while ((pos = line.find(c)) != std::string::npos) { + vec.push_back(line.substr(0, pos)); + line.erase(0, pos + 1); + } + vec.push_back(line); + return vec; +} + + +void Server::setupChannel(const std::string &channelName, int fd, const std::string &password) { + Channel newChannel; + newChannel.setName(channelName); + newChannel.setTopic("No topic"); + newChannel.setClients(fd, _clients[fd].getNickname()); + newChannel.setOperators(fd); + newChannel.setChannelType(password.empty() ? 0 : 1); + newChannel.setHasPassword(password.empty() ? 0 : 1); + newChannel.setChPassword(password); + channels[channelName] = newChannel; +} + +void Server::JoinMessage(int fd, const std::string &channelName) { + std::string message = ":" + getNameId(fd) + " 332 JOIN :" + channels[channelName].getTopic() + "\n"; + sendMessage(fd, message); +} + + + + +std::string Server::getNameId(int fd) +{ + auto it = _clients.find(fd); + if (it != _clients.end()) + { + return it->second.getNickname(); + } + std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; + sendMessage(fd, message); + return "ERROR"; +} + + + + +void Server::joinCmd(std::vector ¶m, int fd) { + if (param.empty() || param[0][0] != '#' || (param[0][0] == '#' && param[0].size() == 1)) { + std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; + sendMessage(fd, message); + return; + } + + std::vector chn = split(param[0], ','); + std::vector key; + if (param.size() == 2) { + key = split(param[1], ','); + } + + for (size_t i = 0; i < chn.size(); ++i) { + auto it = channels.find(chn[i]); + bool channelCreated = (it == channels.end()); + + if (channelCreated) { + setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); + sendJoinMessage(fd, chn[i]); + continue; + } + + Channel &channel = it->second; + + if (channel.isClientInChannel(fd) == 1) { + std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; + sendMessage(fd, message); + continue; + } + + if (channel.getChannelType() == 1) { + if (channel.getInvitedList().empty() && param.size() != 2) { + std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; + sendMessage(fd, message); + continue; + } + + if (channel.isClientInvited(fd)) { + channel.setClients(fd, _clients[fd].getNickname()); + sendJoinMessage(fd, chn[i]); + continue; + } + + if (channel.getHasPassword() == 1) { + if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { + channel.setClients(fd, _clients[fd].getNickname()); + sendJoinMessage(fd, chn[i]); + } else { + std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; + sendMessage(fd, message); + } + continue; + } + } + + if (channel.getHasPassword() == 1) { + if (key.size() > i && channel.getChPassword() == key[i]) { + channel.setClients(fd, _clients[fd].getNickname()); + sendJoinMessage(fd, chn[i]); + } else { + std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; + sendMessage(fd, message); + } + continue; + } + + channel.setClients(fd, _clients[fd].getNickname()); + sendJoinMessage(fd, chn[i]); + } +} + + +void Server::command(int fd) { + std::string line = _clients[fd].get_message(); + std::istringstream stream(line); + std::string command; + std::vector res; + + stream >> command; + std::transform(command.begin(), command.end(), command.begin(), ::tolower); + + std::string arg; + while (stream >> arg) { + res.push_back(arg); + } + + if (command == "join") + joinCmd(res, fd); + else { + std::string msg = "421 " + _clients[fd].getNickname() + " " + command + " :Unknown command\n"; + sendMessage(fd, msg); + } +} diff --git a/irc_server.cpp b/irc_server.cpp index c9eef1c..6b625ac 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -84,6 +84,8 @@ while (1) { std::cout << clients[l].get_client_pfd().fd << " is authenticated" << std::endl; clients[l].print_client(); + + // work will bw done here } else { @@ -100,3 +102,7 @@ while (1) } return (0); } + + + + diff --git a/server.hpp b/server.hpp index 1318b6e..296a697 100644 --- a/server.hpp +++ b/server.hpp @@ -8,6 +8,9 @@ #include #include #include +#include +#include "client.hpp" +#include "Channel.hpp" class Server { @@ -15,6 +18,9 @@ class Server int sockfd; struct addrinfo hints, *server; std::vector fds; + std::map channels; + std::map _clients; + public : Server(std::string ip, std::string port); void bind_socket(); @@ -24,6 +30,13 @@ class Server int get_sockfd(); ~Server(); + void joinCmd(std::vector ¶m, int fd); + std::string getNameId(int fd); + void sendJoinMessage(int fd, const std::string &channelName); + void setupChannel(const std::string &channelName, int fd, const std::string &password); + void JoinMessage(int fd, const std::string &channelName); + void command(int fd); + }; #endif From f4ce9d81438bae26f39db875202f3f4e585b2309 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Mon, 15 Jul 2024 22:24:58 +0100 Subject: [PATCH 16/56] bugs foxed --- Channel.cpp | 34 +++++++------- Channel.hpp | 8 ++-- Makefile | 2 +- client.cpp | 11 ++++- client.hpp | 1 + cmd.cpp | 39 +++++++---------- irc_server.cpp | 117 +++++++++++++++++++++++-------------------------- irc_server.hpp | 2 +- server.cpp | 2 +- server.hpp | 2 +- 10 files changed, 103 insertions(+), 115 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 20caec9..c0415eb 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -10,11 +10,11 @@ Channel::Channel() { channelType = 0; hasPassword = 0; } -Channel::Channel(std::string channelName, int channelOperators , int channelType) { +Channel::Channel(std::string channelName , int chType) { name = channelName; topic = ""; chPassword = ""; - channelType = channelType; + channelType = chType; hasPassword = 0; } @@ -58,25 +58,23 @@ void Channel::setClients(int id, const std::string &userName) { clients[id].set_nickname(userName); } -void Channel::setOperators(int operator) { - operators.push_back(operator); +void Channel::setOperators(int& op) { + operators.push_back(op); } void Channel::setChPassword(std::string channelPassword) { chPassword = channelPassword; } -void Channel::setChannelType(int channelType) { - channelType = channelType; +void Channel::setChannelType(int chType) { + channelType = chType; } -void Channel::setHasPassword(int hasPassword) { - hasPassword = hasPassword; +void Channel::setHasPassword(int hasPsd) { + hasPassword = hasPsd; } -void Channel::setTopic(std::string channelTopic) { - topic = channelTopic; -} + void Channel::setInvitedList(int id, client &c){ inviteList[id] = c; @@ -135,9 +133,10 @@ const std::map &Channel::getClientsFromChannel() const{ } int Channel::getClientID(const std::string &nickname) const { - for (const auto &client : clients) { - if (client.second.getNickname() == nickname) { - return client.first; + std::map::const_iterator it; + for (it = clients.begin(); it != clients.end(); ++it) { + if (it->second.getNickname() == nickname) { + return it->first; } } return -1; @@ -156,9 +155,7 @@ size_t Channel::getClientNb() const { return clients.size(); } -int Channel::getHasPassword() const { - return hasPassword; -} + void Channel::removeClient(int id) { clients.erase(id); @@ -169,13 +166,12 @@ void Channel::removeInitedClient(int id) { } void Channel::removeOperator(int id) { - auto it = std::find(operators.begin(), operators.end(), id); + std::vector::iterator it = std::find(operators.begin(), operators.end(), id); if (it != operators.end()) { operators.erase(it); } } - bool Channel::isClientInvited(int clientId) const{ bool isInvited = (inviteList.count(clientId) > 0); return isInvited; diff --git a/Channel.hpp b/Channel.hpp index 4184762..1fa4e5e 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -21,7 +21,7 @@ class Channel { public: Channel(); - Channel(std::string channelName, int channelOperators , int channelType); + Channel(std::string channelName, int channelType); Channel(const Channel ©); Channel &operator=(const Channel ©); ~Channel(); @@ -31,7 +31,7 @@ class Channel { void setTopic(std::string channelTopic); // void setClients(std::map channelClients); void setClients(int id, const std::string &userName); - void setOperators(int operator); + void setOperators(int& op); void setChPassword(std::string channelPassword); void setChannelType(int channelType); void setHasPassword(int hasPassword); @@ -52,13 +52,13 @@ class Channel { std::map getInvitedList() const; bool isClientInvited(int clientId) const; - const std::map &Channel::getClientsFromChannel() const; + const std::map &getClientsFromChannel() const; void removeClient(int id); void removeInitedClient(int id); void removeOperator(int id); -} +}; diff --git a/Makefile b/Makefile index 0ee5865..654c8cc 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ NAME=FT_IRC CC = c++ FLAGS = -Wall -Wextra -Werror -std=c++98 -SRC = irc_server.cpp server.cpp client.cpp +SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp OBJ = $(SRC:.cpp=.o) all: $(NAME) diff --git a/client.cpp b/client.cpp index d66d597..3e76cd8 100644 --- a/client.cpp +++ b/client.cpp @@ -1,6 +1,13 @@ #include "client.hpp" +client::client() +{ + this->is_authenticated = false; + this->is_registered = false; + this->index = 0; +} + client::client(pollfd client_pfd, std::string password) { this->client_pfd = client_pfd; @@ -154,14 +161,14 @@ void client::set_massage(std::string massage) } // get message -std::string client::get_massage() +std::string client::get_message() { return this->massage; } void client::print_massage() { - this->index++;*/36250= + this->index++; std::cout << "--------------" << "the cleint " << this->client_pfd.fd << " : " << this->index << " : print massage method start ----------------" << std::endl; std::cout << this->massage; std::cout << "--------------print massage method end----------------" << std::endl; diff --git a/client.hpp b/client.hpp index bbf7939..362fa21 100644 --- a/client.hpp +++ b/client.hpp @@ -22,6 +22,7 @@ class client int index; public : + client(); client(pollfd client_pfd, std::string password); ~client(); void set_nickname(std::string nickname); diff --git a/cmd.cpp b/cmd.cpp index 3e80ae9..e6b98b0 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -1,8 +1,11 @@ #include "Server.hpp" #include "Channel.hpp" #include "client.hpp" - - +#include +#include +#include +#include +#include void sendMessage(int fd, const std::string& msg) { if (send(fd, msg.c_str(), msg.size(), 0) == -1) { @@ -21,7 +24,6 @@ std::vector split(std::string line, char c) { return vec; } - void Server::setupChannel(const std::string &channelName, int fd, const std::string &password) { Channel newChannel; newChannel.setName(channelName); @@ -39,14 +41,9 @@ void Server::JoinMessage(int fd, const std::string &channelName) { sendMessage(fd, message); } - - - -std::string Server::getNameId(int fd) -{ - auto it = _clients.find(fd); - if (it != _clients.end()) - { +std::string Server::getNameId(int fd) { + std::map::iterator it = _clients.find(fd); + if (it != _clients.end()) { return it->second.getNickname(); } std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; @@ -54,9 +51,6 @@ std::string Server::getNameId(int fd) return "ERROR"; } - - - void Server::joinCmd(std::vector ¶m, int fd) { if (param.empty() || param[0][0] != '#' || (param[0][0] == '#' && param[0].size() == 1)) { std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; @@ -71,12 +65,12 @@ void Server::joinCmd(std::vector ¶m, int fd) { } for (size_t i = 0; i < chn.size(); ++i) { - auto it = channels.find(chn[i]); + std::map::iterator it = channels.find(chn[i]); bool channelCreated = (it == channels.end()); if (channelCreated) { setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); - sendJoinMessage(fd, chn[i]); + JoinMessage(fd, chn[i]); continue; } @@ -97,14 +91,14 @@ void Server::joinCmd(std::vector ¶m, int fd) { if (channel.isClientInvited(fd)) { channel.setClients(fd, _clients[fd].getNickname()); - sendJoinMessage(fd, chn[i]); + JoinMessage(fd, chn[i]); continue; } if (channel.getHasPassword() == 1) { if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { channel.setClients(fd, _clients[fd].getNickname()); - sendJoinMessage(fd, chn[i]); + JoinMessage(fd, chn[i]); } else { std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; sendMessage(fd, message); @@ -116,7 +110,7 @@ void Server::joinCmd(std::vector ¶m, int fd) { if (channel.getHasPassword() == 1) { if (key.size() > i && channel.getChPassword() == key[i]) { channel.setClients(fd, _clients[fd].getNickname()); - sendJoinMessage(fd, chn[i]); + JoinMessage(fd, chn[i]); } else { std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; sendMessage(fd, message); @@ -125,11 +119,10 @@ void Server::joinCmd(std::vector ¶m, int fd) { } channel.setClients(fd, _clients[fd].getNickname()); - sendJoinMessage(fd, chn[i]); + JoinMessage(fd, chn[i]); } } - void Server::command(int fd) { std::string line = _clients[fd].get_message(); std::istringstream stream(line); @@ -144,9 +137,9 @@ void Server::command(int fd) { res.push_back(arg); } - if (command == "join") + if (command == "join") { joinCmd(res, fd); - else { + } else { std::string msg = "421 " + _clients[fd].getNickname() + " " + command + " :Unknown command\n"; sendMessage(fd, msg); } diff --git a/irc_server.cpp b/irc_server.cpp index 6b625ac..137eeb4 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -1,7 +1,7 @@ #include "irc_server.hpp" -#include "server.hpp" +#include "Server.hpp" #include "client.hpp" - +#include // for std::transform int main(int argc, char *argv[]) { @@ -11,71 +11,65 @@ int main(int argc, char *argv[]) return (1); } -Server irc_server("0.0.0.0", argv[1]); -irc_server.setsockopt(); -irc_server.bind_socket(); -irc_server.listen_socket(); - - - -std::vector fds; + Server irc_server("0.0.0.0", argv[1]); + irc_server.setsockopt(); + irc_server.bind_socket(); + irc_server.listen_socket(); -std::vector clients; + std::vector fds; + std::vector clients; -fds = irc_server.get_fds(); + fds = irc_server.get_fds(); - -while (1) -{ - int r = poll(&fds[0], fds.size(), -1); - if (r == -1) - { - std::cout << "error in poll function" << std::endl; - } - unsigned int i = 0; - while ( i < fds.size()) + while (1) { - - if (fds[i].revents & POLLIN) + int r = poll(&fds[0], fds.size(), -1); + if (r == -1) + { + std::cout << "error in poll function" << std::endl; + } + unsigned int i = 0; + while ( i < fds.size()) { - if (fds[i].fd == irc_server.get_sockfd()) + if (fds[i].revents & POLLIN) { - // New client - sockaddr_in clientaddr; - socklen_t client_len = sizeof(clientaddr); - int clientfd = accept(irc_server.get_sockfd(), (struct sockaddr*)&clientaddr, &client_len); - - if (clientfd == -1) + if (fds[i].fd == irc_server.get_sockfd()) { - std::cout << "error in accept function" << std::endl; + // New client + sockaddr_in clientaddr; + socklen_t client_len = sizeof(clientaddr); + int clientfd = accept(irc_server.get_sockfd(), (struct sockaddr*)&clientaddr, &client_len); + + if (clientfd == -1) + { + std::cout << "error in accept function" << std::endl; + } + else + { + // std::cout << "new client connected " << inet_ntoa(clientaddr.sin_addr) << std::endl; + pollfd client_pfd; + + client_pfd.fd = clientfd; + client_pfd.events = POLLIN; + fds.push_back(client_pfd); + + clients.push_back(client(client_pfd, argv[2])); + } } else { - // std::cout << "new client connected " << inet_ntoa(clientaddr.sin_addr) << std::endl; - pollfd client_pfd; - - client_pfd.fd = clientfd; - client_pfd.events = POLLIN; - fds.push_back(client_pfd); - - clients.push_back(client(client_pfd, argv[2])); - } - } - else - { - - char buffer[1024]; - int r = recv(fds[i].fd, buffer, sizeof(buffer), 0); - if (r > 0) - { - buffer[r] = '\0'; - - // std::cout << buffer; - unsigned int l = 0; - while (l < clients.size()) + char buffer[1024]; + int r = recv(fds[i].fd, buffer, sizeof(buffer), 0); + if (r > 0) { - if ((clients[l].get_client_pfd().fd == fds[i].fd)) + buffer[r] = '\0'; + + // std::cout << buffer; + unsigned int l = 0; + while (l < clients.size()) { + if ((clients[l].get_client_pfd().fd == fds[i].fd)) + { clients[l].set_massage(buffer); // clients[l].print_massage(); @@ -86,23 +80,20 @@ while (1) clients[l].print_client(); // work will bw done here + irc_server.command(fds[i].fd); } else { std::cout << clients[l].get_client_pfd().fd << " is not authenticated" << std::endl; } + } + l++; } - l++; } } } + i++; } - i++; } + return (0); } -return (0); -} - - - - diff --git a/irc_server.hpp b/irc_server.hpp index 4d1d513..92b35ed 100644 --- a/irc_server.hpp +++ b/irc_server.hpp @@ -1,6 +1,6 @@ #ifndef IRC_SERVER_HPP #define IRC_SERVER_HPP -#include "server.hpp" +#include "Server.hpp" #endif \ No newline at end of file diff --git a/server.cpp b/server.cpp index 1c349ab..9118f43 100644 --- a/server.cpp +++ b/server.cpp @@ -1,4 +1,4 @@ -#include "server.hpp" +#include "Server.hpp" Server::Server(std::string ip, std::string port) { diff --git a/server.hpp b/server.hpp index 296a697..e633ddb 100644 --- a/server.hpp +++ b/server.hpp @@ -32,7 +32,7 @@ class Server void joinCmd(std::vector ¶m, int fd); std::string getNameId(int fd); - void sendJoinMessage(int fd, const std::string &channelName); + void joinMessage(int fd, const std::string &channelName); void setupChannel(const std::string &channelName, int fd, const std::string &password); void JoinMessage(int fd, const std::string &channelName); void command(int fd); From ef85d71f75dc0530d1710246e89552a33f391ac3 Mon Sep 17 00:00:00 2001 From: goulem Date: Wed, 17 Jul 2024 16:33:07 +0100 Subject: [PATCH 17/56] test --- Channel.cpp | 314 +++++++++++++++++++++++++++++++--------------------- Channel.hpp | 105 ++++++++++-------- client.cpp | 48 ++++++++ client.hpp | 16 +++ cmd.cpp | 269 ++++++++++++++++++++++---------------------- server.hpp | 6 +- 6 files changed, 449 insertions(+), 309 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index c0415eb..878e4b1 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -1,179 +1,235 @@ #include "Channel.hpp" + -// canonical form : +#include "../includes/headers.hpp" - -Channel::Channel() { - name = ""; - topic = ""; - chPassword = ""; - channelType = 0; - hasPassword = 0; -} -Channel::Channel(std::string channelName , int chType) { - name = channelName; - topic = ""; - chPassword = ""; - channelType = chType; - hasPassword = 0; +Channel::Channel() +{ + this->_name = ""; + this->_pass = ""; + this->_mode = ""; + this->_topic = ""; + this->_limit = CHANMAX; + this->_is_private = false; + this->_inviteMode = false; + this->_topicMode = false; + this->_limitMode = false; } -Channel::Channel(const Channel ©) { - name = copy.name; - topic = copy.topic; - clients = copy.clients; - operators = copy.operators; - chPassword = copy.chPassword; - channelType = copy.channelType; - hasPassword = copy.hasPassword; +Channel::Channel(std::string name, std::string pass) +{ + this->_name = name; + this->_pass = pass; + this->_mode = ""; + this->_topic = ""; + this->_limit = CHANMAX; + this->_inviteMode = false; + this->_is_private = false; + this->_topicMode = false; + this->_limitMode = false; } -Channel &Channel::operator=(const Channel ©) { - if (this == ©) { - name = copy.name; - topic = copy.topic; - clients = copy.clients; - operators = copy.operators; - chPassword = copy.chPassword; - channelType = copy.channelType; - hasPassword = copy.hasPassword; - } - return *this; -} -Channel::~Channel() { +Channel::~Channel() +{ } -void Channel::setName(std::string channelName) { - name = channelName; +//getters +std::string Channel::get_name() const +{ + return (this->_name); } - -// setters and getters : - -void Channel::setTopic(std::string channelTopic) { - topic = channelTopic; +std::string Channel::get_pass() const +{ + return (this->_pass); } - -void Channel::setClients(int id, const std::string &userName) { - clients[id].set_nickname(userName); +std::string Channel::get_topic() const +{ + return (this->_topic); } - -void Channel::setOperators(int& op) { - operators.push_back(op); +std::string Channel::get_mode() const +{ + return (this->_mode); +} +int Channel::get_limit() const +{ + return this->_limit; +} +bool Channel::get_inviteMode() const +{ + return (this->_inviteMode); +} +bool Channel::get_is_private() const +{ + return (this->_is_private); } -void Channel::setChPassword(std::string channelPassword) { - chPassword = channelPassword; +bool Channel::get_topicMode() const +{ + return this->_topicMode; } -void Channel::setChannelType(int chType) { - channelType = chType; +bool Channel::get_limitMode() const +{ + return this->_limitMode; } -void Channel::setHasPassword(int hasPsd) { - hasPassword = hasPsd; +std::string Channel::get_creation_time() const +{ + return this->_creation_time; } +std::vector Channel::get_members() const +{ + return this->members; +} +std::vector Channel::get_moderators() const +{ + return this->_moderators; +} -void Channel::setInvitedList(int id, client &c){ - inviteList[id] = c; +//setters +void Channel::set_name(std::string name) +{ + this->_name = name; } -std::string Channel::getName() { - return name; +void Channel::set_creation_time(std::string time) +{ + this->_creation_time = time; } - -std::string Channel::getTopic() { - return topic; +void Channel::set_pass(std::string pass) +{ + this->_pass = pass; } - - - -// std::map Channel::getClients() { -// return clients; -// } - -std::vector &Channel::getOperators() { - return operators; +void Channel::set_topic(std::string topic) +{ + this->_topic = topic; } - -std::string Channel::getChPassword() { - return chPassword; +void Channel::set_mode(std::string mode) +{ + this->_mode = mode; } - -int Channel::getChannelType() { - return channelType; +void Channel::set_limit(int limit) +{ + this->_limit = limit; } - -// int Channel::getHasPassword() { -// return hasPassword; -// } - -int Channel::getHasPassword() const{ - return hasPassword; +void Channel::set_inviteMode(bool _inviteMode) +{ + this->_inviteMode = _inviteMode; } - - -std::map Channel::getInvitedList() const{ - return inviteList; - +void Channel::set_is_private(bool is_private) +{ + this->_is_private = is_private; } -std::map::const_iterator Channel::beginClientIter() const { - return clients.begin(); +void Channel::set_topicMode(bool topicMode) +{ + this->_topicMode = topicMode; } -std::map::const_iterator Channel::endClientIter() const { - return clients.end(); +void Channel::set_limitMode(bool limitMode) +{ + this->_limitMode = limitMode; } -const std::map &Channel::getClientsFromChannel() const{ - return clients; - +//methods +void Channel::add_member(int fd) +{ + this->members.push_back(fd); } - -int Channel::getClientID(const std::string &nickname) const { - std::map::const_iterator it; - for (it = clients.begin(); it != clients.end(); ++it) { - if (it->second.getNickname() == nickname) { - return it->first; - } - } - return -1; +void Channel::add_moderator(int fd) +{ + this->_moderators.push_back(fd); } -int Channel::isClientInChannel(int fd) { - std::map::iterator it; - it = clients.find(fd); - if (it != clients.end()) { - return 1; - } - return 0; +void Channel::add_invited_list(std::string nick) +{ + this->_invited_list.push_back(nick); } -size_t Channel::getClientNb() const { - return clients.size(); +bool Channel::is_invited(std::string nick) +{ + for (size_t i = 0; i < this->_invited_list.size(); i++) + { + if (this->_invited_list[i] == nick) + return true; + } + return false; } +// for part - -void Channel::removeClient(int id) { - clients.erase(id); -} - -void Channel::removeInitedClient(int id) { - inviteList.erase(id); +bool Channel::channel_exist(std::map &channels, std::string channel_name) +{ + std::map::iterator it = channels.begin(); + std::map::iterator ite = channels.end(); + for (; it != ite; it++) + { + if (it->first == channel_name) + return true; + } + return false; } -void Channel::removeOperator(int id) { - std::vector::iterator it = std::find(operators.begin(), operators.end(), id); - if (it != operators.end()) { - operators.erase(it); - } +bool Channel::is_member(int fd) +{ + for (size_t i = 0; i < this->members.size(); i++) + { + if (this->members[i] == fd) + return true; + } + return false; } -bool Channel::isClientInvited(int clientId) const{ - bool isInvited = (inviteList.count(clientId) > 0); - return isInvited; +bool Channel::is_moderator(int fd) +{ + for (size_t i = 0; i < this->_moderators.size(); i++) + { + if (this->_moderators[i] == fd) + return true; + } + return false; +} + +void Channel::remove_member(int fd) +{ + for (size_t i = 0; i < this->members.size(); i++) + { + if (this->members[i] == fd) + { + this->members.erase(this->members.begin() + i); + return; + } + } +} + +void Channel::remove_moderator(int fd) +{ + for (size_t i = 0; i < this->_moderators.size(); i++) + { + if (this->_moderators[i] == fd) + { + this->_moderators.erase(this->_moderators.begin() + i); + return; + } + } +} + +bool Channel::is_empty() const +{ + if(this->get_name().empty()) + return true; + return false; + +} + +void Channel::broadcast_message(std::string message, int fd) +{ + for (size_t i = 0; i < this->members.size(); i++) + { + if(this->members[i] != fd) + send(this->members[i], message.c_str(), message.size(), 0); + } } diff --git a/Channel.hpp b/Channel.hpp index 1fa4e5e..8fb6b92 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -6,58 +6,71 @@ #include #include #include "client.hpp" +class Channel +{ + private: + std::string _name; + std::string _pass; + std::string _topic; + std::string _mode; + std::string _creation_time; + int _limit; + bool _is_private; + bool _inviteMode; + bool _topicMode; + bool _limitMode; -class Channel { - private: - std::string name; - std::string topic; - std::map clients; - std::vector operators; - std::string chPassword; - std::map inviteList; - // std::map channels; - int channelType; - int hasPassword; + std::vector members; + std::vector _moderators; + std::vector _bans_list; + std::vector _invited_list; + public: + //constructors + Channel(); + Channel(std::string name, std::string pass); + ~Channel(); + //getters + std::string get_name() const; + std::string get_pass() const; + std::string get_topic() const; + std::string get_mode() const; + int get_limit() const; - public: - Channel(); - Channel(std::string channelName, int channelType); - Channel(const Channel ©); - Channel &operator=(const Channel ©); - ~Channel(); + bool get_inviteMode() const; + bool get_is_private() const; + bool get_topicMode() const; + bool get_limitMode() const; + std::string get_creation_time() const; + std::vector get_members() const; + std::vector get_moderators() const; + //setters + void set_name(std::string name); + void set_creation_time(std::string time); + void set_pass(std::string pass); + void set_topic(std::string topic); + void set_mode(std::string mode); + void set_limit(int limit); + void set_inviteMode(bool inviteMode); + void set_is_private(bool is_private); + void set_topicMode(bool topicMode); + void set_limitMode(bool limitMode); - // setters : - void setName(std::string channelName); - void setTopic(std::string channelTopic); - // void setClients(std::map channelClients); - void setClients(int id, const std::string &userName); - void setOperators(int& op); - void setChPassword(std::string channelPassword); - void setChannelType(int channelType); - void setHasPassword(int hasPassword); - void setInvitedList(int id, client &c); + //methods + void add_member(int fd); + void add_moderator(int fd); + void remove_member(int fd); + void remove_moderator(int fd); + void add_invited_list(std::string nick); - // getters : - std::string getName(); - std::string getTopic(); - std::vector &getOperators(); - std::string getChPassword(); - std::map::const_iterator beginClientIter() const; - std::map::const_iterator endClientIter() const; - int getChannelType(); - int getClientID(const std::string &nickname) const; - int isClientInChannel(int fd); - int getHasPassword() const; - size_t getClientNb() const; - std::map getInvitedList() const; - bool isClientInvited(int clientId) const; - - const std::map &getClientsFromChannel() const; - void removeClient(int id); - void removeInitedClient(int id); - void removeOperator(int id); + bool is_invited(std::string nick); + // for part + bool channel_exist(std::map &channels, std::string channel_name); + bool is_member(int fd); + bool is_moderator(int fd); + void broadcast_message(std::string message, int fd); + bool is_empty() const; }; diff --git a/client.cpp b/client.cpp index 3e76cd8..d627658 100644 --- a/client.cpp +++ b/client.cpp @@ -185,3 +185,51 @@ void client::print_client() + + + + +bool Client::get_print() const{ + + return this->_print; +} +std::vector &Client::get_channel(){ + + return _channels; +} + +void Client::set_print(bool print) +{ + this->_print = print; +} + +void Client::set_channel(std::string channel) +{ + this->_channels.push_back(channel); +} + +bool Client::check_member(std::string member) +{ + for (size_t i = 0; i < this->_channels.size(); i++) + { + if (this->_channels[i] == member) + return true; + } + return false; +} + + + +/*********** part ****************/ + +void Client::remove_channel(std::string channel) +{ + for (size_t i = 0; i < this->_channels.size(); i++) + { + if (this->_channels[i] == channel) + { + this->_channels.erase(this->_channels.begin() + i); + return ; + } + } +} \ No newline at end of file diff --git a/client.hpp b/client.hpp index 362fa21..057507e 100644 --- a/client.hpp +++ b/client.hpp @@ -20,6 +20,9 @@ class client bool is_registered; std::string massage; int index; + std::vector _channels; + bool _print; + public : client(); @@ -40,6 +43,19 @@ class client std::string get_message(); + + + + // + bool get_print() const; + + void set_channel(std::string channel); + std::vector &get_channel(); + bool check_member(std::string memeber); + void remove_channel(std::string channel); + void set_print(bool print); + + }; std::vector buffer_to_line(std::string buffer); diff --git a/cmd.cpp b/cmd.cpp index e6b98b0..e3e4f82 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -1,146 +1,151 @@ -#include "Server.hpp" -#include "Channel.hpp" -#include "client.hpp" -#include -#include -#include -#include -#include - -void sendMessage(int fd, const std::string& msg) { - if (send(fd, msg.c_str(), msg.size(), 0) == -1) { - throw std::runtime_error("error: send() failed"); - } +void ft_replace(std::string &str, char c, std::string rep) +{ + size_t pos = str.find(c); + while(pos != std::string::npos) + { + str.replace(pos, 1, rep); + pos = str.find('\t'); + } } -std::vector split(std::string line, char c) { - std::vector vec; - size_t pos; - while ((pos = line.find(c)) != std::string::npos) { - vec.push_back(line.substr(0, pos)); - line.erase(0, pos + 1); - } - vec.push_back(line); - return vec; -} +std::string to_upper(std::string str) +{ + for(int i = 0; str[i]; i++) + str[i] = std::toupper(str[i]); -void Server::setupChannel(const std::string &channelName, int fd, const std::string &password) { - Channel newChannel; - newChannel.setName(channelName); - newChannel.setTopic("No topic"); - newChannel.setClients(fd, _clients[fd].getNickname()); - newChannel.setOperators(fd); - newChannel.setChannelType(password.empty() ? 0 : 1); - newChannel.setHasPassword(password.empty() ? 0 : 1); - newChannel.setChPassword(password); - channels[channelName] = newChannel; + return str; } -void Server::JoinMessage(int fd, const std::string &channelName) { - std::string message = ":" + getNameId(fd) + " 332 JOIN :" + channels[channelName].getTopic() + "\n"; - sendMessage(fd, message); -} +std::vector modifier(std::string str) +{ + std::vector split; + ft_replace(str, '\t', " "); + ft_replace(str, '\r', " "); + ft_replace(str, '\n', " "); + split = ft_split(str, ' '); -std::string Server::getNameId(int fd) { - std::map::iterator it = _clients.find(fd); - if (it != _clients.end()) { - return it->second.getNickname(); - } - std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; - sendMessage(fd, message); - return "ERROR"; + return split; } -void Server::joinCmd(std::vector ¶m, int fd) { - if (param.empty() || param[0][0] != '#' || (param[0][0] == '#' && param[0].size() == 1)) { - std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; - sendMessage(fd, message); - return; - } - - std::vector chn = split(param[0], ','); - std::vector key; - if (param.size() == 2) { - key = split(param[1], ','); - } - - for (size_t i = 0; i < chn.size(); ++i) { - std::map::iterator it = channels.find(chn[i]); - bool channelCreated = (it == channels.end()); - - if (channelCreated) { - setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); - JoinMessage(fd, chn[i]); - continue; - } - - Channel &channel = it->second; - - if (channel.isClientInChannel(fd) == 1) { - std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; - sendMessage(fd, message); - continue; - } - - if (channel.getChannelType() == 1) { - if (channel.getInvitedList().empty() && param.size() != 2) { - std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; - sendMessage(fd, message); - continue; - } - - if (channel.isClientInvited(fd)) { - channel.setClients(fd, _clients[fd].getNickname()); - JoinMessage(fd, chn[i]); - continue; - } +void server::parse_request(char *read, int fd, fd_set *master) +{ + // std::cout << read << std::endl; + Client client(fd); + std::string request(read); + std::string response; + std::vector split; + + if(!this->_map.count(fd)) + this->_map.insert(std::make_pair(fd, client)); + split = modifier(request); + if(split.empty()) + response = ""; + else if(to_upper(split[0]) == "PASS") + response = pass_response(split, this->_map[fd]); + else if(to_upper(split[0]) == "USER") + response = user_response(split, this->_map[fd]); + else if(to_upper(split[0]) == "NICK") + response = nick_response(split, this->_map[fd]); + else if(to_upper(split[0]) == "JOIN" ) + response = join_response(split, this->_map[fd]) +; + else + response = ""; + send(fd, response.c_str(), response.size(), 0); +} - if (channel.getHasPassword() == 1) { - if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { - channel.setClients(fd, _clients[fd].getNickname()); - JoinMessage(fd, chn[i]); - } else { - std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; - sendMessage(fd, message); - } - continue; - } - } - if (channel.getHasPassword() == 1) { - if (key.size() > i && channel.getChPassword() == key[i]) { - channel.setClients(fd, _clients[fd].getNickname()); - JoinMessage(fd, chn[i]); - } else { - std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; - sendMessage(fd, message); - } - continue; - } +#include "../includes/headers.hpp" - channel.setClients(fd, _clients[fd].getNickname()); - JoinMessage(fd, chn[i]); - } +std::string make_time(void) +{ + time_t curr_time; + curr_time = time(NULL); + return std::to_string(curr_time); } -void Server::command(int fd) { - std::string line = _clients[fd].get_message(); - std::istringstream stream(line); - std::string command; - std::vector res; - stream >> command; - std::transform(command.begin(), command.end(), command.begin(), ::tolower); - - std::string arg; - while (stream >> arg) { - res.push_back(arg); - } - - if (command == "join") { - joinCmd(res, fd); - } else { - std::string msg = "421 " + _clients[fd].getNickname() + " " + command + " :Unknown command\n"; - sendMessage(fd, msg); - } -} +std::string server::join_response(std::vector split, Client &client) +{ + Channel mychannel; + + if(!client.get_print()) + return (":localhost 451 * JOIN :You must finish connecting with nickname first.\r\n"); + if(split.size() == 1 || (split.size() == 2 && split[1] == "#")) + return(":localhost 461 " + client.get_nick() + " " + split[0] + " :Not enough parameters\r\n"); + else if(split.size() >= 2) + { + std::vector names; + std::vector key; + names = ft_split(split[1], ','); + if(split.size() > 2) + key = ft_split(split[2], ','); + for(size_t i = 0; i < names.size(); i++) + { + if(names[i][0] != '#') + mysend(client.get_fd(), ":localhost 403 " + client.get_nick() + " " + names[i] + " :No such channel\r\n"); + else if(client.check_member(names[i])) + mysend(client.get_fd(), ":localhost 443 " + client.get_nick() + " " + names[i] + ":is already on channel\r\n"); + else + { + if(!this->_channels.count(names[i])) + {//if channel does not exist + client.set_channel(names[i]); + if(key.size() > i) + mychannel = Channel(names[i], key[i]); + else + mychannel = Channel(names[i], ""); + + mychannel.add_member(client.get_fd()); + mychannel.add_moderator(client.get_fd()); + mychannel.set_creation_time(make_time()); + this->_channels.insert(make_pair(names[i], mychannel)); + + mysend(client.get_fd(), ":" + client.get_nick() + "!" + client.get_userName() + "@" + get_adderss() + " JOIN :" + names[i] + "\r\n"); + } + else + {//if channel exists + if(this->_channels[names[i]].get_limitMode() && this->_channels[names[i]].get_limit() <= (int)this->_channels[names[i]].get_members().size()) + mysend(client.get_fd(), ":localhost 471 " + client.get_nick() + " " + names[i] + " :Cannot join channel (+l)\r\n"); + else if(this->_channels[names[i]].get_inviteMode()) + { + if(this->_channels[names[i]].is_invited(client.get_nick())) + { + client.set_channel(names[i]); + this->_channels[names[i]].add_member(client.get_fd()); + this->_channels[names[i]].broadcast_message(":" + client.get_nick() + "!~" + client.get_userName() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); + } + else + mysend(client.get_fd(), ":localhost 473 " + client.get_nick() + " " + names[i] + " :Cannot join channel (+i)\r\n"); + } + else + { + if(key.size() > i) + {//if key is provided + if(this->_channels[names[i]].get_pass() == key[i]) + { + client.set_channel(names[i]); + this->_channels[names[i]].add_member(client.get_fd()); + this->_channels[names[i]].broadcast_message(":" + client.get_nick() + "!~" + client.get_userName() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); + } + else + mysend(client.get_fd(), ":localhost 475 " + client.get_nick() + " " + names[i] + " :Cannot join channel (+k)\r\n"); + } + else + {//if key is not provided + if(this->_channels[names[i]].get_pass() == "") + { + client.set_channel(names[i]); + this->_channels[names[i]].add_member(client.get_fd()); + this->_channels[names[i]].broadcast_message(":" + client.get_nick() + "!~" + client.get_userName() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); + } + else + mysend(client.get_fd(), ":localhost 475 " + client.get_nick() + " " + names[i] + " :Cannot join channel (+k)\r\n"); + } + } + } + } + } + } + return (""); +} \ No newline at end of file diff --git a/server.hpp b/server.hpp index e633ddb..7622a3a 100644 --- a/server.hpp +++ b/server.hpp @@ -18,8 +18,10 @@ class Server int sockfd; struct addrinfo hints, *server; std::vector fds; - std::map channels; - std::map _clients; + + std::map _map;//fd, client + static bool romoved_channel; + std::map _channels;//channel name, channel public : Server(std::string ip, std::string port); From 4d032df6c3286807dbc9828355e2381aed706355 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Wed, 17 Jul 2024 16:39:07 +0100 Subject: [PATCH 18/56] update --- Channel.cpp | 1 - cmd.cpp | 9 +-------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 878e4b1..0bc5ee7 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -1,7 +1,6 @@ #include "Channel.hpp" -#include "../includes/headers.hpp" Channel::Channel() { diff --git a/cmd.cpp b/cmd.cpp index e3e4f82..a8131e5 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -40,22 +40,15 @@ void server::parse_request(char *read, int fd, fd_set *master) split = modifier(request); if(split.empty()) response = ""; - else if(to_upper(split[0]) == "PASS") - response = pass_response(split, this->_map[fd]); - else if(to_upper(split[0]) == "USER") - response = user_response(split, this->_map[fd]); - else if(to_upper(split[0]) == "NICK") response = nick_response(split, this->_map[fd]); else if(to_upper(split[0]) == "JOIN" ) - response = join_response(split, this->_map[fd]) -; + response = join_response(split, this->_map[fd]); else response = ""; send(fd, response.c_str(), response.size(), 0); } -#include "../includes/headers.hpp" std::string make_time(void) { From a69ca21c7bcd4275da65c48f5143d3773ac423f2 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Wed, 17 Jul 2024 16:41:34 +0100 Subject: [PATCH 19/56] .just a test baby --- Channel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 0bc5ee7..90d9f64 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -8,7 +8,7 @@ Channel::Channel() this->_pass = ""; this->_mode = ""; this->_topic = ""; - this->_limit = CHANMAX; + this->_limit = 50; this->_is_private = false; this->_inviteMode = false; this->_topicMode = false; @@ -21,7 +21,7 @@ Channel::Channel(std::string name, std::string pass) this->_pass = pass; this->_mode = ""; this->_topic = ""; - this->_limit = CHANMAX; + this->_limit = 50; this->_inviteMode = false; this->_is_private = false; this->_topicMode = false; From 84a7e6527ea4aad0fad52ad0299d840b804d3a2a Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Wed, 17 Jul 2024 16:47:44 +0100 Subject: [PATCH 20/56] testing --- cmd.cpp | 19 +++++++++++++++---- server.hpp | 12 ++++-------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/cmd.cpp b/cmd.cpp index a8131e5..38ef0bc 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -1,3 +1,15 @@ +#include "server.hpp" +#include +#include +#include +#include +#include "client.hpp" +#include "Channel.hpp" +#include + + + + void ft_replace(std::string &str, char c, std::string rep) { size_t pos = str.find(c); @@ -27,10 +39,10 @@ std::vector modifier(std::string str) return split; } -void server::parse_request(char *read, int fd, fd_set *master) +void Server::parse_request(char *read, int fd, fd_set *master) { // std::cout << read << std::endl; - Client client(fd); + client client(fd); std::string request(read); std::string response; std::vector split; @@ -40,7 +52,6 @@ void server::parse_request(char *read, int fd, fd_set *master) split = modifier(request); if(split.empty()) response = ""; - response = nick_response(split, this->_map[fd]); else if(to_upper(split[0]) == "JOIN" ) response = join_response(split, this->_map[fd]); else @@ -58,7 +69,7 @@ std::string make_time(void) } -std::string server::join_response(std::vector split, Client &client) +std::string Server::join_response(std::vector split, Client &client) { Channel mychannel; diff --git a/server.hpp b/server.hpp index 7622a3a..5db24cf 100644 --- a/server.hpp +++ b/server.hpp @@ -19,9 +19,9 @@ class Server struct addrinfo hints, *server; std::vector fds; - std::map _map;//fd, client + std::map _map; static bool romoved_channel; - std::map _channels;//channel name, channel + std::map _channels; public : Server(std::string ip, std::string port); @@ -32,12 +32,8 @@ class Server int get_sockfd(); ~Server(); - void joinCmd(std::vector ¶m, int fd); - std::string getNameId(int fd); - void joinMessage(int fd, const std::string &channelName); - void setupChannel(const std::string &channelName, int fd, const std::string &password); - void JoinMessage(int fd, const std::string &channelName); - void command(int fd); + void parse_request(char *read, int fd, fd_set *master); + std::string join_response(std::vector split, Client &client); }; From bc21d588fbab45dd125108da98c5a2c3f2a8e691 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Wed, 17 Jul 2024 17:50:38 +0100 Subject: [PATCH 21/56] pushed --- Channel.cpp | 5 +++-- client.cpp | 24 ++++++++++++++------ client.hpp | 5 ++++- cmd.cpp | 64 ++++++++++++++++++++++++++++++++++++++--------------- server.hpp | 2 +- 5 files changed, 71 insertions(+), 29 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 90d9f64..ec846ca 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -1,5 +1,7 @@ #include "Channel.hpp" - +#include // For socket-related functions +#include // For IPv4 conversion functions like inet_pton +#include // For close() Channel::Channel() @@ -231,4 +233,3 @@ void Channel::broadcast_message(std::string message, int fd) send(this->members[i], message.c_str(), message.size(), 0); } } - diff --git a/client.cpp b/client.cpp index d627658..a4d25d0 100644 --- a/client.cpp +++ b/client.cpp @@ -184,31 +184,39 @@ void client::print_client() } +pollfd client::get_pollfd() +{ + return this->client_pfd; +} +void client::set_pollfd(pollfd pfd) +{ + this->client_pfd = pfd; +} -bool Client::get_print() const{ +bool client::get_print() const{ return this->_print; } -std::vector &Client::get_channel(){ +std::vector &client::get_channel(){ return _channels; } -void Client::set_print(bool print) +void client::set_print(bool print) { this->_print = print; } -void Client::set_channel(std::string channel) +void client::set_channel(std::string channel) { this->_channels.push_back(channel); } -bool Client::check_member(std::string member) +bool client::check_member(std::string member) { for (size_t i = 0; i < this->_channels.size(); i++) { @@ -219,10 +227,12 @@ bool Client::check_member(std::string member) } + client::client(int fd) { + client_pfd.fd = fd; + } -/*********** part ****************/ -void Client::remove_channel(std::string channel) +void client::remove_channel(std::string channel) { for (size_t i = 0; i < this->_channels.size(); i++) { diff --git a/client.hpp b/client.hpp index 057507e..b91d603 100644 --- a/client.hpp +++ b/client.hpp @@ -41,8 +41,11 @@ class client void print_massage(); void print_client(); std::string get_message(); + void set_pollfd(pollfd pfd); + // get pollfd: + pollfd get_pollfd(); - + client(int fd); diff --git a/cmd.cpp b/cmd.cpp index 38ef0bc..522b40e 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -8,7 +8,35 @@ #include +std::vector ft_split(std::string str, char sep) +{ + std::vector res; + std::string word; + std::stringstream stream(str); + + for(; std::getline(stream, word, sep); ){ + if (!word.empty()) + res.push_back(word); + } + return (res); +} + +void ft_send(int fd, std::string message) +{ + send(fd, message.c_str(), message.size(), 0); +} + +std::string get_adderss() +{ + char hostname[1024]; + hostname[1023] = '\0'; + gethostname(hostname, 1023); + struct hostent *host = gethostbyname(hostname); + if (host) + return std::string(inet_ntoa(*(struct in_addr*)*host->h_addr_list)); + return "localhost"; +} void ft_replace(std::string &str, char c, std::string rep) { @@ -69,14 +97,14 @@ std::string make_time(void) } -std::string Server::join_response(std::vector split, Client &client) +std::string Server::join_response(std::vector split, client &client) { Channel mychannel; if(!client.get_print()) return (":localhost 451 * JOIN :You must finish connecting with nickname first.\r\n"); if(split.size() == 1 || (split.size() == 2 && split[1] == "#")) - return(":localhost 461 " + client.get_nick() + " " + split[0] + " :Not enough parameters\r\n"); + return(":localhost 461 " + client.getNickname() + " " + split[0] + " :Not enough parameters\r\n"); else if(split.size() >= 2) { std::vector names; @@ -87,9 +115,9 @@ std::string Server::join_response(std::vector split, Client &client for(size_t i = 0; i < names.size(); i++) { if(names[i][0] != '#') - mysend(client.get_fd(), ":localhost 403 " + client.get_nick() + " " + names[i] + " :No such channel\r\n"); + ft_send(client.get_pollfd().fd, ":localhost 403 " + client.getNickname() + " " + names[i] + " :No such channel\r\n"); else if(client.check_member(names[i])) - mysend(client.get_fd(), ":localhost 443 " + client.get_nick() + " " + names[i] + ":is already on channel\r\n"); + ft_send(client.get_pollfd().fd, ":localhost 443 " + client.getNickname() + " " + names[i] + ":is already on channel\r\n"); else { if(!this->_channels.count(names[i])) @@ -100,27 +128,27 @@ std::string Server::join_response(std::vector split, Client &client else mychannel = Channel(names[i], ""); - mychannel.add_member(client.get_fd()); - mychannel.add_moderator(client.get_fd()); + mychannel.add_member(client.get_pollfd().fd); + mychannel.add_moderator(client.get_pollfd().fd); mychannel.set_creation_time(make_time()); this->_channels.insert(make_pair(names[i], mychannel)); - mysend(client.get_fd(), ":" + client.get_nick() + "!" + client.get_userName() + "@" + get_adderss() + " JOIN :" + names[i] + "\r\n"); + ft_send(client.get_pollfd().fd, ":" + client.getNickname() + "!" + client.getUsername() + "@" + get_adderss() + " JOIN :" + names[i] + "\r\n"); } else {//if channel exists if(this->_channels[names[i]].get_limitMode() && this->_channels[names[i]].get_limit() <= (int)this->_channels[names[i]].get_members().size()) - mysend(client.get_fd(), ":localhost 471 " + client.get_nick() + " " + names[i] + " :Cannot join channel (+l)\r\n"); + ft_send(client.get_pollfd().fd, ":localhost 471 " + client.getNickname() + " " + names[i] + " :Cannot join channel (+l)\r\n"); else if(this->_channels[names[i]].get_inviteMode()) { - if(this->_channels[names[i]].is_invited(client.get_nick())) + if(this->_channels[names[i]].is_invited(client.getNickname())) { client.set_channel(names[i]); - this->_channels[names[i]].add_member(client.get_fd()); - this->_channels[names[i]].broadcast_message(":" + client.get_nick() + "!~" + client.get_userName() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); + this->_channels[names[i]].add_member(client.get_pollfd().fd); + this->_channels[names[i]].broadcast_message(":" + client.getNickname() + "!~" + client.getUsername() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); } else - mysend(client.get_fd(), ":localhost 473 " + client.get_nick() + " " + names[i] + " :Cannot join channel (+i)\r\n"); + ft_send(client.get_pollfd().fd, ":localhost 473 " + client.getNickname() + " " + names[i] + " :Cannot join channel (+i)\r\n"); } else { @@ -129,22 +157,22 @@ std::string Server::join_response(std::vector split, Client &client if(this->_channels[names[i]].get_pass() == key[i]) { client.set_channel(names[i]); - this->_channels[names[i]].add_member(client.get_fd()); - this->_channels[names[i]].broadcast_message(":" + client.get_nick() + "!~" + client.get_userName() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); + this->_channels[names[i]].add_member(client.get_pollfd().fd); + this->_channels[names[i]].broadcast_message(":" + client.getNickname() + "!~" + client.getUsername() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); } else - mysend(client.get_fd(), ":localhost 475 " + client.get_nick() + " " + names[i] + " :Cannot join channel (+k)\r\n"); + ft_send(client.get_pollfd().fd, ":localhost 475 " + client.getNickname() + " " + names[i] + " :Cannot join channel (+k)\r\n"); } else {//if key is not provided if(this->_channels[names[i]].get_pass() == "") { client.set_channel(names[i]); - this->_channels[names[i]].add_member(client.get_fd()); - this->_channels[names[i]].broadcast_message(":" + client.get_nick() + "!~" + client.get_userName() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); + this->_channels[names[i]].add_member(client.get_pollfd().fd); + this->_channels[names[i]].broadcast_message(":" + client.getNickname() + "!~" + client.getUsername() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); } else - mysend(client.get_fd(), ":localhost 475 " + client.get_nick() + " " + names[i] + " :Cannot join channel (+k)\r\n"); + ft_send(client.get_pollfd().fd, ":localhost 475 " + client.getNickname() + " " + names[i] + " :Cannot join channel (+k)\r\n"); } } } diff --git a/server.hpp b/server.hpp index 5db24cf..98b430f 100644 --- a/server.hpp +++ b/server.hpp @@ -33,7 +33,7 @@ class Server ~Server(); void parse_request(char *read, int fd, fd_set *master); - std::string join_response(std::vector split, Client &client); + std::string join_response(std::vector split, client &client); }; From 1cfbcc0262c36d0116f59ffb2e523b06e8f011cc Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Wed, 17 Jul 2024 21:33:05 +0100 Subject: [PATCH 22/56] last update --- Channel.cpp | 315 ++++++++++++++++++++----------------------------- Channel.hpp | 105 ++++++++--------- client.cpp | 61 ---------- client.hpp | 22 +--- cmd.cpp | 287 ++++++++++++++++++++------------------------ irc_server.cpp | 4 +- irc_server.hpp | 2 +- server.cpp | 2 +- server.hpp | 17 +-- 9 files changed, 314 insertions(+), 501 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index ec846ca..5a9ff57 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -1,235 +1,178 @@ #include "Channel.hpp" -#include // For socket-related functions -#include // For IPv4 conversion functions like inet_pton -#include // For close() +// canonical form : -Channel::Channel() -{ - this->_name = ""; - this->_pass = ""; - this->_mode = ""; - this->_topic = ""; - this->_limit = 50; - this->_is_private = false; - this->_inviteMode = false; - this->_topicMode = false; - this->_limitMode = false; -} -Channel::Channel(std::string name, std::string pass) -{ - this->_name = name; - this->_pass = pass; - this->_mode = ""; - this->_topic = ""; - this->_limit = 50; - this->_inviteMode = false; - this->_is_private = false; - this->_topicMode = false; - this->_limitMode = false; +Channel::Channel() { + name = ""; + topic = ""; + chPassword = ""; + channelType = 0; + hasPassword = 0; } - - -Channel::~Channel() -{ +Channel::Channel(std::string channelName , int chType) { + name = channelName; + topic = ""; + chPassword = ""; + channelType = chType; + hasPassword = 0; } -//getters -std::string Channel::get_name() const -{ - return (this->_name); -} -std::string Channel::get_pass() const -{ - return (this->_pass); +Channel::Channel(const Channel ©) { + name = copy.name; + topic = copy.topic; + clients = copy.clients; + operators = copy.operators; + chPassword = copy.chPassword; + channelType = copy.channelType; + hasPassword = copy.hasPassword; } -std::string Channel::get_topic() const -{ - return (this->_topic); -} -std::string Channel::get_mode() const -{ - return (this->_mode); + +Channel &Channel::operator=(const Channel ©) { + if (this == ©) { + name = copy.name; + topic = copy.topic; + clients = copy.clients; + operators = copy.operators; + chPassword = copy.chPassword; + channelType = copy.channelType; + hasPassword = copy.hasPassword; + } + return *this; } -int Channel::get_limit() const -{ - return this->_limit; + +Channel::~Channel() { } -bool Channel::get_inviteMode() const -{ - return (this->_inviteMode); + +void Channel::setName(std::string channelName) { + name = channelName; } -bool Channel::get_is_private() const -{ - return (this->_is_private); + +// setters and getters : + +void Channel::setTopic(std::string channelTopic) { + topic = channelTopic; } -bool Channel::get_topicMode() const -{ - return this->_topicMode; +void Channel::setClients(int id, const std::string &userName) { + clients[id].set_nickname(userName); } -bool Channel::get_limitMode() const -{ - return this->_limitMode; +void Channel::setOperators(int& op) { + operators.push_back(op); } -std::string Channel::get_creation_time() const -{ - return this->_creation_time; +void Channel::setChPassword(std::string channelPassword) { + chPassword = channelPassword; } -std::vector Channel::get_members() const -{ - return this->members; +void Channel::setChannelType(int chType) { + channelType = chType; } -std::vector Channel::get_moderators() const -{ - return this->_moderators; +void Channel::setHasPassword(int hasPsd) { + hasPassword = hasPsd; } -//setters -void Channel::set_name(std::string name) -{ - this->_name = name; + + +void Channel::setInvitedList(int id, client &c){ + inviteList[id] = c; } -void Channel::set_creation_time(std::string time) -{ - this->_creation_time = time; +std::string Channel::getName() { + return name; } -void Channel::set_pass(std::string pass) -{ - this->_pass = pass; + +std::string Channel::getTopic() { + return topic; } -void Channel::set_topic(std::string topic) -{ - this->_topic = topic; + + + +// std::map Channel::getClients() { +// return clients; +// } + +std::vector &Channel::getOperators() { + return operators; } -void Channel::set_mode(std::string mode) -{ - this->_mode = mode; + +std::string Channel::getChPassword() { + return chPassword; } -void Channel::set_limit(int limit) -{ - this->_limit = limit; + +int Channel::getChannelType() { + return channelType; } -void Channel::set_inviteMode(bool _inviteMode) -{ - this->_inviteMode = _inviteMode; + +// int Channel::getHasPassword() { +// return hasPassword; +// } + +int Channel::getHasPassword() const{ + return hasPassword; } -void Channel::set_is_private(bool is_private) -{ - this->_is_private = is_private; + + +std::map Channel::getInvitedList() const{ + return inviteList; + } -void Channel::set_topicMode(bool topicMode) -{ - this->_topicMode = topicMode; +std::map::const_iterator Channel::beginClientIter() const { + return clients.begin(); } -void Channel::set_limitMode(bool limitMode) -{ - this->_limitMode = limitMode; +std::map::const_iterator Channel::endClientIter() const { + return clients.end(); } -//methods -void Channel::add_member(int fd) -{ - this->members.push_back(fd); +const std::map &Channel::getClientsFromChannel() const{ + return clients; + } -void Channel::add_moderator(int fd) -{ - this->_moderators.push_back(fd); + +int Channel::getClientID(const std::string &nickname) const { + std::map::const_iterator it; + for (it = clients.begin(); it != clients.end(); ++it) { + if (it->second.getNickname() == nickname) { + return it->first; + } + } + return -1; } -void Channel::add_invited_list(std::string nick) -{ - this->_invited_list.push_back(nick); +int Channel::isClientInChannel(int fd) { + std::map::iterator it; + it = clients.find(fd); + if (it != clients.end()) { + return 1; + } + return 0; } -bool Channel::is_invited(std::string nick) -{ - for (size_t i = 0; i < this->_invited_list.size(); i++) - { - if (this->_invited_list[i] == nick) - return true; - } - return false; +size_t Channel::getClientNb() const { + return clients.size(); } -// for part -bool Channel::channel_exist(std::map &channels, std::string channel_name) -{ - std::map::iterator it = channels.begin(); - std::map::iterator ite = channels.end(); - for (; it != ite; it++) - { - if (it->first == channel_name) - return true; - } - return false; + +void Channel::removeClient(int id) { + clients.erase(id); } -bool Channel::is_member(int fd) -{ - for (size_t i = 0; i < this->members.size(); i++) - { - if (this->members[i] == fd) - return true; - } - return false; +void Channel::removeInitedClient(int id) { + inviteList.erase(id); } -bool Channel::is_moderator(int fd) -{ - for (size_t i = 0; i < this->_moderators.size(); i++) - { - if (this->_moderators[i] == fd) - return true; - } - return false; -} - -void Channel::remove_member(int fd) -{ - for (size_t i = 0; i < this->members.size(); i++) - { - if (this->members[i] == fd) - { - this->members.erase(this->members.begin() + i); - return; - } - } -} - -void Channel::remove_moderator(int fd) -{ - for (size_t i = 0; i < this->_moderators.size(); i++) - { - if (this->_moderators[i] == fd) - { - this->_moderators.erase(this->_moderators.begin() + i); - return; - } - } -} - -bool Channel::is_empty() const -{ - if(this->get_name().empty()) - return true; - return false; - -} - -void Channel::broadcast_message(std::string message, int fd) -{ - for (size_t i = 0; i < this->members.size(); i++) - { - if(this->members[i] != fd) - send(this->members[i], message.c_str(), message.size(), 0); - } +void Channel::removeOperator(int id) { + std::vector::iterator it = std::find(operators.begin(), operators.end(), id); + if (it != operators.end()) { + operators.erase(it); + } } + +bool Channel::isClientInvited(int clientId) const{ + bool isInvited = (inviteList.count(clientId) > 0); + return isInvited; +} \ No newline at end of file diff --git a/Channel.hpp b/Channel.hpp index 8fb6b92..1fa4e5e 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -6,71 +6,58 @@ #include #include #include "client.hpp" -class Channel -{ - private: - std::string _name; - std::string _pass; - std::string _topic; - std::string _mode; - std::string _creation_time; - int _limit; - bool _is_private; - bool _inviteMode; - bool _topicMode; - bool _limitMode; - std::vector members; - std::vector _moderators; - std::vector _bans_list; - std::vector _invited_list; - public: - //constructors - Channel(); - Channel(std::string name, std::string pass); - ~Channel(); - //getters - std::string get_name() const; - std::string get_pass() const; - std::string get_topic() const; - std::string get_mode() const; - int get_limit() const; +class Channel { + private: + std::string name; + std::string topic; + std::map clients; + std::vector operators; + std::string chPassword; + std::map inviteList; + // std::map channels; + int channelType; + int hasPassword; - bool get_inviteMode() const; - bool get_is_private() const; - bool get_topicMode() const; - bool get_limitMode() const; - std::string get_creation_time() const; - std::vector get_members() const; - std::vector get_moderators() const; - //setters - void set_name(std::string name); - void set_creation_time(std::string time); - void set_pass(std::string pass); - void set_topic(std::string topic); - void set_mode(std::string mode); - void set_limit(int limit); - void set_inviteMode(bool inviteMode); - void set_is_private(bool is_private); - void set_topicMode(bool topicMode); - void set_limitMode(bool limitMode); + public: + Channel(); + Channel(std::string channelName, int channelType); + Channel(const Channel ©); + Channel &operator=(const Channel ©); + ~Channel(); - //methods - void add_member(int fd); - void add_moderator(int fd); - void remove_member(int fd); - void remove_moderator(int fd); - void add_invited_list(std::string nick); + // setters : + void setName(std::string channelName); + void setTopic(std::string channelTopic); + // void setClients(std::map channelClients); + void setClients(int id, const std::string &userName); + void setOperators(int& op); + void setChPassword(std::string channelPassword); + void setChannelType(int channelType); + void setHasPassword(int hasPassword); + void setInvitedList(int id, client &c); + // getters : + std::string getName(); + std::string getTopic(); + std::vector &getOperators(); + std::string getChPassword(); + std::map::const_iterator beginClientIter() const; + std::map::const_iterator endClientIter() const; + int getChannelType(); + int getClientID(const std::string &nickname) const; + int isClientInChannel(int fd); + int getHasPassword() const; + size_t getClientNb() const; + std::map getInvitedList() const; + bool isClientInvited(int clientId) const; + + const std::map &getClientsFromChannel() const; + void removeClient(int id); + void removeInitedClient(int id); + void removeOperator(int id); - bool is_invited(std::string nick); - // for part - bool channel_exist(std::map &channels, std::string channel_name); - bool is_member(int fd); - bool is_moderator(int fd); - void broadcast_message(std::string message, int fd); - bool is_empty() const; }; diff --git a/client.cpp b/client.cpp index a4d25d0..cce05d6 100644 --- a/client.cpp +++ b/client.cpp @@ -181,65 +181,4 @@ void client::print_client() std::cout << "realname : " << this->realname << std::endl; std::cout << "password sabmited : " << this->sabmit_password << std::endl; std::cout << "password : " << this->password << std::endl; -} - - -pollfd client::get_pollfd() -{ - return this->client_pfd; -} - -void client::set_pollfd(pollfd pfd) -{ - this->client_pfd = pfd; -} - - - - -bool client::get_print() const{ - - return this->_print; -} -std::vector &client::get_channel(){ - - return _channels; -} - -void client::set_print(bool print) -{ - this->_print = print; -} - -void client::set_channel(std::string channel) -{ - this->_channels.push_back(channel); -} - -bool client::check_member(std::string member) -{ - for (size_t i = 0; i < this->_channels.size(); i++) - { - if (this->_channels[i] == member) - return true; - } - return false; -} - - - client::client(int fd) { - client_pfd.fd = fd; - } - - -void client::remove_channel(std::string channel) -{ - for (size_t i = 0; i < this->_channels.size(); i++) - { - if (this->_channels[i] == channel) - { - this->_channels.erase(this->_channels.begin() + i); - return ; - } - } } \ No newline at end of file diff --git a/client.hpp b/client.hpp index b91d603..4591929 100644 --- a/client.hpp +++ b/client.hpp @@ -20,9 +20,6 @@ class client bool is_registered; std::string massage; int index; - std::vector _channels; - bool _print; - public : client(); @@ -41,27 +38,10 @@ class client void print_massage(); void print_client(); std::string get_message(); - void set_pollfd(pollfd pfd); - // get pollfd: - pollfd get_pollfd(); - - client(int fd); - - - - // - bool get_print() const; - - void set_channel(std::string channel); - std::vector &get_channel(); - bool check_member(std::string memeber); - void remove_channel(std::string channel); - void set_print(bool print); }; std::vector buffer_to_line(std::string buffer); -#endif - +#endif \ No newline at end of file diff --git a/cmd.cpp b/cmd.cpp index 522b40e..ee3869d 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -1,183 +1,146 @@ #include "server.hpp" -#include -#include -#include -#include -#include "client.hpp" #include "Channel.hpp" -#include - - -std::vector ft_split(std::string str, char sep) -{ - std::vector res; - std::string word; - std::stringstream stream(str); - - for(; std::getline(stream, word, sep); ){ - if (!word.empty()) - res.push_back(word); +#include "client.hpp" +#include +#include +#include +#include +#include + +void sendMessage(int fd, const std::string& msg) { + if (send(fd, msg.c_str(), msg.size(), 0) == -1) { + throw std::runtime_error("error: send() failed"); } - return (res); } -void ft_send(int fd, std::string message) -{ - send(fd, message.c_str(), message.size(), 0); - +std::vector split(std::string line, char c) { + std::vector vec; + size_t pos; + while ((pos = line.find(c)) != std::string::npos) { + vec.push_back(line.substr(0, pos)); + line.erase(0, pos + 1); + } + vec.push_back(line); + return vec; } -std::string get_adderss() -{ - char hostname[1024]; - hostname[1023] = '\0'; - gethostname(hostname, 1023); - struct hostent *host = gethostbyname(hostname); - if (host) - return std::string(inet_ntoa(*(struct in_addr*)*host->h_addr_list)); - return "localhost"; +void Server::setupChannel(const std::string &channelName, int fd, const std::string &password) { + Channel newChannel; + newChannel.setName(channelName); + newChannel.setTopic("No topic"); + newChannel.setClients(fd, _clients[fd].getNickname()); + newChannel.setOperators(fd); + newChannel.setChannelType(password.empty() ? 0 : 1); + newChannel.setHasPassword(password.empty() ? 0 : 1); + newChannel.setChPassword(password); + channels[channelName] = newChannel; } -void ft_replace(std::string &str, char c, std::string rep) -{ - size_t pos = str.find(c); - while(pos != std::string::npos) - { - str.replace(pos, 1, rep); - pos = str.find('\t'); - } +void Server::JoinMessage(int fd, const std::string &channelName) { + std::string message = ":" + getNameId(fd) + " 332 JOIN :" + channels[channelName].getTopic() + "\n"; + sendMessage(fd, message); } -std::string to_upper(std::string str) -{ - for(int i = 0; str[i]; i++) - str[i] = std::toupper(str[i]); - - return str; +std::string Server::getNameId(int fd) { + std::map::iterator it = _clients.find(fd); + if (it != _clients.end()) { + return it->second.getNickname(); + } + std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; + sendMessage(fd, message); + return "ERROR"; } -std::vector modifier(std::string str) -{ - std::vector split; - ft_replace(str, '\t', " "); - ft_replace(str, '\r', " "); - ft_replace(str, '\n', " "); - split = ft_split(str, ' '); +void Server::joinCmd(std::vector ¶m, int fd) { + if (param.empty() || param[0][0] != '#' || (param[0][0] == '#' && param[0].size() == 1)) { + std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; + sendMessage(fd, message); + return; + } - return split; -} + std::vector chn = split(param[0], ','); + std::vector key; + if (param.size() == 2) { + key = split(param[1], ','); + } -void Server::parse_request(char *read, int fd, fd_set *master) -{ - // std::cout << read << std::endl; - client client(fd); - std::string request(read); - std::string response; - std::vector split; - - if(!this->_map.count(fd)) - this->_map.insert(std::make_pair(fd, client)); - split = modifier(request); - if(split.empty()) - response = ""; - else if(to_upper(split[0]) == "JOIN" ) - response = join_response(split, this->_map[fd]); - else - response = ""; - send(fd, response.c_str(), response.size(), 0); + for (size_t i = 0; i < chn.size(); ++i) { + std::map::iterator it = channels.find(chn[i]); + bool channelCreated = (it == channels.end()); + + if (channelCreated) { + setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); + JoinMessage(fd, chn[i]); + continue; + } + + Channel &channel = it->second; + + if (channel.isClientInChannel(fd) == 1) { + std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; + sendMessage(fd, message); + continue; + } + + if (channel.getChannelType() == 1) { + if (channel.getInvitedList().empty() && param.size() != 2) { + std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; + sendMessage(fd, message); + continue; + } + + if (channel.isClientInvited(fd)) { + channel.setClients(fd, _clients[fd].getNickname()); + JoinMessage(fd, chn[i]); + continue; + } + + if (channel.getHasPassword() == 1) { + if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { + channel.setClients(fd, _clients[fd].getNickname()); + JoinMessage(fd, chn[i]); + } else { + std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; + sendMessage(fd, message); + } + continue; + } + } + + if (channel.getHasPassword() == 1) { + if (key.size() > i && channel.getChPassword() == key[i]) { + channel.setClients(fd, _clients[fd].getNickname()); + JoinMessage(fd, chn[i]); + } else { + std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; + sendMessage(fd, message); + } + continue; + } + + channel.setClients(fd, _clients[fd].getNickname()); + JoinMessage(fd, chn[i]); + } } +void Server::command(int fd) { + std::string line = _clients[fd].get_message(); + std::istringstream stream(line); + std::string command; + std::vector res; + stream >> command; + std::transform(command.begin(), command.end(), command.begin(), ::tolower); -std::string make_time(void) -{ - time_t curr_time; - curr_time = time(NULL); - return std::to_string(curr_time); -} - + std::string arg; + while (stream >> arg) { + res.push_back(arg); + } -std::string Server::join_response(std::vector split, client &client) -{ - Channel mychannel; - - if(!client.get_print()) - return (":localhost 451 * JOIN :You must finish connecting with nickname first.\r\n"); - if(split.size() == 1 || (split.size() == 2 && split[1] == "#")) - return(":localhost 461 " + client.getNickname() + " " + split[0] + " :Not enough parameters\r\n"); - else if(split.size() >= 2) - { - std::vector names; - std::vector key; - names = ft_split(split[1], ','); - if(split.size() > 2) - key = ft_split(split[2], ','); - for(size_t i = 0; i < names.size(); i++) - { - if(names[i][0] != '#') - ft_send(client.get_pollfd().fd, ":localhost 403 " + client.getNickname() + " " + names[i] + " :No such channel\r\n"); - else if(client.check_member(names[i])) - ft_send(client.get_pollfd().fd, ":localhost 443 " + client.getNickname() + " " + names[i] + ":is already on channel\r\n"); - else - { - if(!this->_channels.count(names[i])) - {//if channel does not exist - client.set_channel(names[i]); - if(key.size() > i) - mychannel = Channel(names[i], key[i]); - else - mychannel = Channel(names[i], ""); - - mychannel.add_member(client.get_pollfd().fd); - mychannel.add_moderator(client.get_pollfd().fd); - mychannel.set_creation_time(make_time()); - this->_channels.insert(make_pair(names[i], mychannel)); - - ft_send(client.get_pollfd().fd, ":" + client.getNickname() + "!" + client.getUsername() + "@" + get_adderss() + " JOIN :" + names[i] + "\r\n"); - } - else - {//if channel exists - if(this->_channels[names[i]].get_limitMode() && this->_channels[names[i]].get_limit() <= (int)this->_channels[names[i]].get_members().size()) - ft_send(client.get_pollfd().fd, ":localhost 471 " + client.getNickname() + " " + names[i] + " :Cannot join channel (+l)\r\n"); - else if(this->_channels[names[i]].get_inviteMode()) - { - if(this->_channels[names[i]].is_invited(client.getNickname())) - { - client.set_channel(names[i]); - this->_channels[names[i]].add_member(client.get_pollfd().fd); - this->_channels[names[i]].broadcast_message(":" + client.getNickname() + "!~" + client.getUsername() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); - } - else - ft_send(client.get_pollfd().fd, ":localhost 473 " + client.getNickname() + " " + names[i] + " :Cannot join channel (+i)\r\n"); - } - else - { - if(key.size() > i) - {//if key is provided - if(this->_channels[names[i]].get_pass() == key[i]) - { - client.set_channel(names[i]); - this->_channels[names[i]].add_member(client.get_pollfd().fd); - this->_channels[names[i]].broadcast_message(":" + client.getNickname() + "!~" + client.getUsername() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); - } - else - ft_send(client.get_pollfd().fd, ":localhost 475 " + client.getNickname() + " " + names[i] + " :Cannot join channel (+k)\r\n"); - } - else - {//if key is not provided - if(this->_channels[names[i]].get_pass() == "") - { - client.set_channel(names[i]); - this->_channels[names[i]].add_member(client.get_pollfd().fd); - this->_channels[names[i]].broadcast_message(":" + client.getNickname() + "!~" + client.getUsername() + "@"+ get_adderss() + " JOIN :" + names[i] + "\r\n", 0); - } - else - ft_send(client.get_pollfd().fd, ":localhost 475 " + client.getNickname() + " " + names[i] + " :Cannot join channel (+k)\r\n"); - } - } - } - } - } - } - return (""); + if (command == "join") { + joinCmd(res, fd); + } else { + std::string msg = "421 " + _clients[fd].getNickname() + " " + command + " :Unknown command\n"; + sendMessage(fd, msg); + } } \ No newline at end of file diff --git a/irc_server.cpp b/irc_server.cpp index 137eeb4..5641e94 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -1,5 +1,5 @@ #include "irc_server.hpp" -#include "Server.hpp" +#include "server.hpp" #include "client.hpp" #include // for std::transform @@ -96,4 +96,4 @@ int main(int argc, char *argv[]) } } return (0); -} +} \ No newline at end of file diff --git a/irc_server.hpp b/irc_server.hpp index 92b35ed..4d1d513 100644 --- a/irc_server.hpp +++ b/irc_server.hpp @@ -1,6 +1,6 @@ #ifndef IRC_SERVER_HPP #define IRC_SERVER_HPP -#include "Server.hpp" +#include "server.hpp" #endif \ No newline at end of file diff --git a/server.cpp b/server.cpp index 9118f43..1c349ab 100644 --- a/server.cpp +++ b/server.cpp @@ -1,4 +1,4 @@ -#include "Server.hpp" +#include "server.hpp" Server::Server(std::string ip, std::string port) { diff --git a/server.hpp b/server.hpp index 98b430f..d436afe 100644 --- a/server.hpp +++ b/server.hpp @@ -18,10 +18,8 @@ class Server int sockfd; struct addrinfo hints, *server; std::vector fds; - - std::map _map; - static bool romoved_channel; - std::map _channels; + std::map channels; + std::map _clients; public : Server(std::string ip, std::string port); @@ -32,10 +30,13 @@ class Server int get_sockfd(); ~Server(); - void parse_request(char *read, int fd, fd_set *master); - std::string join_response(std::vector split, client &client); + void joinCmd(std::vector ¶m, int fd); + std::string getNameId(int fd); + void joinMessage(int fd, const std::string &channelName); + void setupChannel(const std::string &channelName, int fd, const std::string &password); + void JoinMessage(int fd, const std::string &channelName); + void command(int fd); }; -#endif - +#endif \ No newline at end of file From be9304892eee566dc214f3d850a204e7a0f8c7d8 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Wed, 17 Jul 2024 21:44:36 +0100 Subject: [PATCH 23/56] mjiid --- Channel.cpp | 23 ----------------------- Channel.hpp | 4 +--- 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 5a9ff57..3df8921 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -1,8 +1,5 @@ #include "Channel.hpp" -// canonical form : - - Channel::Channel() { name = ""; topic = ""; @@ -89,10 +86,6 @@ std::string Channel::getTopic() { -// std::map Channel::getClients() { -// return clients; -// } - std::vector &Channel::getOperators() { return operators; } @@ -156,22 +149,6 @@ size_t Channel::getClientNb() const { } - -void Channel::removeClient(int id) { - clients.erase(id); -} - -void Channel::removeInitedClient(int id) { - inviteList.erase(id); -} - -void Channel::removeOperator(int id) { - std::vector::iterator it = std::find(operators.begin(), operators.end(), id); - if (it != operators.end()) { - operators.erase(it); - } -} - bool Channel::isClientInvited(int clientId) const{ bool isInvited = (inviteList.count(clientId) > 0); return isInvited; diff --git a/Channel.hpp b/Channel.hpp index 1fa4e5e..0a1268f 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -53,9 +53,7 @@ class Channel { bool isClientInvited(int clientId) const; const std::map &getClientsFromChannel() const; - void removeClient(int id); - void removeInitedClient(int id); - void removeOperator(int id); + }; From dcb25b6fbf6d5e0c1afd6cda117ff72a59fa8a84 Mon Sep 17 00:00:00 2001 From: Abdelmajid El-oualy Date: Thu, 18 Jul 2024 12:33:25 +0100 Subject: [PATCH 24/56] fix the server massage --- client.cpp | 22 ++++++++++++++++------ client.hpp | 2 ++ irc_server.cpp | 24 +++++++++++++++--------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/client.cpp b/client.cpp index cce05d6..4f3a3c8 100644 --- a/client.cpp +++ b/client.cpp @@ -76,7 +76,6 @@ bool client::set_authenticated() std::string line; if (this->is_authenticated == true) { - std::cout << this->nickname << " is authenticated" << std::endl; return (true); }else { @@ -86,8 +85,8 @@ bool client::set_authenticated() - std::cout << "---------------vvv--------------------" << std::endl; - std::cout << "the size of lines : " << lines.size() << std::endl; + // std::cout << "--------------- not authonticatef --------------------" << std::endl; + // std::cout << "the size of lines : " << lines.size() << std::endl; for (unsigned int i = 0; i < lines.size(); i++) { // std::cout << lines[i] << std::endl; @@ -120,9 +119,9 @@ bool client::set_authenticated() this->is_authenticated = true; return (true); } - print_client(); + // print_client(); - std::cout << "---------------vvv--------------------" << std::endl; + // std::cout << "--------------- not authonticatef --------------------" << std::endl; @@ -155,7 +154,7 @@ void client::set_client_pfd(pollfd client_pfd) -void client::set_massage(std::string massage) +void client::set_massage_for_auth(std::string massage) { this->massage = this->massage + massage; } @@ -181,4 +180,15 @@ void client::print_client() std::cout << "realname : " << this->realname << std::endl; std::cout << "password sabmited : " << this->sabmit_password << std::endl; std::cout << "password : " << this->password << std::endl; +} + + +void client::clear_massage() +{ + this->massage = ""; +} + +void client::set_massage(std::string massage) +{ + this->massage = massage; } \ No newline at end of file diff --git a/client.hpp b/client.hpp index 4591929..a3eb9bd 100644 --- a/client.hpp +++ b/client.hpp @@ -34,10 +34,12 @@ class client std::string getUsername() const; pollfd get_client_pfd(); void set_client_pfd(pollfd client_pfd); + void set_massage_for_auth(std::string massage); void set_massage(std::string massage); void print_massage(); void print_client(); std::string get_message(); + void clear_massage(); }; diff --git a/irc_server.cpp b/irc_server.cpp index 5641e94..1e7a798 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -70,21 +70,27 @@ int main(int argc, char *argv[]) { if ((clients[l].get_client_pfd().fd == fds[i].fd)) { - clients[l].set_massage(buffer); - - // clients[l].print_massage(); - if (clients[l].set_authenticated() == true) { - std::cout << clients[l].get_client_pfd().fd << " is authenticated" << std::endl; - clients[l].print_client(); - + clients[l].set_massage(buffer); // work will bw done here irc_server.command(fds[i].fd); - } + + // std::cout << clients[l].get_message(); + + + } else { - std::cout << clients[l].get_client_pfd().fd << " is not authenticated" << std::endl; + clients[l].set_massage_for_auth(buffer); + // std::cout << clients[l].get_client_pfd().fd << " is not authenticated" << std::endl; + if (clients[l].set_authenticated() == true) + { + std::cout << "now is lol" << std::endl; + clients[l].clear_massage(); + std::cout << clients[l].get_message() << std::endl; + } + } } l++; From 9432d7931f0ac930509856c5fa37930395f723c4 Mon Sep 17 00:00:00 2001 From: Abdelmajid El-oualy Date: Thu, 18 Jul 2024 12:41:05 +0100 Subject: [PATCH 25/56] fix some error massages --- irc_server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/irc_server.cpp b/irc_server.cpp index 1e7a798..278e4b1 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -76,7 +76,7 @@ int main(int argc, char *argv[]) // work will bw done here irc_server.command(fds[i].fd); - // std::cout << clients[l].get_message(); + std::cout << "we are reciving message from authenticated client : " << clients[l].get_message() << std::endl; } @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) // std::cout << clients[l].get_client_pfd().fd << " is not authenticated" << std::endl; if (clients[l].set_authenticated() == true) { - std::cout << "now is lol" << std::endl; + std::cout << "now is authenticated" << std::endl; clients[l].clear_massage(); std::cout << clients[l].get_message() << std::endl; } From b1010b797657d6cbabc0f6e3cfa64e8a924fa64c Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Fri, 19 Jul 2024 19:03:58 +0100 Subject: [PATCH 26/56] done --- cmd.cpp | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/cmd.cpp b/cmd.cpp index ee3869d..c7e1478 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -30,12 +30,20 @@ void Server::setupChannel(const std::string &channelName, int fd, const std::str newChannel.setTopic("No topic"); newChannel.setClients(fd, _clients[fd].getNickname()); newChannel.setOperators(fd); - newChannel.setChannelType(password.empty() ? 0 : 1); - newChannel.setHasPassword(password.empty() ? 0 : 1); - newChannel.setChPassword(password); + + if (password.empty()) { + newChannel.setChannelType(0); + newChannel.setHasPassword(0); + } else { + newChannel.setChannelType(1); + newChannel.setHasPassword(1); + newChannel.setChPassword(password); + } + channels[channelName] = newChannel; } + void Server::JoinMessage(int fd, const std::string &channelName) { std::string message = ":" + getNameId(fd) + " 332 JOIN :" + channels[channelName].getTopic() + "\n"; sendMessage(fd, message); @@ -52,22 +60,30 @@ std::string Server::getNameId(int fd) { } void Server::joinCmd(std::vector ¶m, int fd) { + // Check if the param vector is empty, or the first parameter does not start with '#', + // or if the first parameter is just '#' with no other characters. if (param.empty() || param[0][0] != '#' || (param[0][0] == '#' && param[0].size() == 1)) { + // Construct an error message indicating "Not enough parameters" and send it to the client. std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; sendMessage(fd, message); return; } + // Split the first parameter by commas to get the channel names. std::vector chn = split(param[0], ','); std::vector key; + // If there are two parameters, split the second parameter by commas to get the keys. if (param.size() == 2) { key = split(param[1], ','); } + // Loop through each channel name. for (size_t i = 0; i < chn.size(); ++i) { + // Find the channel in the channels map. std::map::iterator it = channels.find(chn[i]); bool channelCreated = (it == channels.end()); + // If the channel doesn't exist, create it and send a join message. if (channelCreated) { setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); JoinMessage(fd, chn[i]); @@ -76,30 +92,37 @@ void Server::joinCmd(std::vector ¶m, int fd) { Channel &channel = it->second; + // Check if the client is already in the channel. if (channel.isClientInChannel(fd) == 1) { std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; sendMessage(fd, message); continue; } + // If the channel is invite-only or has a password, handle those cases. if (channel.getChannelType() == 1) { + // If the channel is invite-only and the client is not invited, send an error message. if (channel.getInvitedList().empty() && param.size() != 2) { std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; sendMessage(fd, message); continue; } + // If the client is invited, add them to the channel and send a join message. if (channel.isClientInvited(fd)) { channel.setClients(fd, _clients[fd].getNickname()); JoinMessage(fd, chn[i]); continue; } + // If the channel has a password, check the provided key. if (channel.getHasPassword() == 1) { + // If the provided key matches the channel password, add the client to the channel. if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { channel.setClients(fd, _clients[fd].getNickname()); JoinMessage(fd, chn[i]); } else { + // If the key doesn't match, send an error message. std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; sendMessage(fd, message); } @@ -107,17 +130,21 @@ void Server::joinCmd(std::vector ¶m, int fd) { } } + // If the channel has a password, check the provided key. if (channel.getHasPassword() == 1) { + // If the provided key matches the channel password, add the client to the channel. if (key.size() > i && channel.getChPassword() == key[i]) { channel.setClients(fd, _clients[fd].getNickname()); JoinMessage(fd, chn[i]); } else { + // If the key doesn't match, send an error message. std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; sendMessage(fd, message); } continue; } + // If none of the above conditions are met, add the client to the channel and send a join message. channel.setClients(fd, _clients[fd].getNickname()); JoinMessage(fd, chn[i]); } From 038971780db510efac9516308c8eaaf96c045ec9 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Tue, 23 Jul 2024 21:16:34 +0100 Subject: [PATCH 27/56] ja2a lfaraj --- Channel.cpp | 5 +- Channel.hpp | 1 - client.cpp | 9 ++- client.hpp | 6 +- cmd.cpp | 169 +++++++++++++++++++++++++++++++++++-------------- irc_server.cpp | 52 +++++++-------- server.hpp | 6 +- 7 files changed, 165 insertions(+), 83 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 3df8921..ce24ddb 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -7,14 +7,15 @@ Channel::Channel() { channelType = 0; hasPassword = 0; } -Channel::Channel(std::string channelName , int chType) { +Channel::Channel(std::string channelName, int chType) { name = channelName; - topic = ""; + topic = "No topic"; // Default topic value chPassword = ""; channelType = chType; hasPassword = 0; } + Channel::Channel(const Channel ©) { name = copy.name; topic = copy.topic; diff --git a/Channel.hpp b/Channel.hpp index 0a1268f..9911629 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -15,7 +15,6 @@ class Channel { std::vector operators; std::string chPassword; std::map inviteList; - // std::map channels; int channelType; int hasPassword; diff --git a/client.cpp b/client.cpp index 4f3a3c8..156673f 100644 --- a/client.cpp +++ b/client.cpp @@ -1,5 +1,7 @@ #include "client.hpp" +std::vector client::fds; +std::vector client::clients; client::client() { @@ -140,7 +142,7 @@ void client::set_registered(bool is_registered) this->is_registered = is_registered; } -pollfd client::get_client_pfd() +pollfd client::get_client_pfd() const { return this->client_pfd; } @@ -191,4 +193,7 @@ void client::clear_massage() void client::set_massage(std::string massage) { this->massage = massage; -} \ No newline at end of file +} + +std::vector& client::get_fds() { return fds; } +std::vector& client::get_clients() { return clients; } \ No newline at end of file diff --git a/client.hpp b/client.hpp index a3eb9bd..e6627ab 100644 --- a/client.hpp +++ b/client.hpp @@ -20,6 +20,8 @@ class client bool is_registered; std::string massage; int index; + static std::vector fds; + static std::vector clients; public : client(); @@ -32,7 +34,7 @@ class client void set_registered(bool is_registered); std::string getNickname() const; std::string getUsername() const; - pollfd get_client_pfd(); + pollfd get_client_pfd() const; void set_client_pfd(pollfd client_pfd); void set_massage_for_auth(std::string massage); void set_massage(std::string massage); @@ -40,6 +42,8 @@ class client void print_client(); std::string get_message(); void clear_massage(); + static std::vector& get_fds(); + static std::vector& get_clients(); }; diff --git a/cmd.cpp b/cmd.cpp index c7e1478..d8761fd 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -25,104 +25,169 @@ std::vector split(std::string line, char c) { } void Server::setupChannel(const std::string &channelName, int fd, const std::string &password) { - Channel newChannel; - newChannel.setName(channelName); - newChannel.setTopic("No topic"); - newChannel.setClients(fd, _clients[fd].getNickname()); - newChannel.setOperators(fd); + if (channels.find(channelName) == channels.end()) { + Channel newChannel(channelName, 0); + channels[channelName] = newChannel; + } else { + // Ensure not to reset the topic if the channel already exists + Channel &channel = channels[channelName]; + if (channel.getTopic() == "No topic") { + channel.setTopic("No topic"); + } + } + // Additional setup code + Channel &channel = channels[channelName]; + channel.setClients(fd, getClientNickname(fd)); if (password.empty()) { - newChannel.setChannelType(0); - newChannel.setHasPassword(0); + channel.setChannelType(0); // Public + channel.setHasPassword(0); } else { - newChannel.setChannelType(1); - newChannel.setHasPassword(1); - newChannel.setChPassword(password); + channel.setChannelType(1); // Password protected + channel.setHasPassword(1); + channel.setChPassword(password); } - channels[channelName] = newChannel; + JoinMessage(fd, channelName); } + + void Server::JoinMessage(int fd, const std::string &channelName) { - std::string message = ":" + getNameId(fd) + " 332 JOIN :" + channels[channelName].getTopic() + "\n"; - sendMessage(fd, message); + if (channels.find(channelName) != channels.end()) { + std::string globmsg = ""; + std::string topic = channels[channelName].getTopic(); // Get topic + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + "127.0.0.1 JOIN " + channelName + " * :realname\r\n"; + globmsg += message; + // :Aurora.AfterNET.Org 353 aet-tass = #test :@aet-tass!aet-tass@88ABE6.25BF1D.D03F86.88C9BD.IP + std::string message2 = ":localhost 353 " + getClientNickname(fd) + " = " + channelName + " :@" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@127.0.0.1\r\n"; + globmsg += message2; + // :Aurora.AfterNET.Org 366 aet-tass #test :End of /NAMES list. + std::string message3 = ":localhost 366 " + getClientNickname(fd) + " " + channelName + " :End of /NAMES list.\r\n"; + globmsg += message3; + // :Aurora.AfterNET.Org 324 aet-tass #test +tn + std::string message4 = ":localhost 324 " + getClientNickname(fd) + " " + channelName + " +tn\r\n"; + globmsg += message4; + // :Aurora.AfterNET.Org 329 aet-tass #test 1721765133 + std::string message5 = ":localhost 329 " + getClientNickname(fd) + " " + channelName + " 1721765133\r\n"; + globmsg += message5; + // :Aurora.AfterNET.Org 354 aet-tass 152 #test aet-tass 88ABE6.25BF1D.D03F86.88C9BD.IP *.afternet.org aet-tass H@x 0 :realnam + std::string message6 = ":localhost 354 " + getClientNickname(fd) + " 152 " + channelName + " " + getClientNickname(fd) + "127.0.0.1 *.localhost " + getClientNickname(fd) + " H@x 0 :realname\r\n"; + globmsg += message6; + // :Aurora.AfterNET.Org 315 aet-tass #test :End of /WHO list. + std::string message7 = ":localhost 315 " + getClientNickname(fd) + " " + channelName + " :End of /WHO list.\r\n"; + globmsg += message7; + + + + // std::string message = ":" + getNameId(fd) + " 332 JOIN " + channelName + " :" + topic + "\n"; + sendMessage(fd, globmsg); + } else { + std::string globmsg = ":" + getNameId(fd) + " 403 " + channelName + " :No such channel\n"; + sendMessage(fd, globmsg); + } } + + std::string Server::getNameId(int fd) { - std::map::iterator it = _clients.find(fd); - if (it != _clients.end()) { - return it->second.getNickname(); + std::vector& clients = client::get_clients(); + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { + if (it->get_client_pfd().fd == fd) { + return it->getNickname(); + } } std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; sendMessage(fd, message); return "ERROR"; } +class IsClientWithFd { +public: + IsClientWithFd(int fd) : fd_(fd) {} + bool operator()(const client& c) const { + return c.get_client_pfd().fd == fd_; + } +private: + int fd_; +}; void Server::joinCmd(std::vector ¶m, int fd) { - // Check if the param vector is empty, or the first parameter does not start with '#', - // or if the first parameter is just '#' with no other characters. - if (param.empty() || param[0][0] != '#' || (param[0][0] == '#' && param[0].size() == 1)) { - // Construct an error message indicating "Not enough parameters" and send it to the client. + // Debugging output for received parameters + std::cout << "Received /join command with parameters: "; + for (size_t i = 0; i < param.size(); ++i) { + std::cout << param[i] << " "; + } + std::cout << std::endl; + + // Check if the param vector is empty or invalid + if (param.empty() || param[0][0] != '#' || (param[0].size() == 1)) { std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; sendMessage(fd, message); + std::cout << "Error: Not enough parameters or invalid channel name." << std::endl; return; } - // Split the first parameter by commas to get the channel names. + // Split the parameters std::vector chn = split(param[0], ','); std::vector key; - // If there are two parameters, split the second parameter by commas to get the keys. if (param.size() == 2) { key = split(param[1], ','); } - // Loop through each channel name. + std::cout << "Channel names to join: "; + for (size_t i = 0; i < chn.size(); ++i) { + std::cout << chn[i] << " "; + } + std::cout << std::endl; + + std::cout << "Keys provided: "; + for (size_t i = 0; i < key.size(); ++i) { + std::cout << key[i] << " "; + } + std::cout << std::endl; + + // Loop through each channel name for (size_t i = 0; i < chn.size(); ++i) { - // Find the channel in the channels map. std::map::iterator it = channels.find(chn[i]); bool channelCreated = (it == channels.end()); - // If the channel doesn't exist, create it and send a join message. + // If channel doesn't exist, create it if (channelCreated) { setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); - JoinMessage(fd, chn[i]); + + // JoinMessage(fd, chn[i]); continue; } Channel &channel = it->second; - // Check if the client is already in the channel. - if (channel.isClientInChannel(fd) == 1) { + // Check if client is already in the channel + if (channel.isClientInChannel(fd)) { std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; sendMessage(fd, message); continue; } - // If the channel is invite-only or has a password, handle those cases. + // Handle invite-only or password-protected channels if (channel.getChannelType() == 1) { - // If the channel is invite-only and the client is not invited, send an error message. if (channel.getInvitedList().empty() && param.size() != 2) { std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; sendMessage(fd, message); continue; } - // If the client is invited, add them to the channel and send a join message. if (channel.isClientInvited(fd)) { - channel.setClients(fd, _clients[fd].getNickname()); + channel.setClients(fd, getClientNickname(fd)); JoinMessage(fd, chn[i]); continue; } - // If the channel has a password, check the provided key. if (channel.getHasPassword() == 1) { - // If the provided key matches the channel password, add the client to the channel. if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { - channel.setClients(fd, _clients[fd].getNickname()); + channel.setClients(fd, getClientNickname(fd)); JoinMessage(fd, chn[i]); } else { - // If the key doesn't match, send an error message. std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; sendMessage(fd, message); } @@ -130,28 +195,40 @@ void Server::joinCmd(std::vector ¶m, int fd) { } } - // If the channel has a password, check the provided key. + // Handle password for existing channels if (channel.getHasPassword() == 1) { - // If the provided key matches the channel password, add the client to the channel. if (key.size() > i && channel.getChPassword() == key[i]) { - channel.setClients(fd, _clients[fd].getNickname()); + channel.setClients(fd, getClientNickname(fd)); JoinMessage(fd, chn[i]); } else { - // If the key doesn't match, send an error message. std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; sendMessage(fd, message); } continue; } - // If none of the above conditions are met, add the client to the channel and send a join message. - channel.setClients(fd, _clients[fd].getNickname()); + // Add the client to the channel and send a join message + channel.setClients(fd, getClientNickname(fd)); JoinMessage(fd, chn[i]); } } + + +std::string Server::getClientNickname(int fd) { + std::vector& clients = client::get_clients(); + std::vector::iterator it = std::find_if(clients.begin(), clients.end(), IsClientWithFd(fd)); + return (it != clients.end()) ? it->getNickname() : "Unknown"; +} + +std::string Server::getClientMessage(int fd) { + std::vector& clients = client::get_clients(); + std::vector::iterator it = std::find_if(clients.begin(), clients.end(), IsClientWithFd(fd)); + return (it != clients.end()) ? it->get_message() : ""; +} + void Server::command(int fd) { - std::string line = _clients[fd].get_message(); + std::string line = getClientMessage(fd); std::istringstream stream(line); std::string command; std::vector res; @@ -164,10 +241,10 @@ void Server::command(int fd) { res.push_back(arg); } - if (command == "join") { + if (command.compare("join") == 0) { joinCmd(res, fd); } else { - std::string msg = "421 " + _clients[fd].getNickname() + " " + command + " :Unknown command\n"; + std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); } -} \ No newline at end of file +} diff --git a/irc_server.cpp b/irc_server.cpp index 278e4b1..315d96e 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -5,7 +5,7 @@ int main(int argc, char *argv[]) { - if(argc != 3) + if (argc != 3) { std::cout << "Usage: ./irc_server " << std::endl; return (1); @@ -16,24 +16,21 @@ int main(int argc, char *argv[]) irc_server.bind_socket(); irc_server.listen_socket(); - std::vector fds; - std::vector clients; - - fds = irc_server.get_fds(); + client::get_fds() = irc_server.get_fds(); while (1) { - int r = poll(&fds[0], fds.size(), -1); + int r = poll(&client::get_fds()[0], client::get_fds().size(), -1); if (r == -1) { std::cout << "error in poll function" << std::endl; } unsigned int i = 0; - while ( i < fds.size()) + while (i < client::get_fds().size()) { - if (fds[i].revents & POLLIN) + if (client::get_fds()[i].revents & POLLIN) { - if (fds[i].fd == irc_server.get_sockfd()) + if (client::get_fds()[i].fd == irc_server.get_sockfd()) { // New client sockaddr_in clientaddr; @@ -51,46 +48,43 @@ int main(int argc, char *argv[]) client_pfd.fd = clientfd; client_pfd.events = POLLIN; - fds.push_back(client_pfd); + client::get_fds().push_back(client_pfd); - clients.push_back(client(client_pfd, argv[2])); + client::get_clients().push_back(client(client_pfd, argv[2])); } } else { char buffer[1024]; - int r = recv(fds[i].fd, buffer, sizeof(buffer), 0); + int r = recv(client::get_fds()[i].fd, buffer, sizeof(buffer), 0); if (r > 0) { buffer[r] = '\0'; // std::cout << buffer; unsigned int l = 0; - while (l < clients.size()) + while (l < client::get_clients().size()) { - if ((clients[l].get_client_pfd().fd == fds[i].fd)) + if (client::get_clients()[l].get_client_pfd().fd == client::get_fds()[i].fd) { - if (clients[l].set_authenticated() == true) + if (client::get_clients()[l].set_authenticated() == true) { - clients[l].set_massage(buffer); - // work will bw done here - irc_server.command(fds[i].fd); - - std::cout << "we are reciving message from authenticated client : " << clients[l].get_message() << std::endl; + client::get_clients()[l].set_massage(buffer); + // work will be done here + irc_server.command(client::get_fds()[i].fd); - - } + std::cout << "we are receiving message from authenticated client: " << client::get_clients()[l].get_message() << std::endl; + } else { - clients[l].set_massage_for_auth(buffer); - // std::cout << clients[l].get_client_pfd().fd << " is not authenticated" << std::endl; - if (clients[l].set_authenticated() == true) + client::get_clients()[l].set_massage_for_auth(buffer); + // std::cout << client::get_clients()[l].get_client_pfd().fd << " is not authenticated" << std::endl; + if (client::get_clients()[l].set_authenticated() == true) { std::cout << "now is authenticated" << std::endl; - clients[l].clear_massage(); - std::cout << clients[l].get_message() << std::endl; + client::get_clients()[l].clear_massage(); + std::cout << client::get_clients()[l].get_message() << std::endl; } - } } l++; @@ -102,4 +96,4 @@ int main(int argc, char *argv[]) } } return (0); -} \ No newline at end of file +} diff --git a/server.hpp b/server.hpp index d436afe..60fb1b1 100644 --- a/server.hpp +++ b/server.hpp @@ -18,8 +18,8 @@ class Server int sockfd; struct addrinfo hints, *server; std::vector fds; - std::map channels; - std::map _clients; + std::map channels; + // std::map _clients; public : Server(std::string ip, std::string port); @@ -36,6 +36,8 @@ class Server void setupChannel(const std::string &channelName, int fd, const std::string &password); void JoinMessage(int fd, const std::string &channelName); void command(int fd); + std::string getClientMessage(int fd); + std::string getClientNickname(int fd); }; From 4df1d37e1a0fb082f124f36535097db3a505e8cb Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Tue, 23 Jul 2024 22:01:15 +0100 Subject: [PATCH 28/56] join is ready just fix unkown command --- cmd.cpp | 43 +++++++++++++------------------------------ 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/cmd.cpp b/cmd.cpp index d8761fd..88dc769 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -47,41 +47,26 @@ void Server::setupChannel(const std::string &channelName, int fd, const std::str channel.setHasPassword(1); channel.setChPassword(password); } - - JoinMessage(fd, channelName); } - - - void Server::JoinMessage(int fd, const std::string &channelName) { if (channels.find(channelName) != channels.end()) { std::string globmsg = ""; std::string topic = channels[channelName].getTopic(); // Get topic std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + "127.0.0.1 JOIN " + channelName + " * :realname\r\n"; globmsg += message; - // :Aurora.AfterNET.Org 353 aet-tass = #test :@aet-tass!aet-tass@88ABE6.25BF1D.D03F86.88C9BD.IP - std::string message2 = ":localhost 353 " + getClientNickname(fd) + " = " + channelName + " :@" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@127.0.0.1\r\n"; + std::string message2 = ":localhost 353 " + getClientNickname(fd) + " = " + channelName + " :@" + getClientNickname(fd) + "\r\n"; globmsg += message2; - // :Aurora.AfterNET.Org 366 aet-tass #test :End of /NAMES list. std::string message3 = ":localhost 366 " + getClientNickname(fd) + " " + channelName + " :End of /NAMES list.\r\n"; globmsg += message3; - // :Aurora.AfterNET.Org 324 aet-tass #test +tn - std::string message4 = ":localhost 324 " + getClientNickname(fd) + " " + channelName + " +tn\r\n"; - globmsg += message4; - // :Aurora.AfterNET.Org 329 aet-tass #test 1721765133 - std::string message5 = ":localhost 329 " + getClientNickname(fd) + " " + channelName + " 1721765133\r\n"; - globmsg += message5; - // :Aurora.AfterNET.Org 354 aet-tass 152 #test aet-tass 88ABE6.25BF1D.D03F86.88C9BD.IP *.afternet.org aet-tass H@x 0 :realnam - std::string message6 = ":localhost 354 " + getClientNickname(fd) + " 152 " + channelName + " " + getClientNickname(fd) + "127.0.0.1 *.localhost " + getClientNickname(fd) + " H@x 0 :realname\r\n"; - globmsg += message6; - // :Aurora.AfterNET.Org 315 aet-tass #test :End of /WHO list. - std::string message7 = ":localhost 315 " + getClientNickname(fd) + " " + channelName + " :End of /WHO list.\r\n"; - globmsg += message7; - - - - // std::string message = ":" + getNameId(fd) + " 332 JOIN " + channelName + " :" + topic + "\n"; + // std::string message4 = ":localhost 324 " + getClientNickname(fd) + " " + channelName + " +tn\r\n"; + // globmsg += message4; + // std::string message5 = ":localhost 329 " + getClientNickname(fd) + " " + channelName + " 1721765133\r\n"; + // globmsg += message5; + // std::string message6 = ":localhost 354 " + getClientNickname(fd) + " 152 " + channelName + " " + getClientNickname(fd) + "127.0.0.1 *.localhost " + getClientNickname(fd) + " H@x 0 :realname\r\n"; + // globmsg += message6; + // std::string message7 = ":localhost 315 " + getClientNickname(fd) + " " + channelName + " :End of /WHO list.\r\n"; + // globmsg += message7; sendMessage(fd, globmsg); } else { std::string globmsg = ":" + getNameId(fd) + " 403 " + channelName + " :No such channel\n"; @@ -89,8 +74,6 @@ void Server::JoinMessage(int fd, const std::string &channelName) { } } - - std::string Server::getNameId(int fd) { std::vector& clients = client::get_clients(); for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { @@ -112,6 +95,7 @@ class IsClientWithFd { private: int fd_; }; + void Server::joinCmd(std::vector ¶m, int fd) { // Debugging output for received parameters std::cout << "Received /join command with parameters: "; @@ -155,8 +139,7 @@ void Server::joinCmd(std::vector ¶m, int fd) { // If channel doesn't exist, create it if (channelCreated) { setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); - - // JoinMessage(fd, chn[i]); + JoinMessage(fd, chn[i]); continue; } @@ -213,8 +196,6 @@ void Server::joinCmd(std::vector ¶m, int fd) { } } - - std::string Server::getClientNickname(int fd) { std::vector& clients = client::get_clients(); std::vector::iterator it = std::find_if(clients.begin(), clients.end(), IsClientWithFd(fd)); @@ -241,6 +222,8 @@ void Server::command(int fd) { res.push_back(arg); } + checkCommand(command, res, fd); + if (command.compare("join") == 0) { joinCmd(res, fd); } else { From 2a387cd81a27179763907a864d50074274565170 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Tue, 23 Jul 2024 22:01:54 +0100 Subject: [PATCH 29/56] join is ready just fix unkown command . --- cmd.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd.cpp b/cmd.cpp index 88dc769..ed8e9df 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -222,8 +222,6 @@ void Server::command(int fd) { res.push_back(arg); } - checkCommand(command, res, fd); - if (command.compare("join") == 0) { joinCmd(res, fd); } else { From 7e8f738879b2f07095bbb951210d973822ffc6df Mon Sep 17 00:00:00 2001 From: mbelouar Date: Tue, 23 Jul 2024 23:24:33 +0100 Subject: [PATCH 30/56] Spliting the joinCmd and starting the kickCmd --- Channel.cpp | 2 +- Channel.hpp | 2 - Makefile | 38 ++++++--- cmd.cpp | 223 +++++----------------------------------------------- joinCmd.cpp | 148 ++++++++++++++++++++++++++++++++++ server.cpp | 25 ++++++ server.hpp | 20 +++-- utils.cpp | 18 +++++ utils.hpp | 11 +++ 9 files changed, 261 insertions(+), 226 deletions(-) create mode 100644 joinCmd.cpp create mode 100644 utils.cpp create mode 100644 utils.hpp diff --git a/Channel.cpp b/Channel.cpp index ce24ddb..92d9ef8 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -153,4 +153,4 @@ size_t Channel::getClientNb() const { bool Channel::isClientInvited(int clientId) const{ bool isInvited = (inviteList.count(clientId) > 0); return isInvited; -} \ No newline at end of file +} diff --git a/Channel.hpp b/Channel.hpp index 9911629..24d9039 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -53,8 +53,6 @@ class Channel { const std::map &getClientsFromChannel() const; - - }; diff --git a/Makefile b/Makefile index 654c8cc..727fb07 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,34 @@ -NAME=FT_IRC +# Colors +WHITE = \033[1;37m +RED = \033[1;31m +GREEN = \033[1;32m +YELLOW = \033[1;33m +RESET = \033[0m -CC = c++ -FLAGS = -Wall -Wextra -Werror -std=c++98 -SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp -OBJ = $(SRC:.cpp=.o) +NAME = ircserv # Change this to your desired executable name +CC = c++ # Change this if your compiler is not g++ +CFLAGS = -Wall -Wextra -Werror -std=c++98 +SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp # Add all source files here +OBJ = ${SRC:.cpp=.o} -all: $(NAME) +all: ${NAME} -$(NAME): $(OBJ) - $(CC) $(FLAGS) $(OBJ) -o $(NAME) +${OBJ}: %.o: %.cpp + @${CC} ${CFLAGS} -c $< -o $@ -%.o: %.cpp - $(CC) $(FLAGS) -c $< -o $@ +${NAME}: ${OBJ} + @echo "$(YELLOW)Compiling $(NAME)...⏳$(RESET)" + @${CC} ${CFLAGS} -o ${NAME} ${OBJ} + @echo "$(GREEN)Compilation completed ✅$(RESET)" clean: - rm -f $(OBJ) + @${RM} ${OBJ} + @echo "$(RED)Obj_files removed.$(RESET)" fclean: clean - rm -f $(NAME) + @${RM} ${NAME} + @echo "$(RED)Executable removed.$(RESET)" -re: fclean all \ No newline at end of file +re: fclean all + +.PHONY: all clean fclean re diff --git a/cmd.cpp b/cmd.cpp index ed8e9df..f4ce71e 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -1,213 +1,13 @@ #include "server.hpp" #include "Channel.hpp" #include "client.hpp" +#include "utils.hpp" #include #include #include #include #include -void sendMessage(int fd, const std::string& msg) { - if (send(fd, msg.c_str(), msg.size(), 0) == -1) { - throw std::runtime_error("error: send() failed"); - } -} - -std::vector split(std::string line, char c) { - std::vector vec; - size_t pos; - while ((pos = line.find(c)) != std::string::npos) { - vec.push_back(line.substr(0, pos)); - line.erase(0, pos + 1); - } - vec.push_back(line); - return vec; -} - -void Server::setupChannel(const std::string &channelName, int fd, const std::string &password) { - if (channels.find(channelName) == channels.end()) { - Channel newChannel(channelName, 0); - channels[channelName] = newChannel; - } else { - // Ensure not to reset the topic if the channel already exists - Channel &channel = channels[channelName]; - if (channel.getTopic() == "No topic") { - channel.setTopic("No topic"); - } - } - - // Additional setup code - Channel &channel = channels[channelName]; - channel.setClients(fd, getClientNickname(fd)); - if (password.empty()) { - channel.setChannelType(0); // Public - channel.setHasPassword(0); - } else { - channel.setChannelType(1); // Password protected - channel.setHasPassword(1); - channel.setChPassword(password); - } -} - -void Server::JoinMessage(int fd, const std::string &channelName) { - if (channels.find(channelName) != channels.end()) { - std::string globmsg = ""; - std::string topic = channels[channelName].getTopic(); // Get topic - std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + "127.0.0.1 JOIN " + channelName + " * :realname\r\n"; - globmsg += message; - std::string message2 = ":localhost 353 " + getClientNickname(fd) + " = " + channelName + " :@" + getClientNickname(fd) + "\r\n"; - globmsg += message2; - std::string message3 = ":localhost 366 " + getClientNickname(fd) + " " + channelName + " :End of /NAMES list.\r\n"; - globmsg += message3; - // std::string message4 = ":localhost 324 " + getClientNickname(fd) + " " + channelName + " +tn\r\n"; - // globmsg += message4; - // std::string message5 = ":localhost 329 " + getClientNickname(fd) + " " + channelName + " 1721765133\r\n"; - // globmsg += message5; - // std::string message6 = ":localhost 354 " + getClientNickname(fd) + " 152 " + channelName + " " + getClientNickname(fd) + "127.0.0.1 *.localhost " + getClientNickname(fd) + " H@x 0 :realname\r\n"; - // globmsg += message6; - // std::string message7 = ":localhost 315 " + getClientNickname(fd) + " " + channelName + " :End of /WHO list.\r\n"; - // globmsg += message7; - sendMessage(fd, globmsg); - } else { - std::string globmsg = ":" + getNameId(fd) + " 403 " + channelName + " :No such channel\n"; - sendMessage(fd, globmsg); - } -} - -std::string Server::getNameId(int fd) { - std::vector& clients = client::get_clients(); - for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { - if (it->get_client_pfd().fd == fd) { - return it->getNickname(); - } - } - std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; - sendMessage(fd, message); - return "ERROR"; -} - -class IsClientWithFd { -public: - IsClientWithFd(int fd) : fd_(fd) {} - bool operator()(const client& c) const { - return c.get_client_pfd().fd == fd_; - } -private: - int fd_; -}; - -void Server::joinCmd(std::vector ¶m, int fd) { - // Debugging output for received parameters - std::cout << "Received /join command with parameters: "; - for (size_t i = 0; i < param.size(); ++i) { - std::cout << param[i] << " "; - } - std::cout << std::endl; - - // Check if the param vector is empty or invalid - if (param.empty() || param[0][0] != '#' || (param[0].size() == 1)) { - std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; - sendMessage(fd, message); - std::cout << "Error: Not enough parameters or invalid channel name." << std::endl; - return; - } - - // Split the parameters - std::vector chn = split(param[0], ','); - std::vector key; - if (param.size() == 2) { - key = split(param[1], ','); - } - - std::cout << "Channel names to join: "; - for (size_t i = 0; i < chn.size(); ++i) { - std::cout << chn[i] << " "; - } - std::cout << std::endl; - - std::cout << "Keys provided: "; - for (size_t i = 0; i < key.size(); ++i) { - std::cout << key[i] << " "; - } - std::cout << std::endl; - - // Loop through each channel name - for (size_t i = 0; i < chn.size(); ++i) { - std::map::iterator it = channels.find(chn[i]); - bool channelCreated = (it == channels.end()); - - // If channel doesn't exist, create it - if (channelCreated) { - setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); - JoinMessage(fd, chn[i]); - continue; - } - - Channel &channel = it->second; - - // Check if client is already in the channel - if (channel.isClientInChannel(fd)) { - std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; - sendMessage(fd, message); - continue; - } - - // Handle invite-only or password-protected channels - if (channel.getChannelType() == 1) { - if (channel.getInvitedList().empty() && param.size() != 2) { - std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; - sendMessage(fd, message); - continue; - } - - if (channel.isClientInvited(fd)) { - channel.setClients(fd, getClientNickname(fd)); - JoinMessage(fd, chn[i]); - continue; - } - - if (channel.getHasPassword() == 1) { - if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { - channel.setClients(fd, getClientNickname(fd)); - JoinMessage(fd, chn[i]); - } else { - std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; - sendMessage(fd, message); - } - continue; - } - } - - // Handle password for existing channels - if (channel.getHasPassword() == 1) { - if (key.size() > i && channel.getChPassword() == key[i]) { - channel.setClients(fd, getClientNickname(fd)); - JoinMessage(fd, chn[i]); - } else { - std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; - sendMessage(fd, message); - } - continue; - } - - // Add the client to the channel and send a join message - channel.setClients(fd, getClientNickname(fd)); - JoinMessage(fd, chn[i]); - } -} - -std::string Server::getClientNickname(int fd) { - std::vector& clients = client::get_clients(); - std::vector::iterator it = std::find_if(clients.begin(), clients.end(), IsClientWithFd(fd)); - return (it != clients.end()) ? it->getNickname() : "Unknown"; -} - -std::string Server::getClientMessage(int fd) { - std::vector& clients = client::get_clients(); - std::vector::iterator it = std::find_if(clients.begin(), clients.end(), IsClientWithFd(fd)); - return (it != clients.end()) ? it->get_message() : ""; -} - void Server::command(int fd) { std::string line = getClientMessage(fd); std::istringstream stream(line); @@ -221,10 +21,25 @@ void Server::command(int fd) { while (stream >> arg) { res.push_back(arg); } - - if (command.compare("join") == 0) { + if (command.compare("join") == 0) joinCmd(res, fd); - } else { + else if (command.compare("kick") == 0) + kickCmd(res, fd); + else if (command.compare("list") == 0) + listCmd(res, fd); + else if (command.compare("part") == 0) + partCmd(res, fd); + else if (command.compare("privmsg") == 0) + privmsgCmd(res, fd); + else if (command.compare("users") == 0) + usersCmd(res, fd); + else if (command.compare("nick") == 0) + nickCmd(res, fd); + else if (command.compare("quit") == 0) + quitCmd(res, fd); + else if (command.compare("topic") == 0) + topicCmd(res, fd); + else { std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); } diff --git a/joinCmd.cpp b/joinCmd.cpp new file mode 100644 index 0000000..081763c --- /dev/null +++ b/joinCmd.cpp @@ -0,0 +1,148 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::setupChannel(const std::string &channelName, int fd, const std::string &password) { + if (channels.find(channelName) == channels.end()) { + Channel newChannel(channelName, 0); + channels[channelName] = newChannel; + } else { + // Ensure not to reset the topic if the channel already exists + Channel &channel = channels[channelName]; + if (channel.getTopic() == "No topic") { + channel.setTopic("No topic"); + } + } + + // Additional setup code + Channel &channel = channels[channelName]; + channel.setClients(fd, getClientNickname(fd)); + if (password.empty()) { + channel.setChannelType(0); // Public + channel.setHasPassword(0); + } else { + channel.setChannelType(1); // Password protected + channel.setHasPassword(1); + channel.setChPassword(password); + } +} + +void Server::JoinMessage(int fd, const std::string &channelName) { + if (channels.find(channelName) != channels.end()) { + std::string globmsg = ""; + std::string topic = channels[channelName].getTopic(); // Get topic + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + "127.0.0.1 JOIN " + channelName + " * :realname\r\n"; + globmsg += message; + std::string message2 = ":localhost 353 " + getClientNickname(fd) + " = " + channelName + " :@" + getClientNickname(fd) + "\r\n"; + globmsg += message2; + std::string message3 = ":localhost 366 " + getClientNickname(fd) + " " + channelName + " :End of /NAMES list.\r\n"; + globmsg += message3; + sendMessage(fd, globmsg); + } else { + std::string globmsg = ":" + getNameId(fd) + " 403 " + channelName + " :No such channel\n"; + sendMessage(fd, globmsg); + } +} + +void Server::joinCmd(std::vector ¶m, int fd) { + // Debugging output for received parameters + std::cout << "Received /join command with parameters: "; + for (size_t i = 0; i < param.size(); ++i) { + std::cout << param[i] << " "; + } + std::cout << std::endl; + + // Check if the param vector is empty or invalid + if (param.empty() || param[0][0] != '#' || (param[0].size() == 1)) { + std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; + sendMessage(fd, message); + std::cout << "Error: Not enough parameters or invalid channel name." << std::endl; + return; + } + + // Split the parameters + std::vector chn = split(param[0], ','); + std::vector key; + if (param.size() == 2) { + key = split(param[1], ','); + } + + std::cout << "Channel names to join: "; + for (size_t i = 0; i < chn.size(); ++i) { + std::cout << chn[i] << " "; + } + std::cout << std::endl; + + std::cout << "Keys provided: "; + for (size_t i = 0; i < key.size(); ++i) { + std::cout << key[i] << " "; + } + std::cout << std::endl; + + // Loop through each channel name + for (size_t i = 0; i < chn.size(); ++i) { + std::map::iterator it = channels.find(chn[i]); + bool channelCreated = (it == channels.end()); + + // If channel doesn't exist, create it + if (channelCreated) { + setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); + JoinMessage(fd, chn[i]); + continue; + } + + Channel &channel = it->second; + + // Check if client is already in the channel + if (channel.isClientInChannel(fd)) { + std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; + sendMessage(fd, message); + continue; + } + + // Handle invite-only or password-protected channels + if (channel.getChannelType() == 1) { + if (channel.getInvitedList().empty() && param.size() != 2) { + std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; + sendMessage(fd, message); + continue; + } + + if (channel.isClientInvited(fd)) { + channel.setClients(fd, getClientNickname(fd)); + JoinMessage(fd, chn[i]); + continue; + } + + if (channel.getHasPassword() == 1) { + if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { + channel.setClients(fd, getClientNickname(fd)); + JoinMessage(fd, chn[i]); + } else { + std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; + sendMessage(fd, message); + } + continue; + } + } + + // Handle password for existing channels + if (channel.getHasPassword() == 1) { + if (key.size() > i && channel.getChPassword() == key[i]) { + channel.setClients(fd, getClientNickname(fd)); + JoinMessage(fd, chn[i]); + } else { + std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; + sendMessage(fd, message); + } + continue; + } + + // Add the client to the channel and send a join message + channel.setClients(fd, getClientNickname(fd)); + JoinMessage(fd, chn[i]); + } +} \ No newline at end of file diff --git a/server.cpp b/server.cpp index 1c349ab..048bd38 100644 --- a/server.cpp +++ b/server.cpp @@ -1,4 +1,5 @@ #include "server.hpp" +#include "utils.hpp" Server::Server(std::string ip, std::string port) { @@ -69,4 +70,28 @@ int Server::get_sockfd() std::vector Server::get_fds() { return this->fds; +} + +std::string Server::getClientNickname(int fd) { + std::vector& clients = client::get_clients(); + std::vector::iterator it = std::find_if(clients.begin(), clients.end(), IsClientWithFd(fd)); + return (it != clients.end()) ? it->getNickname() : "Unknown"; +} + +std::string Server::getClientMessage(int fd) { + std::vector& clients = client::get_clients(); + std::vector::iterator it = std::find_if(clients.begin(), clients.end(), IsClientWithFd(fd)); + return (it != clients.end()) ? it->get_message() : ""; +} + +std::string Server::getNameId(int fd) { + std::vector& clients = client::get_clients(); + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { + if (it->get_client_pfd().fd == fd) { + return it->getNickname(); + } + } + std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; + sendMessage(fd, message); + return "ERROR"; } \ No newline at end of file diff --git a/server.hpp b/server.hpp index 60fb1b1..e8b5508 100644 --- a/server.hpp +++ b/server.hpp @@ -33,12 +33,20 @@ class Server void joinCmd(std::vector ¶m, int fd); std::string getNameId(int fd); void joinMessage(int fd, const std::string &channelName); - void setupChannel(const std::string &channelName, int fd, const std::string &password); - void JoinMessage(int fd, const std::string &channelName); - void command(int fd); - std::string getClientMessage(int fd); - std::string getClientNickname(int fd); + void setupChannel(const std::string &channelName, int fd, const std::string &password); + void JoinMessage(int fd, const std::string &channelName); + void command(int fd); + std::string getClientMessage(int fd); + std::string getClientNickname(int fd); - + class IsClientWithFd { + public: + IsClientWithFd(int fd) : fd_(fd) {} + bool operator()(const client& c) const { + return c.get_client_pfd().fd == fd_; + } + private: + int fd_; + }; }; #endif \ No newline at end of file diff --git a/utils.cpp b/utils.cpp new file mode 100644 index 0000000..62f41d1 --- /dev/null +++ b/utils.cpp @@ -0,0 +1,18 @@ +#include "utils.hpp" + +void sendMessage(int fd, const std::string& message) { + if (send(fd, message.c_str(), message.size(), 0) == -1) { + perror("send"); + } +} + +std::vector split(std::string line, char c) { + std::vector vec; + size_t pos; + while ((pos = line.find(c)) != std::string::npos) { + vec.push_back(line.substr(0, pos)); + line.erase(0, pos + 1); + } + vec.push_back(line); + return vec; +} \ No newline at end of file diff --git a/utils.hpp b/utils.hpp new file mode 100644 index 0000000..d056f4d --- /dev/null +++ b/utils.hpp @@ -0,0 +1,11 @@ +#ifndef UTILS_HPP +#define UTILS_HPP + +#include +#include +#include + +void sendMessage(int fd, const std::string& message); +std::vector split(std::string line, char c); + +#endif // UTILS_HPP \ No newline at end of file From 1d23a318f4c190bfa4bbaea9ae089fcf69f50765 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Wed, 24 Jul 2024 02:05:44 +0100 Subject: [PATCH 31/56] KICK is DONE still just some additional settings --- Channel.cpp | 4 ++++ Channel.hpp | 2 ++ Makefile | 2 +- cmd.cpp | 18 ++++----------- kickCmd.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++ server.hpp | 1 + 6 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 kickCmd.cpp diff --git a/Channel.cpp b/Channel.cpp index 92d9ef8..f2e006d 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -154,3 +154,7 @@ bool Channel::isClientInvited(int clientId) const{ bool isInvited = (inviteList.count(clientId) > 0); return isInvited; } + +void Channel::removeClient(int fd) { + clients.erase(fd); +} \ No newline at end of file diff --git a/Channel.hpp b/Channel.hpp index 24d9039..cd7c9e1 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -53,6 +53,8 @@ class Channel { const std::map &getClientsFromChannel() const; + void removeClient(int fd); + }; diff --git a/Makefile b/Makefile index 727fb07..d0aef56 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ RESET = \033[0m NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 -SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp # Add all source files here +SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp # Add all source files here OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/cmd.cpp b/cmd.cpp index f4ce71e..ee0e826 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -25,20 +25,10 @@ void Server::command(int fd) { joinCmd(res, fd); else if (command.compare("kick") == 0) kickCmd(res, fd); - else if (command.compare("list") == 0) - listCmd(res, fd); - else if (command.compare("part") == 0) - partCmd(res, fd); - else if (command.compare("privmsg") == 0) - privmsgCmd(res, fd); - else if (command.compare("users") == 0) - usersCmd(res, fd); - else if (command.compare("nick") == 0) - nickCmd(res, fd); - else if (command.compare("quit") == 0) - quitCmd(res, fd); - else if (command.compare("topic") == 0) - topicCmd(res, fd); + // else if (command.compare("privmsg") == 0) + // privmsgCmd(res, fd); + // else if (command.compare("topic") == 0) + // topicCmd(res, fd); else { std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); diff --git a/kickCmd.cpp b/kickCmd.cpp new file mode 100644 index 0000000..fab3195 --- /dev/null +++ b/kickCmd.cpp @@ -0,0 +1,65 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::kickCmd(std::vector& args, int fd) { + if (args.size() <= 2) { + std::string msg = "461 " + getClientNickname(fd) + " KICK :Not enough parameters\n"; + sendMessage(fd, msg); + return; + } + + const std::string& channelName = args[1]; + std::string userToKick = args[2]; + if (userToKick[0] == ':') { + userToKick = userToKick.substr(1); + } + + std::map::iterator it = channels.find(channelName); + if (it == channels.end()) { + std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; + sendMessage(fd, msg); + return; + } + + Channel& channel = it->second; + int fdToKick = channel.getClientID(userToKick); + if (fdToKick == -1) { + std::string msg = "401 " + getClientNickname(fd) + " " + userToKick + " :No such nick/channel\n"; + sendMessage(fd, msg); + return; + } + + if (!channel.isClientInChannel(fdToKick)) { + std::string msg = "441 " + getClientNickname(fd) + " " + userToKick + " " + channelName + " :They aren't on that channel\n"; + sendMessage(fd, msg); + return; + } + else { + std::cout << "Kicking user \"" << userToKick << "\" is on the channel \"" << channelName + "\"" << std::endl; + } + + + // std::cout << "Channel '" << it->first << "' BEFORE kick:" << std::endl; + // const std::map& clientsBeforeKick = it->second.getClientsFromChannel(); + // std::map::const_iterator itClientBefore; + // for (itClientBefore = clientsBeforeKick.begin(); itClientBefore != clientsBeforeKick.end(); ++itClientBefore) { + // std::cout << "Client ID: " << itClientBefore->first << ", Nickname: " << itClientBefore->second.getNickname() << std::endl; + // } + + channel.removeClient(fdToKick); + + // std::cout << "Channel '" << it->first << "' AFTER kick:" << std::endl; + // const std::map& clientsAfterKick = it->second.getClientsFromChannel(); + // std::map::const_iterator itClientAfter; + // for (itClientAfter = clientsAfterKick.begin(); itClientAfter != clientsAfterKick.end(); ++itClientAfter) { + // std::cout << "Client ID: " << itClientAfter->first << ", Nickname: " << itClientAfter->second.getNickname() << std::endl; + // } + + + std::string msg = ":" + getClientNickname(fd) + " KICK " + channelName + " " + userToKick + " :Kicked by " + getClientNickname(fd) + "\n"; + sendMessage(fd, msg); +} \ No newline at end of file diff --git a/server.hpp b/server.hpp index e8b5508..43b853d 100644 --- a/server.hpp +++ b/server.hpp @@ -31,6 +31,7 @@ class Server ~Server(); void joinCmd(std::vector ¶m, int fd); + void kickCmd(std::vector ¶m, int fd); std::string getNameId(int fd); void joinMessage(int fd, const std::string &channelName); void setupChannel(const std::string &channelName, int fd, const std::string &password); From f3ffc95076663e58074398203e4651492ce630fb Mon Sep 17 00:00:00 2001 From: mbelouar Date: Wed, 24 Jul 2024 02:51:30 +0100 Subject: [PATCH 32/56] start coding the topicCmd --- Makefile | 2 +- cmd.cpp | 4 ++-- server.hpp | 1 + topicCmd.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 topicCmd.cpp diff --git a/Makefile b/Makefile index d0aef56..1457cde 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ RESET = \033[0m NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 -SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp # Add all source files here +SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp # Add all source files here OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/cmd.cpp b/cmd.cpp index ee0e826..141194b 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -25,10 +25,10 @@ void Server::command(int fd) { joinCmd(res, fd); else if (command.compare("kick") == 0) kickCmd(res, fd); + else if (command.compare("topic") == 0) + topicCmd(res, fd); // else if (command.compare("privmsg") == 0) // privmsgCmd(res, fd); - // else if (command.compare("topic") == 0) - // topicCmd(res, fd); else { std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); diff --git a/server.hpp b/server.hpp index 43b853d..6d51d37 100644 --- a/server.hpp +++ b/server.hpp @@ -32,6 +32,7 @@ class Server void joinCmd(std::vector ¶m, int fd); void kickCmd(std::vector ¶m, int fd); + void topicCmd(std::vector ¶m, int fd); std::string getNameId(int fd); void joinMessage(int fd, const std::string &channelName); void setupChannel(const std::string &channelName, int fd, const std::string &password); diff --git a/topicCmd.cpp b/topicCmd.cpp new file mode 100644 index 0000000..f371b18 --- /dev/null +++ b/topicCmd.cpp @@ -0,0 +1,38 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::topicCmd(std::vector& args, int fd) { + + // std::cout << "args are : " << args[0] << " " << args[1] << " " << args[2] << std::endl; + + if (args.size() <= 1) { + std::string msg = "461 " + getClientNickname(fd) + " :Not enough parameters\n"; + sendMessage(fd, msg); + return; + } + + const std::string& channelName = args[1]; + std::map::iterator it = channels.find(channelName); + if (it == channels.end()) { + std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; + sendMessage(fd, msg); + } + else { + std::string msg = "332 " + getClientNickname(fd) + " " + channelName + " :" + it->second.getTopic() + "\n"; + sendMessage(fd, msg); + + // Uncomment and adapt this block for topic setting once supported + Channel& channel = it->second; + if (args.size() == 3) { + std::string newTopic = args[2]; + channel.setTopic(newTopic); + std::string msg = "332 " + getClientNickname(fd) + " " + channelName + " :" + newTopic + "\n"; + sendMessage(fd, msg); + } + } +} + From 0c8e5f5d6df4f9d0f9ff22ea8ad0f5647c05d1ac Mon Sep 17 00:00:00 2001 From: mbelouar Date: Wed, 24 Jul 2024 22:53:01 +0100 Subject: [PATCH 33/56] must add privmsg, names to list the users in the channels and also topic commands --- Makefile | 2 +- client.hpp | 35 ++++---- cmd.cpp | 9 ++- joinCmd.cpp | 215 +++++++++++++++++++++++++++++-------------------- kickCmd.cpp | 15 ---- privmsgCmd.cpp | 26 ++++++ server.hpp | 4 +- topicCmd.cpp | 32 ++++---- 8 files changed, 202 insertions(+), 136 deletions(-) create mode 100644 privmsgCmd.cpp diff --git a/Makefile b/Makefile index 1457cde..f1b3a42 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ RESET = \033[0m NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 -SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp # Add all source files here +SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp privmsgCmd.cpp # Add all source files here OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/client.hpp b/client.hpp index e6627ab..20e5366 100644 --- a/client.hpp +++ b/client.hpp @@ -27,23 +27,24 @@ class client client(); client(pollfd client_pfd, std::string password); ~client(); - void set_nickname(std::string nickname); - void set_username(std::string username); - void set_realname(std::string realname); - bool set_authenticated(); - void set_registered(bool is_registered); - std::string getNickname() const; - std::string getUsername() const; - pollfd get_client_pfd() const; - void set_client_pfd(pollfd client_pfd); - void set_massage_for_auth(std::string massage); - void set_massage(std::string massage); - void print_massage(); - void print_client(); - std::string get_message(); - void clear_massage(); - static std::vector& get_fds(); - static std::vector& get_clients(); + + pollfd get_client_pfd() const; + std::string getNickname() const; + std::string getUsername() const; + std::string get_message(); + void set_nickname(std::string nickname); + void set_username(std::string username); + void set_realname(std::string realname); + bool set_authenticated(); + void set_registered(bool is_registered); + void set_client_pfd(pollfd client_pfd); + void set_massage_for_auth(std::string massage); + void set_massage(std::string massage); + void print_massage(); + void print_client(); + void clear_massage(); + static std::vector& get_fds(); + static std::vector& get_clients(); }; diff --git a/cmd.cpp b/cmd.cpp index 141194b..abe38f5 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -21,14 +21,19 @@ void Server::command(int fd) { while (stream >> arg) { res.push_back(arg); } + // int size = res.size(); + // std::cout << "size of res is : " << size << std::endl; + // for (int i = 0; i < size; i++) { + // std::cout << "res[" << i << "] = " << res[i] << std::endl; + // } if (command.compare("join") == 0) joinCmd(res, fd); else if (command.compare("kick") == 0) kickCmd(res, fd); else if (command.compare("topic") == 0) topicCmd(res, fd); - // else if (command.compare("privmsg") == 0) - // privmsgCmd(res, fd); + else if (command.compare("privmsg") == 0) + privmsgCmd(res, fd); else { std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); diff --git a/joinCmd.cpp b/joinCmd.cpp index 081763c..3829d22 100644 --- a/joinCmd.cpp +++ b/joinCmd.cpp @@ -36,7 +36,7 @@ void Server::JoinMessage(int fd, const std::string &channelName) { std::string topic = channels[channelName].getTopic(); // Get topic std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + "127.0.0.1 JOIN " + channelName + " * :realname\r\n"; globmsg += message; - std::string message2 = ":localhost 353 " + getClientNickname(fd) + " = " + channelName + " :@" + getClientNickname(fd) + "\r\n"; + std::string message2 = ":localhost 353 " + getClientNickname(fd) + " = " + channelName + " :@" + getClientNickname(fd) + " \r\n"; globmsg += message2; std::string message3 = ":localhost 366 " + getClientNickname(fd) + " " + channelName + " :End of /NAMES list.\r\n"; globmsg += message3; @@ -48,101 +48,144 @@ void Server::JoinMessage(int fd, const std::string &channelName) { } void Server::joinCmd(std::vector ¶m, int fd) { - // Debugging output for received parameters - std::cout << "Received /join command with parameters: "; - for (size_t i = 0; i < param.size(); ++i) { - std::cout << param[i] << " "; - } - std::cout << std::endl; - - // Check if the param vector is empty or invalid - if (param.empty() || param[0][0] != '#' || (param[0].size() == 1)) { + if (param.empty() || param[0][0] != '#' || param[0].size() <= 1) { std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; sendMessage(fd, message); - std::cout << "Error: Not enough parameters or invalid channel name." << std::endl; return; } - // Split the parameters - std::vector chn = split(param[0], ','); - std::vector key; - if (param.size() == 2) { - key = split(param[1], ','); - } + std::string channelName = param[0]; - std::cout << "Channel names to join: "; - for (size_t i = 0; i < chn.size(); ++i) { - std::cout << chn[i] << " "; - } - std::cout << std::endl; + std::map::iterator it = channels.find(channelName); + bool channelCreated = (it == channels.end()); - std::cout << "Keys provided: "; - for (size_t i = 0; i < key.size(); ++i) { - std::cout << key[i] << " "; + if (channelCreated) { + // Create the channel if it doesn't exist + setupChannel(channelName, fd, (param.size() == 2) ? param[1] : ""); + JoinMessage(fd, channelName); } - std::cout << std::endl; - - // Loop through each channel name - for (size_t i = 0; i < chn.size(); ++i) { - std::map::iterator it = channels.find(chn[i]); - bool channelCreated = (it == channels.end()); - - // If channel doesn't exist, create it - if (channelCreated) { - setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); - JoinMessage(fd, chn[i]); - continue; - } - - Channel &channel = it->second; + else { + std::cout << "Channel \"" << channelName << "\" already exists \""<< std::endl; + // std::cout << "client name is : " << getClientNickname(fd) << std::endl; + // std::cout << "channel name is : " << channelName << std::endl; - // Check if client is already in the channel - if (channel.isClientInChannel(fd)) { - std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; - sendMessage(fd, message); - continue; - } + // Get reference to the existing channel + Channel &channel = channels[channelName]; - // Handle invite-only or password-protected channels - if (channel.getChannelType() == 1) { - if (channel.getInvitedList().empty() && param.size() != 2) { - std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; - sendMessage(fd, message); - continue; - } - - if (channel.isClientInvited(fd)) { - channel.setClients(fd, getClientNickname(fd)); - JoinMessage(fd, chn[i]); - continue; - } - - if (channel.getHasPassword() == 1) { - if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { - channel.setClients(fd, getClientNickname(fd)); - JoinMessage(fd, chn[i]); - } else { - std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; - sendMessage(fd, message); - } - continue; - } - } + // Add the client to the channel + channel.setClients(fd, getClientNickname(fd)); - // Handle password for existing channels - if (channel.getHasPassword() == 1) { - if (key.size() > i && channel.getChPassword() == key[i]) { - channel.setClients(fd, getClientNickname(fd)); - JoinMessage(fd, chn[i]); - } else { - std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; - sendMessage(fd, message); - } - continue; - } + // print the clients in the channel + // std::map clients = channel.getClientsFromChannel(); + // std::map::iterator it = clients.begin(); + // while (it != clients.end()) { + // std::cout << "client id : " << it->first << " client name : " << it->second.getNickname() << std::endl; + // it++; + // } - // Add the client to the channel and send a join message - channel.setClients(fd, getClientNickname(fd)); - JoinMessage(fd, chn[i]); + // // Inform the client about joining the channel + JoinMessage(fd, channelName); } -} \ No newline at end of file + +} + + +// void Server::joinCmd(std::vector ¶m, int fd) { +// // Debugging output for received parameters +// std::cout << "Received /join command with parameters: "; +// for (size_t i = 0; i < param.size(); ++i) { +// std::cout << param[i] << " "; +// } +// std::cout << std::endl; + +// // Check if the param vector is empty or invalid +// if (param.empty() || param[0][0] != '#' || (param[0].size() == 1)) { +// std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; +// sendMessage(fd, message); +// std::cout << "Error: Not enough parameters or invalid channel name." << std::endl; +// return; +// } + +// // Split the parameters +// std::vector chn = split(param[0], ','); +// std::vector key; +// if (param.size() == 2) { +// key = split(param[1], ','); +// } + +// std::cout << "Channel names to join: "; +// for (size_t i = 0; i < chn.size(); ++i) { +// std::cout << chn[i] << " "; +// } +// std::cout << std::endl; + +// std::cout << "Keys provided: "; +// for (size_t i = 0; i < key.size(); ++i) { +// std::cout << key[i] << " "; +// } +// std::cout << std::endl; + +// // Loop through each channel name +// for (size_t i = 0; i < chn.size(); ++i) { +// std::map::iterator it = channels.find(chn[i]); +// bool channelCreated = (it == channels.end()); + +// // If channel doesn't exist, create it +// if (channelCreated) { +// setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); +// JoinMessage(fd, chn[i]); +// continue; +// } + +// Channel &channel = it->second; + +// // Check if client is already in the channel +// if (channel.isClientInChannel(fd)) { +// std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; +// sendMessage(fd, message); +// continue; +// } + +// // Handle invite-only or password-protected channels +// if (channel.getChannelType() == 1) { +// if (channel.getInvitedList().empty() && param.size() != 2) { +// std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; +// sendMessage(fd, message); +// continue; +// } + +// if (channel.isClientInvited(fd)) { +// channel.setClients(fd, getClientNickname(fd)); +// JoinMessage(fd, chn[i]); +// continue; +// } + +// if (channel.getHasPassword() == 1) { +// if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { +// channel.setClients(fd, getClientNickname(fd)); +// JoinMessage(fd, chn[i]); +// } else { +// std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; +// sendMessage(fd, message); +// } +// continue; +// } +// } + +// // Handle password for existing channels +// if (channel.getHasPassword() == 1) { +// if (key.size() > i && channel.getChPassword() == key[i]) { +// channel.setClients(fd, getClientNickname(fd)); +// JoinMessage(fd, chn[i]); +// } else { +// std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; +// sendMessage(fd, message); +// } +// continue; +// } + +// // Add the client to the channel and send a join message +// channel.setClients(fd, getClientNickname(fd)); +// JoinMessage(fd, chn[i]); +// } +// } \ No newline at end of file diff --git a/kickCmd.cpp b/kickCmd.cpp index fab3195..2cb9863 100644 --- a/kickCmd.cpp +++ b/kickCmd.cpp @@ -42,23 +42,8 @@ void Server::kickCmd(std::vector& args, int fd) { std::cout << "Kicking user \"" << userToKick << "\" is on the channel \"" << channelName + "\"" << std::endl; } - - // std::cout << "Channel '" << it->first << "' BEFORE kick:" << std::endl; - // const std::map& clientsBeforeKick = it->second.getClientsFromChannel(); - // std::map::const_iterator itClientBefore; - // for (itClientBefore = clientsBeforeKick.begin(); itClientBefore != clientsBeforeKick.end(); ++itClientBefore) { - // std::cout << "Client ID: " << itClientBefore->first << ", Nickname: " << itClientBefore->second.getNickname() << std::endl; - // } - channel.removeClient(fdToKick); - // std::cout << "Channel '" << it->first << "' AFTER kick:" << std::endl; - // const std::map& clientsAfterKick = it->second.getClientsFromChannel(); - // std::map::const_iterator itClientAfter; - // for (itClientAfter = clientsAfterKick.begin(); itClientAfter != clientsAfterKick.end(); ++itClientAfter) { - // std::cout << "Client ID: " << itClientAfter->first << ", Nickname: " << itClientAfter->second.getNickname() << std::endl; - // } - std::string msg = ":" + getClientNickname(fd) + " KICK " + channelName + " " + userToKick + " :Kicked by " + getClientNickname(fd) + "\n"; sendMessage(fd, msg); diff --git a/privmsgCmd.cpp b/privmsgCmd.cpp new file mode 100644 index 0000000..d9f8ed0 --- /dev/null +++ b/privmsgCmd.cpp @@ -0,0 +1,26 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::privmsgCmd(std::vector& args, int fd) { + if (args.size() < 2) { + std::string msg = "411 " + getClientNickname(fd) + " :No recipient given (PRIVMSG)\n"; + sendMessage(fd, msg); + return; + } + + const std::string& recipient = args[0]; + const std::string& message = args[1]; + + std::map::iterator it = clients.find(recipient); + if (it == clients.end()) { + std::string msg = "401 " + getClientNickname(fd) + " " + recipient + " :No such nick/channel\n"; + sendMessage(fd, msg); + } else { + std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + " PRIVMSG " + recipient + " :" + message + "\n"; + sendMessage(fd, msg); + } +} diff --git a/server.hpp b/server.hpp index 6d51d37..25940f9 100644 --- a/server.hpp +++ b/server.hpp @@ -19,7 +19,7 @@ class Server struct addrinfo hints, *server; std::vector fds; std::map channels; - // std::map _clients; + // std::map _clients; public : Server(std::string ip, std::string port); @@ -31,6 +31,8 @@ class Server ~Server(); void joinCmd(std::vector ¶m, int fd); + void privmsgCmd(std::vector& args, int fd); + int getClientFdByNickname(const std::string& nickname); void kickCmd(std::vector ¶m, int fd); void topicCmd(std::vector ¶m, int fd); std::string getNameId(int fd); diff --git a/topicCmd.cpp b/topicCmd.cpp index f371b18..a963bac 100644 --- a/topicCmd.cpp +++ b/topicCmd.cpp @@ -8,14 +8,18 @@ void Server::topicCmd(std::vector& args, int fd) { // std::cout << "args are : " << args[0] << " " << args[1] << " " << args[2] << std::endl; + // std::cout << "size of args is : " << args.size() << std::endl; + // int size = args.size(); + // for (int i = 0; i < size; i++) { + // std::cout << "args[" << i << "] = " << args[i] << std::endl; + // } + // if (args.size() <= 1 && args[0] == getClientNickname(fd)) { + // std::string msg = "403 " + getClientNickname(fd) + " :No such channel\n"; + // sendMessage(fd, msg); + // return; + // } - if (args.size() <= 1) { - std::string msg = "461 " + getClientNickname(fd) + " :Not enough parameters\n"; - sendMessage(fd, msg); - return; - } - - const std::string& channelName = args[1]; + const std::string& channelName = args[0]; std::map::iterator it = channels.find(channelName); if (it == channels.end()) { std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; @@ -26,13 +30,13 @@ void Server::topicCmd(std::vector& args, int fd) { sendMessage(fd, msg); // Uncomment and adapt this block for topic setting once supported - Channel& channel = it->second; - if (args.size() == 3) { - std::string newTopic = args[2]; - channel.setTopic(newTopic); - std::string msg = "332 " + getClientNickname(fd) + " " + channelName + " :" + newTopic + "\n"; - sendMessage(fd, msg); - } + // Channel& channel = it->second; + // if (args.size() == 3) { + // std::string newTopic = args[2]; + // channel.setTopic(newTopic); + // std::string msg = "332 " + getClientNickname(fd) + " " + channelName + " :" + newTopic + "\n"; + // sendMessage(fd, msg); + // } } } From 40f41e58e18e057d40a7d08b1d1cfc92e0ef7d25 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Wed, 24 Jul 2024 23:42:05 +0100 Subject: [PATCH 34/56] topic command is DONE --- Makefile | 2 +- cmd.cpp | 4 ++-- topicCmd.cpp | 42 +++++++++++++++++++++--------------------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index f1b3a42..4aee2ae 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ RESET = \033[0m NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 -SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp privmsgCmd.cpp # Add all source files here +SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp #privmsgCmd.cpp # Add all source files here OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/cmd.cpp b/cmd.cpp index abe38f5..9470132 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -32,8 +32,8 @@ void Server::command(int fd) { kickCmd(res, fd); else if (command.compare("topic") == 0) topicCmd(res, fd); - else if (command.compare("privmsg") == 0) - privmsgCmd(res, fd); + // else if (command.compare("privmsg") == 0) + // privmsgCmd(res, fd); else { std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); diff --git a/topicCmd.cpp b/topicCmd.cpp index a963bac..b842927 100644 --- a/topicCmd.cpp +++ b/topicCmd.cpp @@ -7,36 +7,36 @@ void Server::topicCmd(std::vector& args, int fd) { - // std::cout << "args are : " << args[0] << " " << args[1] << " " << args[2] << std::endl; - // std::cout << "size of args is : " << args.size() << std::endl; - // int size = args.size(); - // for (int i = 0; i < size; i++) { - // std::cout << "args[" << i << "] = " << args[i] << std::endl; - // } - // if (args.size() <= 1 && args[0] == getClientNickname(fd)) { - // std::string msg = "403 " + getClientNickname(fd) + " :No such channel\n"; - // sendMessage(fd, msg); - // return; - // } - const std::string& channelName = args[0]; std::map::iterator it = channels.find(channelName); + if (it == channels.end()) { std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; sendMessage(fd, msg); } + else if (args.size() == 1) { + const std::string& topic = it->second.getTopic(); + if (topic.empty()) { + std::string msg = "331 " + getClientNickname(fd) + " " + channelName + " :No topic is set\n"; + sendMessage(fd, msg); + } + else { + std::string msg = "332 " + getClientNickname(fd) + " " + channelName + " " + topic + "\n"; + sendMessage(fd, msg); + } + } else { - std::string msg = "332 " + getClientNickname(fd) + " " + channelName + " :" + it->second.getTopic() + "\n"; + // Set topic + std:: string newTopic = args[1]; + for (size_t i = 2; i < args.size(); ++i) { + newTopic += " " + args[i]; + } + std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + "127.0.0.1 TOPIC " + channelName + " " + newTopic + "\n"; sendMessage(fd, msg); - // Uncomment and adapt this block for topic setting once supported - // Channel& channel = it->second; - // if (args.size() == 3) { - // std::string newTopic = args[2]; - // channel.setTopic(newTopic); - // std::string msg = "332 " + getClientNickname(fd) + " " + channelName + " :" + newTopic + "\n"; - // sendMessage(fd, msg); - // } + Channel& channel = it->second; + channel.setTopic(newTopic); } } + From 9f0a6d0f1df48d8486ac54c64bb5846084f1df00 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Thu, 25 Jul 2024 00:12:04 +0100 Subject: [PATCH 35/56] start implement the who command --- Makefile | 2 +- cmd.cpp | 2 ++ server.hpp | 1 + whocmd.cpp | 26 ++++++++++++++++++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 whocmd.cpp diff --git a/Makefile b/Makefile index 4aee2ae..9ddd8d4 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ RESET = \033[0m NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 -SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp #privmsgCmd.cpp # Add all source files here +SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp whoCmd.cpp #privmsgCmd.cpp # Add all source files here OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/cmd.cpp b/cmd.cpp index 9470132..b5fda04 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -32,6 +32,8 @@ void Server::command(int fd) { kickCmd(res, fd); else if (command.compare("topic") == 0) topicCmd(res, fd); + else if (command.compare("who") == 0) + whoCmd(res, fd); // else if (command.compare("privmsg") == 0) // privmsgCmd(res, fd); else { diff --git a/server.hpp b/server.hpp index 25940f9..63a269d 100644 --- a/server.hpp +++ b/server.hpp @@ -32,6 +32,7 @@ class Server void joinCmd(std::vector ¶m, int fd); void privmsgCmd(std::vector& args, int fd); + void whoCmd(std::vector& args, int fd); int getClientFdByNickname(const std::string& nickname); void kickCmd(std::vector ¶m, int fd); void topicCmd(std::vector ¶m, int fd); diff --git a/whocmd.cpp b/whocmd.cpp new file mode 100644 index 0000000..6ad10ae --- /dev/null +++ b/whocmd.cpp @@ -0,0 +1,26 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::whoCmd(std::vector& args, int fd) { + if (args.size() == 0) { + std::string msg = "431 " + getClientNickname(fd) + " :No nickname given\n"; + sendMessage(fd, msg); + return; + } + + const std::string& channelName = args[0]; + std::map::iterator it = channels.find(channelName); + + if (it == channels.end()) { + std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; + sendMessage(fd, msg); + } + else { + // must know the clients in the channel + std::cout << "List of users in the channel \"" << channelName << "\" :" << std::endl; + } +} \ No newline at end of file From 860f9c03f375d1c257b163a2428af845ba78ea31 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Thu, 25 Jul 2024 02:44:46 +0100 Subject: [PATCH 36/56] privmsg working just for channels --- Channel.hpp | 29 ++++++++++++++--------------- Makefile | 2 +- cmd.cpp | 18 +++++++++++------- irc_server.cpp | 2 +- privmsgCmd.cpp | 39 ++++++++++++++++++++++++++++++++------- server.hpp | 1 + whocmd.cpp | 37 +++++++++++++++++++++++++++++++------ 7 files changed, 91 insertions(+), 37 deletions(-) diff --git a/Channel.hpp b/Channel.hpp index cd7c9e1..6170ef1 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -37,21 +37,20 @@ class Channel { void setInvitedList(int id, client &c); // getters : - std::string getName(); - std::string getTopic(); - std::vector &getOperators(); - std::string getChPassword(); - std::map::const_iterator beginClientIter() const; - std::map::const_iterator endClientIter() const; - int getChannelType(); - int getClientID(const std::string &nickname) const; - int isClientInChannel(int fd); - int getHasPassword() const; - size_t getClientNb() const; - std::map getInvitedList() const; - bool isClientInvited(int clientId) const; - - const std::map &getClientsFromChannel() const; + std::string getName(); + std::string getTopic(); + std::vector &getOperators(); + std::string getChPassword(); + std::map::const_iterator beginClientIter() const; + std::map::const_iterator endClientIter() const; + int getChannelType(); + int getClientID(const std::string &nickname) const; + int isClientInChannel(int fd); + int getHasPassword() const; + size_t getClientNb() const; + std::map getInvitedList() const; + bool isClientInvited(int clientId) const; + const std::map &getClientsFromChannel() const; void removeClient(int fd); diff --git a/Makefile b/Makefile index 9ddd8d4..ab34c2d 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ RESET = \033[0m NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 -SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp whoCmd.cpp #privmsgCmd.cpp # Add all source files here +SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp whoCmd.cpp privmsgCmd.cpp # Add all source files here OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/cmd.cpp b/cmd.cpp index b5fda04..dcfcec9 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -21,11 +21,11 @@ void Server::command(int fd) { while (stream >> arg) { res.push_back(arg); } - // int size = res.size(); - // std::cout << "size of res is : " << size << std::endl; - // for (int i = 0; i < size; i++) { - // std::cout << "res[" << i << "] = " << res[i] << std::endl; - // } + int size = res.size(); + std::cout << "size of res is : " << size << std::endl; + for (int i = 0; i < size; i++) { + std::cout << "res[" << i << "] = " << res[i] << std::endl; + } if (command.compare("join") == 0) joinCmd(res, fd); else if (command.compare("kick") == 0) @@ -34,8 +34,12 @@ void Server::command(int fd) { topicCmd(res, fd); else if (command.compare("who") == 0) whoCmd(res, fd); - // else if (command.compare("privmsg") == 0) - // privmsgCmd(res, fd); + // else if (command.compare("nick") == 0) + // nickCmd(res, fd); + // else if (command.compare("mode") == 0) + // modeCmd(res, fd); + else if (command.compare("privmsg") == 0) + privmsgCmd(res, fd); else { std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); diff --git a/irc_server.cpp b/irc_server.cpp index 315d96e..b3ae69a 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -72,7 +72,7 @@ int main(int argc, char *argv[]) client::get_clients()[l].set_massage(buffer); // work will be done here irc_server.command(client::get_fds()[i].fd); - + // print the client name and message std::cout << "we are receiving message from authenticated client: " << client::get_clients()[l].get_message() << std::endl; } else diff --git a/privmsgCmd.cpp b/privmsgCmd.cpp index d9f8ed0..b21c279 100644 --- a/privmsgCmd.cpp +++ b/privmsgCmd.cpp @@ -6,21 +6,46 @@ #include "utils.hpp" void Server::privmsgCmd(std::vector& args, int fd) { - if (args.size() < 2) { + + if (args.size() < 1) { std::string msg = "411 " + getClientNickname(fd) + " :No recipient given (PRIVMSG)\n"; sendMessage(fd, msg); return; } + else if (args.size() == 1) { + std::string msg = "412 " + getClientNickname(fd) + " :No text to send\n"; + sendMessage(fd, msg); + return; + } const std::string& recipient = args[0]; - const std::string& message = args[1]; + std::string message = args[1]; + for (size_t i = 2; i < args.size(); ++i) { + message += " " + args[i]; + } - std::map::iterator it = clients.find(recipient); - if (it == clients.end()) { + std::map::iterator clientIt = clients.find(recipient); + std::map::iterator channelIt = channels.find(recipient); + + if (clientIt == clients.end() && channelIt == channels.end()) { + // Recipient not found in both clients and channels std::string msg = "401 " + getClientNickname(fd) + " " + recipient + " :No such nick/channel\n"; sendMessage(fd, msg); - } else { - std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + " PRIVMSG " + recipient + " :" + message + "\n"; - sendMessage(fd, msg); + } + else if (clientIt != clients.end()) { + // Recipient found as a client + client& recipientClient = clientIt->second; + std::string msg = ":" + getClientNickname(fd) + " PRIVMSG " + recipient + " :" + message + "\n"; + sendMessage(recipientClient.get_client_pfd().fd, msg); + } + else if (channelIt != channels.end()) { + // Recipient found as a channel + std::cout << "Channel found" << std::endl; + Channel& channel = channelIt->second; + // t!tttt@88ABE6.25BF1D.D03F86.88C9BD.IP + std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@127.0.0.1" + " PRIVMSG " + recipient + " :" + message + "\n"; + for (std::map::const_iterator it = channel.beginClientIter(); it != channel.endClientIter(); ++it) { + sendMessage(it->first, msg); + } } } diff --git a/server.hpp b/server.hpp index 63a269d..d1c3e7c 100644 --- a/server.hpp +++ b/server.hpp @@ -19,6 +19,7 @@ class Server struct addrinfo hints, *server; std::vector fds; std::map channels; + std::map clients; // std::map _clients; public : diff --git a/whocmd.cpp b/whocmd.cpp index 6ad10ae..857e9fb 100644 --- a/whocmd.cpp +++ b/whocmd.cpp @@ -7,7 +7,8 @@ void Server::whoCmd(std::vector& args, int fd) { if (args.size() == 0) { - std::string msg = "431 " + getClientNickname(fd) + " :No nickname given\n"; + // No channel name provided + std::string msg = "431 " + getClientNickname(fd) + " :No channel given\n"; sendMessage(fd, msg); return; } @@ -16,11 +17,35 @@ void Server::whoCmd(std::vector& args, int fd) { std::map::iterator it = channels.find(channelName); if (it == channels.end()) { + // Channel not found std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; sendMessage(fd, msg); + } else { + // Channel exists, prepare to list the clients + Channel& channel = it->second; + std::string msg; + + // Start with a header message + msg = ":" + getClientNickname(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :"; + + // List all clients in the channel + bool first = true; + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (!first) { + msg += " "; + } + first = false; + msg += clientIt->second.getNickname(); // Adjust if you need more details + } + + msg += "\n"; + + // End of list message + msg += ":" + getClientNickname(fd) + " 366 " + getClientNickname(fd) + " " + channelName + " :End of /WHO list.\n"; + + // Send the response to the requesting client + sendMessage(fd, msg); } - else { - // must know the clients in the channel - std::cout << "List of users in the channel \"" << channelName << "\" :" << std::endl; - } -} \ No newline at end of file +} From f6de91805708634c202b8efbfe7fbc893c292316 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Fri, 26 Jul 2024 19:14:57 +0100 Subject: [PATCH 37/56] Fixing the hostname and password checks --- client.cpp | 74 ++++++++++++++++++++++++-------------------------- client.hpp | 2 ++ irc_server.cpp | 2 ++ server.cpp | 6 ++++ server.hpp | 1 + 5 files changed, 47 insertions(+), 38 deletions(-) diff --git a/client.cpp b/client.cpp index 156673f..6488799 100644 --- a/client.cpp +++ b/client.cpp @@ -19,7 +19,6 @@ client::client(pollfd client_pfd, std::string password) this->index = 0; } - client::~client() { // std::cout << "client with nickname " << this->nickname << " is destroyed" << std::endl; @@ -69,24 +68,16 @@ std::vector buffer_to_line(std::string buffer, std::string siparato return lines; } - - - - bool client::set_authenticated() { std::string line; if (this->is_authenticated == true) { return (true); - }else - { - + } + else { std::vector lines = buffer_to_line(this->massage, "\r\n"); - - - // std::cout << "--------------- not authonticatef --------------------" << std::endl; // std::cout << "the size of lines : " << lines.size() << std::endl; for (unsigned int i = 0; i < lines.size(); i++) @@ -101,39 +92,43 @@ bool client::set_authenticated() { std::string username = lines[i].substr(5, lines[i].size()); this->set_username(username); + + + // try to grt the hodt name { this->username = user_abdel-ou user_abdel-ou localhost :realname} try to get the host name + + size_t found1 = this->username.find(" "); + if (found1 != std::string::npos) { + size_t found2 = this->username.find(" ", found1 + 1); + if (found2 != std::string::npos) { + + std::string tmp_realname = this->username.substr(found2 + 1, this->username.size()); + + size_t found3 = tmp_realname.find(" "); + if (found3 != std::string::npos) { + std::string realname = tmp_realname.substr(0, found3); + // std::cout << "realname : " << realname << std::endl; + this->hostname = realname; + + // std::cout << "hostname : " << this->hostname << std::endl; + + } + } + } + } if (lines[i].find("PASS") != std::string::npos) { - std::string password = lines[i].substr(5, lines[i].size()); - this->sabmit_password = password; - if (this->password == password) - { - this->is_authenticated = true; - this->password = ""; - } + this->sabmit_password = lines[i].substr(5, lines[i].size()); + } - - } - if (this->nickname.size() > 0 && this->username.size() > 0) + if ((this->nickname.size() > 0) && (this->username.size() > 0) && (this->password == this->sabmit_password)) { this->is_authenticated = true; return (true); } - // print_client(); - - // std::cout << "--------------- not authonticatef --------------------" << std::endl; - - - - - - - - } - return (false); } @@ -152,10 +147,6 @@ void client::set_client_pfd(pollfd client_pfd) this->client_pfd = client_pfd; } - - - - void client::set_massage_for_auth(std::string massage) { this->massage = this->massage + massage; @@ -195,5 +186,12 @@ void client::set_massage(std::string massage) this->massage = massage; } + +std::string client::get_host_name() +{ + return this->hostname; +} + std::vector& client::get_fds() { return fds; } -std::vector& client::get_clients() { return clients; } \ No newline at end of file +std::vector& client::get_clients() { return clients; } + diff --git a/client.hpp b/client.hpp index 20e5366..6e6f5ad 100644 --- a/client.hpp +++ b/client.hpp @@ -13,6 +13,7 @@ class client std::string nickname; std::string username; std::string realname; + std::string hostname; std::string password; std::string sabmit_password; @@ -45,6 +46,7 @@ class client void clear_massage(); static std::vector& get_fds(); static std::vector& get_clients(); + std::string get_host_name(); }; diff --git a/irc_server.cpp b/irc_server.cpp index b3ae69a..fbaaf1e 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -70,6 +70,8 @@ int main(int argc, char *argv[]) if (client::get_clients()[l].set_authenticated() == true) { client::get_clients()[l].set_massage(buffer); + // print host name + // std::cout << client::get_clients()[l].get_host_name() << std::endl; // work will be done here irc_server.command(client::get_fds()[i].fd); // print the client name and message diff --git a/server.cpp b/server.cpp index 048bd38..bad394b 100644 --- a/server.cpp +++ b/server.cpp @@ -84,6 +84,12 @@ std::string Server::getClientMessage(int fd) { return (it != clients.end()) ? it->get_message() : ""; } +std::string Server::getClientHostName(int fd) { + std::vector& clients = client::get_clients(); + std::vector::iterator it = std::find_if(clients.begin(), clients.end(), IsClientWithFd(fd)); + return (it != clients.end()) ? it->get_host_name() : ""; +} + std::string Server::getNameId(int fd) { std::vector& clients = client::get_clients(); for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { diff --git a/server.hpp b/server.hpp index d1c3e7c..83e7f16 100644 --- a/server.hpp +++ b/server.hpp @@ -44,6 +44,7 @@ class Server void command(int fd); std::string getClientMessage(int fd); std::string getClientNickname(int fd); + std::string getClientHostName(int fd); class IsClientWithFd { public: From 3836f2f6ceeb2fa3afa4fadfbea6a01b96d954fe Mon Sep 17 00:00:00 2001 From: mbelouar Date: Fri, 26 Jul 2024 21:21:10 +0100 Subject: [PATCH 38/56] fixing 2 users join same channel but still fix the PART command when leaving a channel to clear the list of users --- cmd.cpp | 10 +++++----- joinCmd.cpp | 45 +++++++++++++++++++++++++++++++-------------- whocmd.cpp | 3 +-- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/cmd.cpp b/cmd.cpp index dcfcec9..781ca11 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -21,11 +21,11 @@ void Server::command(int fd) { while (stream >> arg) { res.push_back(arg); } - int size = res.size(); - std::cout << "size of res is : " << size << std::endl; - for (int i = 0; i < size; i++) { - std::cout << "res[" << i << "] = " << res[i] << std::endl; - } + // int size = res.size(); + // std::cout << "size of res is : " << size << std::endl; + // for (int i = 0; i < size; i++) { + // std::cout << "res[" << i << "] = " << res[i] << std::endl; + // } if (command.compare("join") == 0) joinCmd(res, fd); else if (command.compare("kick") == 0) diff --git a/joinCmd.cpp b/joinCmd.cpp index 3829d22..77a1004 100644 --- a/joinCmd.cpp +++ b/joinCmd.cpp @@ -31,15 +31,41 @@ void Server::setupChannel(const std::string &channelName, int fd, const std::str } void Server::JoinMessage(int fd, const std::string &channelName) { + + std::map::iterator it = channels.find(channelName); + if (channels.find(channelName) != channels.end()) { std::string globmsg = ""; std::string topic = channels[channelName].getTopic(); // Get topic - std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + "127.0.0.1 JOIN " + channelName + " * :realname\r\n"; + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " JOIN " + channelName + " * :realname\r\n"; globmsg += message; - std::string message2 = ":localhost 353 " + getClientNickname(fd) + " = " + channelName + " :@" + getClientNickname(fd) + " \r\n"; - globmsg += message2; - std::string message3 = ":localhost 366 " + getClientNickname(fd) + " " + channelName + " :End of /NAMES list.\r\n"; + + Channel& channel = it->second; + std::string message2 = ":" + getClientHostName(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :"; + bool first = true; + + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (!first) { + message2 += " "; + } + first = false; + message2 += "@" + clientIt->second.getNickname() + "!" + clientIt->second.getNickname() + "@" + getClientHostName(fd); + } + message2 += "\n"; + globmsg += message2; + + std::string message3 = ":" + getClientHostName(fd) + " 366 " + getClientNickname(fd) + " " + channelName + " :End of /NAMES list.\r\n"; globmsg += message3; + + // send to other clients in the channel like this message :simo!simo@88ABE6.25BF1D.D03F86.88C9BD.IP JOIN #chan * :realname + for (std::map::const_iterator it = channel.beginClientIter(); it != channel.endClientIter(); ++it) { + if (it->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " JOIN " + channelName + " * :realname\r\n"; + sendMessage(it->first, message); + } + } sendMessage(fd, globmsg); } else { std::string globmsg = ":" + getNameId(fd) + " 403 " + channelName + " :No such channel\n"; @@ -75,18 +101,9 @@ void Server::joinCmd(std::vector ¶m, int fd) { // Add the client to the channel channel.setClients(fd, getClientNickname(fd)); - // print the clients in the channel - // std::map clients = channel.getClientsFromChannel(); - // std::map::iterator it = clients.begin(); - // while (it != clients.end()) { - // std::cout << "client id : " << it->first << " client name : " << it->second.getNickname() << std::endl; - // it++; - // } - - // // Inform the client about joining the channel + // Inform the client about joining the channel JoinMessage(fd, channelName); } - } diff --git a/whocmd.cpp b/whocmd.cpp index 857e9fb..57fb04b 100644 --- a/whocmd.cpp +++ b/whocmd.cpp @@ -25,8 +25,7 @@ void Server::whoCmd(std::vector& args, int fd) { Channel& channel = it->second; std::string msg; - // Start with a header message - msg = ":" + getClientNickname(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :"; + msg = ":" + getClientHostName(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :"; // List all clients in the channel bool first = true; From d6c6473cd29a99d2cb679ba479237871523f4686 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Fri, 26 Jul 2024 22:01:44 +0100 Subject: [PATCH 39/56] Add PART command --- Makefile | 3 ++- cmd.cpp | 4 ++-- partCmd.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ server.hpp | 1 + 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 partCmd.cpp diff --git a/Makefile b/Makefile index ab34c2d..0c91a93 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,8 @@ RESET = \033[0m NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 -SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp whoCmd.cpp privmsgCmd.cpp # Add all source files here +SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp whoCmd.cpp privmsgCmd.cpp \ + partCmd.cpp OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/cmd.cpp b/cmd.cpp index 781ca11..4fa8b3d 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -34,8 +34,8 @@ void Server::command(int fd) { topicCmd(res, fd); else if (command.compare("who") == 0) whoCmd(res, fd); - // else if (command.compare("nick") == 0) - // nickCmd(res, fd); + else if (command.compare("part") == 0) + partCmd(res, fd); // else if (command.compare("mode") == 0) // modeCmd(res, fd); else if (command.compare("privmsg") == 0) diff --git a/partCmd.cpp b/partCmd.cpp new file mode 100644 index 0000000..b2b8b1a --- /dev/null +++ b/partCmd.cpp @@ -0,0 +1,42 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::partCmd(std::vector& args, int fd) { + if (args.size() == 0) { + std::string msg = "461 " + getClientNickname(fd) + " PART :Not enough parameters\n"; + sendMessage(fd, msg); + return; + } + + const std::string& channelName = args[0]; + std::map::iterator it = channels.find(channelName); + if (it == channels.end()) { + std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; + sendMessage(fd, msg); + return; + } + + Channel& channel = it->second; + if (!channel.isClientInChannel(fd)) { + std::string msg = "442 " + getClientNickname(fd) + " " + channelName + " :You're not on that channel\n"; + sendMessage(fd, msg); + return; + } + + channel.removeClient(fd); + // :simo!simo@88ABE6.25BF1D.D03F86.88C9BD.IP PART #chan :Leaving + std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " PART " + channelName + " :Leaving\n"; + + // Send the message to all clients in the channel + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + sendMessage(clientIt->first, msg); + } + + sendMessage(fd, msg); +} \ No newline at end of file diff --git a/server.hpp b/server.hpp index 83e7f16..6114ece 100644 --- a/server.hpp +++ b/server.hpp @@ -37,6 +37,7 @@ class Server int getClientFdByNickname(const std::string& nickname); void kickCmd(std::vector ¶m, int fd); void topicCmd(std::vector ¶m, int fd); + void partCmd(std::vector& args, int fd); std::string getNameId(int fd); void joinMessage(int fd, const std::string &channelName); void setupChannel(const std::string &channelName, int fd, const std::string &password); From b958aa06cc197ad08984cbdc2274a32e3ec2639a Mon Sep 17 00:00:00 2001 From: mbelouar Date: Fri, 26 Jul 2024 23:06:53 +0100 Subject: [PATCH 40/56] PRIVMSG is DONE --- privmsgCmd.cpp | 58 +++++++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/privmsgCmd.cpp b/privmsgCmd.cpp index b21c279..33500fe 100644 --- a/privmsgCmd.cpp +++ b/privmsgCmd.cpp @@ -8,12 +8,12 @@ void Server::privmsgCmd(std::vector& args, int fd) { if (args.size() < 1) { - std::string msg = "411 " + getClientNickname(fd) + " :No recipient given (PRIVMSG)\n"; + std::string msg = "411 " + getClientNickname(fd) + " :No recipient given (PRIVMSG)\n\r"; sendMessage(fd, msg); return; } else if (args.size() == 1) { - std::string msg = "412 " + getClientNickname(fd) + " :No text to send\n"; + std::string msg = "412 " + getClientNickname(fd) + " :No text to send\n\r"; sendMessage(fd, msg); return; } @@ -24,28 +24,42 @@ void Server::privmsgCmd(std::vector& args, int fd) { message += " " + args[i]; } - std::map::iterator clientIt = clients.find(recipient); - std::map::iterator channelIt = channels.find(recipient); + std::vector& clients = client::get_clients(); + bool recipientFound = false; + client* recipientClient = nullptr; - if (clientIt == clients.end() && channelIt == channels.end()) { - // Recipient not found in both clients and channels - std::string msg = "401 " + getClientNickname(fd) + " " + recipient + " :No such nick/channel\n"; - sendMessage(fd, msg); - } - else if (clientIt != clients.end()) { - // Recipient found as a client - client& recipientClient = clientIt->second; - std::string msg = ":" + getClientNickname(fd) + " PRIVMSG " + recipient + " :" + message + "\n"; - sendMessage(recipientClient.get_client_pfd().fd, msg); + // Check if the recipient is a client + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { + if (it->getNickname() == recipient) { + recipientClient = &(*it); // Point to the recipient client + recipientFound = true; + break; + } } - else if (channelIt != channels.end()) { - // Recipient found as a channel - std::cout << "Channel found" << std::endl; - Channel& channel = channelIt->second; - // t!tttt@88ABE6.25BF1D.D03F86.88C9BD.IP - std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@127.0.0.1" + " PRIVMSG " + recipient + " :" + message + "\n"; - for (std::map::const_iterator it = channel.beginClientIter(); it != channel.endClientIter(); ++it) { - sendMessage(it->first, msg); + + if (!recipientFound) { + // Recipient not found as a client + std::map::iterator channelIt = channels.find(recipient); + + if (channelIt == channels.end()) { + std::string msg = "401 " + getClientNickname(fd) + " " + recipient + " :No such nick/channel\n\r"; + sendMessage(fd, msg); + } + else { + std::cout << "Channel found" << std::endl; + Channel& channel = channelIt->second; + std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " PRIVMSG " + recipient + " :" + message + "\n\r"; + for (std::map::const_iterator it = channel.beginClientIter(); it != channel.endClientIter(); ++it) { + if (it->first != fd) { + sendMessage(it->first, msg); + } + } } } + else { + // Recipient found as a client + std::cout << "Client found" << std::endl; + std::string msg = ":" + getClientNickname(fd) + " PRIVMSG " + recipient + " :" + message + "\n\r"; + sendMessage(recipientClient->get_client_pfd().fd, msg); + } } From 463183784bab80e1cd8fed2f2250804097161582 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sat, 27 Jul 2024 00:59:36 +0100 Subject: [PATCH 41/56] KICK is DONE, still just MODE command and operators (will be handled in MODE) --- Channel.cpp | 2 +- Channel.hpp | 8 ++++---- cmd.cpp | 4 ++-- kickCmd.cpp | 13 +++++++++---- server.hpp | 2 +- whocmd.cpp | 2 +- 6 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index f2e006d..2c6ac32 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -56,7 +56,7 @@ void Channel::setClients(int id, const std::string &userName) { clients[id].set_nickname(userName); } -void Channel::setOperators(int& op) { +void Channel::setOperators(int op) { operators.push_back(op); } diff --git a/Channel.hpp b/Channel.hpp index 6170ef1..cb165cd 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -11,11 +11,11 @@ class Channel { private: std::string name; std::string topic; - std::map clients; - std::vector operators; std::string chPassword; + std::vector operators; + std::map clients; std::map inviteList; - int channelType; + int channelType; int hasPassword; public: @@ -30,7 +30,7 @@ class Channel { void setTopic(std::string channelTopic); // void setClients(std::map channelClients); void setClients(int id, const std::string &userName); - void setOperators(int& op); + void setOperators(int op); void setChPassword(std::string channelPassword); void setChannelType(int channelType); void setHasPassword(int hasPassword); diff --git a/cmd.cpp b/cmd.cpp index 4fa8b3d..aeb394c 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -36,10 +36,10 @@ void Server::command(int fd) { whoCmd(res, fd); else if (command.compare("part") == 0) partCmd(res, fd); - // else if (command.compare("mode") == 0) - // modeCmd(res, fd); else if (command.compare("privmsg") == 0) privmsgCmd(res, fd); + // else if (command.compare("mode") == 0) + // modeCmd(res, fd); else { std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); diff --git a/kickCmd.cpp b/kickCmd.cpp index 2cb9863..f669f49 100644 --- a/kickCmd.cpp +++ b/kickCmd.cpp @@ -20,7 +20,7 @@ void Server::kickCmd(std::vector& args, int fd) { std::map::iterator it = channels.find(channelName); if (it == channels.end()) { - std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; + std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n\r"; sendMessage(fd, msg); return; } @@ -28,13 +28,13 @@ void Server::kickCmd(std::vector& args, int fd) { Channel& channel = it->second; int fdToKick = channel.getClientID(userToKick); if (fdToKick == -1) { - std::string msg = "401 " + getClientNickname(fd) + " " + userToKick + " :No such nick/channel\n"; + std::string msg = "401 " + getClientNickname(fd) + " " + userToKick + " :No such nick/channel\n\r"; sendMessage(fd, msg); return; } if (!channel.isClientInChannel(fdToKick)) { - std::string msg = "441 " + getClientNickname(fd) + " " + userToKick + " " + channelName + " :They aren't on that channel\n"; + std::string msg = "441 " + getClientNickname(fd) + " " + userToKick + " " + channelName + " :They aren't on that channel\n\r"; sendMessage(fd, msg); return; } @@ -45,6 +45,11 @@ void Server::kickCmd(std::vector& args, int fd) { channel.removeClient(fdToKick); - std::string msg = ":" + getClientNickname(fd) + " KICK " + channelName + " " + userToKick + " :Kicked by " + getClientNickname(fd) + "\n"; + std::string msg = ":" + getClientNickname(fd) + " KICK " + channelName + " " + userToKick + " :" + getClientNickname(fd) + "\n\r"; sendMessage(fd, msg); + + // Send the message to the client being kicked + std::string kickMsg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " KICK " + channelName + " " + userToKick + " :" + getClientNickname(fd) + "\n\r"; + sendMessage(fdToKick, kickMsg); + } \ No newline at end of file diff --git a/server.hpp b/server.hpp index 6114ece..6ddd251 100644 --- a/server.hpp +++ b/server.hpp @@ -34,10 +34,10 @@ class Server void joinCmd(std::vector ¶m, int fd); void privmsgCmd(std::vector& args, int fd); void whoCmd(std::vector& args, int fd); - int getClientFdByNickname(const std::string& nickname); void kickCmd(std::vector ¶m, int fd); void topicCmd(std::vector ¶m, int fd); void partCmd(std::vector& args, int fd); + int getClientFdByNickname(const std::string& nickname); std::string getNameId(int fd); void joinMessage(int fd, const std::string &channelName); void setupChannel(const std::string &channelName, int fd, const std::string &password); diff --git a/whocmd.cpp b/whocmd.cpp index 57fb04b..d84c9ad 100644 --- a/whocmd.cpp +++ b/whocmd.cpp @@ -25,7 +25,7 @@ void Server::whoCmd(std::vector& args, int fd) { Channel& channel = it->second; std::string msg; - msg = ":" + getClientHostName(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :"; + msg = ":" + getClientHostName(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :@"; // List all clients in the channel bool first = true; From 9088cfe7f7a08887a536bb353206f3b7dc73f861 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sat, 27 Jul 2024 02:11:11 +0100 Subject: [PATCH 42/56] NICK is DONE --- Makefile | 2 +- client.cpp | 17 +++++++++++++++++ client.hpp | 2 ++ cmd.cpp | 6 ++++-- modeCmd.cpp | 17 +++++++++++++++++ nickCmd.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ server.hpp | 2 ++ 7 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 modeCmd.cpp create mode 100644 nickCmd.cpp diff --git a/Makefile b/Makefile index 0c91a93..766bff7 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp whoCmd.cpp privmsgCmd.cpp \ - partCmd.cpp + partCmd.cpp modeCmd.cpp nickCmd.cpp OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/client.cpp b/client.cpp index 6488799..82273c5 100644 --- a/client.cpp +++ b/client.cpp @@ -49,6 +49,7 @@ std::string client::getUsername()const { return this->username; } + std::vector buffer_to_line(std::string buffer, std::string siparator) { std::vector lines; @@ -192,6 +193,22 @@ std::string client::get_host_name() return this->hostname; } +int client::getFd() const +{ + return this->client_pfd.fd; +} + +void client::modify_client(int fd, const std::string& newNickname) +{ + std::vector& clients = client::get_clients(); + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { + if (it->getFd() == fd) { + it->set_nickname(newNickname); + return; + } + } +} + std::vector& client::get_fds() { return fds; } std::vector& client::get_clients() { return clients; } diff --git a/client.hpp b/client.hpp index 6e6f5ad..0046724 100644 --- a/client.hpp +++ b/client.hpp @@ -47,6 +47,8 @@ class client static std::vector& get_fds(); static std::vector& get_clients(); std::string get_host_name(); + int getFd() const; + static void modify_client(int fd, const std::string& newNickname); }; diff --git a/cmd.cpp b/cmd.cpp index aeb394c..e9163e7 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -38,8 +38,10 @@ void Server::command(int fd) { partCmd(res, fd); else if (command.compare("privmsg") == 0) privmsgCmd(res, fd); - // else if (command.compare("mode") == 0) - // modeCmd(res, fd); + else if (command.compare("nick") == 0) + nickCmd(res, fd); + else if (command.compare("mode") == 0) + modeCmd(res, fd); else { std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); diff --git a/modeCmd.cpp b/modeCmd.cpp new file mode 100644 index 0000000..a02e8b9 --- /dev/null +++ b/modeCmd.cpp @@ -0,0 +1,17 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::modeCmd(std::vector ¶m, int fd) { + if (param.size() < 2) { + std::string message = "461 " + getClientNickname(fd) + " MODE :Not enough parameters\n"; + sendMessage(fd, message); + return; + } + + // Implement the mode command here +} + diff --git a/nickCmd.cpp b/nickCmd.cpp new file mode 100644 index 0000000..befd386 --- /dev/null +++ b/nickCmd.cpp @@ -0,0 +1,51 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::nickCmd(std::vector& args, int fd) { + if (args.size() == 0) { + std::string msg = "431 " + getClientNickname(fd) + " :No nickname given\n\r"; + sendMessage(fd, msg); + return; + } + + const std::string& newNickname = args[0]; + + std::cout << "New nickname: " << newNickname << std::endl; + + // Check if the nickname is already in use + const std::vector& clients = client::get_clients(); + for (std::vector::const_iterator it = clients.begin(); it != clients.end(); ++it) { + if (it->getNickname() == newNickname) { + std::string msg = "433 " + newNickname + " :Nickname is already in use\n\r"; + sendMessage(fd, msg); + return; + } + } + + // print the name of the client before changing it + std::string oldNickname = getClientNickname(fd); + std::cout << "Fd: " << fd << " old nickname: " << oldNickname << std::endl; + + // Modify the client's nickname + client::modify_client(fd, newNickname); + + // print the name of the client after changing it + std::cout << "Fd: " << fd << " new nickname: " << getClientNickname(fd) << std::endl; + + // Notify other clients about the nickname change + std::string notice = ":" + oldNickname + "!" + oldNickname + "@" + getClientHostName(fd) + " NICK :" + newNickname + "\n\r"; + for (std::vector::const_iterator it = clients.begin(); it != clients.end(); ++it) { + if (it->getFd() != fd) { + sendMessage(it->getFd(), notice); + } + } + + // // Confirm the change to the client + // :bello!bik@88ABE6.25BF1D.D03F86.88C9BD.IP NICK :bik + std::string msg = ":" + oldNickname + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " NICK :" + getClientNickname(fd) + "\n\r"; + sendMessage(fd, msg); +} diff --git a/server.hpp b/server.hpp index 6ddd251..d3b8df5 100644 --- a/server.hpp +++ b/server.hpp @@ -33,8 +33,10 @@ class Server void joinCmd(std::vector ¶m, int fd); void privmsgCmd(std::vector& args, int fd); + void modeCmd(std::vector& args, int fd); void whoCmd(std::vector& args, int fd); void kickCmd(std::vector ¶m, int fd); + void nickCmd(std::vector ¶m, int fd); void topicCmd(std::vector ¶m, int fd); void partCmd(std::vector& args, int fd); int getClientFdByNickname(const std::string& nickname); From f183446fe0dcebc31395e391daad95b37da55b53 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sat, 27 Jul 2024 02:37:13 +0100 Subject: [PATCH 43/56] QUIT is DONE --- Makefile | 2 +- cmd.cpp | 2 ++ quitCmd.cpp | 27 +++++++++++++++++++++++++++ server.hpp | 1 + 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 quitCmd.cpp diff --git a/Makefile b/Makefile index 766bff7..c99c963 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp whoCmd.cpp privmsgCmd.cpp \ - partCmd.cpp modeCmd.cpp nickCmd.cpp + partCmd.cpp modeCmd.cpp nickCmd.cpp quitCmd.cpp #listCmd.cpp OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/cmd.cpp b/cmd.cpp index e9163e7..ee5deb7 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -42,6 +42,8 @@ void Server::command(int fd) { nickCmd(res, fd); else if (command.compare("mode") == 0) modeCmd(res, fd); + else if (command.compare("quit") == 0) + quitCmd(res, fd); else { std::string msg = "421 " + getClientNickname(fd) + " " + command + " :Unknown command\n"; sendMessage(fd, msg); diff --git a/quitCmd.cpp b/quitCmd.cpp new file mode 100644 index 0000000..c34aefa --- /dev/null +++ b/quitCmd.cpp @@ -0,0 +1,27 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::quitCmd(std::vector& args, int fd) { + if (args.size() == 0) { + std::string msg = "QUIT :Leaving\n"; + sendMessage(fd, msg); + return; + } + + const std::vector& clients = client::get_clients(); + // notify all clients that the user is leaving + // :simo!simo@88ABE6.25BF1D.D03F86.88C9BD.IP QUIT :Quit: #cha + std::string notice = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " QUIT :Quit: " + args[0] + "\n"; + for (std::vector::const_iterator it = clients.begin(); it != clients.end(); ++it) { + if (it->getFd() != fd) { + sendMessage(it->getFd(), notice); + } + } + + std::string msg = "QUIT :" + args[0] + "\n"; + sendMessage(fd, msg); +} \ No newline at end of file diff --git a/server.hpp b/server.hpp index d3b8df5..4ec0346 100644 --- a/server.hpp +++ b/server.hpp @@ -39,6 +39,7 @@ class Server void nickCmd(std::vector ¶m, int fd); void topicCmd(std::vector ¶m, int fd); void partCmd(std::vector& args, int fd); + void quitCmd(std::vector& args, int fd); int getClientFdByNickname(const std::string& nickname); std::string getNameId(int fd); void joinMessage(int fd, const std::string &channelName); From 627dd0ae42926698d58d2260f6a7ea079c5a56b5 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sat, 27 Jul 2024 02:42:29 +0100 Subject: [PATCH 44/56] Start implementing INVITE command --- Makefile | 2 +- cmd.cpp | 2 ++ inviteCmd.cpp | 15 +++++++++++++++ server.hpp | 1 + 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 inviteCmd.cpp diff --git a/Makefile b/Makefile index c99c963..5d7123c 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ NAME = ircserv # Change this to your desired executable name CC = c++ # Change this if your compiler is not g++ CFLAGS = -Wall -Wextra -Werror -std=c++98 SRC = irc_server.cpp server.cpp client.cpp cmd.cpp Channel.cpp joinCmd.cpp utils.cpp kickCmd.cpp topicCmd.cpp whoCmd.cpp privmsgCmd.cpp \ - partCmd.cpp modeCmd.cpp nickCmd.cpp quitCmd.cpp #listCmd.cpp + partCmd.cpp modeCmd.cpp nickCmd.cpp quitCmd.cpp inviteCmd.cpp #listCmd.cpp OBJ = ${SRC:.cpp=.o} all: ${NAME} diff --git a/cmd.cpp b/cmd.cpp index ee5deb7..8311727 100644 --- a/cmd.cpp +++ b/cmd.cpp @@ -42,6 +42,8 @@ void Server::command(int fd) { nickCmd(res, fd); else if (command.compare("mode") == 0) modeCmd(res, fd); + else if (command.compare("invite") == 0) + inviteCmd(res, fd); else if (command.compare("quit") == 0) quitCmd(res, fd); else { diff --git a/inviteCmd.cpp b/inviteCmd.cpp new file mode 100644 index 0000000..c7f118c --- /dev/null +++ b/inviteCmd.cpp @@ -0,0 +1,15 @@ +#include "server.hpp" +#include "client.hpp" +#include +#include +#include +#include "utils.hpp" + +void Server::inviteCmd(std::vector& args, int fd) { + // start implementation invite command + if (args.size() < 2) { + std::string msg = "461 " + getClientNickname(fd) + " INVITE :Not enough parameters\n"; + sendMessage(fd, msg); + return; + } +} \ No newline at end of file diff --git a/server.hpp b/server.hpp index 4ec0346..c3f26ed 100644 --- a/server.hpp +++ b/server.hpp @@ -39,6 +39,7 @@ class Server void nickCmd(std::vector ¶m, int fd); void topicCmd(std::vector ¶m, int fd); void partCmd(std::vector& args, int fd); + void inviteCmd(std::vector& args, int fd); void quitCmd(std::vector& args, int fd); int getClientFdByNickname(const std::string& nickname); std::string getNameId(int fd); From 0cc3d303e1255c49da1c35261387ef3f155e5351 Mon Sep 17 00:00:00 2001 From: Ayoub Et-tass Date: Sat, 27 Jul 2024 22:58:07 +0100 Subject: [PATCH 45/56] Add MODE command but still some errors to fix --- Channel.cpp | 4 +- Channel.hpp | 2 +- joinCmd.cpp | 145 ++++++++++------------------------- modeCmd.cpp | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++-- server.cpp | 7 +- server.hpp | 17 +++- whocmd.cpp | 3 +- 7 files changed, 278 insertions(+), 117 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 2c6ac32..0f3a196 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -56,8 +56,8 @@ void Channel::setClients(int id, const std::string &userName) { clients[id].set_nickname(userName); } -void Channel::setOperators(int op) { - operators.push_back(op); +void Channel::setOperators(const std::vector &op) { + operators = op; } void Channel::setChPassword(std::string channelPassword) { diff --git a/Channel.hpp b/Channel.hpp index cb165cd..a08d5b6 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -30,7 +30,7 @@ class Channel { void setTopic(std::string channelTopic); // void setClients(std::map channelClients); void setClients(int id, const std::string &userName); - void setOperators(int op); + void setOperators(const std::vector& op); void setChPassword(std::string channelPassword); void setChannelType(int channelType); void setHasPassword(int hasPassword); diff --git a/joinCmd.cpp b/joinCmd.cpp index 77a1004..b9a8479 100644 --- a/joinCmd.cpp +++ b/joinCmd.cpp @@ -53,7 +53,7 @@ void Server::JoinMessage(int fd, const std::string &channelName) { first = false; message2 += "@" + clientIt->second.getNickname() + "!" + clientIt->second.getNickname() + "@" + getClientHostName(fd); } - message2 += "\n"; + message2 += "\r\n"; globmsg += message2; std::string message3 = ":" + getClientHostName(fd) + " 366 " + getClientNickname(fd) + " " + channelName + " :End of /NAMES list.\r\n"; @@ -88,12 +88,28 @@ void Server::joinCmd(std::vector ¶m, int fd) { if (channelCreated) { // Create the channel if it doesn't exist setupChannel(channelName, fd, (param.size() == 2) ? param[1] : ""); + + // Add the client as a moderator by default + Channel &channel = channels[channelName]; + std::vector operators = channel.getOperators(); + if (std::find(operators.begin(), operators.end(), fd) == operators.end()) { + operators.push_back(fd); + channel.setOperators(operators); + } + + // Debug output to check moderators + std::cout << "Channel \"" << channelName << "\" created. Debug output:" << std::endl; + std::cout << "Current moderators for channel " << channelName << ": "; + std::vector::iterator it = operators.begin(); + while (it != operators.end()) { + std::cout << *it << " "; + ++it; + } + std::cout << std::endl; + JoinMessage(fd, channelName); - } - else { - std::cout << "Channel \"" << channelName << "\" already exists \""<< std::endl; - // std::cout << "client name is : " << getClientNickname(fd) << std::endl; - // std::cout << "channel name is : " << channelName << std::endl; + } else { + std::cout << "Channel \"" << channelName << "\" already exists." << std::endl; // Get reference to the existing channel Channel &channel = channels[channelName]; @@ -101,108 +117,25 @@ void Server::joinCmd(std::vector ¶m, int fd) { // Add the client to the channel channel.setClients(fd, getClientNickname(fd)); + // Add the client as a moderator if they are not already + std::vector operators = channel.getOperators(); + if (std::find(operators.begin(), operators.end(), fd) == operators.end()) { + operators.push_back(fd); + channel.setOperators(operators); + } + + // Debug output to check moderators + std::cout << "Channel \"" << channelName << "\" joined. Debug output:" << std::endl; + std::cout << "Current moderators for channel " << channelName << ": "; + std::vector::iterator it = operators.begin(); + while (it != operators.end()) { + std::cout << *it << " "; + ++it; + } + std::cout << std::endl; + // Inform the client about joining the channel JoinMessage(fd, channelName); } } - -// void Server::joinCmd(std::vector ¶m, int fd) { -// // Debugging output for received parameters -// std::cout << "Received /join command with parameters: "; -// for (size_t i = 0; i < param.size(); ++i) { -// std::cout << param[i] << " "; -// } -// std::cout << std::endl; - -// // Check if the param vector is empty or invalid -// if (param.empty() || param[0][0] != '#' || (param[0].size() == 1)) { -// std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; -// sendMessage(fd, message); -// std::cout << "Error: Not enough parameters or invalid channel name." << std::endl; -// return; -// } - -// // Split the parameters -// std::vector chn = split(param[0], ','); -// std::vector key; -// if (param.size() == 2) { -// key = split(param[1], ','); -// } - -// std::cout << "Channel names to join: "; -// for (size_t i = 0; i < chn.size(); ++i) { -// std::cout << chn[i] << " "; -// } -// std::cout << std::endl; - -// std::cout << "Keys provided: "; -// for (size_t i = 0; i < key.size(); ++i) { -// std::cout << key[i] << " "; -// } -// std::cout << std::endl; - -// // Loop through each channel name -// for (size_t i = 0; i < chn.size(); ++i) { -// std::map::iterator it = channels.find(chn[i]); -// bool channelCreated = (it == channels.end()); - -// // If channel doesn't exist, create it -// if (channelCreated) { -// setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); -// JoinMessage(fd, chn[i]); -// continue; -// } - -// Channel &channel = it->second; - -// // Check if client is already in the channel -// if (channel.isClientInChannel(fd)) { -// std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; -// sendMessage(fd, message); -// continue; -// } - -// // Handle invite-only or password-protected channels -// if (channel.getChannelType() == 1) { -// if (channel.getInvitedList().empty() && param.size() != 2) { -// std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; -// sendMessage(fd, message); -// continue; -// } - -// if (channel.isClientInvited(fd)) { -// channel.setClients(fd, getClientNickname(fd)); -// JoinMessage(fd, chn[i]); -// continue; -// } - -// if (channel.getHasPassword() == 1) { -// if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { -// channel.setClients(fd, getClientNickname(fd)); -// JoinMessage(fd, chn[i]); -// } else { -// std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; -// sendMessage(fd, message); -// } -// continue; -// } -// } - -// // Handle password for existing channels -// if (channel.getHasPassword() == 1) { -// if (key.size() > i && channel.getChPassword() == key[i]) { -// channel.setClients(fd, getClientNickname(fd)); -// JoinMessage(fd, chn[i]); -// } else { -// std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; -// sendMessage(fd, message); -// } -// continue; -// } - -// // Add the client to the channel and send a join message -// channel.setClients(fd, getClientNickname(fd)); -// JoinMessage(fd, chn[i]); -// } -// } \ No newline at end of file diff --git a/modeCmd.cpp b/modeCmd.cpp index a02e8b9..3f7f70a 100644 --- a/modeCmd.cpp +++ b/modeCmd.cpp @@ -5,13 +5,220 @@ #include #include "utils.hpp" -void Server::modeCmd(std::vector ¶m, int fd) { - if (param.size() < 2) { - std::string message = "461 " + getClientNickname(fd) + " MODE :Not enough parameters\n"; +int Server::IsModerator(Channel &ch, std::string nickname) { + std::vector v = ch.getOperators(); + int i = ch.getClientID(nickname); + if (std::find(v.begin(), v.end(), i) != v.end()) + return 1; + return 0; +} + +void Server::RemoveModerator(Channel &ch, std::string nickname) { + std::vector v = ch.getOperators(); + int i = ch.getClientID(nickname); + v.erase(std::remove(v.begin(), v.end(), i), v.end()); + ch.setOperators(v); +} + + + + +// Validate the MODE command parameters +bool Server::validateModeCommand(const std::vector &vec, int fd) { + std::string message; + + if (vec.size() < 2) { + message = ":" + getClientNickname(fd) + " 461 * :Not enough parameters\n"; + sendMessage(fd, message); + return false; + } + + std::map::iterator it = channels.find(vec[0]); + if (it == channels.end()) { + message = ":" + getClientNickname(fd) + " 403 * :No such channel\n"; + sendMessage(fd, message); + return false; + } + + if (vec.size() == 1) { + message = ":" + getClientNickname(fd) + " 324 * :Not enough parameters\n"; + sendMessage(fd, message); + return false; + } + + return true; +} + +// Check if the client is a channel operator +bool Server::isOperator(int fd, Channel &channel) { + std::vector operators = channel.getOperators(); + return (std::find(operators.begin(), operators.end(), fd) != operators.end()); +} + +// Handle mode changes based on the mode command +void Server::handleModeChange(const std::vector &vec, int fd, Channel &channel) { + std::string message; + int clientId = channel.getClientID(vec[2]); + + if (vec[1][0] == '+') { + if (vec[1][1] == 'i') { + handlePrivateMode(channel, fd); + } else if (vec[1][1] == 'k') { + handlePasswordMode(channel, vec, fd, clientId); + } else if (vec[1][1] == 'o') { + handleOperatorMode(channel, vec, fd, clientId); + } + } else if (vec[1][0] == '-') { + if (vec[1][1] == 'i') { + handlePublicMode(channel, fd); + } else if (vec[1][1] == 'k') { + handleRemovePasswordMode(channel, fd); + } else if (vec[1][1] == 'o') { + handleRemoveOperatorMode(channel, vec, fd, clientId); + } + } +} + +// Handle the private mode (+i) +void Server::handlePrivateMode(Channel &channel, int fd) { + std::string message; + + if (channel.getChannelType() == 1) { + message = ":" + getClientNickname(fd) + " 342 * :Channel is already private\n"; + sendMessage(fd, message); + } else { + channel.setChannelType(1); + channel.setHasPassword(0); + channel.setChPassword(""); + message = ":" + getClientNickname(fd) + " 342 * :Channel is private now\n"; + sendMessage(fd, message); + } +} + +// Handle the password mode (+k) +void Server::handlePasswordMode(Channel &channel, const std::vector &vec, int fd, int clientId) { + std::string message; + + if (clientId == -1) { + message = ":" + getClientNickname(fd) + " 401 * :No such nick/channel\n"; + sendMessage(fd, message); + } else { + if (vec.size() == 3) { + channel.setChannelType(1); + channel.setChPassword(vec[2]); + message = ":" + getClientNickname(fd) + " 400 * :We have set the password\n"; + sendMessage(fd, message); + } else { + message = ":" + getClientNickname(fd) + " 696 * :Invalid mode params\n"; + sendMessage(fd, message); + } + } +} + +// Handle the operator mode (+o) +void Server::handleOperatorMode(Channel &channel, const std::vector &vec, int fd, int clientId) { + std::string message; + + if (vec.size() == 3) { + if (clientId != -1) { + if (IsModerator(channel, vec[2]) == 1) { + message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is already a moderator\n"; + sendMessage(fd, message); + } else { + std::vector ops = channel.getOperators(); + ops.push_back(clientId); + channel.setOperators(ops); + message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is a moderator now\n"; + sendMessage(fd, message); + } + } else { + message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is not a member of channel\n"; + sendMessage(fd, message); + } + } else { + message = ":" + getClientNickname(fd) + " 696 * :Invalid mode params\n"; sendMessage(fd, message); - return; } +} - // Implement the mode command here +// Handle the public mode (-i) +void Server::handlePublicMode(Channel &channel, int fd) { + std::string message; + + if (channel.getChannelType() == 0) { + message = ":" + getClientNickname(fd) + " 342 * :Channel is already public\n"; + sendMessage(fd, message); + } else { + channel.setChannelType(0); + message = ":" + getClientNickname(fd) + " 342 * :Channel is public now\n"; + sendMessage(fd, message); + } } +// Handle the remove password mode (-k) +void Server::handleRemovePasswordMode(Channel &channel, int fd) { + std::string message; + + if (channel.getChannelType() == 1 && !channel.getChPassword().empty()) { + channel.setChPassword(""); + message = ":" + getClientNickname(fd) + " 400 * :Password removed\n"; + sendMessage(fd, message); + } else { + message = ":" + getClientNickname(fd) + " 342 * :Channel is not password protected\n"; + sendMessage(fd, message); + } +} + +// Handle the remove operator mode (-o) +void Server::handleRemoveOperatorMode(Channel &channel, const std::vector &vec, int fd, int clientId) { + std::string message; + + if (vec.size() == 3) { + if (clientId != -1) { + std::vector ops = channel.getOperators(); + std::vector::iterator it = std::find(ops.begin(), ops.end(), clientId); + if (it != ops.end()) { + ops.erase(it); + channel.setOperators(ops); + message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is no longer a moderator\n"; + sendMessage(fd, message); + } else { + message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is not a moderator\n"; + sendMessage(fd, message); + } + } else { + message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is not a member of channel\n"; + sendMessage(fd, message); + } + } else { + message = ":" + getClientNickname(fd) + " 696 * :Invalid mode params\n"; + sendMessage(fd, message); + } +} + +// Main function to handle the MODE command +void Server::modeCmd(std::vector &vec, int fd) { + std::map::iterator it; + std::string message; + + std::cout << "Received mode command: " << std::endl; + std::cout << "Channel: " << vec[0] << ", Mode: " << vec[1] << std::endl; + if (vec.size() > 2) { + std::cout << "Parameter: " << vec[2] << std::endl; + } + + if (!validateModeCommand(vec, fd)) return; + + it = channels.find(vec[0]); + Channel &channel = it->second; + + if (!isOperator(fd, channel)) { + message = ":" + getClientNickname(fd) + " 482 * :You're not a channel operator\n"; + sendMessage(fd, message); + return; + } + + if (vec[1].size() == 2) { + handleModeChange(vec, fd, channel); + } +} \ No newline at end of file diff --git a/server.cpp b/server.cpp index bad394b..9b2f793 100644 --- a/server.cpp +++ b/server.cpp @@ -100,4 +100,9 @@ std::string Server::getNameId(int fd) { std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; sendMessage(fd, message); return "ERROR"; -} \ No newline at end of file +} + +// bool Server::isClientModerator(Channel &ch, int clientID) { +// std::vector operators = ch.getOperators(); +// return std::find(operators.begin(), operators.end(), clientID) != operators.end(); +// } diff --git a/server.hpp b/server.hpp index c3f26ed..0a84c98 100644 --- a/server.hpp +++ b/server.hpp @@ -33,7 +33,8 @@ class Server void joinCmd(std::vector ¶m, int fd); void privmsgCmd(std::vector& args, int fd); - void modeCmd(std::vector& args, int fd); + // void modeCmd(std::vector& args, int fd); + void modeCmd(std::vector ¶m, int fd); void whoCmd(std::vector& args, int fd); void kickCmd(std::vector ¶m, int fd); void nickCmd(std::vector ¶m, int fd); @@ -51,6 +52,20 @@ class Server std::string getClientNickname(int fd); std::string getClientHostName(int fd); + int IsModerator(Channel &ch, std::string nickname); + void RemoveModerator(Channel &ch, std::string nickname); + // bool isClientModerator(Channel &ch, int clientID); + + void handlePrivateMode(Channel &channel, int fd); + void handlePasswordMode(Channel &channel, const std::vector &vec, int fd, int clientId); + void handleOperatorMode(Channel &channel, const std::vector &vec, int fd, int clientId); + void handlePublicMode(Channel &channel, int fd); + void handleRemovePasswordMode(Channel &channel, int fd); + void handleRemoveOperatorMode(Channel &channel, const std::vector &vec, int fd, int clientId); + bool validateModeCommand(const std::vector &vec, int fd); + bool isOperator(int fd, Channel &channel); + void handleModeChange(const std::vector &vec, int fd, Channel &channel); + class IsClientWithFd { public: IsClientWithFd(int fd) : fd_(fd) {} diff --git a/whocmd.cpp b/whocmd.cpp index d84c9ad..a1b665d 100644 --- a/whocmd.cpp +++ b/whocmd.cpp @@ -25,7 +25,7 @@ void Server::whoCmd(std::vector& args, int fd) { Channel& channel = it->second; std::string msg; - msg = ":" + getClientHostName(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :@"; + msg = ":" + getClientHostName(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :"; // List all clients in the channel bool first = true; @@ -40,6 +40,7 @@ void Server::whoCmd(std::vector& args, int fd) { } msg += "\n"; + std::cout << "The message is : " << msg << std::endl; // End of list message msg += ":" + getClientNickname(fd) + " 366 " + getClientNickname(fd) + " " + channelName + " :End of /WHO list.\n"; From 76eca602523c9b159705195f6c8abf8a33140e5c Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sun, 28 Jul 2024 00:00:25 +0100 Subject: [PATCH 46/56] Add the operators to their vector in the channel --- Channel.cpp | 14 +++++++++++++- Channel.hpp | 3 +++ joinCmd.cpp | 12 ++++++++++-- whocmd.cpp | 12 ++++++++++-- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 2c6ac32..e968261 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -157,4 +157,16 @@ bool Channel::isClientInvited(int clientId) const{ void Channel::removeClient(int fd) { clients.erase(fd); -} \ No newline at end of file +} + +void Channel::addOperator(int id) { + operators.push_back(id); +} + +void Channel::removeOperator(int id) { + operators.erase(std::remove(operators.begin(), operators.end(), id), operators.end()); +} + +bool Channel::isOperator(int id) { + return std::find(operators.begin(), operators.end(), id) != operators.end(); +} diff --git a/Channel.hpp b/Channel.hpp index cb165cd..337c5ff 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -53,6 +53,9 @@ class Channel { const std::map &getClientsFromChannel() const; void removeClient(int fd); + void addOperator(int id); + void removeOperator(int id); + bool isOperator(int id); }; diff --git a/joinCmd.cpp b/joinCmd.cpp index 77a1004..152d2cc 100644 --- a/joinCmd.cpp +++ b/joinCmd.cpp @@ -7,7 +7,7 @@ void Server::setupChannel(const std::string &channelName, int fd, const std::string &password) { if (channels.find(channelName) == channels.end()) { - Channel newChannel(channelName, 0); + Channel newChannel(channelName, 0); channels[channelName] = newChannel; } else { // Ensure not to reset the topic if the channel already exists @@ -51,7 +51,13 @@ void Server::JoinMessage(int fd, const std::string &channelName) { message2 += " "; } first = false; - message2 += "@" + clientIt->second.getNickname() + "!" + clientIt->second.getNickname() + "@" + getClientHostName(fd); + // :luna.AfterNET.Org 353 simo = #chan :simo!dd@88ABE6.25BF1D.D03F86.88C9BD.IP @bello!dd@88ABE6.25BF1D.D03F86.88C9BD.I + // if the client is an operator + if (channel.isOperator(clientIt->first)) { + message2 += "@" + clientIt->second.getNickname() + "!" + clientIt->second.getNickname() + "@" + getClientHostName(clientIt->first); + } else { + message2 += clientIt->second.getNickname() + "!" + clientIt->second.getNickname() + "@" + getClientHostName(clientIt->first); + } } message2 += "\n"; globmsg += message2; @@ -88,6 +94,8 @@ void Server::joinCmd(std::vector ¶m, int fd) { if (channelCreated) { // Create the channel if it doesn't exist setupChannel(channelName, fd, (param.size() == 2) ? param[1] : ""); + // add the client to the operator list + channels[channelName].addOperator(fd); JoinMessage(fd, channelName); } else { diff --git a/whocmd.cpp b/whocmd.cpp index d84c9ad..7546ce4 100644 --- a/whocmd.cpp +++ b/whocmd.cpp @@ -25,7 +25,7 @@ void Server::whoCmd(std::vector& args, int fd) { Channel& channel = it->second; std::string msg; - msg = ":" + getClientHostName(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :@"; + msg = ":" + getClientHostName(fd) + " 353 " + getClientNickname(fd) + " = " + channelName + " :"; // List all clients in the channel bool first = true; @@ -36,7 +36,15 @@ void Server::whoCmd(std::vector& args, int fd) { msg += " "; } first = false; - msg += clientIt->second.getNickname(); // Adjust if you need more details + // msg += clientIt->second.getNickname(); // Adjust if you need more details + // check if the client is an operator + if (channel.isOperator(clientIt->first)) { + std::cout << "Operator: " << clientIt->second.getNickname() << std::endl; + msg += "@" + clientIt->second.getNickname(); + } else { + msg += clientIt->second.getNickname(); + std::cout << "Not Operator: " << clientIt->second.getNickname() << std::endl; + } } msg += "\n"; From d6109af32dde3b5ad79a0a582750ecaaceacd582 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sun, 28 Jul 2024 00:29:33 +0100 Subject: [PATCH 47/56] Add the operators to their vector in the channel 2 --- Channel.cpp | 4 +- Channel.hpp | 2 +- joinCmd.cpp | 126 +++++++++++++++++++++++++----- modeCmd.cpp | 217 ++-------------------------------------------------- server.cpp | 7 +- server.hpp | 17 +--- whocmd.cpp | 1 - 7 files changed, 116 insertions(+), 258 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 1fe1494..e968261 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -56,8 +56,8 @@ void Channel::setClients(int id, const std::string &userName) { clients[id].set_nickname(userName); } -void Channel::setOperators(const std::vector &op) { - operators = op; +void Channel::setOperators(int op) { + operators.push_back(op); } void Channel::setChPassword(std::string channelPassword) { diff --git a/Channel.hpp b/Channel.hpp index 0b3cf4f..337c5ff 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -30,7 +30,7 @@ class Channel { void setTopic(std::string channelTopic); // void setClients(std::map channelClients); void setClients(int id, const std::string &userName); - void setOperators(const std::vector& op); + void setOperators(int op); void setChPassword(std::string channelPassword); void setChannelType(int channelType); void setHasPassword(int hasPassword); diff --git a/joinCmd.cpp b/joinCmd.cpp index 5adff44..152d2cc 100644 --- a/joinCmd.cpp +++ b/joinCmd.cpp @@ -59,7 +59,7 @@ void Server::JoinMessage(int fd, const std::string &channelName) { message2 += clientIt->second.getNickname() + "!" + clientIt->second.getNickname() + "@" + getClientHostName(clientIt->first); } } - message2 += "\r\n"; + message2 += "\n"; globmsg += message2; std::string message3 = ":" + getClientHostName(fd) + " 366 " + getClientNickname(fd) + " " + channelName + " :End of /NAMES list.\r\n"; @@ -97,8 +97,11 @@ void Server::joinCmd(std::vector ¶m, int fd) { // add the client to the operator list channels[channelName].addOperator(fd); JoinMessage(fd, channelName); - } else { - std::cout << "Channel \"" << channelName << "\" already exists." << std::endl; + } + else { + std::cout << "Channel \"" << channelName << "\" already exists \""<< std::endl; + // std::cout << "client name is : " << getClientNickname(fd) << std::endl; + // std::cout << "channel name is : " << channelName << std::endl; // Get reference to the existing channel Channel &channel = channels[channelName]; @@ -106,25 +109,108 @@ void Server::joinCmd(std::vector ¶m, int fd) { // Add the client to the channel channel.setClients(fd, getClientNickname(fd)); - // Add the client as a moderator if they are not already - std::vector operators = channel.getOperators(); - if (std::find(operators.begin(), operators.end(), fd) == operators.end()) { - operators.push_back(fd); - channel.setOperators(operators); - } - - // Debug output to check moderators - std::cout << "Channel \"" << channelName << "\" joined. Debug output:" << std::endl; - std::cout << "Current moderators for channel " << channelName << ": "; - std::vector::iterator it = operators.begin(); - while (it != operators.end()) { - std::cout << *it << " "; - ++it; - } - std::cout << std::endl; - // Inform the client about joining the channel JoinMessage(fd, channelName); } } + +// void Server::joinCmd(std::vector ¶m, int fd) { +// // Debugging output for received parameters +// std::cout << "Received /join command with parameters: "; +// for (size_t i = 0; i < param.size(); ++i) { +// std::cout << param[i] << " "; +// } +// std::cout << std::endl; + +// // Check if the param vector is empty or invalid +// if (param.empty() || param[0][0] != '#' || (param[0].size() == 1)) { +// std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; +// sendMessage(fd, message); +// std::cout << "Error: Not enough parameters or invalid channel name." << std::endl; +// return; +// } + +// // Split the parameters +// std::vector chn = split(param[0], ','); +// std::vector key; +// if (param.size() == 2) { +// key = split(param[1], ','); +// } + +// std::cout << "Channel names to join: "; +// for (size_t i = 0; i < chn.size(); ++i) { +// std::cout << chn[i] << " "; +// } +// std::cout << std::endl; + +// std::cout << "Keys provided: "; +// for (size_t i = 0; i < key.size(); ++i) { +// std::cout << key[i] << " "; +// } +// std::cout << std::endl; + +// // Loop through each channel name +// for (size_t i = 0; i < chn.size(); ++i) { +// std::map::iterator it = channels.find(chn[i]); +// bool channelCreated = (it == channels.end()); + +// // If channel doesn't exist, create it +// if (channelCreated) { +// setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); +// JoinMessage(fd, chn[i]); +// continue; +// } + +// Channel &channel = it->second; + +// // Check if client is already in the channel +// if (channel.isClientInChannel(fd)) { +// std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; +// sendMessage(fd, message); +// continue; +// } + +// // Handle invite-only or password-protected channels +// if (channel.getChannelType() == 1) { +// if (channel.getInvitedList().empty() && param.size() != 2) { +// std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; +// sendMessage(fd, message); +// continue; +// } + +// if (channel.isClientInvited(fd)) { +// channel.setClients(fd, getClientNickname(fd)); +// JoinMessage(fd, chn[i]); +// continue; +// } + +// if (channel.getHasPassword() == 1) { +// if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { +// channel.setClients(fd, getClientNickname(fd)); +// JoinMessage(fd, chn[i]); +// } else { +// std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; +// sendMessage(fd, message); +// } +// continue; +// } +// } + +// // Handle password for existing channels +// if (channel.getHasPassword() == 1) { +// if (key.size() > i && channel.getChPassword() == key[i]) { +// channel.setClients(fd, getClientNickname(fd)); +// JoinMessage(fd, chn[i]); +// } else { +// std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; +// sendMessage(fd, message); +// } +// continue; +// } + +// // Add the client to the channel and send a join message +// channel.setClients(fd, getClientNickname(fd)); +// JoinMessage(fd, chn[i]); +// } +// } \ No newline at end of file diff --git a/modeCmd.cpp b/modeCmd.cpp index 3f7f70a..a02e8b9 100644 --- a/modeCmd.cpp +++ b/modeCmd.cpp @@ -5,220 +5,13 @@ #include #include "utils.hpp" -int Server::IsModerator(Channel &ch, std::string nickname) { - std::vector v = ch.getOperators(); - int i = ch.getClientID(nickname); - if (std::find(v.begin(), v.end(), i) != v.end()) - return 1; - return 0; -} - -void Server::RemoveModerator(Channel &ch, std::string nickname) { - std::vector v = ch.getOperators(); - int i = ch.getClientID(nickname); - v.erase(std::remove(v.begin(), v.end(), i), v.end()); - ch.setOperators(v); -} - - - - -// Validate the MODE command parameters -bool Server::validateModeCommand(const std::vector &vec, int fd) { - std::string message; - - if (vec.size() < 2) { - message = ":" + getClientNickname(fd) + " 461 * :Not enough parameters\n"; - sendMessage(fd, message); - return false; - } - - std::map::iterator it = channels.find(vec[0]); - if (it == channels.end()) { - message = ":" + getClientNickname(fd) + " 403 * :No such channel\n"; - sendMessage(fd, message); - return false; - } - - if (vec.size() == 1) { - message = ":" + getClientNickname(fd) + " 324 * :Not enough parameters\n"; - sendMessage(fd, message); - return false; - } - - return true; -} - -// Check if the client is a channel operator -bool Server::isOperator(int fd, Channel &channel) { - std::vector operators = channel.getOperators(); - return (std::find(operators.begin(), operators.end(), fd) != operators.end()); -} - -// Handle mode changes based on the mode command -void Server::handleModeChange(const std::vector &vec, int fd, Channel &channel) { - std::string message; - int clientId = channel.getClientID(vec[2]); - - if (vec[1][0] == '+') { - if (vec[1][1] == 'i') { - handlePrivateMode(channel, fd); - } else if (vec[1][1] == 'k') { - handlePasswordMode(channel, vec, fd, clientId); - } else if (vec[1][1] == 'o') { - handleOperatorMode(channel, vec, fd, clientId); - } - } else if (vec[1][0] == '-') { - if (vec[1][1] == 'i') { - handlePublicMode(channel, fd); - } else if (vec[1][1] == 'k') { - handleRemovePasswordMode(channel, fd); - } else if (vec[1][1] == 'o') { - handleRemoveOperatorMode(channel, vec, fd, clientId); - } - } -} - -// Handle the private mode (+i) -void Server::handlePrivateMode(Channel &channel, int fd) { - std::string message; - - if (channel.getChannelType() == 1) { - message = ":" + getClientNickname(fd) + " 342 * :Channel is already private\n"; - sendMessage(fd, message); - } else { - channel.setChannelType(1); - channel.setHasPassword(0); - channel.setChPassword(""); - message = ":" + getClientNickname(fd) + " 342 * :Channel is private now\n"; - sendMessage(fd, message); - } -} - -// Handle the password mode (+k) -void Server::handlePasswordMode(Channel &channel, const std::vector &vec, int fd, int clientId) { - std::string message; - - if (clientId == -1) { - message = ":" + getClientNickname(fd) + " 401 * :No such nick/channel\n"; - sendMessage(fd, message); - } else { - if (vec.size() == 3) { - channel.setChannelType(1); - channel.setChPassword(vec[2]); - message = ":" + getClientNickname(fd) + " 400 * :We have set the password\n"; - sendMessage(fd, message); - } else { - message = ":" + getClientNickname(fd) + " 696 * :Invalid mode params\n"; - sendMessage(fd, message); - } - } -} - -// Handle the operator mode (+o) -void Server::handleOperatorMode(Channel &channel, const std::vector &vec, int fd, int clientId) { - std::string message; - - if (vec.size() == 3) { - if (clientId != -1) { - if (IsModerator(channel, vec[2]) == 1) { - message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is already a moderator\n"; - sendMessage(fd, message); - } else { - std::vector ops = channel.getOperators(); - ops.push_back(clientId); - channel.setOperators(ops); - message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is a moderator now\n"; - sendMessage(fd, message); - } - } else { - message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is not a member of channel\n"; - sendMessage(fd, message); - } - } else { - message = ":" + getClientNickname(fd) + " 696 * :Invalid mode params\n"; - sendMessage(fd, message); - } -} - -// Handle the public mode (-i) -void Server::handlePublicMode(Channel &channel, int fd) { - std::string message; - - if (channel.getChannelType() == 0) { - message = ":" + getClientNickname(fd) + " 342 * :Channel is already public\n"; - sendMessage(fd, message); - } else { - channel.setChannelType(0); - message = ":" + getClientNickname(fd) + " 342 * :Channel is public now\n"; - sendMessage(fd, message); - } -} - -// Handle the remove password mode (-k) -void Server::handleRemovePasswordMode(Channel &channel, int fd) { - std::string message; - - if (channel.getChannelType() == 1 && !channel.getChPassword().empty()) { - channel.setChPassword(""); - message = ":" + getClientNickname(fd) + " 400 * :Password removed\n"; - sendMessage(fd, message); - } else { - message = ":" + getClientNickname(fd) + " 342 * :Channel is not password protected\n"; +void Server::modeCmd(std::vector ¶m, int fd) { + if (param.size() < 2) { + std::string message = "461 " + getClientNickname(fd) + " MODE :Not enough parameters\n"; sendMessage(fd, message); + return; } -} -// Handle the remove operator mode (-o) -void Server::handleRemoveOperatorMode(Channel &channel, const std::vector &vec, int fd, int clientId) { - std::string message; - - if (vec.size() == 3) { - if (clientId != -1) { - std::vector ops = channel.getOperators(); - std::vector::iterator it = std::find(ops.begin(), ops.end(), clientId); - if (it != ops.end()) { - ops.erase(it); - channel.setOperators(ops); - message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is no longer a moderator\n"; - sendMessage(fd, message); - } else { - message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is not a moderator\n"; - sendMessage(fd, message); - } - } else { - message = ":" + getClientNickname(fd) + " 400 * :" + "The user " + vec[2] + " is not a member of channel\n"; - sendMessage(fd, message); - } - } else { - message = ":" + getClientNickname(fd) + " 696 * :Invalid mode params\n"; - sendMessage(fd, message); - } + // Implement the mode command here } -// Main function to handle the MODE command -void Server::modeCmd(std::vector &vec, int fd) { - std::map::iterator it; - std::string message; - - std::cout << "Received mode command: " << std::endl; - std::cout << "Channel: " << vec[0] << ", Mode: " << vec[1] << std::endl; - if (vec.size() > 2) { - std::cout << "Parameter: " << vec[2] << std::endl; - } - - if (!validateModeCommand(vec, fd)) return; - - it = channels.find(vec[0]); - Channel &channel = it->second; - - if (!isOperator(fd, channel)) { - message = ":" + getClientNickname(fd) + " 482 * :You're not a channel operator\n"; - sendMessage(fd, message); - return; - } - - if (vec[1].size() == 2) { - handleModeChange(vec, fd, channel); - } -} \ No newline at end of file diff --git a/server.cpp b/server.cpp index 9b2f793..bad394b 100644 --- a/server.cpp +++ b/server.cpp @@ -100,9 +100,4 @@ std::string Server::getNameId(int fd) { std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; sendMessage(fd, message); return "ERROR"; -} - -// bool Server::isClientModerator(Channel &ch, int clientID) { -// std::vector operators = ch.getOperators(); -// return std::find(operators.begin(), operators.end(), clientID) != operators.end(); -// } +} \ No newline at end of file diff --git a/server.hpp b/server.hpp index 0a84c98..c3f26ed 100644 --- a/server.hpp +++ b/server.hpp @@ -33,8 +33,7 @@ class Server void joinCmd(std::vector ¶m, int fd); void privmsgCmd(std::vector& args, int fd); - // void modeCmd(std::vector& args, int fd); - void modeCmd(std::vector ¶m, int fd); + void modeCmd(std::vector& args, int fd); void whoCmd(std::vector& args, int fd); void kickCmd(std::vector ¶m, int fd); void nickCmd(std::vector ¶m, int fd); @@ -52,20 +51,6 @@ class Server std::string getClientNickname(int fd); std::string getClientHostName(int fd); - int IsModerator(Channel &ch, std::string nickname); - void RemoveModerator(Channel &ch, std::string nickname); - // bool isClientModerator(Channel &ch, int clientID); - - void handlePrivateMode(Channel &channel, int fd); - void handlePasswordMode(Channel &channel, const std::vector &vec, int fd, int clientId); - void handleOperatorMode(Channel &channel, const std::vector &vec, int fd, int clientId); - void handlePublicMode(Channel &channel, int fd); - void handleRemovePasswordMode(Channel &channel, int fd); - void handleRemoveOperatorMode(Channel &channel, const std::vector &vec, int fd, int clientId); - bool validateModeCommand(const std::vector &vec, int fd); - bool isOperator(int fd, Channel &channel); - void handleModeChange(const std::vector &vec, int fd, Channel &channel); - class IsClientWithFd { public: IsClientWithFd(int fd) : fd_(fd) {} diff --git a/whocmd.cpp b/whocmd.cpp index c82d6cc..7546ce4 100644 --- a/whocmd.cpp +++ b/whocmd.cpp @@ -48,7 +48,6 @@ void Server::whoCmd(std::vector& args, int fd) { } msg += "\n"; - std::cout << "The message is : " << msg << std::endl; // End of list message msg += ":" + getClientNickname(fd) + " 366 " + getClientNickname(fd) + " " + channelName + " :End of /WHO list.\n"; From d2469c856eb4f064aff0a9e1c03d861a36fe09dc Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sun, 28 Jul 2024 02:34:44 +0100 Subject: [PATCH 48/56] Fixing the MODE command still just k and l, also TOPIC is updated --- Channel.cpp | 2 +- joinCmd.cpp | 110 +++-------------------------- modeCmd.cpp | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++- server.hpp | 2 +- topicCmd.cpp | 17 +++-- 5 files changed, 216 insertions(+), 110 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index e968261..edf539a 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -149,7 +149,6 @@ size_t Channel::getClientNb() const { return clients.size(); } - bool Channel::isClientInvited(int clientId) const{ bool isInvited = (inviteList.count(clientId) > 0); return isInvited; @@ -170,3 +169,4 @@ void Channel::removeOperator(int id) { bool Channel::isOperator(int id) { return std::find(operators.begin(), operators.end(), id) != operators.end(); } + diff --git a/joinCmd.cpp b/joinCmd.cpp index 152d2cc..a780363 100644 --- a/joinCmd.cpp +++ b/joinCmd.cpp @@ -106,6 +106,15 @@ void Server::joinCmd(std::vector ¶m, int fd) { // Get reference to the existing channel Channel &channel = channels[channelName]; + // Check if the channel is invite-only and if the client is invited + if (channel.getChannelType() & 2) { // Check for invite-only flag + if (!channel.isClientInvited(fd)) { + std::string message = ":" + getNameId(fd) + " 473 " + channelName + " :Cannot join channel (+i)\n"; + sendMessage(fd, message); + return; + } + } + // Add the client to the channel channel.setClients(fd, getClientNickname(fd)); @@ -113,104 +122,3 @@ void Server::joinCmd(std::vector ¶m, int fd) { JoinMessage(fd, channelName); } } - - -// void Server::joinCmd(std::vector ¶m, int fd) { -// // Debugging output for received parameters -// std::cout << "Received /join command with parameters: "; -// for (size_t i = 0; i < param.size(); ++i) { -// std::cout << param[i] << " "; -// } -// std::cout << std::endl; - -// // Check if the param vector is empty or invalid -// if (param.empty() || param[0][0] != '#' || (param[0].size() == 1)) { -// std::string message = ":" + getNameId(fd) + " 461 JOIN :Not enough parameters\n"; -// sendMessage(fd, message); -// std::cout << "Error: Not enough parameters or invalid channel name." << std::endl; -// return; -// } - -// // Split the parameters -// std::vector chn = split(param[0], ','); -// std::vector key; -// if (param.size() == 2) { -// key = split(param[1], ','); -// } - -// std::cout << "Channel names to join: "; -// for (size_t i = 0; i < chn.size(); ++i) { -// std::cout << chn[i] << " "; -// } -// std::cout << std::endl; - -// std::cout << "Keys provided: "; -// for (size_t i = 0; i < key.size(); ++i) { -// std::cout << key[i] << " "; -// } -// std::cout << std::endl; - -// // Loop through each channel name -// for (size_t i = 0; i < chn.size(); ++i) { -// std::map::iterator it = channels.find(chn[i]); -// bool channelCreated = (it == channels.end()); - -// // If channel doesn't exist, create it -// if (channelCreated) { -// setupChannel(chn[i], fd, (param.size() == 2 && key.size() > i) ? key[i] : ""); -// JoinMessage(fd, chn[i]); -// continue; -// } - -// Channel &channel = it->second; - -// // Check if client is already in the channel -// if (channel.isClientInChannel(fd)) { -// std::string message = ":" + getNameId(fd) + " 443 * :You are already in this channel\n"; -// sendMessage(fd, message); -// continue; -// } - -// // Handle invite-only or password-protected channels -// if (channel.getChannelType() == 1) { -// if (channel.getInvitedList().empty() && param.size() != 2) { -// std::string message = ":" + getNameId(fd) + " 473 * Cannot join channel (+i)\n"; -// sendMessage(fd, message); -// continue; -// } - -// if (channel.isClientInvited(fd)) { -// channel.setClients(fd, getClientNickname(fd)); -// JoinMessage(fd, chn[i]); -// continue; -// } - -// if (channel.getHasPassword() == 1) { -// if ((key.size() > i && channel.getChPassword() == key[i]) || key.empty()) { -// channel.setClients(fd, getClientNickname(fd)); -// JoinMessage(fd, chn[i]); -// } else { -// std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; -// sendMessage(fd, message); -// } -// continue; -// } -// } - -// // Handle password for existing channels -// if (channel.getHasPassword() == 1) { -// if (key.size() > i && channel.getChPassword() == key[i]) { -// channel.setClients(fd, getClientNickname(fd)); -// JoinMessage(fd, chn[i]); -// } else { -// std::string message = ":" + getNameId(fd) + " 475 * Cannot join channel (+k)\n"; -// sendMessage(fd, message); -// } -// continue; -// } - -// // Add the client to the channel and send a join message -// channel.setClients(fd, getClientNickname(fd)); -// JoinMessage(fd, chn[i]); -// } -// } \ No newline at end of file diff --git a/modeCmd.cpp b/modeCmd.cpp index a02e8b9..1e3bc29 100644 --- a/modeCmd.cpp +++ b/modeCmd.cpp @@ -7,11 +7,200 @@ void Server::modeCmd(std::vector ¶m, int fd) { if (param.size() < 2) { - std::string message = "461 " + getClientNickname(fd) + " MODE :Not enough parameters\n"; + std::string message = ":" + getClientHostName(fd) + " 461 " + getClientNickname(fd) + " MODE :Not enough parameters\n"; sendMessage(fd, message); return; } - // Implement the mode command here -} + const std::string& channelName = param[0]; + std::map::iterator it = channels.find(channelName); + + if (it == channels.end()) { + std::string message = ":" + getClientHostName(fd) + " 403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; + sendMessage(fd, message); + return; + } + + Channel& channel = it->second; + if (!channel.isClientInChannel(fd)) { + std::string message = ":" + getClientHostName(fd) + " 442 " + getClientNickname(fd) + " " + channelName + " :You're not on that channel\n"; + sendMessage(fd, message); + return; + } + + // Check if the client is an operator + const std::vector& operators = channel.getOperators(); + bool isOperator = false; + for (std::vector::const_iterator itOp = operators.begin(); itOp != operators.end(); ++itOp) { + if (*itOp == fd) { + isOperator = true; + break; + } + } + // // print operators + // std::vector ops = channel.getOperators(); + // for (size_t i = 0; i < ops.size(); i++) { + // // print operator's nickname + // std::cout << "Operator: " << getClientNickname(ops[i]) << std::endl; + // } + // :luna.AfterNET.Org 482 simo #chan :You're not channel operat + if (!isOperator) { + std::string message = ":" + getClientHostName(fd) + " 482 " + getClientNickname(fd) + " " + channelName + " :You're not channel operator\r\n"; + sendMessage(fd, message); + return; + } + + //print param + for (size_t i = 0; i < param.size(); i++) { + std::cout << "param: " << param[i] << std::endl; + } + + // Process mode changes + std::string modeChanges = param[1]; + std::vector targets; + if (param.size() > 2) { + targets = split(param[2], ','); // Split all clients to be affected by the mode change + } + + // the MODE command is started here + bool addingMode = true; + for (std::string::size_type i = 0; i < modeChanges.size(); ++i) { + char mode = modeChanges[i]; + if (mode == '+') { + addingMode = true; + continue; + } else if (mode == '-') { + addingMode = false; + continue; + } + // std::cout << "mode: " << mode << std::endl; + switch (mode) { + case 'i': { + if (addingMode) { + channel.setChannelType(channel.getChannelType() | 2); // Set to invite-only + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +i\r\n"; + sendMessage(fd, message); + + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +i\r\n"; + sendMessage(clientIt->first, message); + } + } + } else { + channel.setChannelType(channel.getChannelType() & ~2); // Remove invite-only + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -i\r\n"; + sendMessage(fd, message); + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -i\r\n"; + sendMessage(clientIt->first, message); + } + } + } + break; + } + case 't': { + if (addingMode) { + channel.setChannelType(channel.getChannelType() | 4); // Set topic restriction + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +t\r\n"; + sendMessage(fd, message); + + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +t\r\n"; + sendMessage(clientIt->first, message); + } + } + } else { + channel.setChannelType(channel.getChannelType() & ~4); // Remove topic restriction + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -t\r\n"; + sendMessage(fd, message); + + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -t\r\n"; + sendMessage(clientIt->first, message); + } + } + } + break; + } + case 'k': { + if (addingMode && !targets.empty()) { + channel.setChPassword(targets[0]); + channel.setHasPassword(1); + sendMessage(fd, ":" + getClientNickname(fd) + " MODE " + channelName + " +k " + targets[0] + "\n"); + } else { + channel.setChPassword(""); + channel.setHasPassword(0); + sendMessage(fd, ":" + getClientNickname(fd) + " MODE " + channelName + " -k\n"); + } + break; + } + case 'o': { + for (std::vector::size_type j = 0; j < targets.size(); ++j) { + const std::string &target = targets[j]; + int clientId = channel.getClientID(target); + if (clientId != -1) { + if (addingMode) { + channel.addOperator(clientId); + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +o " + target + "\r\n"; + sendMessage(fd, message); + + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +o " + target + "\r\n"; + sendMessage(clientIt->first, message); + } + } + } else { + channel.removeOperator(clientId); + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -o " + target + "\r\n"; + sendMessage(fd, message); + + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -o " + target + "\r\n"; + sendMessage(clientIt->first, message); + } + } + } + } + } + // std::cout << "Operator mode changed for client " << targets[0] << std::endl; + // //print operators + // std::vector ops = channel.getOperators(); + // for (size_t i = 0; i < ops.size(); i++) { + // // print operator's nickname + // std::cout << ">> Operator: " << getClientNickname(ops[i]) << std::endl; + // } + break; + } + default: { + std::string message = "472 " + getClientNickname(fd) + " " + channelName + " " + mode + " :is unknown mode char to me\n"; + sendMessage(fd, message); + break; + } + } + } +} diff --git a/server.hpp b/server.hpp index c3f26ed..7db59dd 100644 --- a/server.hpp +++ b/server.hpp @@ -33,7 +33,7 @@ class Server void joinCmd(std::vector ¶m, int fd); void privmsgCmd(std::vector& args, int fd); - void modeCmd(std::vector& args, int fd); + void modeCmd(std::vector ¶m, int fd); void whoCmd(std::vector& args, int fd); void kickCmd(std::vector ¶m, int fd); void nickCmd(std::vector ¶m, int fd); diff --git a/topicCmd.cpp b/topicCmd.cpp index b842927..860ed7a 100644 --- a/topicCmd.cpp +++ b/topicCmd.cpp @@ -11,17 +11,17 @@ void Server::topicCmd(std::vector& args, int fd) { std::map::iterator it = channels.find(channelName); if (it == channels.end()) { - std::string msg = "403 " + getClientNickname(fd) + " " + channelName + " :No such channel\n"; + std::string msg = ":" + getClientHostName(fd) + " 403 " + getClientNickname(fd) + " " + channelName + " :No such channel\r\n"; sendMessage(fd, msg); } else if (args.size() == 1) { const std::string& topic = it->second.getTopic(); if (topic.empty()) { - std::string msg = "331 " + getClientNickname(fd) + " " + channelName + " :No topic is set\n"; + std::string msg = ":" + getClientHostName(fd) + " 331 " + getClientNickname(fd) + " " + channelName + " :No topic is set\r\n"; sendMessage(fd, msg); } else { - std::string msg = "332 " + getClientNickname(fd) + " " + channelName + " " + topic + "\n"; + std::string msg = ":" + getClientHostName(fd) + " 332 " + getClientNickname(fd) + " " + channelName + " :" + topic + "\r\n"; sendMessage(fd, msg); } } @@ -31,9 +31,18 @@ void Server::topicCmd(std::vector& args, int fd) { for (size_t i = 2; i < args.size(); ++i) { newTopic += " " + args[i]; } - std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + "127.0.0.1 TOPIC " + channelName + " " + newTopic + "\n"; + std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " TOPIC " + channelName + " :" + newTopic + "\r\n"; sendMessage(fd, msg); + // notify all clients in the channel + std::map::const_iterator clientIt; + const std::map& clients = it->second.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + sendMessage(clientIt->first, msg); + } + } + Channel& channel = it->second; channel.setTopic(newTopic); } From e0690dd83844fad253d377048736670bad72d4fa Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sun, 28 Jul 2024 04:04:40 +0100 Subject: [PATCH 49/56] MODE command is DONE --- Channel.cpp | 7 +++++ Channel.hpp | 3 ++ irc_server.cpp | 2 +- joinCmd.cpp | 15 ++++++++++ modeCmd.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 94 insertions(+), 8 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index edf539a..5b705c6 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -170,3 +170,10 @@ bool Channel::isOperator(int id) { return std::find(operators.begin(), operators.end(), id) != operators.end(); } +int Channel::getChannelLimit() const { + return channeLimit; +} + +void Channel::setChannelLimit(int limit) { + channeLimit = limit; +} diff --git a/Channel.hpp b/Channel.hpp index 337c5ff..28e33b9 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -17,6 +17,7 @@ class Channel { std::map inviteList; int channelType; int hasPassword; + int channeLimit; public: Channel(); @@ -35,6 +36,7 @@ class Channel { void setChannelType(int channelType); void setHasPassword(int hasPassword); void setInvitedList(int id, client &c); + void setChannelLimit(int limit); // getters : std::string getName(); @@ -43,6 +45,7 @@ class Channel { std::string getChPassword(); std::map::const_iterator beginClientIter() const; std::map::const_iterator endClientIter() const; + int getChannelLimit() const; int getChannelType(); int getClientID(const std::string &nickname) const; int isClientInChannel(int fd); diff --git a/irc_server.cpp b/irc_server.cpp index fbaaf1e..5cbf0e3 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -83,7 +83,7 @@ int main(int argc, char *argv[]) // std::cout << client::get_clients()[l].get_client_pfd().fd << " is not authenticated" << std::endl; if (client::get_clients()[l].set_authenticated() == true) { - std::cout << "now is authenticated" << std::endl; + std::cout << "Now is authenticated" << std::endl; client::get_clients()[l].clear_massage(); std::cout << client::get_clients()[l].get_message() << std::endl; } diff --git a/joinCmd.cpp b/joinCmd.cpp index a780363..f2fc568 100644 --- a/joinCmd.cpp +++ b/joinCmd.cpp @@ -87,6 +87,7 @@ void Server::joinCmd(std::vector ¶m, int fd) { } std::string channelName = param[0]; + std::string password = (param.size() > 1) ? param[1] : ""; std::map::iterator it = channels.find(channelName); bool channelCreated = (it == channels.end()); @@ -115,6 +116,20 @@ void Server::joinCmd(std::vector ¶m, int fd) { } } + // Check if the channel has a password and if the provided password is correct + if (channel.getChPassword() != password) { + std::string message = ":" + getNameId(fd) + " 475 " + channelName + " :Cannot join channel (+k) - incorrect key\n"; + sendMessage(fd, message); + return; + } + + // Check if the channel has a user limit and if the limit is reached + if (channel.getChannelLimit() > 0 && channel.getClientsFromChannel().size() >= static_cast(channel.getChannelLimit())) { + std::string message = ":" + getNameId(fd) + " 471 " + channelName + " :Cannot join channel (+l) - channel is full\n"; + sendMessage(fd, message); + return; + } + // Add the client to the channel channel.setClients(fd, getClientNickname(fd)); diff --git a/modeCmd.cpp b/modeCmd.cpp index 1e3bc29..8075e53 100644 --- a/modeCmd.cpp +++ b/modeCmd.cpp @@ -52,7 +52,7 @@ void Server::modeCmd(std::vector ¶m, int fd) { //print param for (size_t i = 0; i < param.size(); i++) { - std::cout << "param: " << param[i] << std::endl; + std::cout << "param[" << i << "]: " << param[i] << std::endl; } // Process mode changes @@ -140,16 +140,39 @@ void Server::modeCmd(std::vector ¶m, int fd) { break; } case 'k': { - if (addingMode && !targets.empty()) { + if (addingMode && targets.empty()) { + std::string message = ":" + getClientHostName(fd) + " 461 " + getClientNickname(fd) + " MODE :Not enough parameters\n"; + sendMessage(fd, message); + return; + } else if (addingMode) { channel.setChPassword(targets[0]); - channel.setHasPassword(1); - sendMessage(fd, ":" + getClientNickname(fd) + " MODE " + channelName + " +k " + targets[0] + "\n"); + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +k " + targets[0] + "\r\n"; + sendMessage(fd, message); + + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +k " + targets[0] + "\r\n"; + sendMessage(clientIt->first, message); + } + } } else { channel.setChPassword(""); - channel.setHasPassword(0); - sendMessage(fd, ":" + getClientNickname(fd) + " MODE " + channelName + " -k\n"); + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -k\r\n"; + sendMessage(fd, message); + + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -k\r\n"; + sendMessage(clientIt->first, message); + } + } } - break; } case 'o': { for (std::vector::size_type j = 0; j < targets.size(); ++j) { @@ -196,6 +219,44 @@ void Server::modeCmd(std::vector ¶m, int fd) { // } break; } + case 'l': { + if (addingMode) { + if (targets.empty()) { + std::string message = ":" + getClientHostName(fd) + " 461 " + getClientNickname(fd) + " MODE :Not enough parameters\n"; + sendMessage(fd, message); + return; + } + int limit = std::stoi(targets[0]); + channel.setChannelLimit(limit); + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +l " + targets[0] + "\r\n"; + sendMessage(fd, message); + + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " +l " + targets[0] + "\r\n"; + sendMessage(clientIt->first, message); + } + } + } else { + channel.setChannelLimit(0); + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -l\r\n"; + sendMessage(fd, message); + + // notify other clients + std::map::const_iterator clientIt; + const std::map& clients = channel.getClientsFromChannel(); + for (clientIt = clients.begin(); clientIt != clients.end(); ++clientIt) { + if (clientIt->first != fd) { + std::string message = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " MODE " + channelName + " -l\r\n"; + sendMessage(clientIt->first, message); + } + } + } + break; + } default: { std::string message = "472 " + getClientNickname(fd) + " " + channelName + " " + mode + " :is unknown mode char to me\n"; sendMessage(fd, message); From 7bcc883ccdb67b3014a35dc790d26e11af859978 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sun, 28 Jul 2024 04:45:55 +0100 Subject: [PATCH 50/56] MODE command is DONE just modify the error message for size=1 --- modeCmd.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modeCmd.cpp b/modeCmd.cpp index 8075e53..b510734 100644 --- a/modeCmd.cpp +++ b/modeCmd.cpp @@ -6,8 +6,9 @@ #include "utils.hpp" void Server::modeCmd(std::vector ¶m, int fd) { - if (param.size() < 2) { - std::string message = ":" + getClientHostName(fd) + " 461 " + getClientNickname(fd) + " MODE :Not enough parameters\n"; + std::cout << "size: " << param.size() << std::endl; + if (param.size() == 1) { + std::string message = ":" + getClientHostName(fd) + " 324 " + getClientNickname(fd) + " " + param[0] + " +tn\r\n"; sendMessage(fd, message); return; } From d42a682870cd79c1d64f57dbdd1c464603a1a47b Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sun, 28 Jul 2024 05:59:14 +0100 Subject: [PATCH 51/56] INVITE command is DONE --- Channel.cpp | 29 ++++++++++++++++++----------- Channel.hpp | 10 +++++++--- inviteCmd.cpp | 33 +++++++++++++++++++++++++++++++-- modeCmd.cpp | 7 ------- server.cpp | 14 +++++++++++--- 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/Channel.cpp b/Channel.cpp index 5b705c6..2797558 100644 --- a/Channel.cpp +++ b/Channel.cpp @@ -74,9 +74,9 @@ void Channel::setHasPassword(int hasPsd) { -void Channel::setInvitedList(int id, client &c){ - inviteList[id] = c; -} +// void Channel::setInvitedList(int id, client &c){ +// inviteList[id] = c; +// } std::string Channel::getName() { return name; } @@ -108,10 +108,9 @@ int Channel::getHasPassword() const{ } -std::map Channel::getInvitedList() const{ - return inviteList; - -} +// std::map Channel::getInvitedList() const{ +// return inviteList; +// } std::map::const_iterator Channel::beginClientIter() const { return clients.begin(); @@ -149,10 +148,10 @@ size_t Channel::getClientNb() const { return clients.size(); } -bool Channel::isClientInvited(int clientId) const{ - bool isInvited = (inviteList.count(clientId) > 0); - return isInvited; -} +// bool Channel::isClientInvited(int clientId) const{ +// bool isInvited = (inviteList.count(clientId) > 0); +// return isInvited; +// } void Channel::removeClient(int fd) { clients.erase(fd); @@ -177,3 +176,11 @@ int Channel::getChannelLimit() const { void Channel::setChannelLimit(int limit) { channeLimit = limit; } + +void Channel::addInvite(int fd) { + inviteList.push_back(fd); +} + +bool Channel::isClientInvited(int fd) const { + return std::find(inviteList.begin(), inviteList.end(), fd) != inviteList.end(); +} \ No newline at end of file diff --git a/Channel.hpp b/Channel.hpp index 28e33b9..b316aa3 100644 --- a/Channel.hpp +++ b/Channel.hpp @@ -14,7 +14,8 @@ class Channel { std::string chPassword; std::vector operators; std::map clients; - std::map inviteList; + // std::map inviteList; + std::vector inviteList; int channelType; int hasPassword; int channeLimit; @@ -35,7 +36,7 @@ class Channel { void setChPassword(std::string channelPassword); void setChannelType(int channelType); void setHasPassword(int hasPassword); - void setInvitedList(int id, client &c); + // void setInvitedList(int id, client &c); void setChannelLimit(int limit); // getters : @@ -51,7 +52,7 @@ class Channel { int isClientInChannel(int fd); int getHasPassword() const; size_t getClientNb() const; - std::map getInvitedList() const; + // std::map getInvitedList() const; bool isClientInvited(int clientId) const; const std::map &getClientsFromChannel() const; @@ -59,6 +60,9 @@ class Channel { void addOperator(int id); void removeOperator(int id); bool isOperator(int id); + void addInvite(int fd); + bool isInvited(int fd); + }; diff --git a/inviteCmd.cpp b/inviteCmd.cpp index c7f118c..cfee0b4 100644 --- a/inviteCmd.cpp +++ b/inviteCmd.cpp @@ -6,10 +6,39 @@ #include "utils.hpp" void Server::inviteCmd(std::vector& args, int fd) { - // start implementation invite command if (args.size() < 2) { - std::string msg = "461 " + getClientNickname(fd) + " INVITE :Not enough parameters\n"; + std::string msg = ":" + getClientHostName(fd) + " 461 " + getClientNickname(fd) + " INVITE :Not enough parameters\r\n"; sendMessage(fd, msg); return; } + + const std::string& nickname = args[0]; + const std::string& channelName = args[1]; + + std::map::iterator it = channels.find(channelName); + + if (it == channels.end()) { + std::string msg = ":" + getClientHostName(fd) + " 403 " + getClientNickname(fd) + " " + channelName + " :No such channel\r\n"; + sendMessage(fd, msg); + } else { + Channel& channel = it->second; + if (!channel.isClientInChannel(fd)) { + std::string msg = ":" + getClientHostName(fd) + " 442 " + getClientNickname(fd) + " " + channelName + " :You're not on that channel\r\n"; + sendMessage(fd, msg); + } else { + int clientFd = getClientFdByNickname(nickname); + if (clientFd == -1) { + std::string msg = ":" + getClientHostName(fd) + " 401 " + getClientNickname(fd) + " " + nickname + " :No such nick/channel\r\n"; + sendMessage(fd, msg); + } else { + // Add the client to the invite list + channel.addInvite(clientFd); + + std::string msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " INVITE " + nickname + " :" + channelName + "\r\n"; + sendMessage(clientFd, msg); + std::string msg2 = ":" + getClientHostName(fd) + " 341 " + getClientNickname(fd) + " " + nickname + " " + channelName + "\r\n"; + sendMessage(fd, msg2); + } + } + } } \ No newline at end of file diff --git a/modeCmd.cpp b/modeCmd.cpp index b510734..14e7198 100644 --- a/modeCmd.cpp +++ b/modeCmd.cpp @@ -211,13 +211,6 @@ void Server::modeCmd(std::vector ¶m, int fd) { } } } - // std::cout << "Operator mode changed for client " << targets[0] << std::endl; - // //print operators - // std::vector ops = channel.getOperators(); - // for (size_t i = 0; i < ops.size(); i++) { - // // print operator's nickname - // std::cout << ">> Operator: " << getClientNickname(ops[i]) << std::endl; - // } break; } case 'l': { diff --git a/server.cpp b/server.cpp index bad394b..241cfcb 100644 --- a/server.cpp +++ b/server.cpp @@ -97,7 +97,15 @@ std::string Server::getNameId(int fd) { return it->getNickname(); } } - std::string message = ":" + std::to_string(fd) + " 401 * :No such nick/channel\n"; - sendMessage(fd, message); return "ERROR"; -} \ No newline at end of file +} + +int Server::getClientFdByNickname(const std::string& nickname) { + std::vector& clients = client::get_clients(); + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { + if (it->getNickname() == nickname) { + return it->get_client_pfd().fd; + } + } + return -1; // Return -1 if no client with the given nickname is found +} From b96ba36edaf4d26f15cb49360bb143efca317eba Mon Sep 17 00:00:00 2001 From: Abdelmajid El-oualy Date: Sun, 28 Jul 2024 12:58:46 +0100 Subject: [PATCH 52/56] try to fix nickname douplicattt --- client.cpp | 36 ++++++++++++++++++++++++++++++++---- client.hpp | 3 ++- irc_server.cpp | 4 ++-- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/client.cpp b/client.cpp index 82273c5..4faec47 100644 --- a/client.cpp +++ b/client.cpp @@ -1,4 +1,5 @@ #include "client.hpp" +#include "utils.hpp" std::vector client::fds; std::vector client::clients; @@ -69,7 +70,23 @@ std::vector buffer_to_line(std::string buffer, std::string siparato return lines; } -bool client::set_authenticated() + bool client::check_nickname(std::string nickname, std::vector& clients) +{ + std::vector::iterator it = clients.begin(); + while (it != clients.end()) + { + // std::cout << "nickname : " << it->getNickname() << std::endl; + if (it->getNickname() == nickname) + { + + return (false); + } + it++; + } + return (true); +} + +bool client::set_authenticated(std::vector clients) { std::string line; if (this->is_authenticated == true) @@ -79,15 +96,26 @@ bool client::set_authenticated() else { std::vector lines = buffer_to_line(this->massage, "\r\n"); - // std::cout << "--------------- not authonticatef --------------------" << std::endl; - // std::cout << "the size of lines : " << lines.size() << std::endl; for (unsigned int i = 0; i < lines.size(); i++) { - // std::cout << lines[i] << std::endl; if (lines[i].find("NICK") != std::string::npos) { std::string nickname = lines[i].substr(5, lines[i].size()); + + int j = 0; + std::string tmp_nickname = nickname; + + while (check_nickname(nickname, clients) == false) + { + nickname = nickname + "_"; + j++; + + } + this->set_nickname(nickname); + std::cout << "the new nickname : " << this->nickname << std::endl; + + } if (lines[i].find("USER") != std::string::npos) { diff --git a/client.hpp b/client.hpp index 0046724..1157643 100644 --- a/client.hpp +++ b/client.hpp @@ -36,7 +36,7 @@ class client void set_nickname(std::string nickname); void set_username(std::string username); void set_realname(std::string realname); - bool set_authenticated(); + bool set_authenticated(std::vector); void set_registered(bool is_registered); void set_client_pfd(pollfd client_pfd); void set_massage_for_auth(std::string massage); @@ -49,6 +49,7 @@ class client std::string get_host_name(); int getFd() const; static void modify_client(int fd, const std::string& newNickname); + bool check_nickname(std::string nickname, std::vector& clients); }; diff --git a/irc_server.cpp b/irc_server.cpp index 5cbf0e3..ddb09b3 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) { if (client::get_clients()[l].get_client_pfd().fd == client::get_fds()[i].fd) { - if (client::get_clients()[l].set_authenticated() == true) + if (client::get_clients()[l].set_authenticated(client::get_clients()) == true) { client::get_clients()[l].set_massage(buffer); // print host name @@ -81,7 +81,7 @@ int main(int argc, char *argv[]) { client::get_clients()[l].set_massage_for_auth(buffer); // std::cout << client::get_clients()[l].get_client_pfd().fd << " is not authenticated" << std::endl; - if (client::get_clients()[l].set_authenticated() == true) + if (client::get_clients()[l].set_authenticated(client::get_clients()) == true) { std::cout << "Now is authenticated" << std::endl; client::get_clients()[l].clear_massage(); From 19ca604e329c1e338bc066bdb752797f0a717272 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sun, 28 Jul 2024 19:58:48 +0100 Subject: [PATCH 53/56] IRC is DONE --- .vscode/settings.json | 67 ------------------------------------------- README.md | 1 - client.cpp | 13 +++++---- 3 files changed, 8 insertions(+), 73 deletions(-) delete mode 100644 .vscode/settings.json delete mode 100644 README.md diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 88e8065..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "files.associations": { - "*.embeddedhtml": "html", - "iostream": "cpp", - "vector": "cpp", - "ostream": "cpp", - "__bit_reference": "cpp", - "__config": "cpp", - "__debug": "cpp", - "__errc": "cpp", - "__functional_base": "cpp", - "__hash_table": "cpp", - "__locale": "cpp", - "__mutex_base": "cpp", - "__node_handle": "cpp", - "__nullptr": "cpp", - "__split_buffer": "cpp", - "__string": "cpp", - "__threading_support": "cpp", - "__tuple": "cpp", - "algorithm": "cpp", - "array": "cpp", - "atomic": "cpp", - "bit": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "cmath": "cpp", - "complex": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "exception": "cpp", - "functional": "cpp", - "initializer_list": "cpp", - "ios": "cpp", - "iosfwd": "cpp", - "istream": "cpp", - "iterator": "cpp", - "limits": "cpp", - "locale": "cpp", - "memory": "cpp", - "mutex": "cpp", - "new": "cpp", - "optional": "cpp", - "ratio": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "typeinfo": "cpp", - "unordered_map": "cpp", - "utility": "cpp", - "__tree": "cpp", - "map": "cpp" - } -} \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index e3e9f92..0000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -# FT_IRC diff --git a/client.cpp b/client.cpp index 4faec47..94c2f21 100644 --- a/client.cpp +++ b/client.cpp @@ -102,17 +102,20 @@ bool client::set_authenticated(std::vector clients) { std::string nickname = lines[i].substr(5, lines[i].size()); - int j = 0; + std::string tmp_nickname = nickname; - while (check_nickname(nickname, clients) == false) + if (check_nickname(nickname, clients) == false) { - nickname = nickname + "_"; - j++; - + std::string message = "433 :nickname is already in use\r\n"; + sendMessage(this->client_pfd.fd, message); + return (false); } + this->set_nickname(nickname); + + std::cout << "the new nickname : " << this->nickname << std::endl; From 20e8f7ed0caaf89e61be1bd1abc946ac9409e685 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Sun, 28 Jul 2024 22:05:22 +0100 Subject: [PATCH 54/56] file transfer is fixed --- privmsgCmd.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/privmsgCmd.cpp b/privmsgCmd.cpp index 33500fe..7b54d1f 100644 --- a/privmsgCmd.cpp +++ b/privmsgCmd.cpp @@ -57,9 +57,14 @@ void Server::privmsgCmd(std::vector& args, int fd) { } } else { - // Recipient found as a client - std::cout << "Client found" << std::endl; - std::string msg = ":" + getClientNickname(fd) + " PRIVMSG " + recipient + " :" + message + "\n\r"; + std::string msg; + if (message[0] == ':') { + std::cout << "Message starts with :" << std::endl; + msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " PRIVMSG " + recipient + " " + message + "\n\r"; + } else { + std::cout << "Message does not start with :" << std::endl; + msg = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " PRIVMSG " + recipient + " :" + message + "\n\r"; + } sendMessage(recipientClient->get_client_pfd().fd, msg); } } From 02d43ef3f709ef0ff17161e9e2b47476be2411b8 Mon Sep 17 00:00:00 2001 From: Abdelmajid El-oualy Date: Mon, 29 Jul 2024 13:03:29 +0100 Subject: [PATCH 55/56] fix nc command line --- client.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/client.cpp b/client.cpp index 94c2f21..f363583 100644 --- a/client.cpp +++ b/client.cpp @@ -93,9 +93,25 @@ bool client::set_authenticated(std::vector clients) { return (true); } - else { - std::vector lines = buffer_to_line(this->massage, "\r\n"); + else { + std::vector lines; + if (this->massage.find("\r\n") != std::string::npos) + { + lines = buffer_to_line(this->massage, "\r\n"); + } + + if (this->massage.find("\r") != std::string::npos && this->massage.find("\r\n") == std::string::npos ) + { + lines = buffer_to_line(this->massage, "\n"); + } + + + + + + std::cout << "the size of the lines : " << lines.size() << std::endl; + for (unsigned int i = 0; i < lines.size(); i++) { if (lines[i].find("NICK") != std::string::npos) @@ -103,9 +119,9 @@ bool client::set_authenticated(std::vector clients) std::string nickname = lines[i].substr(5, lines[i].size()); - std::string tmp_nickname = nickname; + std::string tmp_nickname = nickname; - if (check_nickname(nickname, clients) == false) + if (check_nickname(nickname, clients) == false) { std::string message = "433 :nickname is already in use\r\n"; sendMessage(this->client_pfd.fd, message); @@ -138,11 +154,8 @@ bool client::set_authenticated(std::vector clients) size_t found3 = tmp_realname.find(" "); if (found3 != std::string::npos) { std::string realname = tmp_realname.substr(0, found3); - // std::cout << "realname : " << realname << std::endl; this->hostname = realname; - // std::cout << "hostname : " << this->hostname << std::endl; - } } } @@ -155,6 +168,7 @@ bool client::set_authenticated(std::vector clients) } } + if ((this->nickname.size() > 0) && (this->username.size() > 0) && (this->password == this->sabmit_password)) { this->is_authenticated = true; From 126747f3b59d71dd3937fbf817a6601343f0a9b3 Mon Sep 17 00:00:00 2001 From: mbelouar Date: Wed, 31 Jul 2024 20:00:19 +0100 Subject: [PATCH 56/56] ALL IS DONE --- client.cpp | 56 ++++++++++++++++++++------------------------------ irc_server.cpp | 3 ++- quitCmd.cpp | 20 +++++++++++++----- 3 files changed, 39 insertions(+), 40 deletions(-) diff --git a/client.cpp b/client.cpp index f363583..1f35e44 100644 --- a/client.cpp +++ b/client.cpp @@ -75,8 +75,8 @@ std::vector buffer_to_line(std::string buffer, std::string siparato std::vector::iterator it = clients.begin(); while (it != clients.end()) { - // std::cout << "nickname : " << it->getNickname() << std::endl; - if (it->getNickname() == nickname) + + if (it->getNickname() == nickname && it->is_authenticated == true) { return (false); @@ -95,47 +95,32 @@ bool client::set_authenticated(std::vector clients) } else { std::vector lines; - if (this->massage.find("\r\n") != std::string::npos) - { - lines = buffer_to_line(this->massage, "\r\n"); - } + if (this->massage.find("\r\n") != std::string::npos) + { + lines = buffer_to_line(this->massage, "\r\n"); + } if (this->massage.find("\r") != std::string::npos && this->massage.find("\r\n") == std::string::npos ) { lines = buffer_to_line(this->massage, "\n"); } - - - - - - - std::cout << "the size of the lines : " << lines.size() << std::endl; for (unsigned int i = 0; i < lines.size(); i++) { - if (lines[i].find("NICK") != std::string::npos) - { - std::string nickname = lines[i].substr(5, lines[i].size()); - - + if (lines[i].find("NICK") != std::string::npos) + { + std::string nickname = lines[i].substr(5, lines[i].size()); + std::string tmp_nickname = nickname; - + if (check_nickname(nickname, clients) == false) { std::string message = "433 :nickname is already in use\r\n"; sendMessage(this->client_pfd.fd, message); return (false); - } - - - this->set_nickname(nickname); - - - std::cout << "the new nickname : " << this->nickname << std::endl; - - - } + } + this->set_nickname(nickname); + } if (lines[i].find("USER") != std::string::npos) { std::string username = lines[i].substr(5, lines[i].size()); @@ -155,20 +140,23 @@ bool client::set_authenticated(std::vector clients) if (found3 != std::string::npos) { std::string realname = tmp_realname.substr(0, found3); this->hostname = realname; - } } } - } if (lines[i].find("PASS") != std::string::npos) { - this->sabmit_password = lines[i].substr(5, lines[i].size()); - + this->sabmit_password = lines[i].substr(5, lines[i].size()); } } - + // check if the password is incorrect + if ((this->sabmit_password.size() > 0 ) && (lines.size() > 3) && (this->password != this->sabmit_password)) + { + std::string message = "464 :password incorrect\r\n"; + sendMessage(this->client_pfd.fd, message); + return (false); + } if ((this->nickname.size() > 0) && (this->username.size() > 0) && (this->password == this->sabmit_password)) { this->is_authenticated = true; diff --git a/irc_server.cpp b/irc_server.cpp index ddb09b3..2901437 100644 --- a/irc_server.cpp +++ b/irc_server.cpp @@ -5,7 +5,8 @@ int main(int argc, char *argv[]) { - if (argc != 3) + // check if the size of the last arg is not equal to 0 + if (argc != 3 || strlen(argv[2]) == 0 || strlen(argv[1]) == 0) { std::cout << "Usage: ./irc_server " << std::endl; return (1); diff --git a/quitCmd.cpp b/quitCmd.cpp index c34aefa..6c0ce4c 100644 --- a/quitCmd.cpp +++ b/quitCmd.cpp @@ -7,18 +7,28 @@ void Server::quitCmd(std::vector& args, int fd) { if (args.size() == 0) { + // erase client from clients vector + std::vector& clients = client::get_clients(); // remove const to allow modification + for (std::vector::iterator it = clients.begin(); it != clients.end(); ) { + if (it->getFd() == fd) { + it = clients.erase(it); + } else { + ++it; // only increment if not erased + } + } std::string msg = "QUIT :Leaving\n"; sendMessage(fd, msg); return; } - const std::vector& clients = client::get_clients(); - // notify all clients that the user is leaving - // :simo!simo@88ABE6.25BF1D.D03F86.88C9BD.IP QUIT :Quit: #cha + std::vector& clients = client::get_clients(); // remove const to allow modification std::string notice = ":" + getClientNickname(fd) + "!" + getClientNickname(fd) + "@" + getClientHostName(fd) + " QUIT :Quit: " + args[0] + "\n"; - for (std::vector::const_iterator it = clients.begin(); it != clients.end(); ++it) { - if (it->getFd() != fd) { + for (std::vector::iterator it = clients.begin(); it != clients.end(); ) { + if (it->getFd() == fd) { + it = clients.erase(it); + } else { sendMessage(it->getFd(), notice); + ++it; // only increment if not erased } }