From 26f51701f6346c4094629889ea6c43c9b48cdcc3 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Tue, 25 Jun 2019 15:15:28 -0700 Subject: [PATCH 01/17] onid folder created from roberwen/ --- projects/bleckw/README.md | 1 + projects/bleckw/dominion/Makefile | 42 + projects/bleckw/dominion/READM.md | 2 + projects/bleckw/dominion/badTestDrawCard | Bin 0 -> 29572 bytes projects/bleckw/dominion/badTestDrawCard.c | 44 + projects/bleckw/dominion/betterTestDrawCard.c | 70 + projects/bleckw/dominion/dominion.c | 1333 +++++++++++++++++ projects/bleckw/dominion/dominion.h | 131 ++ projects/bleckw/dominion/dominion_helpers.h | 15 + projects/bleckw/dominion/interface.c | 363 +++++ projects/bleckw/dominion/interface.h | 128 ++ projects/bleckw/dominion/playdom | Bin 0 -> 86888 bytes projects/bleckw/dominion/playdom.c | 134 ++ projects/bleckw/dominion/player | Bin 0 -> 108236 bytes projects/bleckw/dominion/player.c | 217 +++ projects/bleckw/dominion/rngs.c | 183 +++ projects/bleckw/dominion/rngs.h | 19 + projects/bleckw/dominion/rt.c | 27 + projects/bleckw/dominion/supplyTest.c | 30 + projects/bleckw/dominion/testBuyCard.c | 94 ++ projects/bleckw/dominion/testDrawCard.c | 93 ++ projects/bleckw/dominion/testInit.c | 56 + projects/bleckw/dominion/testShuffle.c | 27 + 23 files changed, 3009 insertions(+) create mode 100644 projects/bleckw/README.md create mode 100644 projects/bleckw/dominion/Makefile create mode 100644 projects/bleckw/dominion/READM.md create mode 100644 projects/bleckw/dominion/badTestDrawCard create mode 100644 projects/bleckw/dominion/badTestDrawCard.c create mode 100644 projects/bleckw/dominion/betterTestDrawCard.c create mode 100644 projects/bleckw/dominion/dominion.c create mode 100644 projects/bleckw/dominion/dominion.h create mode 100644 projects/bleckw/dominion/dominion_helpers.h create mode 100644 projects/bleckw/dominion/interface.c create mode 100644 projects/bleckw/dominion/interface.h create mode 100644 projects/bleckw/dominion/playdom create mode 100644 projects/bleckw/dominion/playdom.c create mode 100644 projects/bleckw/dominion/player create mode 100644 projects/bleckw/dominion/player.c create mode 100644 projects/bleckw/dominion/rngs.c create mode 100644 projects/bleckw/dominion/rngs.h create mode 100644 projects/bleckw/dominion/rt.c create mode 100644 projects/bleckw/dominion/supplyTest.c create mode 100644 projects/bleckw/dominion/testBuyCard.c create mode 100644 projects/bleckw/dominion/testDrawCard.c create mode 100644 projects/bleckw/dominion/testInit.c create mode 100644 projects/bleckw/dominion/testShuffle.c diff --git a/projects/bleckw/README.md b/projects/bleckw/README.md new file mode 100644 index 00000000..264b0477 --- /dev/null +++ b/projects/bleckw/README.md @@ -0,0 +1 @@ +#Your onid folder should contain a readme file that contains your name and your ONID. diff --git a/projects/bleckw/dominion/Makefile b/projects/bleckw/dominion/Makefile new file mode 100644 index 00000000..bcc1cf2c --- /dev/null +++ b/projects/bleckw/dominion/Makefile @@ -0,0 +1,42 @@ +CFLAGS= -Wall -fpic -coverage -lm -std=c99 + +rngs.o: rngs.h rngs.c + gcc -c rngs.c -g $(CFLAGS) + +dominion.o: dominion.h dominion.c rngs.o + gcc -c dominion.c -g $(CFLAGS) + +playdom: dominion.o playdom.c + gcc -o playdom playdom.c -g dominion.o rngs.o $(CFLAGS) +#To run playdom you need to entere: ./playdom like ./playdom 10*/ +testDrawCard: testDrawCard.c dominion.o rngs.o + gcc -o testDrawCard -g testDrawCard.c dominion.o rngs.o $(CFLAGS) + + +######### + +badTestDrawCard: badTestDrawCard.c dominion.o rngs.o + gcc -o badTestDrawCard -g badTestDrawCard.c dominion.o rngs.o $(CFLAGS) + +testBuyCard: testDrawCard.c dominion.o rngs.o + gcc -o testDrawCard -g testDrawCard.c dominion.o rngs.o $(CFLAGS) + +testAll: dominion.o testSuite.c + gcc -o testSuite testSuite.c -g dominion.o rngs.o $(CFLAGS) + +interface.o: interface.h interface.c + gcc -c interface.c -g $(CFLAGS) + +runtests: testDrawCard + ./testDrawCard &> unittestresult.out + gcov dominion.c >> unittestresult.out + cat dominion.c.gcov >> unittestresult.out + + +player: player.c interface.o + gcc -o player player.c -g dominion.o rngs.o interface.o $(CFLAGS) + +all: playdom player + +clean: + rm -f *.o playdom.exe playdom player player.exe *.gcov *.gcda *.gcno *.so *.out testDrawCard testDrawCard.exe diff --git a/projects/bleckw/dominion/READM.md b/projects/bleckw/dominion/READM.md new file mode 100644 index 00000000..c3599f6a --- /dev/null +++ b/projects/bleckw/dominion/READM.md @@ -0,0 +1,2 @@ +run make all #To compile the dominion code +run ./playdom 30 # to run playdom code diff --git a/projects/bleckw/dominion/badTestDrawCard b/projects/bleckw/dominion/badTestDrawCard new file mode 100644 index 0000000000000000000000000000000000000000..362cc238c1c401460e9b674c41da7cc146018dcc GIT binary patch literal 29572 zcmeHwf1DK6m2dS-qe##iBN#L$b_^)-DGU(}dB5-JYfoO91T_uO;Oy?twVRv0JVU{d&44(@392|A z?{2)KJC9q)uj3>%2F2&rNF2i9JUW3sKNyd9b@#09^0Er~-CryDU7|2FtO+J7etG%G zFTS?1rK7PENQL}fQ~YjG3r3i%BxerKvqCG5WfvZ5d!?`gZexve4I+}6}C;9&ng274hZ-Q|P}dHDI$PDVix zkJl_&xx`ljdk`X3s61^i3Z|XFhJ~#VBOY&SiFe)Ey1Kn3-qGFpvHUbU+8gQh#r}lp zcvn2Wraj*a#qw2vp7Kpr6od=;eZu2L`j+}5$u~ps)BQ@=&yVe$8sOJZ-(8>2DAeC7 z#ZL=J_{es$x+^~_irc&D`e1umv%ggw<8O$}k3z-h+1x0#T+JxMK;!*oya9n_)bThO;lA0&%U! zllR%UpTOii+RfA7Z~y$8Gm%$;+xWy3ai6bY=HZ%+_LA-qzcB)4J#072*v8P5SJA3azHZdN z;?Az_#@0EP&w(7xtAT{;T->a$0{S5R7ZgnW9KVih;J60f7%!?(W6S2iRnvk8W2JC+OQo}f4R-F7k zcpfls*yUb{ggJZ90rP_4!CkRL-NfLA=~>irz&tfIinkM;NDhbW=tO2q4s|zzK9<@h zF)B{}j$#wDw~bJ=iOb3Mf?=wtcYn;0xm!NUy zXAhY?31E}Zr`?-{@?C1)IRQ_%>I8F$9u=D8WRsbNN6d+4oymB*Rg=w>Dh2mkhI5kA zIXVoT)zma6&|k^@72ByCD6$5X#?VagnLyW82K4kaqvwOzvx-q+Uw8oC^t+8uI?3-Szv2WT_W7oZ8M~9c$IrpdNGSsx) zsojUlw%e1P+HsMHg`L_lnL^&EOigua_sUd-Q#&G4)12DZWNL;}yGN$Za%x|asfbfM zEK@W2LSq(uZOP3`;w9T(y`6egMsC;bkJ+{3&_)}(Inle{-G)T6cOq=opZIH8#ae-HKE?Iw~_pk#QB0PIR;?I%W<~VX#fKu{P^W>qim|ugz9X z>o+Zb4_*NF8L|MOFr3lM_t~>DYfNN~WgKJ)(JaoGX!LlxI!t*poTX7xZu(26v4pXM z!u%{@+_HHVXI@z{d9s(Bnom|RnfaVoG?@ZRf~omr1(Vws;c;v2#ED-(FV&6Pmrvs> zefbR0evv$jwL@{VRVeOEbK@S7;ZxjW$nYtvs&34*T77xRMg0}#z$b$_Q%q|=q z2q_(pr)&Ddq6I=%Qt={_0%r;{g%&?wKrRLs@_fB=U2(6>L6))zCpuOYoiI~B^D`Rg zAH0lA{AN;armjYYXl;Unp>90Z|3WN+tmaqf-D06v)8TcrS=}CItKgH|9kOLAZz}&N zBp59RcCwcycr3hOamUKLzzk0>ZZNyR=|www#@$;Wb#em!nTm#60(LHQH8Km>43}o3 z+nXNfUl0KYT)wQ)n`IU>tp9NzCJ92V~UPA z(Y>NYdoyoA#CdO#y$`Dfn-0py+tJtLyj*?Li*o+x-_K=K%$fB1rF;noZ||Hj!O3@9 z1zu@uDxMT0mas&=Bl43w?xAsp%#?|;v~?D+cxBFqP}{@EvtNj%PX6i#;FQ=V33rlV ztUoQS_4m?R52@m1j>Y1oiLG16*nPLkS7nMt$sKY$m_wI9r|w~FWOyPVLjS}Pdt!;rr7C|*D&lP?JOpl%=@Aj_@Q}yW7E)x| zq57aQocrXce*sMqsmxOdGSUK_-6=U#iN>0#TaW{K(XI`moV8u%4;R-;jrDITRrUANS=*!N;7s zvE*+c-wV1;o_uPmlLIyiQg*J8U&^P;Z4PKpb2gsGAC zX7?WET8COjZRvZmXb7)#RLlao7N1XF-{*O z&m@MANMw@7Kt8FMyiAe90FGMw38uv@Du3MgiD=gW~oCZstH|)SLFrv!W zQ)F8_g|Y@nrpISB#;4tL(5}ncwfmRZm@#F@y9~3`lH_)wH*>&0<8K2o=dk2z>(q_9?te0ZI}9WUve%ni&9jxg$n~+XnV8d?b=S@$ zB8F4XVJ;px@?-tGq&?*1H1L5Fep;=Zu^KB_U&Z?OSDqwft61htKl4k5QR{qinO!#_ z=WKi1G)B9 zM45lX94^PAEO0|K-VNBw)u_UsJ0+QK6*HfGD47n~J48B`cpVcw1wi=4)-UZJmXnxp z@JmA@OYHEV62gUb2qF3~vhq`S=H|25@%zC9Qa~k4h0W9jlqt|ZUq%JC^*D+hfi9Xw z>`WRQV^RWVkU_I>fK22WOB!VcRWN`nSb<oL{=Y=xe$ z_i@xa?-ge!2Z!Ug0{5fySvR8+(%IG{WYPWU5&{J}5YdHj`y1~76)acC62K_(|02u~ zi1t<;c^w0pjxGu`xdttImOnEFReu?VK-wBdBQT=SoWDgXxl_QV^^icP>(FYeK$p_6 zHj-1O8xOB{=ym?~R>a0pub{};IeH!!Ll9Z|% zN0`3*;%BH;$^sOiZz4LAnHzH8)iD1AF#04vof>|0fd0780OFMtsN zED_TKLi?z)$UGUx<&7cJibhJ1$eEh~qH3YPfN-U{+TP}(u46+Nk--M2@EF+xAG?1A z>#<=BilkV1Vdq4;DXvrynG_&C0K{XH%UQI}Jq7MBIb7}t&bGAyjdDMPBAlH}E=(86 zu>kC!#o7=UtUqW1!x&g4$DwTvl5@v-{()y(1IRp*Ii$Ms<`DF-rTU~w^oeP4uar{I z8iL*+i!CqP>O+2p242#av;>VL_Nil5=lpg56|123H?dQP%e40IqK@uDp0ka~g}aNi z|Lo~<^cAZo|n4!t=s`IWj5Sv0)B<8{;c&y##C+DN@5o(cdR`GG&+pcLM=qoES$L z7Vsq@)7rrJOV7*n{K;Kmxis*&9MQWv!n^tcoLFLDom}@8(D|Z{SmB|`HV86? z1v2H7XoQ{&#Ll`zK#$6e7s*Qm1x0g!+<1{nDG+M{Z4RtLThJ}a01w65Q!3_-?hO+4QAV_0S9y79EhtK zsI38b5y4Qc(fls=PD8D>RZW3+i#d$*AF2gc zrb>qLckid?Ttr?40Vq9Z-ubGTLayBywEq-*Wu^|=zmFV@0#=n@>iq31Kc^?OzvSGr%k}t)pAS zl|X-njzGo-!QP&QMYk&C20@_Ewq~>DGN9PjOx6r0rK1D)9TBzX7f2DJufX9U^yOZp zRbP7hoc_#mwKx4?$lPc`&>%^EpT7aM2g~%Xw%Qd;$(ls(mD(G`u2X4xZxb-HzNik= zFLqbWp_28pOz%n-)F0UY<=$ke`USnHpQ+3w)Sow-%sM$k`!wjO!V01Y_8XvbwD|kr{Gqyic(1RuE{~Us1Bf2Vj(6ko8jGX8}HI`!un?GU39AO~X%y-dIdYt#Ohz?UE zaN>sg$XlzNOUlfRpO)jDhLXI?%7)DW1iN|yU=DWEIKpLs8k{-UISn8azG-tJB}DGSA~a6>vJAal@QDvkl|r)eg#s|kiQuQBWHV+(G_od~EW>5>tni@s`)D58Jqlbdir#uGF9cfpYSsL8rZpRURaC*&2BHf02Z%v!YciXD2JlL@|4Ou96$CAVVU;hK z`W@y=wT&d#TtfYBe4pRh;74(xB#NT^6JyVd;Ci%0lh_=XjGVk~rBL?% zj=}{oiZmyG(9@AA37l;{j_#vaP2p!50dEMA%Xg+38-_!81&Fm0CO17RWO}d0s3JEWpMf0nc)5Vxkn2$puUflF2u~#9M-u z+;|xffuet(B(TqIr?TMVzV}N6ENOSIZl1G~*`c&vYd=Q?Ny6ax>BM|!Tl;}rx+|_j zxxXu1O1%exWRX+Id$)N-W8nnkXxAX|RIqKoE%zfBRmn(5TC@21&pXbe9N!zxw0nbG zxF5oZ&NEw07l=dOunXyQsPB)Sd;?l7EZCj;D20Cw`Trz)I(#p>ptOT}HaIyq3(qlz z@x`l1(WSj_3z%!=1TaeZkTXr|^E3$2Dm?{bLqX-(7AyCUYbr;KdL}Ym5G%P;2xt!d z1IUznW>^q3uhS~LLZSx>am1RYo5h@+ZzE1wBh%X*U~u*P33xmUonWL0kE}MB-o@B~ zq(Cp6@OBEdG1wuMXooLO!DOjSn(D@&;O5H?q1xfY%X^Pc5Gh;o1fyRvOE5e z%T30C8y>nT$EMY4bbi5kcOC$7p4$gGZT^tolTAKH-+*amDrHxv7ylR1`egk7MmjlB zfN(!D^CvHWYS+3hLt3ZSld$&cBHB3p}h+vn5X{5!%_&k|L)M{k7a?tqP zH9#8HWn{`_niiNjga`6P`aPKze10y|aJ@$6$G&vhhr|8>t-#@?lukb?)1s~ieEE(q z|8AKUb#?jj*ZA_k=F7iUrbS&>$h2ttmwfpD&4+WgFO50MlMN9t(;Ot?0Ka**@g!{Z z8Qd@9eiQdQxHGul#~lLR$+*wJJq!0d+>3E9#a)NH9(OD5J8@gM{~GuI#Qg;BZMb*g z{t@nf!Hp$PuIPM9{(BIdkwVXF+kYN|sL1xGqvMjj`>`uli)QeUe4^IniK19ygE&iu zV`qR%97~hO&IGP^?2M<&I7MY112eG2R#^$Q+*tInm7%QnW3V{Qrr8pe{!|@WixtZ# zr!`N;g5NL#%*5`7V8)afXWsdznfp8vu37&w)Kvu?c;u2>T% zczkfe8F)rCOnjE%8?PGIxpyDf7JuJ>@oeMRB(|y43AS{UOH>HJV}$x38?|btqR5BH zUO~|Y5q6TQdL~Q@J{S!2Q8C4iij3~hJPM;JSqH^0Sx0cO@kiA`&6lhr5Q%U{?3mht zHbSF?-^)a_&fUMlfJ2+pQMzMj1ZFJ`%uRS9`$ptLrCvc%7ywa(%Gt$oS8|Cxu>`uT zv2{?D)?7gxY==Cb`ti*52@;%{W#?owH=uKLb-rWh4o^EqC!9(iYd&D6FuBq|Kt$8C z`)OJkZ2WQ_n@Ed;>;M$RNSl`|b0wf4ni^byf`pblNX(@kEPxypXpLivE z59ZIxPk5)`C*0S6%+7GJnI#%~Fn?Cwk2T|M_{6t3Z;t3Qc)|YV_f|N_m%O{e@Q%~6 z37G~wf@26S=nOM8mu=vv!K|0Ot3M2~BaILKdV=G+<>m%8@eAh4%YzjZkI%IH=L>QE zS)4BnRvsL{a&TP(UP2T#vWu(@3s;|bIPS$$tAPO@9E|ce;y`nbh7YIg;g=r+e|(qZ z;h%5}_}I1c@Q+1)d;~NTTAlZM3}y$4#N>nCcgH`><(^{<`p}_|oSuE5-T1~XBh^p4 zrzd+Dqr0RhlU}BTvV)`Z=*lj_$3%Ig#uecoMcGC8M^SbW{!x@&gkMtG<8Idner1pU zX_Os{z}UUtE{?A3BK)H$y9oa%$}Yk`in5FFkD}}%{F2HZb5Fp6D{t9jAE#`dWS3{( zgZ>ZkotWQn2woXK+#G&Om64Y4a@c9xFb!ixdA*5rxc_&f2thxEJn_jZJ`%3R`U;B( z;!oJ&r!&E!#b`6=&SWM0?NoD>-$Wu*tDWFCkwc95;q>4l3Yalu1(Co6kzI#xN^uhV zXISZp!{{R3k^F0d{HyBrnHIP6!M7?pZVqwr?W><#57YV!s{6s8SN4F?zZ{fD$XlR! zF@2amJoE-2wZ$POaXPc_LF#$Ka?106|C^5wad;m}!s2zQWQOzW@_U-1S%fi*2zL79 zk45;nWoy6ur3fp=E#hY)Y~zUpwE6LjbbP|I^6C?g9rAe0Z$k?|GOf=_Nf-e0a~ct@ zi_IdYGNZmy{DjIp4Cy1&e9K3pITn6@5|{$j_a~|iNB#aphSDj2-z4$8heas0TK!`scdnk730~}`BxI+|O zAc}g&W6pehW{-7x-KfGC7R3C(8hZv<#KrglkvSyR8>vYLG1Q=Pga*?Y^~LO|Bl1VD z)TDpWMg1IgcLO7>Fz`kFq<;+qJ2h!5krF3AiIM{`^Zcp!vi{~h=ImW!byB?Esf1l} z#e+8erZvR2xt}=;vDTy(FraxmC$C0Iew8gcool1BQGyRR>`7Om3?G3JvA=g83Cz@Y z0c)N;5>pmp)0M4w^BEtuy4@X9qI`g3_YHLJmi{d~bBT`%V zHoli3TYT*?8|UnuKck4UK8s-j7dZ) z{qN?0X)kUf#2A;{q*9ky;QnP*fkG^&y_MG|m1;B^j?3eWCyQ7B;B{v<& zcJ>~W!zH;e8hl|Qi&Hd$dBb420{a!u2)sAuy@J2qa0o`Eu`KRt3CGyid&n?156{m% zj=?8(M{YwA4v2pq+bQ_727f?@0J<7bEY*V@t1L1PAamX;gRg?`>oF|F;GqWV-ZN9^ zN+Z_aiy16;xB0ijgVFcaN8g(nGJm*daL-`$kf_TNPCB*tKOr7i{S8=Akvyg+1cK@> zq8*AZnLZm)HhV>Sz7pTtq$W)wHVrVb_`^?-Ff3NzG5bVmu!Z`poR`}jeb;bnp>lC% z&HW~oum9Wx#IHDyMp%u;xC^jzgTEsYb^ChX#p$inrEVG^I|fYD-4b$nUJCP+l%4&- zWf%Y01SgtU3NzVCBt%6}P4<}^U;C7K->|2Ycioq<^CGr>?Kj*fP@SNOfCd`gV?I~= zZt??TF#2N6MPwPZzZ)-1d?tp!UXgALr=T8^vC7*jKu z;wR5*=P|X1DeP3>q$E?dOl@U~`)--VBl~_FvT-t0mY`%|+K_+$Z7Y zQUIMV{#Fr37j?y16+7n!n25_ThVlOSl9i2J-T13yk%rFt+pnnaY?w2}xNgZcHP_Zg zRz_E>Tmf*&vSl(Ix%TQQ#>%zz-H`+kBh6ir?)LUb;~gE1ZC%Z`HGXc2F(um8-Pjqa zk94$mHFqN~(u|BX$m(irY>3QW7-?u;)7;$^Y441*Gctn_@&}HANy*P)TIvS}<jz4PO zhvR_q3T-kvXB1F2)i<{o$d4eu@s8$hre`DF)Y9JGNuUxyYkf;gdxFpcLXEA7jynle z1M0wEr|)he6a(~^UG1HM$8rE&iTXBCay@|V=GI1F=_?e+-+rGSZ(WO88xuXrdgB%C z&23%A=JJk~`a6kbJY2rEzO6wdzg51vM`k`zzQ*{c^4r(8cQvl;>1;E8UEb8w(o)ly zxb=$mp0;k|z4FGk22qkNzYgT>twt)m-1ugAMPmzgg;sQTHrBTqTf$d0cCWy$l(8es zJurp&LRf6>l&=N58nq>6{2|od+EL%xXjo;CD%#WpHpXM+VI8 z`&ISO&7);KtuZBcm+=eWjhqgYKK!Iu)`o4d`j+OeHww)EQ`W`zwYNcC?-LK(h2?8| znwnY~jRR0hN6VeEO;43$W2*5=bmSj^w&fgf(!y;jZ$|fYN-f*ff`q zc?89ygQ-pm+HJg4j*bzU9V<7=u4u=9b?}q&uQs=}HFkCx{b1AA1?;}tNpdG1o4$_6 z7C!oVjj%D^7s4~!&*%7hK1YT`&R=8ms;s5HP3X4E_-?pIYWas@pnOxHZ{~B${etL0 zKKmXDL6wywWvePjLgOb5Ps)b3l=YP@@4Kw8EYcSqFRP4g{wy|m$>x`;eho8^@~^_p zi!ke7MF1CJ%D)^N#7ys3^crT~v9!NW(Z8?gHLU4Jz=s!M*6)W!{rD||WiV%<|K$qS z^y6Vt=jr`0=_|2|Pu$ZKy@oaYFy!JznDzT%(r0llm1SosdJQv=?e8d{_rs)LgiRwW*+Moh3Z9mKP>3sDww@k(<@lhFGm?K!ld`Z zq#sxKS1Ec8Yx=&k1-VD>he^L`f#khHw_m}U-Y+lf_rrpIq0IUVO|M{0ACc92_4{Gc z_bL2lMXzB^?`_h9kEq|*pMt(h*59e=6|Cu3F@cLO()(f3k1vvCcPV-e6aQGoPX&IB zBJO%cuVGCeK^ZT?tUp2k7h%?4spvN=dJVIj^)F`v7hk0J!=&%KRF*xa+pl2alYX2D zTzrw<50idXwJdv5(QBCaq~C;_m!|i_q|a8%vS$>%hBbXhSde@4epu9x1HQz4QP;0v zO`l}~7hja$50ifRRkG|2MXzDvQ~qx;fr~HF`{5(`Z_K8F`RA8_OU*yonB+YN?d1HU zVb;g`$8q!0^^Xfk(I9hVsZ3v@=ryeAE11Bg>HRR+!Hjm#g{mVFhdd@u-5e|M`I~SN?Q|hLyj5S;4E+czsjB{2O7^^}i}u#{=(a{AyW# zNWnVZm;@rquj8*zC|Jic{3{eJ*Z%n&1?&0t0tIXT!#~z7`a{JRmnnFal7E?o)%<^h zg0=sqt;l~66xVG9uw4LeEP(GXfd8%l{!Rh>Q~|uL0Nzmmzfb@_0U7@h_xEr=iTf$s z-^aZL_tUu9pZ|m#SM_)CI2Qbf5!Z{W`11T(Aii9!1>$P46%VY);=W~Ayu^Akt`~rD zE_c)_42x#}N-dsHE46roZ&ei6hZ~HzUK+-OYsNT_7>LzSd`)AwSPe0u*F$k{8H)dI zEwF-%H|JMy@xTHXYi+E2<85kD7;p103gg}q7i(*^vWs`Am0!HexAKeom&Wn@syDD} zAlCkY9J!AmHv-fafL{FTWxrnVtEIkL)>GT7ut!}xp`X*^laWB z^0wx;bI +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int checkDrawCard(int p, struct gameState *post) { + int r; + + r = drawCard (p, post); +} + +int main () { + + int i, n, r, p, deckCount, discardCount, handCount; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + struct gameState G; + + printf ("Testing drawCard.\n"); + + printf ("RANDOM TESTS.\n"); + + SelectStream(2); + PutSeed(3); + + for (n = 0; n < 2000; n++) { + for (i = 0; i < sizeof(struct gameState); i++) { + ((char*)&G)[i] = floor(Random() * 256); + } + p = floor(Random() * 1000); + checkDrawCard(p, &G); + } + + printf ("ALL TESTS OK\n"); + + exit(0); +} diff --git a/projects/bleckw/dominion/betterTestDrawCard.c b/projects/bleckw/dominion/betterTestDrawCard.c new file mode 100644 index 00000000..befb2921 --- /dev/null +++ b/projects/bleckw/dominion/betterTestDrawCard.c @@ -0,0 +1,70 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int checkDrawCard(int p, struct gameState *post) { + int r; + + r = drawCard (p, post); + + assert (r == 0); +} + +int main () { + + int i, n, r, p, deckCount, discardCount, handCount; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + struct gameState G; + + printf ("Testing drawCard.\n"); + + printf ("RANDOM TESTS.\n"); + + SelectStream(2); + PutSeed(3); + + for (n = 0; n < 2000; n++) { + for (i = 0; i < sizeof(struct gameState); i++) { + ((char*)&G)[i] = floor(Random() * 256); + } + p = floor(Random() * 2); + G.deckCount[p] = floor(Random() * MAX_DECK); + G.discardCount[p] = floor(Random() * MAX_DECK); + G.handCount[p] = floor(Random() * MAX_HAND); + checkDrawCard(p, &G); + } + + printf ("ALL TESTS OK\n"); + + exit(0); + + printf ("SIMPLE FIXED TESTS.\n"); + for (p = 0; p < 2; p++) { + for (deckCount = 0; deckCount < 5; deckCount++) { + for (discardCount = 0; discardCount < 5; discardCount++) { + for (handCount = 0; handCount < 5; handCount++) { + memset(&G, 23, sizeof(struct gameState)); + r = initializeGame(2, k, 1, &G); + G.deckCount[p] = deckCount; + memset(G.deck[p], 0, sizeof(int) * deckCount); + G.discardCount[p] = discardCount; + memset(G.discard[p], 0, sizeof(int) * discardCount); + G.handCount[p] = handCount; + memset(G.hand[p], 0, sizeof(int) * handCount); + checkDrawCard(p, &G); + } + } + } + } + + return 0; +} diff --git a/projects/bleckw/dominion/dominion.c b/projects/bleckw/dominion/dominion.c new file mode 100644 index 00000000..88f32414 --- /dev/null +++ b/projects/bleckw/dominion/dominion.c @@ -0,0 +1,1333 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include "rngs.h" +#include +#include +#include + +int compare(const void* a, const void* b) { + if (*(int*)a > *(int*)b) + return 1; + if (*(int*)a < *(int*)b) + return -1; + return 0; +} + +struct gameState* newGame() { + struct gameState* g = malloc(sizeof(struct gameState)); + return g; +} + +int* kingdomCards(int k1, int k2, int k3, int k4, int k5, int k6, int k7, + int k8, int k9, int k10) { + int* k = malloc(10 * sizeof(int)); + k[0] = k1; + k[1] = k2; + k[2] = k3; + k[3] = k4; + k[4] = k5; + k[5] = k6; + k[6] = k7; + k[7] = k8; + k[8] = k9; + k[9] = k10; + return k; +} + +int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed, + struct gameState *state) { + + int i; + int j; + int it; + //set up random number generator + SelectStream(1); + PutSeed((long)randomSeed); + + //check number of players + if (numPlayers > MAX_PLAYERS || numPlayers < 2) + { + return -1; + } + + //set number of players + state->numPlayers = numPlayers; + + //check selected kingdom cards are different + for (i = 0; i < 10; i++) + { + for (j = 0; j < 10; j++) + { + if (j != i && kingdomCards[j] == kingdomCards[i]) + { + return -1; + } + } + } + + + //initialize supply + /////////////////////////////// + + //set number of Curse cards + if (numPlayers == 2) + { + state->supplyCount[curse] = 10; + } + else if (numPlayers == 3) + { + state->supplyCount[curse] = 20; + } + else + { + state->supplyCount[curse] = 30; + } + + //set number of Victory cards + if (numPlayers == 2) + { + state->supplyCount[estate] = 8; + state->supplyCount[duchy] = 8; + state->supplyCount[province] = 8; + } + else + { + state->supplyCount[estate] = 12; + state->supplyCount[duchy] = 12; + state->supplyCount[province] = 12; + } + + //set number of Treasure cards + state->supplyCount[copper] = 60 - (7 * numPlayers); + state->supplyCount[silver] = 40; + state->supplyCount[gold] = 30; + + //set number of Kingdom cards + for (i = adventurer; i <= treasure_map; i++) //loop all cards + { + for (j = 0; j < 10; j++) //loop chosen cards + { + if (kingdomCards[j] == i) + { + //check if card is a 'Victory' Kingdom card + if (kingdomCards[j] == great_hall || kingdomCards[j] == gardens) + { + if (numPlayers == 2){ + state->supplyCount[i] = 8; + } + else{ state->supplyCount[i] = 12; } + } + else + { + state->supplyCount[i] = 10; + } + break; + } + else //card is not in the set choosen for the game + { + state->supplyCount[i] = -1; + } + } + + } + + //////////////////////// + //supply intilization complete + + //set player decks + for (i = 0; i < numPlayers; i++) + { + state->deckCount[i] = 0; + for (j = 0; j < 3; j++) + { + state->deck[i][j] = estate; + state->deckCount[i]++; + } + for (j = 3; j < 10; j++) + { + state->deck[i][j] = copper; + state->deckCount[i]++; + } + } + + //shuffle player decks + for (i = 0; i < numPlayers; i++) + { + if ( shuffle(i, state) < 0 ) + { + return -1; + } + } + + //draw player hands + for (i = 0; i < numPlayers; i++) + { + //initialize hand size to zero + state->handCount[i] = 0; + state->discardCount[i] = 0; + //draw 5 cards + // for (j = 0; j < 5; j++) + // { + // drawCard(i, state); + // } + } + + //set embargo tokens to 0 for all supply piles + for (i = 0; i <= treasure_map; i++) + { + state->embargoTokens[i] = 0; + } + + //initialize first player's turn + state->outpostPlayed = 0; + state->phase = 0; + state->numActions = 1; + state->numBuys = 1; + state->playedCardCount = 0; + state->whoseTurn = 0; + state->handCount[state->whoseTurn] = 0; + //int it; move to top + + //Moved draw cards to here, only drawing at the start of a turn + for (it = 0; it < 5; it++){ + drawCard(state->whoseTurn, state); + } + + updateCoins(state->whoseTurn, state, 0); + + return 0; +} + +int shuffle(int player, struct gameState *state) { + + + int newDeck[MAX_DECK]; + int newDeckPos = 0; + int card; + int i; + + if (state->deckCount[player] < 1) + return -1; + qsort ((void*)(state->deck[player]), state->deckCount[player], sizeof(int), compare); + /* SORT CARDS IN DECK TO ENSURE DETERMINISM! */ + + while (state->deckCount[player] > 0) { + card = floor(Random() * state->deckCount[player]); + newDeck[newDeckPos] = state->deck[player][card]; + newDeckPos++; + for (i = card; i < state->deckCount[player]-1; i++) { + state->deck[player][i] = state->deck[player][i+1]; + } + state->deckCount[player]--; + } + for (i = 0; i < newDeckPos; i++) { + state->deck[player][i] = newDeck[i]; + state->deckCount[player]++; + } + + return 0; +} + +int playCard(int handPos, int choice1, int choice2, int choice3, struct gameState *state) +{ + int card; + int coin_bonus = 0; //tracks coins gain from actions + + //check if it is the right phase + if (state->phase != 0) + { + return -1; + } + + //check if player has enough actions + if ( state->numActions < 1 ) + { + return -1; + } + + //get card played + card = handCard(handPos, state); + + //check if selected card is an action + if ( card < adventurer || card > treasure_map ) + { + return -1; + } + + //play card + if ( cardEffect(card, choice1, choice2, choice3, state, handPos, &coin_bonus) < 0 ) + { + return -1; + } + + //reduce number of actions + state->numActions--; + + //update coins (Treasure cards may be added with card draws) + updateCoins(state->whoseTurn, state, coin_bonus); + + return 0; +} + +int buyCard(int supplyPos, struct gameState *state) { + int who; + if (DEBUG){ + printf("Entering buyCard...\n"); + } + + // I don't know what to do about the phase thing. + + who = state->whoseTurn; + + if (state->numBuys < 1){ + if (DEBUG) + printf("You do not have any buys left\n"); + return -1; + } else if (supplyCount(supplyPos, state) <1){ + if (DEBUG) + printf("There are not any of that type of card left\n"); + return -1; + } else if (state->coins < getCost(supplyPos)){ + if (DEBUG) + printf("You do not have enough money to buy that. You have %d coins.\n", state->coins); + return -1; + } else { + state->phase=1; + //state->supplyCount[supplyPos]--; + gainCard(supplyPos, state, 0, who); //card goes in discard, this might be wrong.. (2 means goes into hand, 0 goes into discard) + + state->coins = (state->coins) - (getCost(supplyPos)); + state->numBuys--; + if (DEBUG) + printf("You bought card number %d for %d coins. You now have %d buys and %d coins.\n", supplyPos, getCost(supplyPos), state->numBuys, state->coins); + } + + //state->discard[who][state->discardCount[who]] = supplyPos; + //state->discardCount[who]++; + + return 0; +} + +int numHandCards(struct gameState *state) { + return state->handCount[ whoseTurn(state) ]; +} + +int handCard(int handPos, struct gameState *state) { + int currentPlayer = whoseTurn(state); + return state->hand[currentPlayer][handPos]; +} + +int supplyCount(int card, struct gameState *state) { + return state->supplyCount[card]; +} + +int fullDeckCount(int player, int card, struct gameState *state) { + int i; + int count = 0; + + for (i = 0; i < state->deckCount[player]; i++) + { + if (state->deck[player][i] == card) count++; + } + + for (i = 0; i < state->handCount[player]; i++) + { + if (state->hand[player][i] == card) count++; + } + + for (i = 0; i < state->discardCount[player]; i++) + { + if (state->discard[player][i] == card) count++; + } + + return count; +} + +int whoseTurn(struct gameState *state) { + return state->whoseTurn; +} + +int endTurn(struct gameState *state) { + int k; + int i; + int currentPlayer = whoseTurn(state); + + //Discard hand + for (i = 0; i < state->handCount[currentPlayer]; i++){ + state->discard[currentPlayer][state->discardCount[currentPlayer]++] = state->hand[currentPlayer][i];//Discard + state->hand[currentPlayer][i] = -1;//Set card to -1 + } + state->handCount[currentPlayer] = 0;//Reset hand count + + //Code for determining the player + if (currentPlayer < (state->numPlayers - 1)){ + state->whoseTurn = currentPlayer + 1;//Still safe to increment + } + else{ + state->whoseTurn = 0;//Max player has been reached, loop back around to player 1 + } + + state->outpostPlayed = 0; + state->phase = 0; + state->numActions = 1; + state->coins = 0; + state->numBuys = 1; + state->playedCardCount = 0; + state->handCount[state->whoseTurn] = 0; + + //int k; move to top + //Next player draws hand + for (k = 0; k < 5; k++){ + drawCard(state->whoseTurn, state);//Draw a card + } + + //Update money + updateCoins(state->whoseTurn, state , 0); + + return 0; +} + +int isGameOver(struct gameState *state) { + int i; + int j; + + //if stack of Province cards is empty, the game ends + if (state->supplyCount[province] == 0) + { + return 1; + } + + //if three supply pile are at 0, the game ends + j = 0; + for (i = 0; i < 25; i++) + { + if (state->supplyCount[i] == 0) + { + j++; + } + } + if ( j >= 3) + { + return 1; + } + + return 0; +} + +int scoreFor (int player, struct gameState *state) { + + int i; + int score = 0; + //score from hand + for (i = 0; i < state->handCount[player]; i++) + { + if (state->hand[player][i] == curse) { score = score - 1; }; + if (state->hand[player][i] == estate) { score = score + 1; }; + if (state->hand[player][i] == duchy) { score = score + 3; }; + if (state->hand[player][i] == province) { score = score + 6; }; + if (state->hand[player][i] == great_hall) { score = score + 1; }; + if (state->hand[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); }; + } + + //score from discard + for (i = 0; i < state->discardCount[player]; i++) + { + if (state->discard[player][i] == curse) { score = score - 1; }; + if (state->discard[player][i] == estate) { score = score + 1; }; + if (state->discard[player][i] == duchy) { score = score + 3; }; + if (state->discard[player][i] == province) { score = score + 6; }; + if (state->discard[player][i] == great_hall) { score = score + 1; }; + if (state->discard[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); }; + } + + //score from deck + for (i = 0; i < state->discardCount[player]; i++) + { + if (state->deck[player][i] == curse) { score = score - 1; }; + if (state->deck[player][i] == estate) { score = score + 1; }; + if (state->deck[player][i] == duchy) { score = score + 3; }; + if (state->deck[player][i] == province) { score = score + 6; }; + if (state->deck[player][i] == great_hall) { score = score + 1; }; + if (state->deck[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); }; + } + + return score; +} + +int getWinners(int players[MAX_PLAYERS], struct gameState *state) { + int i; + int j; + int highScore; + int currentPlayer; + + //get score for each player + for (i = 0; i < MAX_PLAYERS; i++) + { + //set unused player scores to -9999 + if (i >= state->numPlayers) + { + players[i] = -9999; + } + else + { + players[i] = scoreFor (i, state); + } + } + + //find highest score + j = 0; + for (i = 0; i < MAX_PLAYERS; i++) + { + if (players[i] > players[j]) + { + j = i; + } + } + highScore = players[j]; + + //add 1 to players who had less turns + currentPlayer = whoseTurn(state); + for (i = 0; i < MAX_PLAYERS; i++) + { + if ( players[i] == highScore && i > currentPlayer ) + { + players[i]++; + } + } + + //find new highest score + j = 0; + for (i = 0; i < MAX_PLAYERS; i++) + { + if ( players[i] > players[j] ) + { + j = i; + } + } + highScore = players[j]; + + //set winners in array to 1 and rest to 0 + for (i = 0; i < MAX_PLAYERS; i++) + { + if ( players[i] == highScore ) + { + players[i] = 1; + } + else + { + players[i] = 0; + } + } + + return 0; +} + +int drawCard(int player, struct gameState *state) +{ int count; + int deckCounter; + if (state->deckCount[player] <= 0){//Deck is empty + + //Step 1 Shuffle the discard pile back into a deck + int i; + //Move discard to deck + for (i = 0; i < state->discardCount[player];i++){ + state->deck[player][i] = state->discard[player][i]; + state->discard[player][i] = -1; + } + + state->deckCount[player] = state->discardCount[player]; + state->discardCount[player] = 0;//Reset discard + + //Shufffle the deck + shuffle(player, state);//Shuffle the deck up and make it so that we can draw + + if (DEBUG){//Debug statements + printf("Deck count now: %d\n", state->deckCount[player]); + } + + state->discardCount[player] = 0; + + //Step 2 Draw Card + count = state->handCount[player];//Get current player's hand count + + if (DEBUG){//Debug statements + printf("Current hand count: %d\n", count); + } + + deckCounter = state->deckCount[player];//Create a holder for the deck count + + if (deckCounter == 0) + return -1; + + state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to hand + state->deckCount[player]--; + state->handCount[player]++;//Increment hand count + } + + else{ + int count = state->handCount[player];//Get current hand count for player + int deckCounter; + if (DEBUG){//Debug statements + printf("Current hand count: %d\n", count); + } + + deckCounter = state->deckCount[player];//Create holder for the deck count + state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to the hand + state->deckCount[player]--; + state->handCount[player]++;//Increment hand count + } + + return 0; +} + +int getCost(int cardNumber) +{ + switch( cardNumber ) + { + case curse: + return 0; + case estate: + return 2; + case duchy: + return 5; + case province: + return 8; + case copper: + return 0; + case silver: + return 3; + case gold: + return 6; + case adventurer: + return 6; + case council_room: + return 5; + case feast: + return 4; + case gardens: + return 4; + case mine: + return 5; + case remodel: + return 4; + case smithy: + return 4; + case village: + return 3; + case baron: + return 4; + case great_hall: + return 3; + case minion: + return 5; + case steward: + return 3; + case tribute: + return 5; + case ambassador: + return 3; + case cutpurse: + return 4; + case embargo: + return 2; + case outpost: + return 5; + case salvager: + return 4; + case sea_hag: + return 4; + case treasure_map: + return 4; + } + + return -1; +} + +int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus) +{ + int i; + int j; + int k; + int x; + int index; + int currentPlayer = whoseTurn(state); + int nextPlayer = currentPlayer + 1; + + int tributeRevealedCards[2] = {-1, -1}; + int temphand[MAX_HAND];// moved above the if statement + int drawntreasure=0; + int cardDrawn; + int z = 0;// this is the counter for the temp hand + if (nextPlayer > (state->numPlayers - 1)){ + nextPlayer = 0; + } + + + //uses switch to select card and perform actions + switch( card ) + { + case adventurer: + while(drawntreasure<2){ + if (state->deckCount[currentPlayer] <1){//if the deck is empty we need to shuffle discard and add to deck + shuffle(currentPlayer, state); + } + drawCard(currentPlayer, state); + cardDrawn = state->hand[currentPlayer][state->handCount[currentPlayer]-1];//top card of hand is most recently drawn card. + if (cardDrawn == copper || cardDrawn == silver || cardDrawn == gold) + drawntreasure++; + else{ + temphand[z]=cardDrawn; + state->handCount[currentPlayer]--; //this should just remove the top card (the most recently drawn one). + z++; + } + } + while(z-1>=0){ + state->discard[currentPlayer][state->discardCount[currentPlayer]++]=temphand[z-1]; // discard all cards in play that have been drawn + z=z-1; + } + return 0; + + case council_room: + //+4 Cards + for (i = 0; i < 4; i++) + { + drawCard(currentPlayer, state); + } + + //+1 Buy + state->numBuys++; + + //Each other player draws a card + for (i = 0; i < state->numPlayers; i++) + { + if ( i != currentPlayer ) + { + drawCard(i, state); + } + } + + //put played card in played card pile + discardCard(handPos, currentPlayer, state, 0); + + return 0; + + case feast: + //gain card with cost up to 5 + //Backup hand + for (i = 0; i <= state->handCount[currentPlayer]; i++){ + temphand[i] = state->hand[currentPlayer][i];//Backup card + state->hand[currentPlayer][i] = -1;//Set to nothing + } + //Backup hand + + //Update Coins for Buy + updateCoins(currentPlayer, state, 5); + x = 1;//Condition to loop on + while( x == 1) {//Buy one card + if (supplyCount(choice1, state) <= 0){ + if (DEBUG) + printf("None of that card left, sorry!\n"); + + if (DEBUG){ + printf("Cards Left: %d\n", supplyCount(choice1, state)); + } + } + else if (state->coins < getCost(choice1)){ + printf("That card is too expensive!\n"); + + if (DEBUG){ + printf("Coins: %d < %d\n", state->coins, getCost(choice1)); + } + } + else{ + + if (DEBUG){ + printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); + } + + gainCard(choice1, state, 0, currentPlayer);//Gain the card + x = 0;//No more buying cards + + if (DEBUG){ + printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); + } + + } + } + + //Reset Hand + for (i = 0; i <= state->handCount[currentPlayer]; i++){ + state->hand[currentPlayer][i] = temphand[i]; + temphand[i] = -1; + } + //Reset Hand + + return 0; + + case gardens: + return -1; + + case mine: + j = state->hand[currentPlayer][choice1]; //store card we will trash + + if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold) + { + return -1; + } + + if (choice2 > treasure_map || choice2 < curse) + { + return -1; + } + + if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) ) + { + return -1; + } + + gainCard(choice2, state, 2, currentPlayer); + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + //discard trashed card + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == j) + { + discardCard(i, currentPlayer, state, 0); + break; + } + } + + return 0; + + case remodel: + j = state->hand[currentPlayer][choice1]; //store card we will trash + + if ( (getCost(state->hand[currentPlayer][choice1]) + 2) > getCost(choice2) ) + { + return -1; + } + + gainCard(choice2, state, 0, currentPlayer); + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + //discard trashed card + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == j) + { + discardCard(i, currentPlayer, state, 0); + break; + } + } + + + return 0; + + case smithy: + //+3 Cards + for (i = 0; i < 3; i++) + { + drawCard(currentPlayer, state); + } + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case village: + //+1 Card + drawCard(currentPlayer, state); + + //+2 Actions + state->numActions = state->numActions + 2; + + //discard played card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case baron: + state->numBuys++;//Increase buys by 1! + if (choice1 > 0){//Boolean true or going to discard an estate + int p = 0;//Iterator for hand! + int card_not_discarded = 1;//Flag for discard set! + while(card_not_discarded){ + if (state->hand[currentPlayer][p] == estate){//Found an estate card! + state->coins += 4;//Add 4 coins to the amount of coins + state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p]; + state->discardCount[currentPlayer]++; + for (;p < state->handCount[currentPlayer]; p++){ + state->hand[currentPlayer][p] = state->hand[currentPlayer][p+1]; + } + state->hand[currentPlayer][state->handCount[currentPlayer]] = -1; + state->handCount[currentPlayer]--; + card_not_discarded = 0;//Exit the loop + } + else if (p > state->handCount[currentPlayer]){ + if(DEBUG) { + printf("No estate cards in your hand, invalid choice\n"); + printf("Must gain an estate if there are any\n"); + } + if (supplyCount(estate, state) > 0){ + gainCard(estate, state, 0, currentPlayer); + state->supplyCount[estate]--;//Decrement estates + if (supplyCount(estate, state) == 0){ + isGameOver(state); + } + } + card_not_discarded = 0;//Exit the loop + } + + else{ + p++;//Next card + } + } + } + + else{ + if (supplyCount(estate, state) > 0){ + gainCard(estate, state, 0, currentPlayer);//Gain an estate + state->supplyCount[estate]--;//Decrement Estates + if (supplyCount(estate, state) == 0){ + isGameOver(state); + } + } + } + + + return 0; + + case great_hall: + //+1 Card + drawCard(currentPlayer, state); + + //+1 Actions + state->numActions++; + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case minion: + //+1 action + state->numActions++; + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + if (choice1) //+2 coins + { + state->coins = state->coins + 2; + } + + else if (choice2) //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4 + { + //discard hand + while(numHandCards(state) > 0) + { + discardCard(handPos, currentPlayer, state, 0); + } + + //draw 4 + for (i = 0; i < 4; i++) + { + drawCard(currentPlayer, state); + } + + //other players discard hand and redraw if hand size > 4 + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + if ( state->handCount[i] > 4 ) + { + //discard hand + while( state->handCount[i] > 0 ) + { + discardCard(handPos, i, state, 0); + } + + //draw 4 + for (j = 0; j < 4; j++) + { + drawCard(i, state); + } + } + } + } + + } + return 0; + + case steward: + if (choice1 == 1) + { + //+2 cards + drawCard(currentPlayer, state); + drawCard(currentPlayer, state); + } + else if (choice1 == 2) + { + //+2 coins + state->coins = state->coins + 2; + } + else + { + //trash 2 cards in hand + discardCard(choice2, currentPlayer, state, 1); + discardCard(choice3, currentPlayer, state, 1); + } + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case tribute: + if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1){ + if (state->deckCount[nextPlayer] > 0){ + tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deckCount[nextPlayer]--; + } + else if (state->discardCount[nextPlayer] > 0){ + tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer]-1]; + state->discardCount[nextPlayer]--; + } + else{ + //No Card to Reveal + if (DEBUG){ + printf("No cards to reveal\n"); + } + } + } + + else{ + if (state->deckCount[nextPlayer] == 0){ + for (i = 0; i < state->discardCount[nextPlayer]; i++){ + state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck + state->deckCount[nextPlayer]++; + state->discard[nextPlayer][i] = -1; + state->discardCount[nextPlayer]--; + } + + shuffle(nextPlayer,state);//Shuffle the deck + } + tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; + state->deckCount[nextPlayer]--; + tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; + state->deckCount[nextPlayer]--; + } + + if (tributeRevealedCards[0] == tributeRevealedCards[1]){//If we have a duplicate card, just drop one + state->playedCards[state->playedCardCount] = tributeRevealedCards[1]; + state->playedCardCount++; + tributeRevealedCards[1] = -1; + } + + for (i = 0; i <= 2; i ++){ + if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold){//Treasure cards + state->coins += 2; + } + + else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall){//Victory Card Found + drawCard(currentPlayer, state); + drawCard(currentPlayer, state); + } + else{//Action Card + state->numActions = state->numActions + 2; + } + } + + return 0; + + case ambassador: + j = 0; //used to check if player has enough cards to discard + + if (choice2 > 2 || choice2 < 0) + { + return -1; + } + + if (choice1 == handPos) + { + return -1; + } + + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (i != handPos && i == state->hand[currentPlayer][choice1] && i != choice1) + { + j++; + } + } + if (j < choice2) + { + return -1; + } + + if (DEBUG) + printf("Player %d reveals card number: %d\n", currentPlayer, state->hand[currentPlayer][choice1]); + + //increase supply count for choosen card by amount being discarded + state->supplyCount[state->hand[currentPlayer][choice1]] += choice2; + + //each other player gains a copy of revealed card + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + gainCard(state->hand[currentPlayer][choice1], state, 0, i); + } + } + + //discard played card from hand + discardCard(handPos, currentPlayer, state, 0); + + //trash copies of cards returned to supply + for (j = 0; j < choice2; j++) + { + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) + { + discardCard(i, currentPlayer, state, 1); + break; + } + } + } + + return 0; + + case cutpurse: + + updateCoins(currentPlayer, state, 2); + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + for (j = 0; j < state->handCount[i]; j++) + { + if (state->hand[i][j] == copper) + { + discardCard(j, i, state, 0); + break; + } + if (j == state->handCount[i]) + { + for (k = 0; k < state->handCount[i]; k++) + { + if (DEBUG) + printf("Player %d reveals card number %d\n", i, state->hand[i][k]); + } + break; + } + } + + } + + } + + //discard played card from hand + discardCard(handPos, currentPlayer, state, 0); + + return 0; + + + case embargo: + //+2 Coins + state->coins = state->coins + 2; + + //see if selected pile is in play + if ( state->supplyCount[choice1] == -1 ) + { + return -1; + } + + //add embargo token to selected supply pile + state->embargoTokens[choice1]++; + + //trash card + discardCard(handPos, currentPlayer, state, 1); + return 0; + + case outpost: + //set outpost flag + state->outpostPlayed++; + + //discard card + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case salvager: + //+1 buy + state->numBuys++; + + if (choice1) + { + //gain coins equal to trashed card + state->coins = state->coins + getCost( handCard(choice1, state) ); + //trash card + discardCard(choice1, currentPlayer, state, 1); + } + + //discard card + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case sea_hag: + for (i = 0; i < state->numPlayers; i++){ + if (i != currentPlayer){ + state->discard[i][state->discardCount[i]] = state->deck[i][state->deckCount[i]--]; state->deckCount[i]--; + state->discardCount[i]++; + state->deck[i][state->deckCount[i]--] = curse;//Top card now a curse + } + } + return 0; + + case treasure_map: + //search hand for another treasure_map + index = -1; + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == treasure_map && i != handPos) + { + index = i; + break; + } + } + if (index > -1) + { + //trash both treasure cards + discardCard(handPos, currentPlayer, state, 1); + discardCard(index, currentPlayer, state, 1); + + //gain 4 Gold cards + for (i = 0; i < 4; i++) + { + gainCard(gold, state, 1, currentPlayer); + } + + //return success + return 1; + } + + //no second treasure_map found in hand + return -1; + } + + return -1; +} + +int discardCard(int handPos, int currentPlayer, struct gameState *state, int trashFlag) +{ + + //if card is not trashed, added to Played pile + if (trashFlag < 1) + { + //add card to played pile + state->playedCards[state->playedCardCount] = state->hand[currentPlayer][handPos]; + state->playedCardCount++; + } + + //set played card to -1 + state->hand[currentPlayer][handPos] = -1; + + //remove card from player's hand + if ( handPos == (state->handCount[currentPlayer] - 1) ) //last card in hand array is played + { + //reduce number of cards in hand + state->handCount[currentPlayer]--; + } + else if ( state->handCount[currentPlayer] == 1 ) //only one card in hand + { + //reduce number of cards in hand + state->handCount[currentPlayer]--; + } + else + { + //replace discarded card with last card in hand + state->hand[currentPlayer][handPos] = state->hand[currentPlayer][ (state->handCount[currentPlayer] - 1)]; + //set last card to -1 + state->hand[currentPlayer][state->handCount[currentPlayer] - 1] = -1; + //reduce number of cards in hand + state->handCount[currentPlayer]--; + } + + return 0; +} + +int gainCard(int supplyPos, struct gameState *state, int toFlag, int player) +{ + //Note: supplyPos is enum of choosen card + + //check if supply pile is empty (0) or card is not used in game (-1) + if ( supplyCount(supplyPos, state) < 1 ) + { + return -1; + } + + //added card for [whoseTurn] current player: + // toFlag = 0 : add to discard + // toFlag = 1 : add to deck + // toFlag = 2 : add to hand + + if (toFlag == 1) + { + state->deck[ player ][ state->deckCount[player] ] = supplyPos; + state->deckCount[player]++; + } + else if (toFlag == 2) + { + state->hand[ player ][ state->handCount[player] ] = supplyPos; + state->handCount[player]++; + } + else + { + state->discard[player][ state->discardCount[player] ] = supplyPos; + state->discardCount[player]++; + } + + //decrease number in supply pile + state->supplyCount[supplyPos]--; + + return 0; +} + +int updateCoins(int player, struct gameState *state, int bonus) +{ + int i; + + //reset coin count + state->coins = 0; + + //add coins for each Treasure card in player's hand + for (i = 0; i < state->handCount[player]; i++) + { + if (state->hand[player][i] == copper) + { + state->coins += 1; + } + else if (state->hand[player][i] == silver) + { + state->coins += 2; + } + else if (state->hand[player][i] == gold) + { + state->coins += 3; + } + } + + //add bonus + state->coins += bonus; + + return 0; +} + + +//end of dominion.c + diff --git a/projects/bleckw/dominion/dominion.h b/projects/bleckw/dominion/dominion.h new file mode 100644 index 00000000..050eed97 --- /dev/null +++ b/projects/bleckw/dominion/dominion.h @@ -0,0 +1,131 @@ +#ifndef _DOMINION_H +#define _DOMINION_H + +// Code from various sources, baseline from Kristen Bartosz + +#define MAX_HAND 500 +#define MAX_DECK 500 + +#define MAX_PLAYERS 4 + +#define DEBUG 0 + +/* http://dominion.diehrstraits.com has card texts */ +/* http://dominion.isotropic.org has other stuff */ + +/* hand# means index of a card in current active player's hand */ + +enum CARD + {curse = 0, + estate, + duchy, + province, + + copper, + silver, + gold, + + adventurer, + /* If no/only 1 treasure found, stop when full deck seen */ + council_room, + feast, /* choice1 is supply # of card gained) */ + gardens, + mine, /* choice1 is hand# of money to trash, choice2 is supply# of + money to put in hand */ + remodel, /* choice1 is hand# of card to remodel, choice2 is supply# */ + smithy, + village, + + baron, /* choice1: boolean for discard of estate */ + /* Discard is always of first (lowest index) estate */ + great_hall, + minion, /* choice1: 1 = +2 coin, 2 = redraw */ + steward, /* choice1: 1 = +2 card, 2 = +2 coin, 3 = trash 2 (choice2,3) */ + tribute, + + ambassador, /* choice1 = hand#, choice2 = number to return to supply */ + cutpurse, + embargo, /* choice1 = supply# */ + outpost, + salvager, /* choice1 = hand# to trash */ + sea_hag, + treasure_map + }; + +struct gameState { + int numPlayers; //number of players + int supplyCount[treasure_map+1]; //this is the amount of a specific type of card given a specific number. + int embargoTokens[treasure_map+1]; + int outpostPlayed; + int outpostTurn; + int whoseTurn; + int phase; + int numActions; /* Starts at 1 each turn */ + int coins; /* Use as you see fit! */ + int numBuys; /* Starts at 1 each turn */ + int hand[MAX_PLAYERS][MAX_HAND]; + int handCount[MAX_PLAYERS]; + int deck[MAX_PLAYERS][MAX_DECK]; + int deckCount[MAX_PLAYERS]; + int discard[MAX_PLAYERS][MAX_DECK]; + int discardCount[MAX_PLAYERS]; + int playedCards[MAX_DECK]; + int playedCardCount; +}; + +/* All functions return -1 on failure, and DO NOT CHANGE GAME STATE; + unless specified for other return, return 0 on success */ + +struct gameState* newGame(); + +int* kingdomCards(int k1, int k2, int k3, int k4, int k5, int k6, int k7, + int k8, int k9, int k10); + +int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed, + struct gameState *state); +/* Responsible for initializing all supplies, and shuffling deck and + drawing starting hands for all players. Check that 10 cards selected + are in fact (different) kingdom cards, and that numPlayers is valid. + +Cards not in game should initialize supply position to -1 */ + +int shuffle(int player, struct gameState *state); +/* Assumes all cards are now in deck array (or hand/played): discard is + empty */ + +int playCard(int handPos, int choice1, int choice2, int choice3, + struct gameState *state); +/* Play card with index handPos from current player's hand */ + +int buyCard(int supplyPos, struct gameState *state); +/* Buy card with supply index supplyPos */ + +int numHandCards(struct gameState *state); +/* How many cards current player has in hand */ + +int handCard(int handNum, struct gameState *state); +/* enum value of indexed card in player's hand */ + +int supplyCount(int card, struct gameState *state); +/* How many of given card are left in supply */ + +int fullDeckCount(int player, int card, struct gameState *state); +/* Here deck = hand + discard + deck */ + +int whoseTurn(struct gameState *state); + +int endTurn(struct gameState *state); +/* Must do phase C and advance to next player; do not advance whose turn + if game is over */ + +int isGameOver(struct gameState *state); + +int scoreFor(int player, struct gameState *state); +/* Negative here does not mean invalid; scores may be negative, + -9999 means invalid input */ + +int getWinners(int players[MAX_PLAYERS], struct gameState *state); +/* Set array position of each player who won (remember ties!) to + 1, others to 0 */ + +#endif diff --git a/projects/bleckw/dominion/dominion_helpers.h b/projects/bleckw/dominion/dominion_helpers.h new file mode 100644 index 00000000..8bcf1a18 --- /dev/null +++ b/projects/bleckw/dominion/dominion_helpers.h @@ -0,0 +1,15 @@ +#ifndef _DOMINION_HELPERS_H +#define _DOMINION_HELPERS_H + +#include "dominion.h" + +int drawCard(int player, struct gameState *state); +int updateCoins(int player, struct gameState *state, int bonus); +int discardCard(int handPos, int currentPlayer, struct gameState *state, + int trashFlag); +int gainCard(int supplyPos, struct gameState *state, int toFlag, int player); +int getCost(int cardNumber); +int cardEffect(int card, int choice1, int choice2, int choice3, + struct gameState *state, int handPos, int *bonus); + +#endif diff --git a/projects/bleckw/dominion/interface.c b/projects/bleckw/dominion/interface.c new file mode 100644 index 00000000..d508824a --- /dev/null +++ b/projects/bleckw/dominion/interface.c @@ -0,0 +1,363 @@ +/* Interactive Dominion Interface + +Sam Heinith CS362 +1/26/2010 +*/ + +#include +#include +#include +#include +#include "rngs.h" +#include "interface.h" +#include "dominion.h" + + +void cardNumToName(int card, char *name){ + switch(card){ + case curse: strcpy(name,"Curse"); + break; + case estate: strcpy(name,"Estate"); + break; + case duchy: strcpy(name,"Duchy"); + break; + case province: strcpy(name,"Province"); + break; + case copper: strcpy(name,"Copper"); + break; + case silver: strcpy(name,"Silver"); + break; + case gold: strcpy(name,"Gold"); + break; + case adventurer: strcpy(name,"Adventurer"); + break; + case council_room: strcpy(name,"Council Room"); + break; + case feast: strcpy(name,"Feast"); + break; + case gardens: strcpy(name,"Gardens"); + break; + case mine: strcpy(name,"Mine"); + break; + case remodel: strcpy(name,"Remodel"); + break; + case smithy: strcpy(name,"Smithy"); + break; + case village: strcpy(name,"Village"); + break; + case baron: strcpy(name,"Baron"); + break; + case great_hall: strcpy(name,"Great Hall"); + break; + case minion: strcpy(name,"Minion"); + break; + case steward: strcpy(name,"Steward"); + break; + case tribute: strcpy(name,"Tribute"); + break; + case ambassador: strcpy(name,"Ambassador"); + break; + case cutpurse: strcpy(name,"Cutpurse"); + break; + case embargo: strcpy(name,"Embargo"); + break; + case outpost: strcpy(name,"Outpost"); + break; + case salvager: strcpy(name,"Salvager"); + break; + case sea_hag: strcpy(name,"Sea Hag"); + break; + case treasure_map: strcpy(name,"Treasure Map"); + break; + + default: strcpy(name,"?"); + } + +} + + + +int getCardCost(int card) { + int cost; + switch(card) { + case curse: cost = CURSE_COST; + break; + case estate: cost = ESTATE_COST; + break; + case duchy: cost = DUCHY_COST; + break; + case province: cost = PROVINCE_COST; + break; + case copper: cost = COPPER_COST; + break; + case silver: cost = SILVER_COST; + break; + case gold: cost = GOLD_COST; + break; + case adventurer: cost = ADVENTURER_COST; + break; + case council_room: cost = COUNCIL_ROOM_COST; + break; + case feast: cost = FEAST_COST; + break; + case gardens: cost = GARDEN_COST; + break; + case mine: cost = MINE_COST; + break; + case remodel: cost = REMODEL_COST; + break; + case smithy: cost = SMITHY_COST; + break; + case village: cost = VILLAGE_COST; + break; + case baron: cost = BARON_COST; + break; + case great_hall: cost = GREAT_HALL_COST; + break; + case minion: cost = MINION_COST; + break; + case steward: cost = STEWARD_COST; + break; + case tribute: cost = TRIBUTE_COST; + break; + case ambassador: cost = AMBASSADOR_COST; + break; + case cutpurse: cost = CUTPURSE_COST; + break; + case embargo: cost = EMBARGO_COST; + break; + case outpost: cost = OUTPOST_COST; + break; + case salvager: cost = SALVAGER_COST; + break; + case sea_hag: cost = SEA_HAG_COST; + break; + case treasure_map: cost = TREASURE_MAP_COST; + break; + default: cost = ONETHOUSAND; + } + return cost; +} + + + + + + +void printHand(int player, struct gameState *game) { + int handCount = game->handCount[player]; + int handIndex; + printf("Player %d's hand:\n", player); + if(handCount > 0) printf("# Card\n"); + for(handIndex = 0; handIndex < handCount; handIndex++) { + int card = game->hand[player][handIndex]; + char name[MAX_STRING_LENGTH]; + cardNumToName(card, name); + printf("%-2d %-13s\n", handIndex, name); + } + printf("\n"); +} + + + +void printDeck(int player, struct gameState *game) { + int deckCount = game->deckCount[player]; + int deckIndex; + printf("Player %d's deck: \n", player); + if(deckCount > 0) printf("# Card\n"); + for(deckIndex = 0; deckIndex < deckCount; deckIndex++) { + int card = game->deck[player][deckIndex]; + char name[MAX_STRING_LENGTH]; + cardNumToName(card, name); + printf("%-2d %-13s\n", deckIndex, name); + } + printf("\n"); +} + +void printPlayed(int player, struct gameState *game) { + int playedCount = game->playedCardCount; + int playedIndex; + printf("Player %d's played cards: \n", player); + if(playedCount > 0) printf("# Card\n"); + for(playedIndex = 0; playedIndex < playedCount; playedIndex++) { + int card = game->playedCards[playedIndex]; + char name[MAX_STRING_LENGTH]; + cardNumToName(card, name); + printf("%-2d %-13s \n", playedIndex, name); + } + printf("\n"); +} + + + +void printDiscard(int player, struct gameState *game) { + int discardCount = game->discardCount[player]; + int discardIndex; + printf("Player %d's discard: \n", player); + if(discardCount > 0) printf("# Card\n"); + for(discardIndex = 0; discardIndex < discardCount; discardIndex++) { + int card = game->discard[player][discardIndex]; + char name[MAX_STRING_LENGTH]; + cardNumToName(card, name); + printf("%-2d %-13s \n", discardIndex, name); + } + printf("\n"); +} + + + + +void printSupply(struct gameState *game) { + int cardNum, cardCost, cardCount; + char name[MAX_STRING_LENGTH]; + printf("# Card Cost Copies\n"); + for(cardNum = 0; cardNum < NUM_TOTAL_K_CARDS; cardNum++){ + cardCount = game->supplyCount[cardNum]; + if(cardCount == -1) continue; + cardNumToName(cardNum, name); + cardCost = getCardCost(cardNum); + printf("%-2d %-13s %-5d %-5d", cardNum, name, cardCost, cardCount); + printf("\n"); + } + printf("\n"); +} + + +void printState(struct gameState *game) { + int numActions = game->numActions; + int numCoins = game->coins; + int numBuys = game->numBuys; + int currentPlayer = game->whoseTurn; + int phase = game->phase; + char phaseName[MAX_STRING_LENGTH]; + phaseNumToName(phase,phaseName); + printf("Player %d:\n%s phase\n%d actions\n%d coins\n%d buys\n\n", currentPlayer, phaseName, numActions, numCoins, numBuys); +} + +void printScores(struct gameState *game) { + int playerNum, score[MAX_PLAYERS]; + int numPlayers = game->numPlayers; + for(playerNum = 0; playerNum < numPlayers; playerNum++) { + score[playerNum] = scoreFor(playerNum,game); + printf("Player %d has a score of %d\n", playerNum, score[playerNum]); + } +} + + +void printHelp(void) { + printf("Commands are: \n\ + add [Supply Card Number] - add any card to your hand (teh hacks)\n\ + buy [Supply Card Number] - buy a card at supply position\n\ + end - end your turn\n\ + init [Number of Players] [Number of Bots] - initialize the game\n\ + num - print number of cards in your hand\n\ + play [Hand Index] [Choice] [Choice] [Choice] - play a card from your hand\n\ + resign - end the game showing the current scores\n\ + show - show your current hand\n\ + stat - show your turn's status\n\ + supp - show the supply\n\ + whos - whos turn\n\ + exit - exit the interface"); + printf("\n\n"); + +} + + +void phaseNumToName(int phase, char *name) { + switch(phase){ + case ACTION_PHASE: strcpy(name,"Action"); + break; + case BUY_PHASE: strcpy(name,"Buy"); + break; + case CLEANUP_PHASE: strcpy(name,"Cleanup"); + break; + } +} + + +int addCardToHand(int player, int card, struct gameState *game) { + if(card >= adventurer && card < NUM_TOTAL_K_CARDS){ + int handTop = game->handCount[player]; + game->hand[player][handTop] = card; + game->handCount[player]++; + return SUCCESS; + } else { + return FAILURE; + } + +} + +void selectKingdomCards(int randomSeed, int kingCards[NUM_K_CARDS]) { + int i, used, card, numSelected = 0; + SelectStream(1); + PutSeed((long)randomSeed); + + + while(numSelected < NUM_K_CARDS) { + used = FALSE; + card = floor(Random() * NUM_TOTAL_K_CARDS); + if(card < adventurer) continue; + for(i = 0; i < numSelected; i++) { + if(kingCards[i] == card) { + used = TRUE; + break; + } + } + if(used == TRUE) continue; + kingCards[numSelected] = card; + numSelected++; + } +} + + +int countHandCoins(int player, struct gameState *game) { + int card, index, coinage = 0; + + for(index = 0; index < game->handCount[player]; index++) { + card = game->hand[player][index]; + switch(card) { + case copper: coinage += COPPER_VALUE; + break; + case silver: coinage += SILVER_VALUE; + break; + case gold: coinage += GOLD_VALUE; + break; + } + } + return coinage; +} + + +void executeBotTurn(int player, int *turnNum, struct gameState *game) { + int coins = countHandCoins(player, game); + + printf("*****************Executing Bot Player %d Turn Number %d*****************\n", player, *turnNum); + printSupply(game); + //sleep(1); //Thinking... + + if(coins >= PROVINCE_COST && supplyCount(province,game) > 0) { + buyCard(province,game); + printf("Player %d buys card Province\n\n", player); + } + else if(supplyCount(province,game) == 0 && coins >= DUCHY_COST ) { + buyCard(duchy,game); + printf("Player %d buys card Duchy\n\n", player); + } + else if(coins >= GOLD_COST && supplyCount(gold,game) > 0) { + buyCard(gold,game); + printf("Player %d buys card Gold\n\n", player); + } + else if(coins >= SILVER_COST && supplyCount(silver,game) > 0) { + buyCard(silver,game); + printf("Player %d buys card Silver\n\n", player); + + } + + + if(player == (game->numPlayers -1)) (*turnNum)++; + endTurn(game); + if(! isGameOver(game)) { + int currentPlayer = whoseTurn(game); + printf("Player %d's turn number %d\n\n", currentPlayer, (*turnNum)); + } +} diff --git a/projects/bleckw/dominion/interface.h b/projects/bleckw/dominion/interface.h new file mode 100644 index 00000000..67b55dce --- /dev/null +++ b/projects/bleckw/dominion/interface.h @@ -0,0 +1,128 @@ +/* Interactive Dominion Interface + + Sam Heinith CS362 + 1/26/2010 +*/ + + + +#ifndef _INTERFACE_H +#define _INTERFACE_H + + + +#include "dominion.h" + +//Last card enum (Treasure map) card number plus one for the 0th card. +#define NUM_TOTAL_K_CARDS (treasure_map + 1) +#define NUM_K_CARDS 10 +#define NUM_V_CARDS_2 8 +#define NUM_V_CARDS_3or4 12 +#define NUM_C_CARDS_2 10 +#define NUM_C_CARDS_3 20 +#define NUM_C_CARDS_4 30 +#define NUM_COPPER 60 +#define NUM_SILVER 40 +#define NUM_GOLD 30 +#define UNUSED -1 +#define START_COPPER 7 +#define START_ESTATE 3 +#define HANDSIZE 5 + +#define COMPARE(string1, string2) strncmp(string1, string2, 4) +#define MAX_STRING_LENGTH 32 +#define TRUE 1 +#define FALSE 0 + +#define SUCCESS 0 +#define FAILURE -1 + +#define MATCH 0 +#define WINNER 1 +#define NOT_WINNER 0 + +//The Game Phases +#define ACTION_PHASE 0 +#define BUY_PHASE 1 +#define CLEANUP_PHASE 2 + +#define COPPER_VALUE 1 +#define SILVER_VALUE 2 +#define GOLD_VALUE 3 + +//From Dominion List Spoiler +#define COPPER_COST 0 +#define SILVER_COST 3 +#define GOLD_COST 6 +#define ESTATE_COST 2 +#define DUCHY_COST 5 +#define PROVINCE_COST 8 +#define CURSE_COST 0 +#define ADVENTURER_COST 6 +#define COUNCIL_ROOM_COST 5 +#define FEAST_COST 4 +#define GARDEN_COST 4 +#define MINE_COST 5 +#define MONEYLENDER_COST 4 +#define REMODEL_COST 4 +#define SMITHY_COST 4 +#define VILLAGE_COST 3 +#define WOODCUTTER_COST 3 +#define BARON_COST 4 +#define GREAT_HALL_COST 3 +#define MINION_COST 5 +#define SHANTY_TOWN_COST 3 +#define STEWARD_COST 3 +#define TRIBUTE_COST 5 +#define WISHING_WELL_COST 3 +#define AMBASSADOR_COST 3 +#define CUTPURSE_COST 4 +#define EMBARGO_COST 2 +#define OUTPOST_COST 5 +#define SALVAGER_COST 4 +#define SEA_HAG_COST 4 +#define TREASURE_MAP_COST 4 +#define ONETHOUSAND 1000 + + +int addCardToHand(int player, int card, struct gameState *game); + +int countHandCoins(int player, struct gameState *game); + + +void executeBotTurn(int player, int *turnNum, struct gameState *game); + +void phaseNumToName(int phase, char *name); +void cardNumToName(int card, char *name); + +int getCardCost(int card); + +void printHelp(void); + +void printHand(int player, struct gameState *game); + +void printDeck(int player, struct gameState *game); + +void printDiscard(int player, struct gameState *game); + +void printPlayed(int player, struct gameState *game); + +void printState(struct gameState *game); + +void printSupply(struct gameState *game); + +void printGameState(struct gameState *game); + +void printScores(struct gameState *game); + +void selectKingdomCards(int randomSeed, int kingdomCards[NUM_K_CARDS]); + + + +#endif + + + + + + diff --git a/projects/bleckw/dominion/playdom b/projects/bleckw/dominion/playdom new file mode 100644 index 0000000000000000000000000000000000000000..0134b6035238caeccc30cecb7bd3742a99e35b7b GIT binary patch literal 86888 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 Q)?a+%{(rZOn&+qg4SN`GGynhq literal 0 HcmV?d00001 diff --git a/projects/bleckw/dominion/playdom.c b/projects/bleckw/dominion/playdom.c new file mode 100644 index 00000000..e79035ef --- /dev/null +++ b/projects/bleckw/dominion/playdom.c @@ -0,0 +1,134 @@ +#include "dominion.h" +#include +#include "rngs.h" +#include + +int main (int argc, char** argv) { + struct gameState G; + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + printf ("Starting game.\n"); + + initializeGame(2, k, atoi(argv[1]), &G); + + int money = 0; + int smithyPos = -1; + int adventurerPos = -1; + int i=0; + + int numSmithies = 0; + int numAdventurers = 0; + + while (!isGameOver(&G)) { + money = 0; + smithyPos = -1; + adventurerPos = -1; + for (i = 0; i < numHandCards(&G); i++) { + if (handCard(i, &G) == copper) + money++; + else if (handCard(i, &G) == silver) + money += 2; + else if (handCard(i, &G) == gold) + money += 3; + else if (handCard(i, &G) == smithy) + smithyPos = i; + else if (handCard(i, &G) == adventurer) + adventurerPos = i; + } + + if (whoseTurn(&G) == 0) { + if (smithyPos != -1) { + printf("0: smithy played from position %d\n", smithyPos); + playCard(smithyPos, -1, -1, -1, &G); + printf("smithy played.\n"); + money = 0; + i=0; + while(i= 8) { + printf("0: bought province\n"); + buyCard(province, &G); + } + else if (money >= 6) { + printf("0: bought gold\n"); + buyCard(gold, &G); + } + else if ((money >= 4) && (numSmithies < 2)) { + printf("0: bought smithy\n"); + buyCard(smithy, &G); + numSmithies++; + } + else if (money >= 3) { + printf("0: bought silver\n"); + buyCard(silver, &G); + } + + printf("0: end turn\n"); + endTurn(&G); + } + else { + if (adventurerPos != -1) { + printf("1: adventurer played from position %d\n", adventurerPos); + playCard(adventurerPos, -1, -1, -1, &G); + money = 0; + i=0; + while(i= 8) { + printf("1: bought province\n"); + buyCard(province, &G); + } + else if ((money >= 6) && (numAdventurers < 2)) { + printf("1: bought adventurer\n"); + buyCard(adventurer, &G); + numAdventurers++; + }else if (money >= 6){ + printf("1: bought gold\n"); + buyCard(gold, &G); + } + else if (money >= 3){ + printf("1: bought silver\n"); + buyCard(silver, &G); + } + printf("1: endTurn\n"); + + endTurn(&G); + } + } // end of While + + printf ("Finished game.\n"); + printf ("Player 0: %d\nPlayer 1: %d\n", scoreFor(0, &G), scoreFor(1, &G)); + + return 0; +} diff --git a/projects/bleckw/dominion/player b/projects/bleckw/dominion/player new file mode 100644 index 0000000000000000000000000000000000000000..7ccb2f8e026c2b5401c6ec66d62e1aeb73aafde9 GIT binary patch literal 108236 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 Q^D@$%hGpdcbCbI9-|qt63jhEB literal 0 HcmV?d00001 diff --git a/projects/bleckw/dominion/player.c b/projects/bleckw/dominion/player.c new file mode 100644 index 00000000..0f3cb992 --- /dev/null +++ b/projects/bleckw/dominion/player.c @@ -0,0 +1,217 @@ +/* Interactive Dominion Interface + Version 7 + + Sam Heinith CS362 + Questions/Comments: + heiniths@onid.orst.edu + 1/26/2010 +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include "dominion.h" +#include "interface.h" +#include "rngs.h" + + +int main2(int argc, char *argv[]) { + //Default cards, as defined in playDom + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, sea_hag, tribute, smithy}; + struct gameState g; + initializeGame(2,k,1,&g); + printf ("SUCCESSFUL INIT\n"); + getchar(); + return 0; +} + +int main(int argc, char* argv[]) { + char *add = "add"; + char *buyC = "buy"; + char *endT = "end"; + char *exit = "exit"; + char *help = "help"; + char *init = "init"; + char *numH = "num"; + char *play = "play"; + char *resign = "resi"; + char *show = "show"; + char *stat = "stat"; + char *supply = "supp"; + char *whos = "whos"; + + char command[MAX_STRING_LENGTH]; + char line[MAX_STRING_LENGTH]; + char cardName[MAX_STRING_LENGTH]; + + //Array to hold bot presence + int isBot[MAX_PLAYERS] = { 0, 0, 0, 0}; + + int players[MAX_PLAYERS]; + int playerNum; + int outcome; + int currentPlayer; + int gameOver = FALSE; + int gameStarted = FALSE; + int turnNum = 0; + + int randomSeed = atoi(argv[1]); + + //Default cards, as defined in playDom + int kCards[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, sea_hag, tribute, smithy}; + + struct gameState g; + struct gameState * game = &g; + + memset(game,0,sizeof(struct gameState)); + + if(argc != 2){ + printf("Usage: player [integer random number seed]\n"); + return EXIT_SUCCESS; + } + + if(randomSeed <= 0){ + printf("Usage: player [integer random number seed]\n"); + return EXIT_SUCCESS; + } + + initializeGame(2,kCards,randomSeed,game); + + printf("Please enter a command or \"help\" for commands\n"); + + + while(TRUE) { + int arg0 = UNUSED; + int arg1 = UNUSED; + int arg2 = UNUSED; + int arg3 = UNUSED; + + outcome = FAILURE; + strcpy(line,""); + strcpy(command,""); + strcpy(cardName,""); + + currentPlayer = whoseTurn(game); + + //If you are getting a seg fault comment this if block out + gameOver = isGameOver(game); + if(gameStarted == TRUE && gameOver == TRUE){ + printScores(game); + getWinners(players, game); + printf("After %d turns, the winner(s) are:\n", turnNum); + for(playerNum = 0; playerNum < game->numPlayers; playerNum++){ + if(players[playerNum] == WINNER) printf("Player %d\n", playerNum); + } + for(playerNum = 0; playerNum < game->numPlayers; playerNum++){ + printHand(playerNum, game); + printPlayed(playerNum, game); + printDiscard(playerNum, game); + printDeck(playerNum, game); + } + + break; //Exit out of the game/while loop + } + + + if(isBot[currentPlayer] == TRUE) { + executeBotTurn(currentPlayer, &turnNum, game); + continue; + } + + printf("$ "); + fgets(line, MAX_STRING_LENGTH, stdin); + sscanf(line, "%s %d %d %d %d", command, &arg0, &arg1, &arg2, &arg3); + + + if(COMPARE(command, add) == 0) { + outcome = addCardToHand(currentPlayer, arg0, game); + cardNumToName(arg0, cardName); + printf("Player %d adds %s to their hand\n\n", currentPlayer, cardName); + } else + if(COMPARE(command, buyC) == 0) { + outcome = buyCard(arg0, game); + cardNumToName(arg0, cardName); + if(outcome == SUCCESS){ + printf("Player %d buys card %d, %s\n\n", currentPlayer, arg0, cardName); + } else { + printf("Player %d cannot buy card %d, %s\n\n", currentPlayer, arg0, cardName); + } + } else + if(COMPARE(command, endT) == 0) { + if(gameStarted == TRUE) { + if(currentPlayer == (game->numPlayers -1)) turnNum++; + endTurn(game); + currentPlayer = whoseTurn(game); + printf("Player %d's turn number %d\n\n", currentPlayer, turnNum); + } + + } else + if(COMPARE(command, exit) == 0) { + break; + } else + if(COMPARE(command, help) == 0) { + printHelp(); + } else + if(COMPARE(command, init) == 0) { + int numHuman = arg0 - arg1; + for(playerNum = numHuman; playerNum < arg0; playerNum++) { + isBot[playerNum] = TRUE; + } + // selectKingdomCards(randomSeed, kCards); //Comment this out to use the default card set defined in playDom. + outcome = initializeGame(arg0, kCards, randomSeed, game); + printf("\n"); + if(outcome == SUCCESS){ + gameStarted = TRUE; + currentPlayer = whoseTurn(game); + printf("Player %d's turn number %d\n\n", currentPlayer, turnNum); + } + + } else + if(COMPARE(command, numH) == 0) { + int numCards = numHandCards(game); + printf("There are %d cards in your hand.\n", numCards); + } else + if(COMPARE(command, play) == 0) { + int card = handCard(arg0,game); + outcome = playCard(arg0, arg1, arg2, arg3, game); + cardNumToName(card, cardName); + if(outcome == SUCCESS){ + printf("Player %d plays %s\n\n", currentPlayer, cardName); + } else { + printf("Player %d cannot play card %d\n\n", currentPlayer, arg0); + } + + } else + if(COMPARE(command, resign) == 0) { + endTurn(game); + printScores(game); + break; + } else + if(COMPARE(command, show) == 0) { + if(gameStarted == FALSE) continue; + printHand(currentPlayer, game); + printPlayed(currentPlayer, game); + //printDiscard(currentPlayer, game); + //printDeck(currentPlayer, game); + } else + if(COMPARE(command, stat) == 0) { + if(gameStarted == FALSE) continue; + printState(game); + } else + if(COMPARE(command, supply) == 0) { + printSupply(game); + } else + if(COMPARE(command, whos) == 0) { + int playerNum = whoseTurn(game); + printf("Player %d's turn\n", playerNum); + } + } + + return EXIT_SUCCESS; + +} diff --git a/projects/bleckw/dominion/rngs.c b/projects/bleckw/dominion/rngs.c new file mode 100644 index 00000000..3a2510a3 --- /dev/null +++ b/projects/bleckw/dominion/rngs.c @@ -0,0 +1,183 @@ +/* ------------------------------------------------------------------------- + * This is an ANSI C library for multi-stream random number generation. + * The use of this library is recommended as a replacement for the ANSI C + * rand() and srand() functions, particularly in simulation applications + * where the statistical 'goodness' of the random number generator is + * important. The library supplies 256 streams of random numbers; use + * SelectStream(s) to switch between streams indexed s = 0,1,...,255. + * + * The streams must be initialized. The recommended way to do this is by + * using the function PlantSeeds(x) with the value of x used to initialize + * the default stream and all other streams initialized automatically with + * values dependent on the value of x. The following convention is used + * to initialize the default stream: + * if x > 0 then x is the state + * if x < 0 then the state is obtained from the system clock + * if x = 0 then the state is to be supplied interactively. + * + * The generator used in this library is a so-called 'Lehmer random number + * generator' which returns a pseudo-random number uniformly distributed + * 0.0 and 1.0. The period is (m - 1) where m = 2,147,483,647 and the + * smallest and largest possible values are (1 / m) and 1 - (1 / m) + * respectively. For more details see: + * + * "Random Number Generators: Good Ones Are Hard To Find" + * Steve Park and Keith Miller + * Communications of the ACM, October 1988 + * + * Name : rngs.c (Random Number Generation - Multiple Streams) + * Authors : Steve Park & Dave Geyer + * Language : ANSI C + * Latest Revision : 09-22-98 + * ------------------------------------------------------------------------- + */ + +#include +#include +#include "rngs.h" + +#define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */ +#define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */ +#define CHECK 399268537 /* DON'T CHANGE THIS VALUE */ +#define STREAMS 256 /* # of streams, DON'T CHANGE THIS VALUE */ +#define A256 22925 /* jump multiplier, DON'T CHANGE THIS VALUE */ +#define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */ + +static long seed[STREAMS] = {DEFAULT}; /* current state of each stream */ +static int stream = 0; /* stream index, 0 is the default */ +static int initialized = 0; /* test for stream initialization */ + + + double Random(void) +/* ---------------------------------------------------------------- + * Random returns a pseudo-random real number uniformly distributed + * between 0.0 and 1.0. + * ---------------------------------------------------------------- + */ +{ + const long Q = MODULUS / MULTIPLIER; + const long R = MODULUS % MULTIPLIER; + long t; + + t = MULTIPLIER * (seed[stream] % Q) - R * (seed[stream] / Q); + if (t > 0) + seed[stream] = t; + else + seed[stream] = t + MODULUS; + return ((double) seed[stream] / MODULUS); +} + + + void PlantSeeds(long x) +/* --------------------------------------------------------------------- + * Use this function to set the state of all the random number generator + * streams by "planting" a sequence of states (seeds), one per stream, + * with all states dictated by the state of the default stream. + * The sequence of planted states is separated one from the next by + * 8,367,782 calls to Random(). + * --------------------------------------------------------------------- + */ +{ + const long Q = MODULUS / A256; + const long R = MODULUS % A256; + int j; + int s; + + initialized = 1; + s = stream; /* remember the current stream */ + SelectStream(0); /* change to stream 0 */ + PutSeed(x); /* set seed[0] */ + stream = s; /* reset the current stream */ + for (j = 1; j < STREAMS; j++) { + x = A256 * (seed[j - 1] % Q) - R * (seed[j - 1] / Q); + if (x > 0) + seed[j] = x; + else + seed[j] = x + MODULUS; + } +} + + + void PutSeed(long x) +/* --------------------------------------------------------------- + * Use this function to set the state of the current random number + * generator stream according to the following conventions: + * if x > 0 then x is the state (unless too large) + * if x < 0 then the state is obtained from the system clock + * if x = 0 then the state is to be supplied interactively + * --------------------------------------------------------------- + */ +{ + char ok = 0; + + if (x > 0) + x = x % MODULUS; /* correct if x is too large */ + if (x < 0) + x = ((unsigned long) time((time_t *) NULL)) % MODULUS; + if (x == 0) + while (!ok) { + printf("\nEnter a positive integer seed (9 digits or less) >> "); + scanf("%ld", &x); + ok = (0 < x) && (x < MODULUS); + if (!ok) + printf("\nInput out of range ... try again\n"); + } + seed[stream] = x; +} + + + void GetSeed(long *x) +/* --------------------------------------------------------------- + * Use this function to get the state of the current random number + * generator stream. + * --------------------------------------------------------------- + */ +{ + *x = seed[stream]; +} + + + void SelectStream(int index) +/* ------------------------------------------------------------------ + * Use this function to set the current random number generator + * stream -- that stream from which the next random number will come. + * ------------------------------------------------------------------ + */ +{ + stream = ((unsigned int) index) % STREAMS; + if ((initialized == 0) && (stream != 0)) /* protect against */ + PlantSeeds(DEFAULT); /* un-initialized streams */ +} + + + void TestRandom(void) +/* ------------------------------------------------------------------ + * Use this (optional) function to test for a correct implementation. + * ------------------------------------------------------------------ + */ +{ + long i; + long x; + double u; + char ok = 0; + + SelectStream(0); /* select the default stream */ + PutSeed(1); /* and set the state to 1 */ + for(i = 0; i < 10000; i++){ + u = Random(); + if (ok) + printf(" %f \n\n", u); + + } + GetSeed(&x); /* get the new state value */ + ok = (x == CHECK); /* and check for correctness */ + + SelectStream(1); /* select stream 1 */ + PlantSeeds(1); /* set the state of all streams */ + GetSeed(&x); /* get the state of stream 1 */ + ok = ok && (x == A256); /* x should be the jump multiplier */ + if (ok) + printf("\n The implementation of rngs.c is correct.\n\n"); + else + printf("\n\a ERROR -- the implementation of rngs.c is not correct.\n\n"); +} diff --git a/projects/bleckw/dominion/rngs.h b/projects/bleckw/dominion/rngs.h new file mode 100644 index 00000000..4bc7c06e --- /dev/null +++ b/projects/bleckw/dominion/rngs.h @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------- + * Name : rngs.h (header file for the library file rngs.c) + * Author : Steve Park & Dave Geyer + * Language : ANSI C + * Latest Revision : 09-22-98 + * ----------------------------------------------------------------------- + */ + +#if !defined( _RNGS_ ) +#define _RNGS_ + +double Random(void); +void PlantSeeds(long x); +void GetSeed(long *x); +void PutSeed(long x); +void SelectStream(int index); +void TestRandom(void); + +#endif diff --git a/projects/bleckw/dominion/rt.c b/projects/bleckw/dominion/rt.c new file mode 100644 index 00000000..79da137c --- /dev/null +++ b/projects/bleckw/dominion/rt.c @@ -0,0 +1,27 @@ +#include "rngs.h" +#include +#include + +int main(int argc, char** argv) { + if (argc < 3) { + printf ("Not enough inputs: seed target\n"); + } + + SelectStream(1); + PutSeed((long)atoi(argv[1])); + + int done = 0; + int c = 1000000000; + + while (!done) { + c = floor(Random() * 1000000000); + // if (c % 100000 == 0) { + // printf ("c = %d\n", c); + // } + if (c == atoi(argv[2])) { + printf ("Found the bug!\n"); + done = 1; + } + } +} + diff --git a/projects/bleckw/dominion/supplyTest.c b/projects/bleckw/dominion/supplyTest.c new file mode 100644 index 00000000..c58a47ec --- /dev/null +++ b/projects/bleckw/dominion/supplyTest.c @@ -0,0 +1,30 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int main () { + + int r; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + struct gameState G; + + r = initializeGame(4, k, 1, &G); + + printf ("initializeGame(4, k, 1, &G) = %d\n", r); + assert(r == 0); + + r = supplyCount(adventurer, &G); + printf ("supplyCount(adventurer, &G) = %d\n", r); + assert(r == 10); + + return 0; +} diff --git a/projects/bleckw/dominion/testBuyCard.c b/projects/bleckw/dominion/testBuyCard.c new file mode 100644 index 00000000..e82049ea --- /dev/null +++ b/projects/bleckw/dominion/testBuyCard.c @@ -0,0 +1,94 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int checkDrawCard(int p, struct gameState *post) { + struct gameState pre; + memcpy (&pre, post, sizeof(struct gameState)); + + int r; + // printf ("drawCard PRE: p %d HC %d DeC %d DiC %d\n", + // p, pre.handCount[p], pre.deckCount[p], pre.discardCount[p]); + + r = drawCard (p, post); + + //printf ("drawCard POST: p %d HC %d DeC %d DiC %d\n", + // p, post->handCount[p], post->deckCount[p], post->discardCount[p]); + + if (pre.deckCount[p] > 0) { + pre.handCount[p]++; + pre.hand[p][pre.handCount[p]-1] = pre.deck[p][pre.deckCount[p]-1]; + pre.deckCount[p]--; + } else if (pre.discardCount[p] > 0) { + memcpy(pre.deck[p], post->deck[p], sizeof(int) * pre.discardCount[p]); + memcpy(pre.discard[p], post->discard[p], sizeof(int)*pre.discardCount[p]); + pre.hand[p][post->handCount[p]-1] = post->hand[p][post->handCount[p]-1]; + pre.handCount[p]++; + pre.deckCount[p] = pre.discardCount[p]-1; + pre.discardCount[p] = 0; + } + + assert (r == 0); + + assert(memcmp(&pre, post, sizeof(struct gameState)) == 0); +} + +int main () { + + int i, n, r, p, deckCount, discardCount, handCount; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + + struct gameState G; + + printf ("Testing buyCard.\n"); + + printf ("RANDOM TESTS.\n"); + + SelectStream(2); + PutSeed(3); + + for (n = 0; n < 2000; n++) { + for (i = 0; i < sizeof(struct gameState); i++) { + ((char*)&G)[i] = floor(Random() * 256); + } + p = floor(Random() * 2); + G.deckCount[p] = floor(Random() * MAX_DECK); + G.discardCount[p] = floor(Random() * MAX_DECK); + G.handCount[p] = floor(Random() * MAX_HAND); + checkDrawCard(p, &G); + } + + printf ("ALL TESTS OK\n"); + + exit(0); + + printf ("SIMPLE FIXED TESTS.\n"); + for (p = 0; p < 2; p++) { + for (deckCount = 0; deckCount < 5; deckCount++) { + for (discardCount = 0; discardCount < 5; discardCount++) { + for (handCount = 0; handCount < 5; handCount++) { + memset(&G, 23, sizeof(struct gameState)); + r = initializeGame(2, k, 1, &G); + G.deckCount[p] = deckCount; + memset(G.deck[p], 0, sizeof(int) * deckCount); + G.discardCount[p] = discardCount; + memset(G.discard[p], 0, sizeof(int) * discardCount); + G.handCount[p] = handCount; + memset(G.hand[p], 0, sizeof(int) * handCount); + checkDrawCard(p, &G); + } + } + } + } + + return 0; +} diff --git a/projects/bleckw/dominion/testDrawCard.c b/projects/bleckw/dominion/testDrawCard.c new file mode 100644 index 00000000..526bd3bb --- /dev/null +++ b/projects/bleckw/dominion/testDrawCard.c @@ -0,0 +1,93 @@ +#include "dominion.h" +#include "dominion_helpers.h" +#include +#include +#include +#include "rngs.h" + +#define DEBUG 0 +#define NOISY_TEST 1 + +int checkDrawCard(int p, struct gameState *post) { + struct gameState pre; + memcpy (&pre, post, sizeof(struct gameState)); + + int r; + // printf ("drawCard PRE: p %d HC %d DeC %d DiC %d\n", + // p, pre.handCount[p], pre.deckCount[p], pre.discardCount[p]); + + r = drawCard (p, post); + + //printf ("drawCard POST: p %d HC %d DeC %d DiC %d\n", + // p, post->handCount[p], post->deckCount[p], post->discardCount[p]); + + if (pre.deckCount[p] > 0) { + pre.handCount[p]++; + pre.hand[p][pre.handCount[p]-1] = pre.deck[p][pre.deckCount[p]-1]; + pre.deckCount[p]--; + } else if (pre.discardCount[p] > 0) { + memcpy(pre.deck[p], post->deck[p], sizeof(int) * pre.discardCount[p]); + memcpy(pre.discard[p], post->discard[p], sizeof(int)*pre.discardCount[p]); + pre.hand[p][post->handCount[p]-1] = post->hand[p][post->handCount[p]-1]; + pre.handCount[p]++; + pre.deckCount[p] = pre.discardCount[p]-1; + pre.discardCount[p] = 0; + } + + assert (r == 0); + + assert(memcmp(&pre, post, sizeof(struct gameState)) == 0); +} + +int main () { + + int i, n, r, p, deckCount, discardCount, handCount; + + int k[10] = {adventurer, council_room, feast, gardens, mine, + remodel, smithy, village, baron, great_hall}; + + struct gameState G; + + printf ("Testing drawCard.\n"); + + printf ("RANDOM TESTS.\n"); + + SelectStream(2); + PutSeed(3); + + for (n = 0; n < 2000; n++) { + for (i = 0; i < sizeof(struct gameState); i++) { + ((char*)&G)[i] = floor(Random() * 256); + } + p = floor(Random() * 2); + G.deckCount[p] = floor(Random() * MAX_DECK); + G.discardCount[p] = floor(Random() * MAX_DECK); + G.handCount[p] = floor(Random() * MAX_HAND); + checkDrawCard(p, &G); + } + + printf ("ALL TESTS OK\n"); + + exit(0); + + printf ("SIMPLE FIXED TESTS.\n"); + for (p = 0; p < 2; p++) { + for (deckCount = 0; deckCount < 5; deckCount++) { + for (discardCount = 0; discardCount < 5; discardCount++) { + for (handCount = 0; handCount < 5; handCount++) { + memset(&G, 23, sizeof(struct gameState)); + r = initializeGame(2, k, 1, &G); + G.deckCount[p] = deckCount; + memset(G.deck[p], 0, sizeof(int) * deckCount); + G.discardCount[p] = discardCount; + memset(G.discard[p], 0, sizeof(int) * discardCount); + G.handCount[p] = handCount; + memset(G.hand[p], 0, sizeof(int) * handCount); + checkDrawCard(p, &G); + } + } + } + } + + return 0; +} diff --git a/projects/bleckw/dominion/testInit.c b/projects/bleckw/dominion/testInit.c new file mode 100644 index 00000000..1c48d217 --- /dev/null +++ b/projects/bleckw/dominion/testInit.c @@ -0,0 +1,56 @@ +#include "dominion.h" +#include +#include +#include "rngs.h" + +int main (int argc, char** argv) { + + struct gameState G; + + int i; + + int start = -1; + + int k[10] = {adventurer, gardens, embargo, village, minion, mine, cutpurse, + sea_hag, tribute, smithy}; + + memset(&G, 'z', sizeof(struct gameState)); + + initializeGame(4, k, atoi(argv[1]), &G); + + printf ("Rough guide to locations in structure:\n"); + printf ("0: numPlayers\n"); + printf ("%ld: supplyCount[0]\n", ((long)&(G.supplyCount[0]))-((long)&G)); + printf ("%ld: embargoTokens[0]\n", ((long)&(G.embargoTokens[0]))-((long)&G)); + printf ("%ld: hand[0][0]\n", ((long)&(G.hand[0][0]))-(long)(&G)); + printf ("%ld: deck[0][0]\n", ((long)&(G.deck[0][0]))-(long)(&G)); + printf ("%ld: discard[0][0]\n", ((long)&(G.discard[0][0]))-(long)(&G)); + printf ("%ld: playerCards[0]\n", ((long)&(G.playedCards[0]))-(long)(&G)); + + for (i = 0; i < sizeof(struct gameState); i++) { + if (((char*)&G)[i] == 'z') { + if (start == -1) { + start = i; + } + } else{ + if (start != -1) { + if (start == (i-1)) { + printf ("Byte %d uninitialized.\n", start); + } else { + printf ("Bytes %d-%d uninitialized.\n", start, i-1); + } + start = -1; + } + } + } + + if (start != -1) { + if (start == (i-1)) { + printf ("Byte %d uninitialized.\n", start); + } else { + printf ("Bytes %d-%d uninitialized.\n", start, i-1); + } + } + + return 0; +} diff --git a/projects/bleckw/dominion/testShuffle.c b/projects/bleckw/dominion/testShuffle.c new file mode 100644 index 00000000..c1fcc7c0 --- /dev/null +++ b/projects/bleckw/dominion/testShuffle.c @@ -0,0 +1,27 @@ +#include "dominion.h" +#include +#include + +int compare(const int* a, const int* b); + +int main () { + struct gameState G; + struct gameState G2; + + // Initialize G. + + memcpy (&G2, &G, sizeof(struct gameState)); + + int ret = shuffle(0,&G); + + if (G.deckCount[0] > 0) { + assert (ret != -1); + + qsort ((void*)(G.deck[0]), G.deckCount[0], sizeof(int), compare); + qsort ((void*)(G2.deck[0]), G2.deckCount[0], sizeof(int), compare); + } else + assert (ret == -1); + + assert(memcmp(&G, &G2, sizeof(struct gameState)) == 0); + +} From df319a95f41a0958551cd1748504281c872281e5 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Tue, 25 Jun 2019 15:29:50 -0700 Subject: [PATCH 02/17] README.md message updated --- projects/bleckw/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/bleckw/README.md b/projects/bleckw/README.md index 264b0477..2dd88fa3 100644 --- a/projects/bleckw/README.md +++ b/projects/bleckw/README.md @@ -1 +1 @@ -#Your onid folder should contain a readme file that contains your name and your ONID. +Jordan Bleck, bleckw From d2f8303b8941e649330dc0be3ad09fede2fe9545 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 3 Jul 2019 16:01:11 -0700 Subject: [PATCH 03/17] updated dominion.c with baron, minion, ambassador, tribute, and mine refactored out of cardeffect into their own functions --- projects/bleckw/dominion/dominion.c | 2539 +++++++++++++++------------ 1 file changed, 1410 insertions(+), 1129 deletions(-) diff --git a/projects/bleckw/dominion/dominion.c b/projects/bleckw/dominion/dominion.c index 88f32414..61bccc32 100644 --- a/projects/bleckw/dominion/dominion.c +++ b/projects/bleckw/dominion/dominion.c @@ -6,1328 +6,1609 @@ #include int compare(const void* a, const void* b) { - if (*(int*)a > *(int*)b) - return 1; - if (*(int*)a < *(int*)b) - return -1; - return 0; + if (*(int*)a > *(int*)b) + return 1; + if (*(int*)a < *(int*)b) + return -1; + return 0; } struct gameState* newGame() { - struct gameState* g = malloc(sizeof(struct gameState)); - return g; + struct gameState* g = malloc(sizeof(struct gameState)); + return g; } int* kingdomCards(int k1, int k2, int k3, int k4, int k5, int k6, int k7, - int k8, int k9, int k10) { - int* k = malloc(10 * sizeof(int)); - k[0] = k1; - k[1] = k2; - k[2] = k3; - k[3] = k4; - k[4] = k5; - k[5] = k6; - k[6] = k7; - k[7] = k8; - k[8] = k9; - k[9] = k10; - return k; + int k8, int k9, int k10) { + int* k = malloc(10 * sizeof(int)); + k[0] = k1; + k[1] = k2; + k[2] = k3; + k[3] = k4; + k[4] = k5; + k[5] = k6; + k[6] = k7; + k[7] = k8; + k[8] = k9; + k[9] = k10; + return k; } int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed, - struct gameState *state) { - - int i; - int j; - int it; - //set up random number generator - SelectStream(1); - PutSeed((long)randomSeed); - - //check number of players - if (numPlayers > MAX_PLAYERS || numPlayers < 2) + struct gameState *state) { + + int i; + int j; + int it; + //set up random number generator + SelectStream(1); + PutSeed((long)randomSeed); + + //check number of players + if (numPlayers > MAX_PLAYERS || numPlayers < 2) { - return -1; + return -1; } - //set number of players - state->numPlayers = numPlayers; + //set number of players + state->numPlayers = numPlayers; - //check selected kingdom cards are different - for (i = 0; i < 10; i++) + //check selected kingdom cards are different + for (i = 0; i < 10; i++) { - for (j = 0; j < 10; j++) + for (j = 0; j < 10; j++) { - if (j != i && kingdomCards[j] == kingdomCards[i]) - { - return -1; - } + if (j != i && kingdomCards[j] == kingdomCards[i]) + { + return -1; + } } } - //initialize supply - /////////////////////////////// + //initialize supply + /////////////////////////////// - //set number of Curse cards - if (numPlayers == 2) + //set number of Curse cards + if (numPlayers == 2) { - state->supplyCount[curse] = 10; + state->supplyCount[curse] = 10; } - else if (numPlayers == 3) + else if (numPlayers == 3) { - state->supplyCount[curse] = 20; + state->supplyCount[curse] = 20; } - else + else { - state->supplyCount[curse] = 30; + state->supplyCount[curse] = 30; } - //set number of Victory cards - if (numPlayers == 2) + //set number of Victory cards + if (numPlayers == 2) { - state->supplyCount[estate] = 8; - state->supplyCount[duchy] = 8; - state->supplyCount[province] = 8; + state->supplyCount[estate] = 8; + state->supplyCount[duchy] = 8; + state->supplyCount[province] = 8; } - else + else { - state->supplyCount[estate] = 12; - state->supplyCount[duchy] = 12; - state->supplyCount[province] = 12; + state->supplyCount[estate] = 12; + state->supplyCount[duchy] = 12; + state->supplyCount[province] = 12; } - //set number of Treasure cards - state->supplyCount[copper] = 60 - (7 * numPlayers); - state->supplyCount[silver] = 40; - state->supplyCount[gold] = 30; + //set number of Treasure cards + state->supplyCount[copper] = 60 - (7 * numPlayers); + state->supplyCount[silver] = 40; + state->supplyCount[gold] = 30; - //set number of Kingdom cards - for (i = adventurer; i <= treasure_map; i++) //loop all cards + //set number of Kingdom cards + for (i = adventurer; i <= treasure_map; i++) //loop all cards { - for (j = 0; j < 10; j++) //loop chosen cards - { - if (kingdomCards[j] == i) - { - //check if card is a 'Victory' Kingdom card - if (kingdomCards[j] == great_hall || kingdomCards[j] == gardens) - { - if (numPlayers == 2){ - state->supplyCount[i] = 8; - } - else{ state->supplyCount[i] = 12; } - } - else - { - state->supplyCount[i] = 10; - } - break; - } - else //card is not in the set choosen for the game - { - state->supplyCount[i] = -1; - } - } - - } - - //////////////////////// - //supply intilization complete - - //set player decks - for (i = 0; i < numPlayers; i++) + for (j = 0; j < 10; j++) //loop chosen cards + { + if (kingdomCards[j] == i) + { + //check if card is a 'Victory' Kingdom card + if (kingdomCards[j] == great_hall || kingdomCards[j] == gardens) + { + if (numPlayers == 2){ + state->supplyCount[i] = 8; + } + else{ state->supplyCount[i] = 12; } + } + else + { + state->supplyCount[i] = 10; + } + break; + } + else //card is not in the set choosen for the game + { + state->supplyCount[i] = -1; + } + } + + } + + //////////////////////// + //supply intilization complete + + //set player decks + for (i = 0; i < numPlayers; i++) { - state->deckCount[i] = 0; - for (j = 0; j < 3; j++) - { - state->deck[i][j] = estate; - state->deckCount[i]++; - } - for (j = 3; j < 10; j++) - { - state->deck[i][j] = copper; - state->deckCount[i]++; - } - } - - //shuffle player decks - for (i = 0; i < numPlayers; i++) + state->deckCount[i] = 0; + for (j = 0; j < 3; j++) + { + state->deck[i][j] = estate; + state->deckCount[i]++; + } + for (j = 3; j < 10; j++) + { + state->deck[i][j] = copper; + state->deckCount[i]++; + } + } + + //shuffle player decks + for (i = 0; i < numPlayers; i++) { - if ( shuffle(i, state) < 0 ) - { - return -1; - } + if ( shuffle(i, state) < 0 ) + { + return -1; + } } - //draw player hands - for (i = 0; i < numPlayers; i++) + //draw player hands + for (i = 0; i < numPlayers; i++) { - //initialize hand size to zero - state->handCount[i] = 0; - state->discardCount[i] = 0; - //draw 5 cards - // for (j = 0; j < 5; j++) - // { - // drawCard(i, state); - // } - } - - //set embargo tokens to 0 for all supply piles - for (i = 0; i <= treasure_map; i++) - { - state->embargoTokens[i] = 0; + //initialize hand size to zero + state->handCount[i] = 0; + state->discardCount[i] = 0; + //draw 5 cards + // for (j = 0; j < 5; j++) + // { + // drawCard(i, state); + // } } - //initialize first player's turn - state->outpostPlayed = 0; - state->phase = 0; - state->numActions = 1; - state->numBuys = 1; - state->playedCardCount = 0; - state->whoseTurn = 0; - state->handCount[state->whoseTurn] = 0; - //int it; move to top + //set embargo tokens to 0 for all supply piles + for (i = 0; i <= treasure_map; i++) + { + state->embargoTokens[i] = 0; + } - //Moved draw cards to here, only drawing at the start of a turn - for (it = 0; it < 5; it++){ - drawCard(state->whoseTurn, state); - } + //initialize first player's turn + state->outpostPlayed = 0; + state->phase = 0; + state->numActions = 1; + state->numBuys = 1; + state->playedCardCount = 0; + state->whoseTurn = 0; + state->handCount[state->whoseTurn] = 0; + //int it; move to top + + //Moved draw cards to here, only drawing at the start of a turn + for (it = 0; it < 5; it++){ + drawCard(state->whoseTurn, state); + } - updateCoins(state->whoseTurn, state, 0); + updateCoins(state->whoseTurn, state, 0); - return 0; + return 0; } int shuffle(int player, struct gameState *state) { - - int newDeck[MAX_DECK]; - int newDeckPos = 0; - int card; - int i; - if (state->deckCount[player] < 1) - return -1; - qsort ((void*)(state->deck[player]), state->deckCount[player], sizeof(int), compare); - /* SORT CARDS IN DECK TO ENSURE DETERMINISM! */ - - while (state->deckCount[player] > 0) { - card = floor(Random() * state->deckCount[player]); - newDeck[newDeckPos] = state->deck[player][card]; - newDeckPos++; - for (i = card; i < state->deckCount[player]-1; i++) { - state->deck[player][i] = state->deck[player][i+1]; - } - state->deckCount[player]--; - } - for (i = 0; i < newDeckPos; i++) { - state->deck[player][i] = newDeck[i]; - state->deckCount[player]++; - } - - return 0; + int newDeck[MAX_DECK]; + int newDeckPos = 0; + int card; + int i; + + if (state->deckCount[player] < 1) + return -1; + qsort ((void*)(state->deck[player]), state->deckCount[player], sizeof(int), compare); + /* SORT CARDS IN DECK TO ENSURE DETERMINISM! */ + + while (state->deckCount[player] > 0) { + card = floor(Random() * state->deckCount[player]); + newDeck[newDeckPos] = state->deck[player][card]; + newDeckPos++; + for (i = card; i < state->deckCount[player]-1; i++) { + state->deck[player][i] = state->deck[player][i+1]; + } + state->deckCount[player]--; + } + for (i = 0; i < newDeckPos; i++) { + state->deck[player][i] = newDeck[i]; + state->deckCount[player]++; + } + + return 0; } int playCard(int handPos, int choice1, int choice2, int choice3, struct gameState *state) { - int card; - int coin_bonus = 0; //tracks coins gain from actions + int card; + int coin_bonus = 0; //tracks coins gain from actions - //check if it is the right phase - if (state->phase != 0) + //check if it is the right phase + if (state->phase != 0) { - return -1; + return -1; } - - //check if player has enough actions - if ( state->numActions < 1 ) + + //check if player has enough actions + if ( state->numActions < 1 ) { - return -1; - } - - //get card played - card = handCard(handPos, state); - - //check if selected card is an action - if ( card < adventurer || card > treasure_map ) + return -1; + } + + //get card played + card = handCard(handPos, state); + + //check if selected card is an action + if ( card < adventurer || card > treasure_map ) { - return -1; + return -1; } - - //play card - if ( cardEffect(card, choice1, choice2, choice3, state, handPos, &coin_bonus) < 0 ) + + //play card + if ( cardEffect(card, choice1, choice2, choice3, state, handPos, &coin_bonus) < 0 ) { - return -1; + return -1; } - - //reduce number of actions - state->numActions--; - //update coins (Treasure cards may be added with card draws) - updateCoins(state->whoseTurn, state, coin_bonus); - - return 0; + //reduce number of actions + state->numActions--; + + //update coins (Treasure cards may be added with card draws) + updateCoins(state->whoseTurn, state, coin_bonus); + + return 0; } int buyCard(int supplyPos, struct gameState *state) { - int who; - if (DEBUG){ - printf("Entering buyCard...\n"); - } + int who; + if (DEBUG){ + printf("Entering buyCard...\n"); + } - // I don't know what to do about the phase thing. + // I don't know what to do about the phase thing. + + who = state->whoseTurn; + + if (state->numBuys < 1){ + if (DEBUG) + printf("You do not have any buys left\n"); + return -1; + } else if (supplyCount(supplyPos, state) <1){ + if (DEBUG) + printf("There are not any of that type of card left\n"); + return -1; + } else if (state->coins < getCost(supplyPos)){ + if (DEBUG) + printf("You do not have enough money to buy that. You have %d coins.\n", state->coins); + return -1; + } else { + state->phase=1; + //state->supplyCount[supplyPos]--; + gainCard(supplyPos, state, 0, who); //card goes in discard, this might be wrong.. (2 means goes into hand, 0 goes into discard) + + state->coins = (state->coins) - (getCost(supplyPos)); + state->numBuys--; + if (DEBUG) + printf("You bought card number %d for %d coins. You now have %d buys and %d coins.\n", supplyPos, getCost(supplyPos), state->numBuys, state->coins); + } - who = state->whoseTurn; + //state->discard[who][state->discardCount[who]] = supplyPos; + //state->discardCount[who]++; - if (state->numBuys < 1){ - if (DEBUG) - printf("You do not have any buys left\n"); - return -1; - } else if (supplyCount(supplyPos, state) <1){ - if (DEBUG) - printf("There are not any of that type of card left\n"); - return -1; - } else if (state->coins < getCost(supplyPos)){ - if (DEBUG) - printf("You do not have enough money to buy that. You have %d coins.\n", state->coins); - return -1; - } else { - state->phase=1; - //state->supplyCount[supplyPos]--; - gainCard(supplyPos, state, 0, who); //card goes in discard, this might be wrong.. (2 means goes into hand, 0 goes into discard) - - state->coins = (state->coins) - (getCost(supplyPos)); - state->numBuys--; - if (DEBUG) - printf("You bought card number %d for %d coins. You now have %d buys and %d coins.\n", supplyPos, getCost(supplyPos), state->numBuys, state->coins); - } - - //state->discard[who][state->discardCount[who]] = supplyPos; - //state->discardCount[who]++; - - return 0; + return 0; } int numHandCards(struct gameState *state) { - return state->handCount[ whoseTurn(state) ]; + return state->handCount[ whoseTurn(state) ]; } int handCard(int handPos, struct gameState *state) { - int currentPlayer = whoseTurn(state); - return state->hand[currentPlayer][handPos]; + int currentPlayer = whoseTurn(state); + return state->hand[currentPlayer][handPos]; } int supplyCount(int card, struct gameState *state) { - return state->supplyCount[card]; + return state->supplyCount[card]; } int fullDeckCount(int player, int card, struct gameState *state) { - int i; - int count = 0; + int i; + int count = 0; - for (i = 0; i < state->deckCount[player]; i++) + for (i = 0; i < state->deckCount[player]; i++) { - if (state->deck[player][i] == card) count++; + if (state->deck[player][i] == card) count++; } - for (i = 0; i < state->handCount[player]; i++) + for (i = 0; i < state->handCount[player]; i++) { - if (state->hand[player][i] == card) count++; + if (state->hand[player][i] == card) count++; } - for (i = 0; i < state->discardCount[player]; i++) + for (i = 0; i < state->discardCount[player]; i++) { - if (state->discard[player][i] == card) count++; + if (state->discard[player][i] == card) count++; } - return count; + return count; } int whoseTurn(struct gameState *state) { - return state->whoseTurn; + return state->whoseTurn; } int endTurn(struct gameState *state) { - int k; - int i; - int currentPlayer = whoseTurn(state); - - //Discard hand - for (i = 0; i < state->handCount[currentPlayer]; i++){ - state->discard[currentPlayer][state->discardCount[currentPlayer]++] = state->hand[currentPlayer][i];//Discard - state->hand[currentPlayer][i] = -1;//Set card to -1 - } - state->handCount[currentPlayer] = 0;//Reset hand count - - //Code for determining the player - if (currentPlayer < (state->numPlayers - 1)){ - state->whoseTurn = currentPlayer + 1;//Still safe to increment - } - else{ - state->whoseTurn = 0;//Max player has been reached, loop back around to player 1 - } - - state->outpostPlayed = 0; - state->phase = 0; - state->numActions = 1; - state->coins = 0; - state->numBuys = 1; - state->playedCardCount = 0; - state->handCount[state->whoseTurn] = 0; - - //int k; move to top - //Next player draws hand - for (k = 0; k < 5; k++){ - drawCard(state->whoseTurn, state);//Draw a card - } - - //Update money - updateCoins(state->whoseTurn, state , 0); - - return 0; + int k; + int i; + int currentPlayer = whoseTurn(state); + + //Discard hand + for (i = 0; i < state->handCount[currentPlayer]; i++){ + state->discard[currentPlayer][state->discardCount[currentPlayer]++] = state->hand[currentPlayer][i];//Discard + state->hand[currentPlayer][i] = -1;//Set card to -1 + } + state->handCount[currentPlayer] = 0;//Reset hand count + + //Code for determining the player + if (currentPlayer < (state->numPlayers - 1)){ + state->whoseTurn = currentPlayer + 1;//Still safe to increment + } + else{ + state->whoseTurn = 0;//Max player has been reached, loop back around to player 1 + } + + state->outpostPlayed = 0; + state->phase = 0; + state->numActions = 1; + state->coins = 0; + state->numBuys = 1; + state->playedCardCount = 0; + state->handCount[state->whoseTurn] = 0; + + //int k; move to top + //Next player draws hand + for (k = 0; k < 5; k++){ + drawCard(state->whoseTurn, state);//Draw a card + } + + //Update money + updateCoins(state->whoseTurn, state , 0); + + return 0; } int isGameOver(struct gameState *state) { - int i; - int j; - - //if stack of Province cards is empty, the game ends - if (state->supplyCount[province] == 0) + int i; + int j; + + //if stack of Province cards is empty, the game ends + if (state->supplyCount[province] == 0) { - return 1; + return 1; } - //if three supply pile are at 0, the game ends - j = 0; - for (i = 0; i < 25; i++) + //if three supply pile are at 0, the game ends + j = 0; + for (i = 0; i < 25; i++) { - if (state->supplyCount[i] == 0) - { - j++; - } + if (state->supplyCount[i] == 0) + { + j++; + } } - if ( j >= 3) + if ( j >= 3) { - return 1; + return 1; } - return 0; + return 0; } int scoreFor (int player, struct gameState *state) { - int i; - int score = 0; - //score from hand - for (i = 0; i < state->handCount[player]; i++) + int i; + int score = 0; + //score from hand + for (i = 0; i < state->handCount[player]; i++) { - if (state->hand[player][i] == curse) { score = score - 1; }; - if (state->hand[player][i] == estate) { score = score + 1; }; - if (state->hand[player][i] == duchy) { score = score + 3; }; - if (state->hand[player][i] == province) { score = score + 6; }; - if (state->hand[player][i] == great_hall) { score = score + 1; }; - if (state->hand[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); }; + if (state->hand[player][i] == curse) { score = score - 1; }; + if (state->hand[player][i] == estate) { score = score + 1; }; + if (state->hand[player][i] == duchy) { score = score + 3; }; + if (state->hand[player][i] == province) { score = score + 6; }; + if (state->hand[player][i] == great_hall) { score = score + 1; }; + if (state->hand[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); }; } - //score from discard - for (i = 0; i < state->discardCount[player]; i++) + //score from discard + for (i = 0; i < state->discardCount[player]; i++) { - if (state->discard[player][i] == curse) { score = score - 1; }; - if (state->discard[player][i] == estate) { score = score + 1; }; - if (state->discard[player][i] == duchy) { score = score + 3; }; - if (state->discard[player][i] == province) { score = score + 6; }; - if (state->discard[player][i] == great_hall) { score = score + 1; }; - if (state->discard[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); }; + if (state->discard[player][i] == curse) { score = score - 1; }; + if (state->discard[player][i] == estate) { score = score + 1; }; + if (state->discard[player][i] == duchy) { score = score + 3; }; + if (state->discard[player][i] == province) { score = score + 6; }; + if (state->discard[player][i] == great_hall) { score = score + 1; }; + if (state->discard[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); }; } - //score from deck - for (i = 0; i < state->discardCount[player]; i++) + //score from deck + for (i = 0; i < state->discardCount[player]; i++) { - if (state->deck[player][i] == curse) { score = score - 1; }; - if (state->deck[player][i] == estate) { score = score + 1; }; - if (state->deck[player][i] == duchy) { score = score + 3; }; - if (state->deck[player][i] == province) { score = score + 6; }; - if (state->deck[player][i] == great_hall) { score = score + 1; }; - if (state->deck[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); }; + if (state->deck[player][i] == curse) { score = score - 1; }; + if (state->deck[player][i] == estate) { score = score + 1; }; + if (state->deck[player][i] == duchy) { score = score + 3; }; + if (state->deck[player][i] == province) { score = score + 6; }; + if (state->deck[player][i] == great_hall) { score = score + 1; }; + if (state->deck[player][i] == gardens) { score = score + ( fullDeckCount(player, 0, state) / 10 ); }; } - return score; + return score; } int getWinners(int players[MAX_PLAYERS], struct gameState *state) { - int i; - int j; - int highScore; - int currentPlayer; + int i; + int j; + int highScore; + int currentPlayer; - //get score for each player - for (i = 0; i < MAX_PLAYERS; i++) + //get score for each player + for (i = 0; i < MAX_PLAYERS; i++) { - //set unused player scores to -9999 - if (i >= state->numPlayers) - { - players[i] = -9999; - } - else - { - players[i] = scoreFor (i, state); - } - } - - //find highest score - j = 0; - for (i = 0; i < MAX_PLAYERS; i++) + //set unused player scores to -9999 + if (i >= state->numPlayers) + { + players[i] = -9999; + } + else + { + players[i] = scoreFor (i, state); + } + } + + //find highest score + j = 0; + for (i = 0; i < MAX_PLAYERS; i++) { - if (players[i] > players[j]) - { - j = i; - } + if (players[i] > players[j]) + { + j = i; + } } - highScore = players[j]; + highScore = players[j]; - //add 1 to players who had less turns - currentPlayer = whoseTurn(state); - for (i = 0; i < MAX_PLAYERS; i++) + //add 1 to players who had less turns + currentPlayer = whoseTurn(state); + for (i = 0; i < MAX_PLAYERS; i++) { - if ( players[i] == highScore && i > currentPlayer ) - { - players[i]++; - } + if ( players[i] == highScore && i > currentPlayer ) + { + players[i]++; + } } - //find new highest score - j = 0; - for (i = 0; i < MAX_PLAYERS; i++) + //find new highest score + j = 0; + for (i = 0; i < MAX_PLAYERS; i++) { - if ( players[i] > players[j] ) - { - j = i; - } + if ( players[i] > players[j] ) + { + j = i; + } } - highScore = players[j]; + highScore = players[j]; - //set winners in array to 1 and rest to 0 - for (i = 0; i < MAX_PLAYERS; i++) + //set winners in array to 1 and rest to 0 + for (i = 0; i < MAX_PLAYERS; i++) { - if ( players[i] == highScore ) - { - players[i] = 1; - } - else - { - players[i] = 0; - } + if ( players[i] == highScore ) + { + players[i] = 1; + } + else + { + players[i] = 0; + } } - return 0; + return 0; } int drawCard(int player, struct gameState *state) { int count; - int deckCounter; - if (state->deckCount[player] <= 0){//Deck is empty - - //Step 1 Shuffle the discard pile back into a deck - int i; - //Move discard to deck - for (i = 0; i < state->discardCount[player];i++){ - state->deck[player][i] = state->discard[player][i]; - state->discard[player][i] = -1; - } + int deckCounter; + if (state->deckCount[player] <= 0){//Deck is empty + + //Step 1 Shuffle the discard pile back into a deck + int i; + //Move discard to deck + for (i = 0; i < state->discardCount[player];i++){ + state->deck[player][i] = state->discard[player][i]; + state->discard[player][i] = -1; + } - state->deckCount[player] = state->discardCount[player]; - state->discardCount[player] = 0;//Reset discard + state->deckCount[player] = state->discardCount[player]; + state->discardCount[player] = 0;//Reset discard - //Shufffle the deck - shuffle(player, state);//Shuffle the deck up and make it so that we can draw - - if (DEBUG){//Debug statements - printf("Deck count now: %d\n", state->deckCount[player]); - } - - state->discardCount[player] = 0; + //Shufffle the deck + shuffle(player, state);//Shuffle the deck up and make it so that we can draw - //Step 2 Draw Card - count = state->handCount[player];//Get current player's hand count - - if (DEBUG){//Debug statements - printf("Current hand count: %d\n", count); - } - - deckCounter = state->deckCount[player];//Create a holder for the deck count + if (DEBUG){//Debug statements + printf("Deck count now: %d\n", state->deckCount[player]); + } - if (deckCounter == 0) - return -1; + state->discardCount[player] = 0; - state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to hand - state->deckCount[player]--; - state->handCount[player]++;//Increment hand count - } + //Step 2 Draw Card + count = state->handCount[player];//Get current player's hand count - else{ - int count = state->handCount[player];//Get current hand count for player - int deckCounter; - if (DEBUG){//Debug statements - printf("Current hand count: %d\n", count); + if (DEBUG){//Debug statements + printf("Current hand count: %d\n", count); + } + + deckCounter = state->deckCount[player];//Create a holder for the deck count + + if (deckCounter == 0) + return -1; + + state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to hand + state->deckCount[player]--; + state->handCount[player]++;//Increment hand count } - deckCounter = state->deckCount[player];//Create holder for the deck count - state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to the hand - state->deckCount[player]--; - state->handCount[player]++;//Increment hand count - } + else{ + int count = state->handCount[player];//Get current hand count for player + int deckCounter; + if (DEBUG){//Debug statements + printf("Current hand count: %d\n", count); + } + + deckCounter = state->deckCount[player];//Create holder for the deck count + state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to the hand + state->deckCount[player]--; + state->handCount[player]++;//Increment hand count + } - return 0; + return 0; } int getCost(int cardNumber) { - switch( cardNumber ) + switch( cardNumber ) { - case curse: - return 0; - case estate: - return 2; - case duchy: - return 5; - case province: - return 8; - case copper: - return 0; - case silver: - return 3; - case gold: - return 6; - case adventurer: - return 6; - case council_room: - return 5; - case feast: - return 4; - case gardens: - return 4; - case mine: - return 5; - case remodel: - return 4; - case smithy: - return 4; - case village: - return 3; - case baron: - return 4; - case great_hall: - return 3; - case minion: - return 5; - case steward: - return 3; - case tribute: - return 5; - case ambassador: - return 3; - case cutpurse: - return 4; - case embargo: - return 2; - case outpost: - return 5; - case salvager: - return 4; - case sea_hag: - return 4; - case treasure_map: - return 4; - } - - return -1; + case curse: + return 0; + case estate: + return 2; + case duchy: + return 5; + case province: + return 8; + case copper: + return 0; + case silver: + return 3; + case gold: + return 6; + case adventurer: + return 6; + case council_room: + return 5; + case feast: + return 4; + case gardens: + return 4; + case mine: + return 5; + case remodel: + return 4; + case smithy: + return 4; + case village: + return 3; + case baron: + return 4; + case great_hall: + return 3; + case minion: + return 5; + case steward: + return 3; + case tribute: + return 5; + case ambassador: + return 3; + case cutpurse: + return 4; + case embargo: + return 2; + case outpost: + return 5; + case salvager: + return 4; + case sea_hag: + return 4; + case treasure_map: + return 4; + } + + return -1; } int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus) { - int i; - int j; - int k; - int x; - int index; - int currentPlayer = whoseTurn(state); - int nextPlayer = currentPlayer + 1; - - int tributeRevealedCards[2] = {-1, -1}; - int temphand[MAX_HAND];// moved above the if statement - int drawntreasure=0; - int cardDrawn; - int z = 0;// this is the counter for the temp hand - if (nextPlayer > (state->numPlayers - 1)){ - nextPlayer = 0; - } - - - //uses switch to select card and perform actions - switch( card ) + int i; + int j; + int k; + int x; + int index; + int currentPlayer = whoseTurn(state); + int nextPlayer = currentPlayer + 1; + + // int tributeRevealedCards[2] = {-1, -1}; + int temphand[MAX_HAND];// moved above the if statement + int drawntreasure=0; + int cardDrawn; + int z = 0;// this is the counter for the temp hand + if (nextPlayer > (state->numPlayers - 1)){ + nextPlayer = 0; + } + + + //uses switch to select card and perform actions + switch( card ) { - case adventurer: - while(drawntreasure<2){ - if (state->deckCount[currentPlayer] <1){//if the deck is empty we need to shuffle discard and add to deck - shuffle(currentPlayer, state); - } - drawCard(currentPlayer, state); - cardDrawn = state->hand[currentPlayer][state->handCount[currentPlayer]-1];//top card of hand is most recently drawn card. - if (cardDrawn == copper || cardDrawn == silver || cardDrawn == gold) - drawntreasure++; - else{ - temphand[z]=cardDrawn; - state->handCount[currentPlayer]--; //this should just remove the top card (the most recently drawn one). - z++; - } - } - while(z-1>=0){ - state->discard[currentPlayer][state->discardCount[currentPlayer]++]=temphand[z-1]; // discard all cards in play that have been drawn - z=z-1; - } - return 0; - - case council_room: - //+4 Cards - for (i = 0; i < 4; i++) - { - drawCard(currentPlayer, state); - } - - //+1 Buy - state->numBuys++; - - //Each other player draws a card - for (i = 0; i < state->numPlayers; i++) - { - if ( i != currentPlayer ) - { - drawCard(i, state); - } - } - - //put played card in played card pile - discardCard(handPos, currentPlayer, state, 0); - - return 0; - - case feast: - //gain card with cost up to 5 - //Backup hand - for (i = 0; i <= state->handCount[currentPlayer]; i++){ - temphand[i] = state->hand[currentPlayer][i];//Backup card - state->hand[currentPlayer][i] = -1;//Set to nothing - } - //Backup hand - - //Update Coins for Buy - updateCoins(currentPlayer, state, 5); - x = 1;//Condition to loop on - while( x == 1) {//Buy one card - if (supplyCount(choice1, state) <= 0){ - if (DEBUG) - printf("None of that card left, sorry!\n"); - - if (DEBUG){ - printf("Cards Left: %d\n", supplyCount(choice1, state)); - } - } - else if (state->coins < getCost(choice1)){ - printf("That card is too expensive!\n"); - - if (DEBUG){ - printf("Coins: %d < %d\n", state->coins, getCost(choice1)); - } - } - else{ - - if (DEBUG){ - printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); - } - - gainCard(choice1, state, 0, currentPlayer);//Gain the card - x = 0;//No more buying cards - - if (DEBUG){ - printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); - } - - } - } - - //Reset Hand - for (i = 0; i <= state->handCount[currentPlayer]; i++){ - state->hand[currentPlayer][i] = temphand[i]; - temphand[i] = -1; - } - //Reset Hand - - return 0; - - case gardens: - return -1; - - case mine: - j = state->hand[currentPlayer][choice1]; //store card we will trash - - if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold) - { - return -1; - } - - if (choice2 > treasure_map || choice2 < curse) - { - return -1; - } - - if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) ) - { - return -1; - } - - gainCard(choice2, state, 2, currentPlayer); - - //discard card from hand - discardCard(handPos, currentPlayer, state, 0); - - //discard trashed card - for (i = 0; i < state->handCount[currentPlayer]; i++) - { - if (state->hand[currentPlayer][i] == j) - { - discardCard(i, currentPlayer, state, 0); - break; - } - } - - return 0; - - case remodel: - j = state->hand[currentPlayer][choice1]; //store card we will trash - - if ( (getCost(state->hand[currentPlayer][choice1]) + 2) > getCost(choice2) ) - { - return -1; - } - - gainCard(choice2, state, 0, currentPlayer); - - //discard card from hand - discardCard(handPos, currentPlayer, state, 0); - - //discard trashed card - for (i = 0; i < state->handCount[currentPlayer]; i++) - { - if (state->hand[currentPlayer][i] == j) - { - discardCard(i, currentPlayer, state, 0); - break; - } - } - - - return 0; - - case smithy: - //+3 Cards - for (i = 0; i < 3; i++) - { - drawCard(currentPlayer, state); - } - - //discard card from hand - discardCard(handPos, currentPlayer, state, 0); - return 0; - - case village: - //+1 Card - drawCard(currentPlayer, state); - - //+2 Actions - state->numActions = state->numActions + 2; - - //discard played card from hand - discardCard(handPos, currentPlayer, state, 0); - return 0; - - case baron: - state->numBuys++;//Increase buys by 1! - if (choice1 > 0){//Boolean true or going to discard an estate - int p = 0;//Iterator for hand! - int card_not_discarded = 1;//Flag for discard set! - while(card_not_discarded){ - if (state->hand[currentPlayer][p] == estate){//Found an estate card! - state->coins += 4;//Add 4 coins to the amount of coins - state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p]; - state->discardCount[currentPlayer]++; - for (;p < state->handCount[currentPlayer]; p++){ - state->hand[currentPlayer][p] = state->hand[currentPlayer][p+1]; - } - state->hand[currentPlayer][state->handCount[currentPlayer]] = -1; - state->handCount[currentPlayer]--; - card_not_discarded = 0;//Exit the loop - } - else if (p > state->handCount[currentPlayer]){ - if(DEBUG) { - printf("No estate cards in your hand, invalid choice\n"); - printf("Must gain an estate if there are any\n"); - } - if (supplyCount(estate, state) > 0){ - gainCard(estate, state, 0, currentPlayer); - state->supplyCount[estate]--;//Decrement estates - if (supplyCount(estate, state) == 0){ - isGameOver(state); - } - } - card_not_discarded = 0;//Exit the loop - } - - else{ - p++;//Next card - } - } - } - - else{ - if (supplyCount(estate, state) > 0){ - gainCard(estate, state, 0, currentPlayer);//Gain an estate - state->supplyCount[estate]--;//Decrement Estates - if (supplyCount(estate, state) == 0){ - isGameOver(state); - } - } - } - - - return 0; - - case great_hall: - //+1 Card - drawCard(currentPlayer, state); - - //+1 Actions - state->numActions++; - - //discard card from hand - discardCard(handPos, currentPlayer, state, 0); - return 0; - - case minion: - //+1 action - state->numActions++; - - //discard card from hand - discardCard(handPos, currentPlayer, state, 0); - - if (choice1) //+2 coins - { - state->coins = state->coins + 2; - } - - else if (choice2) //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4 - { - //discard hand - while(numHandCards(state) > 0) - { - discardCard(handPos, currentPlayer, state, 0); - } - - //draw 4 - for (i = 0; i < 4; i++) - { - drawCard(currentPlayer, state); - } - - //other players discard hand and redraw if hand size > 4 - for (i = 0; i < state->numPlayers; i++) - { - if (i != currentPlayer) - { - if ( state->handCount[i] > 4 ) - { - //discard hand - while( state->handCount[i] > 0 ) - { - discardCard(handPos, i, state, 0); - } - - //draw 4 - for (j = 0; j < 4; j++) - { - drawCard(i, state); - } - } - } - } - - } - return 0; - - case steward: - if (choice1 == 1) - { - //+2 cards - drawCard(currentPlayer, state); - drawCard(currentPlayer, state); - } - else if (choice1 == 2) - { - //+2 coins - state->coins = state->coins + 2; - } - else - { - //trash 2 cards in hand - discardCard(choice2, currentPlayer, state, 1); - discardCard(choice3, currentPlayer, state, 1); - } - - //discard card from hand - discardCard(handPos, currentPlayer, state, 0); - return 0; - - case tribute: - if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1){ - if (state->deckCount[nextPlayer] > 0){ - tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; - state->deckCount[nextPlayer]--; - } - else if (state->discardCount[nextPlayer] > 0){ - tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer]-1]; - state->discardCount[nextPlayer]--; - } - else{ - //No Card to Reveal - if (DEBUG){ - printf("No cards to reveal\n"); - } - } - } - - else{ - if (state->deckCount[nextPlayer] == 0){ - for (i = 0; i < state->discardCount[nextPlayer]; i++){ - state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck - state->deckCount[nextPlayer]++; - state->discard[nextPlayer][i] = -1; - state->discardCount[nextPlayer]--; - } - - shuffle(nextPlayer,state);//Shuffle the deck - } - tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; - state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; - state->deckCount[nextPlayer]--; - tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; - state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; - state->deckCount[nextPlayer]--; - } - - if (tributeRevealedCards[0] == tributeRevealedCards[1]){//If we have a duplicate card, just drop one - state->playedCards[state->playedCardCount] = tributeRevealedCards[1]; - state->playedCardCount++; - tributeRevealedCards[1] = -1; - } - - for (i = 0; i <= 2; i ++){ - if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold){//Treasure cards - state->coins += 2; - } - - else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall){//Victory Card Found - drawCard(currentPlayer, state); - drawCard(currentPlayer, state); - } - else{//Action Card - state->numActions = state->numActions + 2; - } - } - - return 0; - - case ambassador: - j = 0; //used to check if player has enough cards to discard - - if (choice2 > 2 || choice2 < 0) - { - return -1; - } - - if (choice1 == handPos) - { - return -1; - } - - for (i = 0; i < state->handCount[currentPlayer]; i++) - { - if (i != handPos && i == state->hand[currentPlayer][choice1] && i != choice1) - { - j++; - } - } - if (j < choice2) - { - return -1; - } - - if (DEBUG) - printf("Player %d reveals card number: %d\n", currentPlayer, state->hand[currentPlayer][choice1]); - - //increase supply count for choosen card by amount being discarded - state->supplyCount[state->hand[currentPlayer][choice1]] += choice2; - - //each other player gains a copy of revealed card - for (i = 0; i < state->numPlayers; i++) - { - if (i != currentPlayer) - { - gainCard(state->hand[currentPlayer][choice1], state, 0, i); - } - } - - //discard played card from hand - discardCard(handPos, currentPlayer, state, 0); - - //trash copies of cards returned to supply - for (j = 0; j < choice2; j++) - { - for (i = 0; i < state->handCount[currentPlayer]; i++) - { - if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) - { - discardCard(i, currentPlayer, state, 1); - break; - } - } - } - - return 0; - - case cutpurse: - - updateCoins(currentPlayer, state, 2); - for (i = 0; i < state->numPlayers; i++) - { - if (i != currentPlayer) - { - for (j = 0; j < state->handCount[i]; j++) - { - if (state->hand[i][j] == copper) - { - discardCard(j, i, state, 0); - break; - } - if (j == state->handCount[i]) - { - for (k = 0; k < state->handCount[i]; k++) - { - if (DEBUG) - printf("Player %d reveals card number %d\n", i, state->hand[i][k]); - } - break; - } - } - - } - - } - - //discard played card from hand - discardCard(handPos, currentPlayer, state, 0); - - return 0; - - - case embargo: - //+2 Coins - state->coins = state->coins + 2; - - //see if selected pile is in play - if ( state->supplyCount[choice1] == -1 ) - { - return -1; - } - - //add embargo token to selected supply pile - state->embargoTokens[choice1]++; - - //trash card - discardCard(handPos, currentPlayer, state, 1); - return 0; - - case outpost: - //set outpost flag - state->outpostPlayed++; - - //discard card - discardCard(handPos, currentPlayer, state, 0); - return 0; - - case salvager: - //+1 buy - state->numBuys++; - - if (choice1) - { - //gain coins equal to trashed card - state->coins = state->coins + getCost( handCard(choice1, state) ); - //trash card - discardCard(choice1, currentPlayer, state, 1); - } - - //discard card - discardCard(handPos, currentPlayer, state, 0); - return 0; - - case sea_hag: - for (i = 0; i < state->numPlayers; i++){ - if (i != currentPlayer){ - state->discard[i][state->discardCount[i]] = state->deck[i][state->deckCount[i]--]; state->deckCount[i]--; - state->discardCount[i]++; - state->deck[i][state->deckCount[i]--] = curse;//Top card now a curse - } - } - return 0; - - case treasure_map: - //search hand for another treasure_map - index = -1; - for (i = 0; i < state->handCount[currentPlayer]; i++) - { - if (state->hand[currentPlayer][i] == treasure_map && i != handPos) - { - index = i; - break; - } - } - if (index > -1) - { - //trash both treasure cards - discardCard(handPos, currentPlayer, state, 1); - discardCard(index, currentPlayer, state, 1); - - //gain 4 Gold cards - for (i = 0; i < 4; i++) - { - gainCard(gold, state, 1, currentPlayer); - } - - //return success - return 1; - } - - //no second treasure_map found in hand - return -1; - } - - return -1; + case adventurer: + while(drawntreasure<2){ + if (state->deckCount[currentPlayer] <1){//if the deck is empty we need to shuffle discard and add to deck + shuffle(currentPlayer, state); + } + drawCard(currentPlayer, state); + cardDrawn = state->hand[currentPlayer][state->handCount[currentPlayer]-1];//top card of hand is most recently drawn card. + if (cardDrawn == copper || cardDrawn == silver || cardDrawn == gold) + drawntreasure++; + else{ + temphand[z]=cardDrawn; + state->handCount[currentPlayer]--; //this should just remove the top card (the most recently drawn one). + z++; + } + } + while(z-1>=0){ + state->discard[currentPlayer][state->discardCount[currentPlayer]++]=temphand[z-1]; // discard all cards in play that have been drawn + z=z-1; + } + return 0; + + case council_room: + //+4 Cards + for (i = 0; i < 4; i++) + { + drawCard(currentPlayer, state); + } + + //+1 Buy + state->numBuys++; + + //Each other player draws a card + for (i = 0; i < state->numPlayers; i++) + { + if ( i != currentPlayer ) + { + drawCard(i, state); + } + } + + //put played card in played card pile + discardCard(handPos, currentPlayer, state, 0); + + return 0; + + case feast: + //gain card with cost up to 5 + //Backup hand + for (i = 0; i <= state->handCount[currentPlayer]; i++){ + temphand[i] = state->hand[currentPlayer][i];//Backup card + state->hand[currentPlayer][i] = -1;//Set to nothing + } + //Backup hand + + //Update Coins for Buy + updateCoins(currentPlayer, state, 5); + x = 1;//Condition to loop on + while( x == 1) {//Buy one card + if (supplyCount(choice1, state) <= 0){ + if (DEBUG) + printf("None of that card left, sorry!\n"); + + if (DEBUG){ + printf("Cards Left: %d\n", supplyCount(choice1, state)); + } + } + else if (state->coins < getCost(choice1)){ + printf("That card is too expensive!\n"); + + if (DEBUG){ + printf("Coins: %d < %d\n", state->coins, getCost(choice1)); + } + } + else{ + + if (DEBUG){ + printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); + } + + gainCard(choice1, state, 0, currentPlayer);//Gain the card + x = 0;//No more buying cards + + if (DEBUG){ + printf("Deck Count: %d\n", state->handCount[currentPlayer] + state->deckCount[currentPlayer] + state->discardCount[currentPlayer]); + } + + } + } + + //Reset Hand + for (i = 0; i <= state->handCount[currentPlayer]; i++){ + state->hand[currentPlayer][i] = temphand[i]; + temphand[i] = -1; + } + //Reset Hand + + return 0; + + case gardens: + return -1; + + case mine: + return mine(choice1, choice2, handpos, currentPlayer, state); + /* + j = state->hand[currentPlayer][choice1]; //store card we will trash + + if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold) + { + return -1; + } + + if (choice2 > treasure_map || choice2 < curse) + { + return -1; + } + + if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) ) + { + return -1; + } + + gainCard(choice2, state, 2, currentPlayer); + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + //discard trashed card + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == j) + { + discardCard(i, currentPlayer, state, 0); + break; + } + } + + return 0; + */ + + case remodel: + j = state->hand[currentPlayer][choice1]; //store card we will trash + + if ( (getCost(state->hand[currentPlayer][choice1]) + 2) > getCost(choice2) ) + { + return -1; + } + + gainCard(choice2, state, 0, currentPlayer); + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + //discard trashed card + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == j) + { + discardCard(i, currentPlayer, state, 0); + break; + } + } + + + return 0; + + case smithy: + //+3 Cards + for (i = 0; i < 3; i++) + { + drawCard(currentPlayer, state); + } + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case village: + //+1 Card + drawCard(currentPlayer, state); + + //+2 Actions + state->numActions = state->numActions + 2; + + //discard played card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case baron: + return baron(choice1, state); + /* + state->numBuys++;//Increase buys by 1! + if (choice1 > 0){//Boolean true or going to discard an estate + int p = 0;//Iterator for hand! + int card_not_discarded = 1;//Flag for discard set! + while(card_not_discarded){ + if (state->hand[currentPlayer][p] == estate){//Found an estate card! + state->coins += 4;//Add 4 coins to the amount of coins + state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p]; + state->discardCount[currentPlayer]++; + for (;p < state->handCount[currentPlayer]; p++){ + state->hand[currentPlayer][p] = state->hand[currentPlayer][p+1]; + } + state->hand[currentPlayer][state->handCount[currentPlayer]] = -1; + state->handCount[currentPlayer]--; + card_not_discarded = 0;//Exit the loop + } + else if (p > state->handCount[currentPlayer]){ + if(DEBUG) { + printf("No estate cards in your hand, invalid choice\n"); + printf("Must gain an estate if there are any\n"); + } + if (supplyCount(estate, state) > 0){ + gainCard(estate, state, 0, currentPlayer); + state->supplyCount[estate]--;//Decrement estates + if (supplyCount(estate, state) == 0){ + isGameOver(state); + } + } + card_not_discarded = 0;//Exit the loop + } + + else{ + p++;//Next card + } + } + } + + else{ + if (supplyCount(estate, state) > 0){ + gainCard(estate, state, 0, currentPlayer);//Gain an estate + state->supplyCount[estate]--;//Decrement Estates + if (supplyCount(estate, state) == 0){ + isGameOver(state); + } + } + } + + + return 0; + */ + + case great_hall: + //+1 Card + drawCard(currentPlayer, state); + + //+1 Actions + state->numActions++; + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case minion: + return minion(choice1, choice2, state); + /* + //+1 action + state->numActions++; + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + if (choice1) //+2 coins + { + state->coins = state->coins + 2; + } + + else if (choice2) //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4 + { + //discard hand + while(numHandCards(state) > 0) + { + discardCard(handPos, currentPlayer, state, 0); + } + + //draw 4 + for (i = 0; i < 4; i++) + { + drawCard(currentPlayer, state); + } + + //other players discard hand and redraw if hand size > 4 + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + if ( state->handCount[i] > 4 ) + { + //discard hand + while( state->handCount[i] > 0 ) + { + discardCard(handPos, i, state, 0); + } + + //draw 4 + for (j = 0; j < 4; j++) + { + drawCard(i, state); + } + } + } + } + + } + return 0; + */ + + case steward: + if (choice1 == 1) + { + //+2 cards + drawCard(currentPlayer, state); + drawCard(currentPlayer, state); + } + else if (choice1 == 2) + { + //+2 coins + state->coins = state->coins + 2; + } + else + { + //trash 2 cards in hand + discardCard(choice2, currentPlayer, state, 1); + discardCard(choice3, currentPlayer, state, 1); + } + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case tribute: + return tribute(currentPlayer, state); + /* + if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1){ + if (state->deckCount[nextPlayer] > 0){ + tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deckCount[nextPlayer]--; + } + else if (state->discardCount[nextPlayer] > 0){ + tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer]-1]; + state->discardCount[nextPlayer]--; + } + else{ + //No Card to Reveal + if (DEBUG){ + printf("No cards to reveal\n"); + } + } + } + + else{ + if (state->deckCount[nextPlayer] == 0){ + for (i = 0; i < state->discardCount[nextPlayer]; i++){ + state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck + state->deckCount[nextPlayer]++; + state->discard[nextPlayer][i] = -1; + state->discardCount[nextPlayer]--; + } + + shuffle(nextPlayer,state);//Shuffle the deck + } + tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; + state->deckCount[nextPlayer]--; + tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; + state->deckCount[nextPlayer]--; + } + + if (tributeRevealedCards[0] == tributeRevealedCards[1]){//If we have a duplicate card, just drop one + state->playedCards[state->playedCardCount] = tributeRevealedCards[1]; + state->playedCardCount++; + tributeRevealedCards[1] = -1; + } + + for (i = 0; i <= 2; i ++){ + if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold){//Treasure cards + state->coins += 2; + } + + else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall){//Victory Card Found + drawCard(currentPlayer, state); + drawCard(currentPlayer, state); + } + else{//Action Card + state->numActions = state->numActions + 2; + } + } + + return 0; + */ + + case ambassador: + return ambassador(choice1, choice2, handpos, currentPlayer, state); + /* + j = 0; //used to check if player has enough cards to discard + + if (choice2 > 2 || choice2 < 0) + { + return -1; + } + + if (choice1 == handPos) + { + return -1; + } + + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (i != handPos && i == state->hand[currentPlayer][choice1] && i != choice1) + { + j++; + } + } + if (j < choice2) + { + return -1; + } + + if (DEBUG) + printf("Player %d reveals card number: %d\n", currentPlayer, state->hand[currentPlayer][choice1]); + + //increase supply count for choosen card by amount being discarded + state->supplyCount[state->hand[currentPlayer][choice1]] += choice2; + + //each other player gains a copy of revealed card + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + gainCard(state->hand[currentPlayer][choice1], state, 0, i); + } + } + + //discard played card from hand + discardCard(handPos, currentPlayer, state, 0); + + //trash copies of cards returned to supply + for (j = 0; j < choice2; j++) + { + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) + { + discardCard(i, currentPlayer, state, 1); + break; + } + } + } + + return 0; + */ + + case cutpurse: + + updateCoins(currentPlayer, state, 2); + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + for (j = 0; j < state->handCount[i]; j++) + { + if (state->hand[i][j] == copper) + { + discardCard(j, i, state, 0); + break; + } + if (j == state->handCount[i]) + { + for (k = 0; k < state->handCount[i]; k++) + { + if (DEBUG) + printf("Player %d reveals card number %d\n", i, state->hand[i][k]); + } + break; + } + } + + } + + } + + //discard played card from hand + discardCard(handPos, currentPlayer, state, 0); + + return 0; + + + case embargo: + //+2 Coins + state->coins = state->coins + 2; + + //see if selected pile is in play + if ( state->supplyCount[choice1] == -1 ) + { + return -1; + } + + //add embargo token to selected supply pile + state->embargoTokens[choice1]++; + + //trash card + discardCard(handPos, currentPlayer, state, 1); + return 0; + + case outpost: + //set outpost flag + state->outpostPlayed++; + + //discard card + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case salvager: + //+1 buy + state->numBuys++; + + if (choice1) + { + //gain coins equal to trashed card + state->coins = state->coins + getCost( handCard(choice1, state) ); + //trash card + discardCard(choice1, currentPlayer, state, 1); + } + + //discard card + discardCard(handPos, currentPlayer, state, 0); + return 0; + + case sea_hag: + for (i = 0; i < state->numPlayers; i++){ + if (i != currentPlayer){ + state->discard[i][state->discardCount[i]] = state->deck[i][state->deckCount[i]--]; state->deckCount[i]--; + state->discardCount[i]++; + state->deck[i][state->deckCount[i]--] = curse;//Top card now a curse + } + } + return 0; + + case treasure_map: + //search hand for another treasure_map + index = -1; + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == treasure_map && i != handPos) + { + index = i; + break; + } + } + if (index > -1) + { + //trash both treasure cards + discardCard(handPos, currentPlayer, state, 1); + discardCard(index, currentPlayer, state, 1); + + //gain 4 Gold cards + for (i = 0; i < 4; i++) + { + gainCard(gold, state, 1, currentPlayer); + } + + //return success + return 1; + } + + //no second treasure_map found in hand + return -1; + } + + return -1; } int discardCard(int handPos, int currentPlayer, struct gameState *state, int trashFlag) { - - //if card is not trashed, added to Played pile - if (trashFlag < 1) + + //if card is not trashed, added to Played pile + if (trashFlag < 1) { - //add card to played pile - state->playedCards[state->playedCardCount] = state->hand[currentPlayer][handPos]; - state->playedCardCount++; - } - - //set played card to -1 - state->hand[currentPlayer][handPos] = -1; - - //remove card from player's hand - if ( handPos == (state->handCount[currentPlayer] - 1) ) //last card in hand array is played + //add card to played pile + state->playedCards[state->playedCardCount] = state->hand[currentPlayer][handPos]; + state->playedCardCount++; + } + + //set played card to -1 + state->hand[currentPlayer][handPos] = -1; + + //remove card from player's hand + if ( handPos == (state->handCount[currentPlayer] - 1) ) //last card in hand array is played { - //reduce number of cards in hand - state->handCount[currentPlayer]--; + //reduce number of cards in hand + state->handCount[currentPlayer]--; } - else if ( state->handCount[currentPlayer] == 1 ) //only one card in hand + else if ( state->handCount[currentPlayer] == 1 ) //only one card in hand { - //reduce number of cards in hand - state->handCount[currentPlayer]--; + //reduce number of cards in hand + state->handCount[currentPlayer]--; } - else + else { - //replace discarded card with last card in hand - state->hand[currentPlayer][handPos] = state->hand[currentPlayer][ (state->handCount[currentPlayer] - 1)]; - //set last card to -1 - state->hand[currentPlayer][state->handCount[currentPlayer] - 1] = -1; - //reduce number of cards in hand - state->handCount[currentPlayer]--; - } - - return 0; + //replace discarded card with last card in hand + state->hand[currentPlayer][handPos] = state->hand[currentPlayer][ (state->handCount[currentPlayer] - 1)]; + //set last card to -1 + state->hand[currentPlayer][state->handCount[currentPlayer] - 1] = -1; + //reduce number of cards in hand + state->handCount[currentPlayer]--; + } + + return 0; } int gainCard(int supplyPos, struct gameState *state, int toFlag, int player) { - //Note: supplyPos is enum of choosen card - - //check if supply pile is empty (0) or card is not used in game (-1) - if ( supplyCount(supplyPos, state) < 1 ) + //Note: supplyPos is enum of choosen card + + //check if supply pile is empty (0) or card is not used in game (-1) + if ( supplyCount(supplyPos, state) < 1 ) { - return -1; + return -1; } - - //added card for [whoseTurn] current player: - // toFlag = 0 : add to discard - // toFlag = 1 : add to deck - // toFlag = 2 : add to hand - if (toFlag == 1) + //added card for [whoseTurn] current player: + // toFlag = 0 : add to discard + // toFlag = 1 : add to deck + // toFlag = 2 : add to hand + + if (toFlag == 1) { - state->deck[ player ][ state->deckCount[player] ] = supplyPos; - state->deckCount[player]++; + state->deck[ player ][ state->deckCount[player] ] = supplyPos; + state->deckCount[player]++; } - else if (toFlag == 2) + else if (toFlag == 2) { - state->hand[ player ][ state->handCount[player] ] = supplyPos; - state->handCount[player]++; + state->hand[ player ][ state->handCount[player] ] = supplyPos; + state->handCount[player]++; } - else + else { - state->discard[player][ state->discardCount[player] ] = supplyPos; - state->discardCount[player]++; - } - - //decrease number in supply pile - state->supplyCount[supplyPos]--; - - return 0; + state->discard[player][ state->discardCount[player] ] = supplyPos; + state->discardCount[player]++; + } + + //decrease number in supply pile + state->supplyCount[supplyPos]--; + + return 0; } int updateCoins(int player, struct gameState *state, int bonus) { - int i; - - //reset coin count - state->coins = 0; + int i; - //add coins for each Treasure card in player's hand - for (i = 0; i < state->handCount[player]; i++) + //reset coin count + state->coins = 0; + + //add coins for each Treasure card in player's hand + for (i = 0; i < state->handCount[player]; i++) { - if (state->hand[player][i] == copper) - { - state->coins += 1; - } - else if (state->hand[player][i] == silver) - { - state->coins += 2; - } - else if (state->hand[player][i] == gold) - { - state->coins += 3; - } + if (state->hand[player][i] == copper) + { + state->coins += 1; + } + else if (state->hand[player][i] == silver) + { + state->coins += 2; + } + else if (state->hand[player][i] == gold) + { + state->coins += 3; + } } - //add bonus - state->coins += bonus; + //add bonus + state->coins += bonus; + + return 0; +} + +//refactored cardEffect functions for assignment 2 +int baron(int choice1, struct gameState* state) +{ + state->numBuys++;//Increase buys by 1! + if (choice1 > 0){//Boolean true or going to discard an estate + int p = 0;//Iterator for hand! + int card_not_discarded = 1;//Flag for discard set! + while(card_not_discarded){ + if (state->hand[currentPlayer][p] == estate){//Found an estate card! + state->coins += 4;//Add 4 coins to the amount of coins + state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p]; + state->discardCount[currentPlayer]++; + for (;p < state->handCount[currentPlayer]; p++){ + state->hand[currentPlayer][p] = state->hand[currentPlayer][p+1]; + } + state->hand[currentPlayer][state->handCount[currentPlayer]] = -1; + state->handCount[currentPlayer]--; + card_not_discarded = 0;//Exit the loop + } + else if (p > state->handCount[currentPlayer]){ + if(DEBUG) { + printf("No estate cards in your hand, invalid choice\n"); + printf("Must gain an estate if there are any\n"); + } + if (supplyCount(estate, state) > 0){ + gainCard(estate, state, 0, currentPlayer); + state->supplyCount[estate]--;//Decrement estates + if (supplyCount(estate, state) == 0){ + isGameOver(state); + } + } + card_not_discarded = 0;//Exit the loop + } + + else{ + p++;//Next card + } + } + } + + else{ + if (supplyCount(estate, state) > 0){ + gainCard(estate, state, 0, currentPlayer);//Gain an estate + state->supplyCount[estate]--;//Decrement Estates + if (supplyCount(estate, state) == 0){ + isGameOver(state); + } + } + } + + + return 0; +} +int minion(int choice1, int choice2, struct gameState* state) +{ + //+1 action + state->numActions++; + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + if (choice1) //+2 coins + { + state->coins = state->coins + 2; + } + + else if (choice2) //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4 + { + //discard hand + while(numHandCards(state) > 0) + { + discardCard(handPos, currentPlayer, state, 0); + } + + //draw 4 + for (i = 0; i < 4; i++) + { + drawCard(currentPlayer, state); + } + + //other players discard hand and redraw if hand size > 4 + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + if ( state->handCount[i] > 4 ) + { + //discard hand + while( state->handCount[i] > 0 ) + { + discardCard(handPos, i, state, 0); + } + + //draw 4 + for (j = 0; j < 4; j++) + { + drawCard(i, state); + } + } + } + } + + } + return 0; + - return 0; } +int ambassador(int choice1, int choice2, int handpos, int currentPlayer, struct gameState* state) +{ + j = 0; //used to check if player has enough cards to discard + + if (choice2 > 2 || choice2 < 0) + { + return -1; + } + + if (choice1 == handPos) + { + return -1; + } + + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (i != handPos && i == state->hand[currentPlayer][choice1] && i != choice1) + { + j++; + } + } + if (j < choice2) + { + return -1; + } + + if (DEBUG) + printf("Player %d reveals card number: %d\n", currentPlayer, state->hand[currentPlayer][choice1]); + + //increase supply count for choosen card by amount being discarded + state->supplyCount[state->hand[currentPlayer][choice1]] += choice2; + + //each other player gains a copy of revealed card + for (i = 0; i < state->numPlayers; i++) + { + if (i != currentPlayer) + { + gainCard(state->hand[currentPlayer][choice1], state, 0, i); + } + } + + //discard played card from hand + discardCard(handPos, currentPlayer, state, 0); + + //trash copies of cards returned to supply + for (j = 0; j < choice2; j++) + { + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) + { + discardCard(i, currentPlayer, state, 1); + break; + } + } + } + + return 0; +} + +tribute(int currentPlayer, struct gameState* state) +{ + int tributeRevealedCards[2] = {-1, -1} + if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1){ + if (state->deckCount[nextPlayer] > 0){ + tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deckCount[nextPlayer]--; + } + else if (state->discardCount[nextPlayer] > 0){ + tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer]-1]; + state->discardCount[nextPlayer]--; + } + else{ + //No Card to Reveal + if (DEBUG){ + printf("No cards to reveal\n"); + } + } + } + + else{ + if (state->deckCount[nextPlayer] == 0){ + for (i = 0; i < state->discardCount[nextPlayer]; i++){ + state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck + state->deckCount[nextPlayer]++; + state->discard[nextPlayer][i] = -1; + state->discardCount[nextPlayer]--; + } + + shuffle(nextPlayer,state);//Shuffle the deck + } + tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; + state->deckCount[nextPlayer]--; + tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; + state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; + state->deckCount[nextPlayer]--; + } + + if (tributeRevealedCards[0] == tributeRevealedCards[1]){//If we have a duplicate card, just drop one + state->playedCards[state->playedCardCount] = tributeRevealedCards[1]; + state->playedCardCount++; + tributeRevealedCards[1] = -1; + } + + for (i = 0; i <= 2; i ++){ + if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold){//Treasure cards + state->coins += 2; + } + + else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall){//Victory Card Found + drawCard(currentPlayer, state); + drawCard(currentPlayer, state); + } + else{//Action Card + state->numActions = state->numActions + 2; + } + } + + return 0; +} + +int mine(int choice1, int choice2, int handpos, int currentPlayer, struct gameState* state) +{ + j = state->hand[currentPlayer][choice1]; //store card we will trash + + if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold) + { + return -1; + } + + if (choice2 > treasure_map || choice2 < curse) + { + return -1; + } + + if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) ) + { + return -1; + } + + gainCard(choice2, state, 2, currentPlayer); + + //discard card from hand + discardCard(handPos, currentPlayer, state, 0); + + //discard trashed card + for (i = 0; i < state->handCount[currentPlayer]; i++) + { + if (state->hand[currentPlayer][i] == j) + { + discardCard(i, currentPlayer, state, 0); + break; + } + } + + return 0; +} //end of dominion.c From b675c8c72b15638bf2d7ffd087959a13ad5a8865 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 3 Jul 2019 16:05:59 -0700 Subject: [PATCH 04/17] removed commented-out old code from before the refactor --- projects/bleckw/dominion/dominion.c | 255 ---------------------------- 1 file changed, 255 deletions(-) diff --git a/projects/bleckw/dominion/dominion.c b/projects/bleckw/dominion/dominion.c index 61bccc32..bd912e60 100644 --- a/projects/bleckw/dominion/dominion.c +++ b/projects/bleckw/dominion/dominion.c @@ -653,7 +653,6 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState int currentPlayer = whoseTurn(state); int nextPlayer = currentPlayer + 1; - // int tributeRevealedCards[2] = {-1, -1}; int temphand[MAX_HAND];// moved above the if statement int drawntreasure=0; int cardDrawn; @@ -769,41 +768,6 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState case mine: return mine(choice1, choice2, handpos, currentPlayer, state); - /* - j = state->hand[currentPlayer][choice1]; //store card we will trash - - if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold) - { - return -1; - } - - if (choice2 > treasure_map || choice2 < curse) - { - return -1; - } - - if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) ) - { - return -1; - } - - gainCard(choice2, state, 2, currentPlayer); - - //discard card from hand - discardCard(handPos, currentPlayer, state, 0); - - //discard trashed card - for (i = 0; i < state->handCount[currentPlayer]; i++) - { - if (state->hand[currentPlayer][i] == j) - { - discardCard(i, currentPlayer, state, 0); - break; - } - } - - return 0; - */ case remodel: j = state->hand[currentPlayer][choice1]; //store card we will trash @@ -855,57 +819,6 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState case baron: return baron(choice1, state); - /* - state->numBuys++;//Increase buys by 1! - if (choice1 > 0){//Boolean true or going to discard an estate - int p = 0;//Iterator for hand! - int card_not_discarded = 1;//Flag for discard set! - while(card_not_discarded){ - if (state->hand[currentPlayer][p] == estate){//Found an estate card! - state->coins += 4;//Add 4 coins to the amount of coins - state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p]; - state->discardCount[currentPlayer]++; - for (;p < state->handCount[currentPlayer]; p++){ - state->hand[currentPlayer][p] = state->hand[currentPlayer][p+1]; - } - state->hand[currentPlayer][state->handCount[currentPlayer]] = -1; - state->handCount[currentPlayer]--; - card_not_discarded = 0;//Exit the loop - } - else if (p > state->handCount[currentPlayer]){ - if(DEBUG) { - printf("No estate cards in your hand, invalid choice\n"); - printf("Must gain an estate if there are any\n"); - } - if (supplyCount(estate, state) > 0){ - gainCard(estate, state, 0, currentPlayer); - state->supplyCount[estate]--;//Decrement estates - if (supplyCount(estate, state) == 0){ - isGameOver(state); - } - } - card_not_discarded = 0;//Exit the loop - } - - else{ - p++;//Next card - } - } - } - - else{ - if (supplyCount(estate, state) > 0){ - gainCard(estate, state, 0, currentPlayer);//Gain an estate - state->supplyCount[estate]--;//Decrement Estates - if (supplyCount(estate, state) == 0){ - isGameOver(state); - } - } - } - - - return 0; - */ case great_hall: //+1 Card @@ -920,57 +833,6 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState case minion: return minion(choice1, choice2, state); - /* - //+1 action - state->numActions++; - - //discard card from hand - discardCard(handPos, currentPlayer, state, 0); - - if (choice1) //+2 coins - { - state->coins = state->coins + 2; - } - - else if (choice2) //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4 - { - //discard hand - while(numHandCards(state) > 0) - { - discardCard(handPos, currentPlayer, state, 0); - } - - //draw 4 - for (i = 0; i < 4; i++) - { - drawCard(currentPlayer, state); - } - - //other players discard hand and redraw if hand size > 4 - for (i = 0; i < state->numPlayers; i++) - { - if (i != currentPlayer) - { - if ( state->handCount[i] > 4 ) - { - //discard hand - while( state->handCount[i] > 0 ) - { - discardCard(handPos, i, state, 0); - } - - //draw 4 - for (j = 0; j < 4; j++) - { - drawCard(i, state); - } - } - } - } - - } - return 0; - */ case steward: if (choice1 == 1) @@ -997,126 +859,9 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState case tribute: return tribute(currentPlayer, state); - /* - if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1){ - if (state->deckCount[nextPlayer] > 0){ - tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; - state->deckCount[nextPlayer]--; - } - else if (state->discardCount[nextPlayer] > 0){ - tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer]-1]; - state->discardCount[nextPlayer]--; - } - else{ - //No Card to Reveal - if (DEBUG){ - printf("No cards to reveal\n"); - } - } - } - - else{ - if (state->deckCount[nextPlayer] == 0){ - for (i = 0; i < state->discardCount[nextPlayer]; i++){ - state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck - state->deckCount[nextPlayer]++; - state->discard[nextPlayer][i] = -1; - state->discardCount[nextPlayer]--; - } - - shuffle(nextPlayer,state);//Shuffle the deck - } - tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; - state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; - state->deckCount[nextPlayer]--; - tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1]; - state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1; - state->deckCount[nextPlayer]--; - } - - if (tributeRevealedCards[0] == tributeRevealedCards[1]){//If we have a duplicate card, just drop one - state->playedCards[state->playedCardCount] = tributeRevealedCards[1]; - state->playedCardCount++; - tributeRevealedCards[1] = -1; - } - - for (i = 0; i <= 2; i ++){ - if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold){//Treasure cards - state->coins += 2; - } - - else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall){//Victory Card Found - drawCard(currentPlayer, state); - drawCard(currentPlayer, state); - } - else{//Action Card - state->numActions = state->numActions + 2; - } - } - - return 0; - */ case ambassador: return ambassador(choice1, choice2, handpos, currentPlayer, state); - /* - j = 0; //used to check if player has enough cards to discard - - if (choice2 > 2 || choice2 < 0) - { - return -1; - } - - if (choice1 == handPos) - { - return -1; - } - - for (i = 0; i < state->handCount[currentPlayer]; i++) - { - if (i != handPos && i == state->hand[currentPlayer][choice1] && i != choice1) - { - j++; - } - } - if (j < choice2) - { - return -1; - } - - if (DEBUG) - printf("Player %d reveals card number: %d\n", currentPlayer, state->hand[currentPlayer][choice1]); - - //increase supply count for choosen card by amount being discarded - state->supplyCount[state->hand[currentPlayer][choice1]] += choice2; - - //each other player gains a copy of revealed card - for (i = 0; i < state->numPlayers; i++) - { - if (i != currentPlayer) - { - gainCard(state->hand[currentPlayer][choice1], state, 0, i); - } - } - - //discard played card from hand - discardCard(handPos, currentPlayer, state, 0); - - //trash copies of cards returned to supply - for (j = 0; j < choice2; j++) - { - for (i = 0; i < state->handCount[currentPlayer]; i++) - { - if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) - { - discardCard(i, currentPlayer, state, 1); - break; - } - } - } - - return 0; - */ case cutpurse: From e0da43da523b280d60c820946b0c095bcd04fa89 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 3 Jul 2019 16:16:33 -0700 Subject: [PATCH 05/17] created the new file dominion_card_effects.h and added function definitions for baron, minion, ambassador, tribute, and mine --- projects/bleckw/dominion/dominion.c | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/bleckw/dominion/dominion.c b/projects/bleckw/dominion/dominion.c index bd912e60..d51dfcd1 100644 --- a/projects/bleckw/dominion/dominion.c +++ b/projects/bleckw/dominion/dominion.c @@ -1,6 +1,7 @@ #include "dominion.h" #include "dominion_helpers.h" #include "rngs.h" +#include "dominion_card_effects.h" #include #include #include From dadd6a58db6788bd5ddefd71d26d7fa5b99206af Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 3 Jul 2019 16:19:18 -0700 Subject: [PATCH 06/17] previous commit did not include the new file dominion_card_effects.h. Including it now. --- projects/bleckw/dominion/dominion_card_effects.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 projects/bleckw/dominion/dominion_card_effects.h diff --git a/projects/bleckw/dominion/dominion_card_effects.h b/projects/bleckw/dominion/dominion_card_effects.h new file mode 100644 index 00000000..dadfc83c --- /dev/null +++ b/projects/bleckw/dominion/dominion_card_effects.h @@ -0,0 +1,14 @@ +#ifndef _DOMINION_CARD_EFFECTS_H +#define _DOMINION_CARD_EFFECTS_H + +int baron(int choice1, struct gameState* state); + +int minion(int choice1, int choice2, struct gameState* state); + +int ambassador(int choice1, int choice2, int handpos, int currentPlayer, struct gameState* state); + +tribute(int currentPlayer, struct gameState* state); + +int mine(int choice1, int choice2, int handpos, int currentPlayer, struct gameState* state); + +#endif From 7fce3d5c771ef7344033af0d2fc6bb75c9619f7d Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 3 Jul 2019 16:25:26 -0700 Subject: [PATCH 07/17] updated the function declarations to include currentPlayer (where missing) --- projects/bleckw/dominion/dominion.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/bleckw/dominion/dominion.c b/projects/bleckw/dominion/dominion.c index d51dfcd1..d2841699 100644 --- a/projects/bleckw/dominion/dominion.c +++ b/projects/bleckw/dominion/dominion.c @@ -819,7 +819,7 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState return 0; case baron: - return baron(choice1, state); + return baron(choice1, currentPlayer, state); case great_hall: //+1 Card @@ -833,7 +833,7 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState return 0; case minion: - return minion(choice1, choice2, state); + return minion(choice1, choice2, currentPlayer, state); case steward: if (choice1 == 1) @@ -1090,7 +1090,7 @@ int updateCoins(int player, struct gameState *state, int bonus) } //refactored cardEffect functions for assignment 2 -int baron(int choice1, struct gameState* state) +int baron(int choice1, int currentPlayer, struct gameState* state) { state->numBuys++;//Increase buys by 1! if (choice1 > 0){//Boolean true or going to discard an estate @@ -1142,7 +1142,7 @@ int baron(int choice1, struct gameState* state) return 0; } -int minion(int choice1, int choice2, struct gameState* state) +int minion(int choice1, int choice2, int currentPlayer, struct gameState* state) { //+1 action state->numActions++; From 3a5cf1bfe6ec05f3ad8102c34f9454952b476d01 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 3 Jul 2019 16:48:57 -0700 Subject: [PATCH 08/17] added additional requirements for minion, ambassador, tribute, mine --- projects/bleckw/dominion/dominion.c | 16 ++++++++-------- projects/bleckw/dominion/dominion_card_effects.h | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/projects/bleckw/dominion/dominion.c b/projects/bleckw/dominion/dominion.c index d2841699..906d5ccb 100644 --- a/projects/bleckw/dominion/dominion.c +++ b/projects/bleckw/dominion/dominion.c @@ -768,7 +768,7 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState return -1; case mine: - return mine(choice1, choice2, handpos, currentPlayer, state); + return mine(choice1, choice2, handPos, currentPlayer, state); case remodel: j = state->hand[currentPlayer][choice1]; //store card we will trash @@ -833,7 +833,7 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState return 0; case minion: - return minion(choice1, choice2, currentPlayer, state); + return minion(choice1, choice2, handPos, currentPlayer, state); case steward: if (choice1 == 1) @@ -859,10 +859,10 @@ int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState return 0; case tribute: - return tribute(currentPlayer, state); + return tribute(currentPlayer, nextPlayer, state); case ambassador: - return ambassador(choice1, choice2, handpos, currentPlayer, state); + return ambassador(choice1, choice2, handPos, currentPlayer, state); case cutpurse: @@ -1142,7 +1142,7 @@ int baron(int choice1, int currentPlayer, struct gameState* state) return 0; } -int minion(int choice1, int choice2, int currentPlayer, struct gameState* state) +int minion(int choice1, int choice2, int handPos, int currentPlayer, struct gameState* state) { //+1 action state->numActions++; @@ -1197,7 +1197,7 @@ int minion(int choice1, int choice2, int currentPlayer, struct gameState* state) } -int ambassador(int choice1, int choice2, int handpos, int currentPlayer, struct gameState* state) +int ambassador(int choice1, int choice2, int handPos, int currentPlayer, struct gameState* state) { j = 0; //used to check if player has enough cards to discard @@ -1257,7 +1257,7 @@ int ambassador(int choice1, int choice2, int handpos, int currentPlayer, struct return 0; } -tribute(int currentPlayer, struct gameState* state) +int tribute(int currentPlayer, int nextPlayer, struct gameState* state) { int tributeRevealedCards[2] = {-1, -1} if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1){ @@ -1319,7 +1319,7 @@ tribute(int currentPlayer, struct gameState* state) return 0; } -int mine(int choice1, int choice2, int handpos, int currentPlayer, struct gameState* state) +int mine(int choice1, int choice2, int handPos, int currentPlayer, struct gameState* state) { j = state->hand[currentPlayer][choice1]; //store card we will trash diff --git a/projects/bleckw/dominion/dominion_card_effects.h b/projects/bleckw/dominion/dominion_card_effects.h index dadfc83c..5d6ad213 100644 --- a/projects/bleckw/dominion/dominion_card_effects.h +++ b/projects/bleckw/dominion/dominion_card_effects.h @@ -1,14 +1,14 @@ #ifndef _DOMINION_CARD_EFFECTS_H #define _DOMINION_CARD_EFFECTS_H -int baron(int choice1, struct gameState* state); +int baron(int choice1, int currentPlayer, struct gameState* state); -int minion(int choice1, int choice2, struct gameState* state); +int minion(int choice1, int choice2, int handPos, int currentPlayer, struct gameState* state); -int ambassador(int choice1, int choice2, int handpos, int currentPlayer, struct gameState* state); +int ambassador(int choice1, int choice2, int handPos, int currentPlayer, struct gameState* state); -tribute(int currentPlayer, struct gameState* state); +int tribute(int currentPlayer, int nextPlayer, struct gameState* state); -int mine(int choice1, int choice2, int handpos, int currentPlayer, struct gameState* state); +int mine(int choice1, int choice2, int handPos, int currentPlayer, struct gameState* state); #endif From 596c960e9a6b722c3e2603f6438ff733441623d3 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 3 Jul 2019 17:12:14 -0700 Subject: [PATCH 09/17] code cleanup in tribute --- projects/bleckw/dominion/dominion.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/projects/bleckw/dominion/dominion.c b/projects/bleckw/dominion/dominion.c index 906d5ccb..672b7ea7 100644 --- a/projects/bleckw/dominion/dominion.c +++ b/projects/bleckw/dominion/dominion.c @@ -1303,11 +1303,12 @@ int tribute(int currentPlayer, int nextPlayer, struct gameState* state) } for (i = 0; i <= 2; i ++){ - if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold){//Treasure cards + int revealedCard = tributeRevealedCards[i]; + if (revealedCard == copper || revealedCard == silver || revealedCard == gold){//Treasure cards state->coins += 2; } - else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall){//Victory Card Found + else if (revealedCard == estate || revealedCard == duchy || revealedCard == province || revealedCard == gardens || revealedCard == great_hall){//Victory Card Found drawCard(currentPlayer, state); drawCard(currentPlayer, state); } From e42c3c955aae6639a17e11d6ec8f62fcf3d0eec1 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 3 Jul 2019 19:22:31 -0700 Subject: [PATCH 10/17] bugs introduced into newly created functions --- projects/bleckw/dominion/dominion.c | 32 +++++++++---------- .../bleckw/dominion/dominion_card_effects.h | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/projects/bleckw/dominion/dominion.c b/projects/bleckw/dominion/dominion.c index 672b7ea7..4006645a 100644 --- a/projects/bleckw/dominion/dominion.c +++ b/projects/bleckw/dominion/dominion.c @@ -1114,7 +1114,7 @@ int baron(int choice1, int currentPlayer, struct gameState* state) printf("Must gain an estate if there are any\n"); } if (supplyCount(estate, state) > 0){ - gainCard(estate, state, 0, currentPlayer); + gainCard(estate, state, 0, nextPlayer); state->supplyCount[estate]--;//Decrement estates if (supplyCount(estate, state) == 0){ isGameOver(state); @@ -1132,17 +1132,15 @@ int baron(int choice1, int currentPlayer, struct gameState* state) else{ if (supplyCount(estate, state) > 0){ gainCard(estate, state, 0, currentPlayer);//Gain an estate - state->supplyCount[estate]--;//Decrement Estates - if (supplyCount(estate, state) == 0){ - isGameOver(state); - } + state->supplyCount[province]--;//Decrement Estates + isGameOver(state); } } return 0; } -int minion(int choice1, int choice2, int handPos, int currentPlayer, struct gameState* state) +int minion(int choice2, int choice1, int handPos, int currentPlayer, struct gameState* state) { //+1 action state->numActions++; @@ -1158,7 +1156,7 @@ int minion(int choice1, int choice2, int handPos, int currentPlayer, struct game else if (choice2) //discard hand, redraw 4, other players with 5+ cards discard hand and draw 4 { //discard hand - while(numHandCards(state) > 0) + while(numHandCards(state) >= 0) { discardCard(handPos, currentPlayer, state, 0); } @@ -1248,8 +1246,7 @@ int ambassador(int choice1, int choice2, int handPos, int currentPlayer, struct { if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1]) { - discardCard(i, currentPlayer, state, 1); - break; + discardCard(i, currentPlayer, state, 0); } } } @@ -1278,7 +1275,7 @@ int tribute(int currentPlayer, int nextPlayer, struct gameState* state) } else{ - if (state->deckCount[nextPlayer] == 0){ + if (state->deckCount[nextPlayer] = 0){ for (i = 0; i < state->discardCount[nextPlayer]; i++){ state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck state->deckCount[nextPlayer]++; @@ -1304,15 +1301,18 @@ int tribute(int currentPlayer, int nextPlayer, struct gameState* state) for (i = 0; i <= 2; i ++){ int revealedCard = tributeRevealedCards[i]; - if (revealedCard == copper || revealedCard == silver || revealedCard == gold){//Treasure cards - state->coins += 2; + if (revealedCard == copper || revealedCard == silver || revealedCard == gold) + {//Treasure cards + state->coins += state->numActions; } - else if (revealedCard == estate || revealedCard == duchy || revealedCard == province || revealedCard == gardens || revealedCard == great_hall){//Victory Card Found + else if (revealedCard == estate || revealedCard == duchy || revealedCard == province || revealedCard == gardens || revealedCard == great_hall) + {//Victory Card Found drawCard(currentPlayer, state); drawCard(currentPlayer, state); } - else{//Action Card + else + {//Action Card state->numActions = state->numActions + 2; } } @@ -1334,7 +1334,7 @@ int mine(int choice1, int choice2, int handPos, int currentPlayer, struct gameSt return -1; } - if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) ) + if ( (getCost(state->hand[currentPlayer][choice1]) + 3) = getCost(choice2) ) { return -1; } @@ -1345,7 +1345,7 @@ int mine(int choice1, int choice2, int handPos, int currentPlayer, struct gameSt discardCard(handPos, currentPlayer, state, 0); //discard trashed card - for (i = 0; i < state->handCount[currentPlayer]; i++) + for (i = 0; i <= state->handCount[currentPlayer]; i++) { if (state->hand[currentPlayer][i] == j) { diff --git a/projects/bleckw/dominion/dominion_card_effects.h b/projects/bleckw/dominion/dominion_card_effects.h index 5d6ad213..e3ab4a79 100644 --- a/projects/bleckw/dominion/dominion_card_effects.h +++ b/projects/bleckw/dominion/dominion_card_effects.h @@ -3,7 +3,7 @@ int baron(int choice1, int currentPlayer, struct gameState* state); -int minion(int choice1, int choice2, int handPos, int currentPlayer, struct gameState* state); +int minion(int choice2, int choice1, int handPos, int currentPlayer, struct gameState* state); int ambassador(int choice1, int choice2, int handPos, int currentPlayer, struct gameState* state); From 61be2324d2ad74c9c128732636111378e3dc9198 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Fri, 19 Jul 2019 16:45:15 -0700 Subject: [PATCH 11/17] Final Project ready on master --- projects/bleckw/FinalProject/.classpath | 10 + projects/bleckw/FinalProject/.project | 17 + projects/bleckw/FinalProject/README.md | 5 + .../src/DomainValidator.java | 2064 +++++++++++++++++ .../src/InetAddressValidator.java | 189 ++ .../src/RegexValidator.java | 229 ++ .../URLValidatorCorrect/src/ResultPair.java | 32 + .../URLValidatorCorrect/src/UrlValidator.java | 543 +++++ .../test/UrlValidatorTest.java | 600 +++++ .../src/DomainValidator.java | 2064 +++++++++++++++++ .../src/InetAddressValidator.java | 189 ++ .../src/RegexValidator.java | 229 ++ .../URLValidatorInCorrect/src/ResultPair.java | 32 + .../src/UrlValidator.java | 543 +++++ .../test/UrlValidatorTest.java | 600 +++++ .../bin/DomainValidator$ArrayType.class | Bin 0 -> 1484 bytes .../bin/DomainValidator$IDNBUGHOLDER.class | Bin 0 -> 838 bytes .../FinalProject/bin/DomainValidator.class | Bin 0 -> 42956 bytes .../bin/InetAddressValidator.class | Bin 0 -> 3501 bytes .../FinalProject/bin/RegexValidator.class | Bin 0 -> 3091 bytes .../bleckw/FinalProject/bin/ResultPair.class | Bin 0 -> 398 bytes .../FinalProject/bin/UrlValidator.class | Bin 0 -> 7447 bytes .../FinalProject/bin/UrlValidatorTest.class | Bin 0 -> 17023 bytes 23 files changed, 7346 insertions(+) create mode 100644 projects/bleckw/FinalProject/.classpath create mode 100644 projects/bleckw/FinalProject/.project create mode 100644 projects/bleckw/FinalProject/README.md create mode 100644 projects/bleckw/FinalProject/URLValidatorCorrect/src/DomainValidator.java create mode 100644 projects/bleckw/FinalProject/URLValidatorCorrect/src/InetAddressValidator.java create mode 100644 projects/bleckw/FinalProject/URLValidatorCorrect/src/RegexValidator.java create mode 100644 projects/bleckw/FinalProject/URLValidatorCorrect/src/ResultPair.java create mode 100644 projects/bleckw/FinalProject/URLValidatorCorrect/src/UrlValidator.java create mode 100644 projects/bleckw/FinalProject/URLValidatorCorrect/test/UrlValidatorTest.java create mode 100644 projects/bleckw/FinalProject/URLValidatorInCorrect/src/DomainValidator.java create mode 100644 projects/bleckw/FinalProject/URLValidatorInCorrect/src/InetAddressValidator.java create mode 100644 projects/bleckw/FinalProject/URLValidatorInCorrect/src/RegexValidator.java create mode 100644 projects/bleckw/FinalProject/URLValidatorInCorrect/src/ResultPair.java create mode 100644 projects/bleckw/FinalProject/URLValidatorInCorrect/src/UrlValidator.java create mode 100644 projects/bleckw/FinalProject/URLValidatorInCorrect/test/UrlValidatorTest.java create mode 100644 projects/bleckw/FinalProject/bin/DomainValidator$ArrayType.class create mode 100644 projects/bleckw/FinalProject/bin/DomainValidator$IDNBUGHOLDER.class create mode 100644 projects/bleckw/FinalProject/bin/DomainValidator.class create mode 100644 projects/bleckw/FinalProject/bin/InetAddressValidator.class create mode 100644 projects/bleckw/FinalProject/bin/RegexValidator.class create mode 100644 projects/bleckw/FinalProject/bin/ResultPair.class create mode 100644 projects/bleckw/FinalProject/bin/UrlValidator.class create mode 100644 projects/bleckw/FinalProject/bin/UrlValidatorTest.class diff --git a/projects/bleckw/FinalProject/.classpath b/projects/bleckw/FinalProject/.classpath new file mode 100644 index 00000000..82484cb7 --- /dev/null +++ b/projects/bleckw/FinalProject/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/projects/bleckw/FinalProject/.project b/projects/bleckw/FinalProject/.project new file mode 100644 index 00000000..8fd58d75 --- /dev/null +++ b/projects/bleckw/FinalProject/.project @@ -0,0 +1,17 @@ + + + FinalProject + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/projects/bleckw/FinalProject/README.md b/projects/bleckw/FinalProject/README.md new file mode 100644 index 00000000..e768f1f3 --- /dev/null +++ b/projects/bleckw/FinalProject/README.md @@ -0,0 +1,5 @@ +Final Project + + + + diff --git a/projects/bleckw/FinalProject/URLValidatorCorrect/src/DomainValidator.java b/projects/bleckw/FinalProject/URLValidatorCorrect/src/DomainValidator.java new file mode 100644 index 00000000..a8e8a793 --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorCorrect/src/DomainValidator.java @@ -0,0 +1,2064 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.net.IDN; +import java.util.Arrays; +import java.util.Locale; + +/** + *

Domain name validation routines.

+ * + *

+ * This validator provides methods for validating Internet domain names + * and top-level domains. + *

+ * + *

Domain names are evaluated according + * to the standards RFC1034, + * section 3, and RFC1123, + * section 2.1. No accommodation is provided for the specialized needs of + * other applications; if the domain name has been URL-encoded, for example, + * validation will fail even though the equivalent plaintext version of the + * same name would have passed. + *

+ * + *

+ * Validation is also provided for top-level domains (TLDs) as defined and + * maintained by the Internet Assigned Numbers Authority (IANA): + *

+ * + *
    + *
  • {@link #isValidInfrastructureTld} - validates infrastructure TLDs + * (.arpa, etc.)
  • + *
  • {@link #isValidGenericTld} - validates generic TLDs + * (.com, .org, etc.)
  • + *
  • {@link #isValidCountryCodeTld} - validates country code TLDs + * (.us, .uk, .cn, etc.)
  • + *
+ * + *

+ * (NOTE: This class does not provide IP address lookup for domain names or + * methods to ensure that a given domain name matches a specific IP; see + * {@link java.net.InetAddress} for that functionality.) + *

+ * + * @version $Revision: 1781829 $ + * @since Validator 1.4 + */ +public class DomainValidator implements Serializable { + + private static final int MAX_DOMAIN_LENGTH = 253; + + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private static final long serialVersionUID = -4407125112880174009L; + + // Regular expression strings for hostnames (derived from RFC2396 and RFC 1123) + + // RFC2396: domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum + // Max 63 characters + private static final String DOMAIN_LABEL_REGEX = "\\p{Alnum}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?"; + + // RFC2396 toplabel = alpha | alpha *( alphanum | "-" ) alphanum + // Max 63 characters + private static final String TOP_LABEL_REGEX = "\\p{Alpha}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?"; + + // RFC2396 hostname = *( domainlabel "." ) toplabel [ "." ] + // Note that the regex currently requires both a domain label and a top level label, whereas + // the RFC does not. This is because the regex is used to detect if a TLD is present. + // If the match fails, input is checked against DOMAIN_LABEL_REGEX (hostnameRegex) + // RFC1123 sec 2.1 allows hostnames to start with a digit + private static final String DOMAIN_NAME_REGEX = + "^(?:" + DOMAIN_LABEL_REGEX + "\\.)+" + "(" + TOP_LABEL_REGEX + ")\\.?$"; + + private final boolean allowLocal; + + /** + * Singleton instance of this validator, which + * doesn't consider local addresses as valid. + */ + private static final DomainValidator DOMAIN_VALIDATOR = new DomainValidator(false); + + /** + * Singleton instance of this validator, which does + * consider local addresses valid. + */ + private static final DomainValidator DOMAIN_VALIDATOR_WITH_LOCAL = new DomainValidator(true); + + /** + * RegexValidator for matching domains. + */ + private final RegexValidator domainRegex = + new RegexValidator(DOMAIN_NAME_REGEX); + /** + * RegexValidator for matching a local hostname + */ + // RFC1123 sec 2.1 allows hostnames to start with a digit + private final RegexValidator hostnameRegex = + new RegexValidator(DOMAIN_LABEL_REGEX); + + /** + * Returns the singleton instance of this validator. It + * will not consider local addresses as valid. + * @return the singleton instance of this validator + */ + public static synchronized DomainValidator getInstance() { + inUse = true; + return DOMAIN_VALIDATOR; + } + + /** + * Returns the singleton instance of this validator, + * with local validation as required. + * @param allowLocal Should local addresses be considered valid? + * @return the singleton instance of this validator + */ + public static synchronized DomainValidator getInstance(boolean allowLocal) { + inUse = true; + if(allowLocal) { + return DOMAIN_VALIDATOR_WITH_LOCAL; + } + return DOMAIN_VALIDATOR; + } + + /** Private constructor. */ + private DomainValidator(boolean allowLocal) { + this.allowLocal = allowLocal; + } + + /** + * Returns true if the specified String parses + * as a valid domain name with a recognized top-level domain. + * The parsing is case-insensitive. + * @param domain the parameter to check for domain name syntax + * @return true if the parameter is a valid domain name + */ + public boolean isValid(String domain) { + if (domain == null) { + return false; + } + domain = unicodeToASCII(domain); + // hosts must be equally reachable via punycode and Unicode; + // Unicode is never shorter than punycode, so check punycode + // if domain did not convert, then it will be caught by ASCII + // checks in the regexes below + if (domain.length() > MAX_DOMAIN_LENGTH) { + return false; + } + String[] groups = domainRegex.match(domain); + if (groups != null && groups.length > 0) { + return isValidTld(groups[0]); + } + return allowLocal && hostnameRegex.isValid(domain); + } + + // package protected for unit test access + // must agree with isValid() above + final boolean isValidDomainSyntax(String domain) { + if (domain == null) { + return false; + } + domain = unicodeToASCII(domain); + // hosts must be equally reachable via punycode and Unicode; + // Unicode is never shorter than punycode, so check punycode + // if domain did not convert, then it will be caught by ASCII + // checks in the regexes below + if (domain.length() > MAX_DOMAIN_LENGTH) { + return false; + } + String[] groups = domainRegex.match(domain); + return (groups != null && groups.length > 0) + || hostnameRegex.isValid(domain); + } + + /** + * Returns true if the specified String matches any + * IANA-defined top-level domain. Leading dots are ignored if present. + * The search is case-insensitive. + * @param tld the parameter to check for TLD status, not null + * @return true if the parameter is a TLD + */ + public boolean isValidTld(String tld) { + tld = unicodeToASCII(tld); + if(allowLocal && isValidLocalTld(tld)) { + return true; + } + return isValidInfrastructureTld(tld) + || isValidGenericTld(tld) + || isValidCountryCodeTld(tld); + } + + /** + * Returns true if the specified String matches any + * IANA-defined infrastructure top-level domain. Leading dots are + * ignored if present. The search is case-insensitive. + * @param iTld the parameter to check for infrastructure TLD status, not null + * @return true if the parameter is an infrastructure TLD + */ + public boolean isValidInfrastructureTld(String iTld) { + final String key = chompLeadingDot(unicodeToASCII(iTld).toLowerCase(Locale.ENGLISH)); + return arrayContains(INFRASTRUCTURE_TLDS, key); + } + + /** + * Returns true if the specified String matches any + * IANA-defined generic top-level domain. Leading dots are ignored + * if present. The search is case-insensitive. + * @param gTld the parameter to check for generic TLD status, not null + * @return true if the parameter is a generic TLD + */ + public boolean isValidGenericTld(String gTld) { + final String key = chompLeadingDot(unicodeToASCII(gTld).toLowerCase(Locale.ENGLISH)); + return (arrayContains(GENERIC_TLDS, key) || arrayContains(genericTLDsPlus, key)) + && !arrayContains(genericTLDsMinus, key); + } + + /** + * Returns true if the specified String matches any + * IANA-defined country code top-level domain. Leading dots are + * ignored if present. The search is case-insensitive. + * @param ccTld the parameter to check for country code TLD status, not null + * @return true if the parameter is a country code TLD + */ + public boolean isValidCountryCodeTld(String ccTld) { + final String key = chompLeadingDot(unicodeToASCII(ccTld).toLowerCase(Locale.ENGLISH)); + return (arrayContains(COUNTRY_CODE_TLDS, key) || arrayContains(countryCodeTLDsPlus, key)) + && !arrayContains(countryCodeTLDsMinus, key); + } + + /** + * Returns true if the specified String matches any + * widely used "local" domains (localhost or localdomain). Leading dots are + * ignored if present. The search is case-insensitive. + * @param lTld the parameter to check for local TLD status, not null + * @return true if the parameter is an local TLD + */ + public boolean isValidLocalTld(String lTld) { + final String key = chompLeadingDot(unicodeToASCII(lTld).toLowerCase(Locale.ENGLISH)); + return arrayContains(LOCAL_TLDS, key); + } + + private String chompLeadingDot(String str) { + if (str.startsWith(".")) { + return str.substring(1); + } + return str; + } + + // --------------------------------------------- + // ----- TLDs defined by IANA + // ----- Authoritative and comprehensive list at: + // ----- http://data.iana.org/TLD/tlds-alpha-by-domain.txt + + // Note that the above list is in UPPER case. + // The code currently converts strings to lower case (as per the tables below) + + // IANA also provide an HTML list at http://www.iana.org/domains/root/db + // Note that this contains several country code entries which are NOT in + // the text file. These all have the "Not assigned" in the "Sponsoring Organisation" column + // For example (as of 2015-01-02): + // .bl country-code Not assigned + // .um country-code Not assigned + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] INFRASTRUCTURE_TLDS = new String[] { + "arpa", // internet infrastructure + }; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] GENERIC_TLDS = new String[] { + // Taken from Version 2017020400, Last Updated Sat Feb 4 07:07:01 2017 UTC + "aaa", // aaa American Automobile Association, Inc. + "aarp", // aarp AARP + "abarth", // abarth Fiat Chrysler Automobiles N.V. + "abb", // abb ABB Ltd + "abbott", // abbott Abbott Laboratories, Inc. + "abbvie", // abbvie AbbVie Inc. + "abc", // abc Disney Enterprises, Inc. + "able", // able Able Inc. + "abogado", // abogado Top Level Domain Holdings Limited + "abudhabi", // abudhabi Abu Dhabi Systems and Information Centre + "academy", // academy Half Oaks, LLC + "accenture", // accenture Accenture plc + "accountant", // accountant dot Accountant Limited + "accountants", // accountants Knob Town, LLC + "aco", // aco ACO Severin Ahlmann GmbH & Co. KG + "active", // active The Active Network, Inc + "actor", // actor United TLD Holdco Ltd. + "adac", // adac Allgemeiner Deutscher Automobil-Club e.V. (ADAC) + "ads", // ads Charleston Road Registry Inc. + "adult", // adult ICM Registry AD LLC + "aeg", // aeg Aktiebolaget Electrolux + "aero", // aero Societe Internationale de Telecommunications Aeronautique (SITA INC USA) + "aetna", // aetna Aetna Life Insurance Company + "afamilycompany", // afamilycompany Johnson Shareholdings, Inc. + "afl", // afl Australian Football League + "agakhan", // agakhan Fondation Aga Khan (Aga Khan Foundation) + "agency", // agency Steel Falls, LLC + "aig", // aig American International Group, Inc. + "aigo", // aigo aigo Digital Technology Co,Ltd. + "airbus", // airbus Airbus S.A.S. + "airforce", // airforce United TLD Holdco Ltd. + "airtel", // airtel Bharti Airtel Limited + "akdn", // akdn Fondation Aga Khan (Aga Khan Foundation) + "alfaromeo", // alfaromeo Fiat Chrysler Automobiles N.V. + "alibaba", // alibaba Alibaba Group Holding Limited + "alipay", // alipay Alibaba Group Holding Limited + "allfinanz", // allfinanz Allfinanz Deutsche Vermögensberatung Aktiengesellschaft + "allstate", // allstate Allstate Fire and Casualty Insurance Company + "ally", // ally Ally Financial Inc. + "alsace", // alsace REGION D ALSACE + "alstom", // alstom ALSTOM + "americanexpress", // americanexpress American Express Travel Related Services Company, Inc. + "americanfamily", // americanfamily AmFam, Inc. + "amex", // amex American Express Travel Related Services Company, Inc. + "amfam", // amfam AmFam, Inc. + "amica", // amica Amica Mutual Insurance Company + "amsterdam", // amsterdam Gemeente Amsterdam + "analytics", // analytics Campus IP LLC + "android", // android Charleston Road Registry Inc. + "anquan", // anquan QIHOO 360 TECHNOLOGY CO. LTD. + "anz", // anz Australia and New Zealand Banking Group Limited + "aol", // aol AOL Inc. + "apartments", // apartments June Maple, LLC + "app", // app Charleston Road Registry Inc. + "apple", // apple Apple Inc. + "aquarelle", // aquarelle Aquarelle.com + "aramco", // aramco Aramco Services Company + "archi", // archi STARTING DOT LIMITED + "army", // army United TLD Holdco Ltd. + "art", // art UK Creative Ideas Limited + "arte", // arte Association Relative à la Télévision Européenne G.E.I.E. + "asda", // asda Wal-Mart Stores, Inc. + "asia", // asia DotAsia Organisation Ltd. + "associates", // associates Baxter Hill, LLC + "athleta", // athleta The Gap, Inc. + "attorney", // attorney United TLD Holdco, Ltd + "auction", // auction United TLD HoldCo, Ltd. + "audi", // audi AUDI Aktiengesellschaft + "audible", // audible Amazon Registry Services, Inc. + "audio", // audio Uniregistry, Corp. + "auspost", // auspost Australian Postal Corporation + "author", // author Amazon Registry Services, Inc. + "auto", // auto Uniregistry, Corp. + "autos", // autos DERAutos, LLC + "avianca", // avianca Aerovias del Continente Americano S.A. Avianca + "aws", // aws Amazon Registry Services, Inc. + "axa", // axa AXA SA + "azure", // azure Microsoft Corporation + "baby", // baby Johnson & Johnson Services, Inc. + "baidu", // baidu Baidu, Inc. + "banamex", // banamex Citigroup Inc. + "bananarepublic", // bananarepublic The Gap, Inc. + "band", // band United TLD Holdco, Ltd + "bank", // bank fTLD Registry Services, LLC + "bar", // bar Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable + "barcelona", // barcelona Municipi de Barcelona + "barclaycard", // barclaycard Barclays Bank PLC + "barclays", // barclays Barclays Bank PLC + "barefoot", // barefoot Gallo Vineyards, Inc. + "bargains", // bargains Half Hallow, LLC + "baseball", // baseball MLB Advanced Media DH, LLC + "basketball", // basketball Fédération Internationale de Basketball (FIBA) + "bauhaus", // bauhaus Werkhaus GmbH + "bayern", // bayern Bayern Connect GmbH + "bbc", // bbc British Broadcasting Corporation + "bbt", // bbt BB&T Corporation + "bbva", // bbva BANCO BILBAO VIZCAYA ARGENTARIA, S.A. + "bcg", // bcg The Boston Consulting Group, Inc. + "bcn", // bcn Municipi de Barcelona + "beats", // beats Beats Electronics, LLC + "beauty", // beauty L'Oréal + "beer", // beer Top Level Domain Holdings Limited + "bentley", // bentley Bentley Motors Limited + "berlin", // berlin dotBERLIN GmbH & Co. KG + "best", // best BestTLD Pty Ltd + "bestbuy", // bestbuy BBY Solutions, Inc. + "bet", // bet Afilias plc + "bharti", // bharti Bharti Enterprises (Holding) Private Limited + "bible", // bible American Bible Society + "bid", // bid dot Bid Limited + "bike", // bike Grand Hollow, LLC + "bing", // bing Microsoft Corporation + "bingo", // bingo Sand Cedar, LLC + "bio", // bio STARTING DOT LIMITED + "biz", // biz Neustar, Inc. + "black", // black Afilias Limited + "blackfriday", // blackfriday Uniregistry, Corp. + "blanco", // blanco BLANCO GmbH + Co KG + "blockbuster", // blockbuster Dish DBS Corporation + "blog", // blog Knock Knock WHOIS There, LLC + "bloomberg", // bloomberg Bloomberg IP Holdings LLC + "blue", // blue Afilias Limited + "bms", // bms Bristol-Myers Squibb Company + "bmw", // bmw Bayerische Motoren Werke Aktiengesellschaft + "bnl", // bnl Banca Nazionale del Lavoro + "bnpparibas", // bnpparibas BNP Paribas + "boats", // boats DERBoats, LLC + "boehringer", // boehringer Boehringer Ingelheim International GmbH + "bofa", // bofa NMS Services, Inc. + "bom", // bom Núcleo de Informação e Coordenação do Ponto BR - NIC.br + "bond", // bond Bond University Limited + "boo", // boo Charleston Road Registry Inc. + "book", // book Amazon Registry Services, Inc. + "booking", // booking Booking.com B.V. + "boots", // boots THE BOOTS COMPANY PLC + "bosch", // bosch Robert Bosch GMBH + "bostik", // bostik Bostik SA + "boston", // boston Boston TLD Management, LLC + "bot", // bot Amazon Registry Services, Inc. + "boutique", // boutique Over Galley, LLC + "box", // box NS1 Limited + "bradesco", // bradesco Banco Bradesco S.A. + "bridgestone", // bridgestone Bridgestone Corporation + "broadway", // broadway Celebrate Broadway, Inc. + "broker", // broker DOTBROKER REGISTRY LTD + "brother", // brother Brother Industries, Ltd. + "brussels", // brussels DNS.be vzw + "budapest", // budapest Top Level Domain Holdings Limited + "bugatti", // bugatti Bugatti International SA + "build", // build Plan Bee LLC + "builders", // builders Atomic Madison, LLC + "business", // business Spring Cross, LLC + "buy", // buy Amazon Registry Services, INC + "buzz", // buzz DOTSTRATEGY CO. + "bzh", // bzh Association www.bzh + "cab", // cab Half Sunset, LLC + "cafe", // cafe Pioneer Canyon, LLC + "cal", // cal Charleston Road Registry Inc. + "call", // call Amazon Registry Services, Inc. + "calvinklein", // calvinklein PVH gTLD Holdings LLC + "cam", // cam AC Webconnecting Holding B.V. + "camera", // camera Atomic Maple, LLC + "camp", // camp Delta Dynamite, LLC + "cancerresearch", // cancerresearch Australian Cancer Research Foundation + "canon", // canon Canon Inc. + "capetown", // capetown ZA Central Registry NPC trading as ZA Central Registry + "capital", // capital Delta Mill, LLC + "capitalone", // capitalone Capital One Financial Corporation + "car", // car Cars Registry Limited + "caravan", // caravan Caravan International, Inc. + "cards", // cards Foggy Hollow, LLC + "care", // care Goose Cross, LLC + "career", // career dotCareer LLC + "careers", // careers Wild Corner, LLC + "cars", // cars Uniregistry, Corp. + "cartier", // cartier Richemont DNS Inc. + "casa", // casa Top Level Domain Holdings Limited + "case", // case CNH Industrial N.V. + "caseih", // caseih CNH Industrial N.V. + "cash", // cash Delta Lake, LLC + "casino", // casino Binky Sky, LLC + "cat", // cat Fundacio puntCAT + "catering", // catering New Falls. LLC + "catholic", // catholic Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "cba", // cba COMMONWEALTH BANK OF AUSTRALIA + "cbn", // cbn The Christian Broadcasting Network, Inc. + "cbre", // cbre CBRE, Inc. + "cbs", // cbs CBS Domains Inc. + "ceb", // ceb The Corporate Executive Board Company + "center", // center Tin Mill, LLC + "ceo", // ceo CEOTLD Pty Ltd + "cern", // cern European Organization for Nuclear Research ("CERN") + "cfa", // cfa CFA Institute + "cfd", // cfd DOTCFD REGISTRY LTD + "chanel", // chanel Chanel International B.V. + "channel", // channel Charleston Road Registry Inc. + "chase", // chase JPMorgan Chase & Co. + "chat", // chat Sand Fields, LLC + "cheap", // cheap Sand Cover, LLC + "chintai", // chintai CHINTAI Corporation + "chloe", // chloe Richemont DNS Inc. + "christmas", // christmas Uniregistry, Corp. + "chrome", // chrome Charleston Road Registry Inc. + "chrysler", // chrysler FCA US LLC. + "church", // church Holly Fileds, LLC + "cipriani", // cipriani Hotel Cipriani Srl + "circle", // circle Amazon Registry Services, Inc. + "cisco", // cisco Cisco Technology, Inc. + "citadel", // citadel Citadel Domain LLC + "citi", // citi Citigroup Inc. + "citic", // citic CITIC Group Corporation + "city", // city Snow Sky, LLC + "cityeats", // cityeats Lifestyle Domain Holdings, Inc. + "claims", // claims Black Corner, LLC + "cleaning", // cleaning Fox Shadow, LLC + "click", // click Uniregistry, Corp. + "clinic", // clinic Goose Park, LLC + "clinique", // clinique The Estée Lauder Companies Inc. + "clothing", // clothing Steel Lake, LLC + "cloud", // cloud ARUBA S.p.A. + "club", // club .CLUB DOMAINS, LLC + "clubmed", // clubmed Club Méditerranée S.A. + "coach", // coach Koko Island, LLC + "codes", // codes Puff Willow, LLC + "coffee", // coffee Trixy Cover, LLC + "college", // college XYZ.COM LLC + "cologne", // cologne NetCologne Gesellschaft für Telekommunikation mbH + "com", // com VeriSign Global Registry Services + "comcast", // comcast Comcast IP Holdings I, LLC + "commbank", // commbank COMMONWEALTH BANK OF AUSTRALIA + "community", // community Fox Orchard, LLC + "company", // company Silver Avenue, LLC + "compare", // compare iSelect Ltd + "computer", // computer Pine Mill, LLC + "comsec", // comsec VeriSign, Inc. + "condos", // condos Pine House, LLC + "construction", // construction Fox Dynamite, LLC + "consulting", // consulting United TLD Holdco, LTD. + "contact", // contact Top Level Spectrum, Inc. + "contractors", // contractors Magic Woods, LLC + "cooking", // cooking Top Level Domain Holdings Limited + "cookingchannel", // cookingchannel Lifestyle Domain Holdings, Inc. + "cool", // cool Koko Lake, LLC + "coop", // coop DotCooperation LLC + "corsica", // corsica Collectivité Territoriale de Corse + "country", // country Top Level Domain Holdings Limited + "coupon", // coupon Amazon Registry Services, Inc. + "coupons", // coupons Black Island, LLC + "courses", // courses OPEN UNIVERSITIES AUSTRALIA PTY LTD + "credit", // credit Snow Shadow, LLC + "creditcard", // creditcard Binky Frostbite, LLC + "creditunion", // creditunion CUNA Performance Resources, LLC + "cricket", // cricket dot Cricket Limited + "crown", // crown Crown Equipment Corporation + "crs", // crs Federated Co-operatives Limited + "cruise", // cruise Viking River Cruises (Bermuda) Ltd. + "cruises", // cruises Spring Way, LLC + "csc", // csc Alliance-One Services, Inc. + "cuisinella", // cuisinella SALM S.A.S. + "cymru", // cymru Nominet UK + "cyou", // cyou Beijing Gamease Age Digital Technology Co., Ltd. + "dabur", // dabur Dabur India Limited + "dad", // dad Charleston Road Registry Inc. + "dance", // dance United TLD Holdco Ltd. + "data", // data Dish DBS Corporation + "date", // date dot Date Limited + "dating", // dating Pine Fest, LLC + "datsun", // datsun NISSAN MOTOR CO., LTD. + "day", // day Charleston Road Registry Inc. + "dclk", // dclk Charleston Road Registry Inc. + "dds", // dds Minds + Machines Group Limited + "deal", // deal Amazon Registry Services, Inc. + "dealer", // dealer Dealer Dot Com, Inc. + "deals", // deals Sand Sunset, LLC + "degree", // degree United TLD Holdco, Ltd + "delivery", // delivery Steel Station, LLC + "dell", // dell Dell Inc. + "deloitte", // deloitte Deloitte Touche Tohmatsu + "delta", // delta Delta Air Lines, Inc. + "democrat", // democrat United TLD Holdco Ltd. + "dental", // dental Tin Birch, LLC + "dentist", // dentist United TLD Holdco, Ltd + "desi", // desi Desi Networks LLC + "design", // design Top Level Design, LLC + "dev", // dev Charleston Road Registry Inc. + "dhl", // dhl Deutsche Post AG + "diamonds", // diamonds John Edge, LLC + "diet", // diet Uniregistry, Corp. + "digital", // digital Dash Park, LLC + "direct", // direct Half Trail, LLC + "directory", // directory Extra Madison, LLC + "discount", // discount Holly Hill, LLC + "discover", // discover Discover Financial Services + "dish", // dish Dish DBS Corporation + "diy", // diy Lifestyle Domain Holdings, Inc. + "dnp", // dnp Dai Nippon Printing Co., Ltd. + "docs", // docs Charleston Road Registry Inc. + "doctor", // doctor Brice Trail, LLC + "dodge", // dodge FCA US LLC. + "dog", // dog Koko Mill, LLC + "doha", // doha Communications Regulatory Authority (CRA) + "domains", // domains Sugar Cross, LLC +// "doosan", // doosan Doosan Corporation (retired) + "dot", // dot Dish DBS Corporation + "download", // download dot Support Limited + "drive", // drive Charleston Road Registry Inc. + "dtv", // dtv Dish DBS Corporation + "dubai", // dubai Dubai Smart Government Department + "duck", // duck Johnson Shareholdings, Inc. + "dunlop", // dunlop The Goodyear Tire & Rubber Company + "duns", // duns The Dun & Bradstreet Corporation + "dupont", // dupont E. I. du Pont de Nemours and Company + "durban", // durban ZA Central Registry NPC trading as ZA Central Registry + "dvag", // dvag Deutsche Vermögensberatung Aktiengesellschaft DVAG + "dvr", // dvr Hughes Satellite Systems Corporation + "earth", // earth Interlink Co., Ltd. + "eat", // eat Charleston Road Registry Inc. + "eco", // eco Big Room Inc. + "edeka", // edeka EDEKA Verband kaufmännischer Genossenschaften e.V. + "edu", // edu EDUCAUSE + "education", // education Brice Way, LLC + "email", // email Spring Madison, LLC + "emerck", // emerck Merck KGaA + "energy", // energy Binky Birch, LLC + "engineer", // engineer United TLD Holdco Ltd. + "engineering", // engineering Romeo Canyon + "enterprises", // enterprises Snow Oaks, LLC + "epost", // epost Deutsche Post AG + "epson", // epson Seiko Epson Corporation + "equipment", // equipment Corn Station, LLC + "ericsson", // ericsson Telefonaktiebolaget L M Ericsson + "erni", // erni ERNI Group Holding AG + "esq", // esq Charleston Road Registry Inc. + "estate", // estate Trixy Park, LLC + "esurance", // esurance Esurance Insurance Company + "eurovision", // eurovision European Broadcasting Union (EBU) + "eus", // eus Puntueus Fundazioa + "events", // events Pioneer Maple, LLC + "everbank", // everbank EverBank + "exchange", // exchange Spring Falls, LLC + "expert", // expert Magic Pass, LLC + "exposed", // exposed Victor Beach, LLC + "express", // express Sea Sunset, LLC + "extraspace", // extraspace Extra Space Storage LLC + "fage", // fage Fage International S.A. + "fail", // fail Atomic Pipe, LLC + "fairwinds", // fairwinds FairWinds Partners, LLC + "faith", // faith dot Faith Limited + "family", // family United TLD Holdco Ltd. + "fan", // fan Asiamix Digital Ltd + "fans", // fans Asiamix Digital Limited + "farm", // farm Just Maple, LLC + "farmers", // farmers Farmers Insurance Exchange + "fashion", // fashion Top Level Domain Holdings Limited + "fast", // fast Amazon Registry Services, Inc. + "fedex", // fedex Federal Express Corporation + "feedback", // feedback Top Level Spectrum, Inc. + "ferrari", // ferrari Fiat Chrysler Automobiles N.V. + "ferrero", // ferrero Ferrero Trading Lux S.A. + "fiat", // fiat Fiat Chrysler Automobiles N.V. + "fidelity", // fidelity Fidelity Brokerage Services LLC + "fido", // fido Rogers Communications Canada Inc. + "film", // film Motion Picture Domain Registry Pty Ltd + "final", // final Núcleo de Informação e Coordenação do Ponto BR - NIC.br + "finance", // finance Cotton Cypress, LLC + "financial", // financial Just Cover, LLC + "fire", // fire Amazon Registry Services, Inc. + "firestone", // firestone Bridgestone Corporation + "firmdale", // firmdale Firmdale Holdings Limited + "fish", // fish Fox Woods, LLC + "fishing", // fishing Top Level Domain Holdings Limited + "fit", // fit Minds + Machines Group Limited + "fitness", // fitness Brice Orchard, LLC + "flickr", // flickr Yahoo! Domain Services Inc. + "flights", // flights Fox Station, LLC + "flir", // flir FLIR Systems, Inc. + "florist", // florist Half Cypress, LLC + "flowers", // flowers Uniregistry, Corp. +// "flsmidth", // flsmidth FLSmidth A/S retired 2016-07-22 + "fly", // fly Charleston Road Registry Inc. + "foo", // foo Charleston Road Registry Inc. + "food", // food Lifestyle Domain Holdings, Inc. + "foodnetwork", // foodnetwork Lifestyle Domain Holdings, Inc. + "football", // football Foggy Farms, LLC + "ford", // ford Ford Motor Company + "forex", // forex DOTFOREX REGISTRY LTD + "forsale", // forsale United TLD Holdco, LLC + "forum", // forum Fegistry, LLC + "foundation", // foundation John Dale, LLC + "fox", // fox FOX Registry, LLC + "free", // free Amazon Registry Services, Inc. + "fresenius", // fresenius Fresenius Immobilien-Verwaltungs-GmbH + "frl", // frl FRLregistry B.V. + "frogans", // frogans OP3FT + "frontdoor", // frontdoor Lifestyle Domain Holdings, Inc. + "frontier", // frontier Frontier Communications Corporation + "ftr", // ftr Frontier Communications Corporation + "fujitsu", // fujitsu Fujitsu Limited + "fujixerox", // fujixerox Xerox DNHC LLC + "fun", // fun DotSpace, Inc. + "fund", // fund John Castle, LLC + "furniture", // furniture Lone Fields, LLC + "futbol", // futbol United TLD Holdco, Ltd. + "fyi", // fyi Silver Tigers, LLC + "gal", // gal Asociación puntoGAL + "gallery", // gallery Sugar House, LLC + "gallo", // gallo Gallo Vineyards, Inc. + "gallup", // gallup Gallup, Inc. + "game", // game Uniregistry, Corp. + "games", // games United TLD Holdco Ltd. + "gap", // gap The Gap, Inc. + "garden", // garden Top Level Domain Holdings Limited + "gbiz", // gbiz Charleston Road Registry Inc. + "gdn", // gdn Joint Stock Company "Navigation-information systems" + "gea", // gea GEA Group Aktiengesellschaft + "gent", // gent COMBELL GROUP NV/SA + "genting", // genting Resorts World Inc. Pte. Ltd. + "george", // george Wal-Mart Stores, Inc. + "ggee", // ggee GMO Internet, Inc. + "gift", // gift Uniregistry, Corp. + "gifts", // gifts Goose Sky, LLC + "gives", // gives United TLD Holdco Ltd. + "giving", // giving Giving Limited + "glade", // glade Johnson Shareholdings, Inc. + "glass", // glass Black Cover, LLC + "gle", // gle Charleston Road Registry Inc. + "global", // global Dot Global Domain Registry Limited + "globo", // globo Globo Comunicação e Participações S.A + "gmail", // gmail Charleston Road Registry Inc. + "gmbh", // gmbh Extra Dynamite, LLC + "gmo", // gmo GMO Internet, Inc. + "gmx", // gmx 1&1 Mail & Media GmbH + "godaddy", // godaddy Go Daddy East, LLC + "gold", // gold June Edge, LLC + "goldpoint", // goldpoint YODOBASHI CAMERA CO.,LTD. + "golf", // golf Lone Falls, LLC + "goo", // goo NTT Resonant Inc. + "goodhands", // goodhands Allstate Fire and Casualty Insurance Company + "goodyear", // goodyear The Goodyear Tire & Rubber Company + "goog", // goog Charleston Road Registry Inc. + "google", // google Charleston Road Registry Inc. + "gop", // gop Republican State Leadership Committee, Inc. + "got", // got Amazon Registry Services, Inc. + "gov", // gov General Services Administration Attn: QTDC, 2E08 (.gov Domain Registration) + "grainger", // grainger Grainger Registry Services, LLC + "graphics", // graphics Over Madison, LLC + "gratis", // gratis Pioneer Tigers, LLC + "green", // green Afilias Limited + "gripe", // gripe Corn Sunset, LLC + "group", // group Romeo Town, LLC + "guardian", // guardian The Guardian Life Insurance Company of America + "gucci", // gucci Guccio Gucci S.p.a. + "guge", // guge Charleston Road Registry Inc. + "guide", // guide Snow Moon, LLC + "guitars", // guitars Uniregistry, Corp. + "guru", // guru Pioneer Cypress, LLC + "hair", // hair L'Oreal + "hamburg", // hamburg Hamburg Top-Level-Domain GmbH + "hangout", // hangout Charleston Road Registry Inc. + "haus", // haus United TLD Holdco, LTD. + "hbo", // hbo HBO Registry Services, Inc. + "hdfc", // hdfc HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED + "hdfcbank", // hdfcbank HDFC Bank Limited + "health", // health DotHealth, LLC + "healthcare", // healthcare Silver Glen, LLC + "help", // help Uniregistry, Corp. + "helsinki", // helsinki City of Helsinki + "here", // here Charleston Road Registry Inc. + "hermes", // hermes Hermes International + "hgtv", // hgtv Lifestyle Domain Holdings, Inc. + "hiphop", // hiphop Uniregistry, Corp. + "hisamitsu", // hisamitsu Hisamitsu Pharmaceutical Co.,Inc. + "hitachi", // hitachi Hitachi, Ltd. + "hiv", // hiv dotHIV gemeinnuetziger e.V. + "hkt", // hkt PCCW-HKT DataCom Services Limited + "hockey", // hockey Half Willow, LLC + "holdings", // holdings John Madison, LLC + "holiday", // holiday Goose Woods, LLC + "homedepot", // homedepot Homer TLC, Inc. + "homegoods", // homegoods The TJX Companies, Inc. + "homes", // homes DERHomes, LLC + "homesense", // homesense The TJX Companies, Inc. + "honda", // honda Honda Motor Co., Ltd. + "honeywell", // honeywell Honeywell GTLD LLC + "horse", // horse Top Level Domain Holdings Limited + "hospital", // hospital Ruby Pike, LLC + "host", // host DotHost Inc. + "hosting", // hosting Uniregistry, Corp. + "hot", // hot Amazon Registry Services, Inc. + "hoteles", // hoteles Travel Reservations SRL + "hotmail", // hotmail Microsoft Corporation + "house", // house Sugar Park, LLC + "how", // how Charleston Road Registry Inc. + "hsbc", // hsbc HSBC Holdings PLC + "htc", // htc HTC corporation + "hughes", // hughes Hughes Satellite Systems Corporation + "hyatt", // hyatt Hyatt GTLD, L.L.C. + "hyundai", // hyundai Hyundai Motor Company + "ibm", // ibm International Business Machines Corporation + "icbc", // icbc Industrial and Commercial Bank of China Limited + "ice", // ice IntercontinentalExchange, Inc. + "icu", // icu One.com A/S + "ieee", // ieee IEEE Global LLC + "ifm", // ifm ifm electronic gmbh +// "iinet", // iinet Connect West Pty. Ltd. (Retired) + "ikano", // ikano Ikano S.A. + "imamat", // imamat Fondation Aga Khan (Aga Khan Foundation) + "imdb", // imdb Amazon Registry Services, Inc. + "immo", // immo Auburn Bloom, LLC + "immobilien", // immobilien United TLD Holdco Ltd. + "industries", // industries Outer House, LLC + "infiniti", // infiniti NISSAN MOTOR CO., LTD. + "info", // info Afilias Limited + "ing", // ing Charleston Road Registry Inc. + "ink", // ink Top Level Design, LLC + "institute", // institute Outer Maple, LLC + "insurance", // insurance fTLD Registry Services LLC + "insure", // insure Pioneer Willow, LLC + "int", // int Internet Assigned Numbers Authority + "intel", // intel Intel Corporation + "international", // international Wild Way, LLC + "intuit", // intuit Intuit Administrative Services, Inc. + "investments", // investments Holly Glen, LLC + "ipiranga", // ipiranga Ipiranga Produtos de Petroleo S.A. + "irish", // irish Dot-Irish LLC + "iselect", // iselect iSelect Ltd + "ismaili", // ismaili Fondation Aga Khan (Aga Khan Foundation) + "ist", // ist Istanbul Metropolitan Municipality + "istanbul", // istanbul Istanbul Metropolitan Municipality / Medya A.S. + "itau", // itau Itau Unibanco Holding S.A. + "itv", // itv ITV Services Limited + "iveco", // iveco CNH Industrial N.V. + "iwc", // iwc Richemont DNS Inc. + "jaguar", // jaguar Jaguar Land Rover Ltd + "java", // java Oracle Corporation + "jcb", // jcb JCB Co., Ltd. + "jcp", // jcp JCP Media, Inc. + "jeep", // jeep FCA US LLC. + "jetzt", // jetzt New TLD Company AB + "jewelry", // jewelry Wild Bloom, LLC + "jio", // jio Affinity Names, Inc. + "jlc", // jlc Richemont DNS Inc. + "jll", // jll Jones Lang LaSalle Incorporated + "jmp", // jmp Matrix IP LLC + "jnj", // jnj Johnson & Johnson Services, Inc. + "jobs", // jobs Employ Media LLC + "joburg", // joburg ZA Central Registry NPC trading as ZA Central Registry + "jot", // jot Amazon Registry Services, Inc. + "joy", // joy Amazon Registry Services, Inc. + "jpmorgan", // jpmorgan JPMorgan Chase & Co. + "jprs", // jprs Japan Registry Services Co., Ltd. + "juegos", // juegos Uniregistry, Corp. + "juniper", // juniper JUNIPER NETWORKS, INC. + "kaufen", // kaufen United TLD Holdco Ltd. + "kddi", // kddi KDDI CORPORATION + "kerryhotels", // kerryhotels Kerry Trading Co. Limited + "kerrylogistics", // kerrylogistics Kerry Trading Co. Limited + "kerryproperties", // kerryproperties Kerry Trading Co. Limited + "kfh", // kfh Kuwait Finance House + "kia", // kia KIA MOTORS CORPORATION + "kim", // kim Afilias Limited + "kinder", // kinder Ferrero Trading Lux S.A. + "kindle", // kindle Amazon Registry Services, Inc. + "kitchen", // kitchen Just Goodbye, LLC + "kiwi", // kiwi DOT KIWI LIMITED + "koeln", // koeln NetCologne Gesellschaft für Telekommunikation mbH + "komatsu", // komatsu Komatsu Ltd. + "kosher", // kosher Kosher Marketing Assets LLC + "kpmg", // kpmg KPMG International Cooperative (KPMG International Genossenschaft) + "kpn", // kpn Koninklijke KPN N.V. + "krd", // krd KRG Department of Information Technology + "kred", // kred KredTLD Pty Ltd + "kuokgroup", // kuokgroup Kerry Trading Co. Limited + "kyoto", // kyoto Academic Institution: Kyoto Jyoho Gakuen + "lacaixa", // lacaixa CAIXA D'ESTALVIS I PENSIONS DE BARCELONA + "ladbrokes", // ladbrokes LADBROKES INTERNATIONAL PLC + "lamborghini", // lamborghini Automobili Lamborghini S.p.A. + "lamer", // lamer The Estée Lauder Companies Inc. + "lancaster", // lancaster LANCASTER + "lancia", // lancia Fiat Chrysler Automobiles N.V. + "lancome", // lancome L'Oréal + "land", // land Pine Moon, LLC + "landrover", // landrover Jaguar Land Rover Ltd + "lanxess", // lanxess LANXESS Corporation + "lasalle", // lasalle Jones Lang LaSalle Incorporated + "lat", // lat ECOM-LAC Federación de Latinoamérica y el Caribe para Internet y el Comercio Electrónico + "latino", // latino Dish DBS Corporation + "latrobe", // latrobe La Trobe University + "law", // law Minds + Machines Group Limited + "lawyer", // lawyer United TLD Holdco, Ltd + "lds", // lds IRI Domain Management, LLC + "lease", // lease Victor Trail, LLC + "leclerc", // leclerc A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc + "lefrak", // lefrak LeFrak Organization, Inc. + "legal", // legal Blue Falls, LLC + "lego", // lego LEGO Juris A/S + "lexus", // lexus TOYOTA MOTOR CORPORATION + "lgbt", // lgbt Afilias Limited + "liaison", // liaison Liaison Technologies, Incorporated + "lidl", // lidl Schwarz Domains und Services GmbH & Co. KG + "life", // life Trixy Oaks, LLC + "lifeinsurance", // lifeinsurance American Council of Life Insurers + "lifestyle", // lifestyle Lifestyle Domain Holdings, Inc. + "lighting", // lighting John McCook, LLC + "like", // like Amazon Registry Services, Inc. + "lilly", // lilly Eli Lilly and Company + "limited", // limited Big Fest, LLC + "limo", // limo Hidden Frostbite, LLC + "lincoln", // lincoln Ford Motor Company + "linde", // linde Linde Aktiengesellschaft + "link", // link Uniregistry, Corp. + "lipsy", // lipsy Lipsy Ltd + "live", // live United TLD Holdco Ltd. + "living", // living Lifestyle Domain Holdings, Inc. + "lixil", // lixil LIXIL Group Corporation + "loan", // loan dot Loan Limited + "loans", // loans June Woods, LLC + "locker", // locker Dish DBS Corporation + "locus", // locus Locus Analytics LLC + "loft", // loft Annco, Inc. + "lol", // lol Uniregistry, Corp. + "london", // london Dot London Domains Limited + "lotte", // lotte Lotte Holdings Co., Ltd. + "lotto", // lotto Afilias Limited + "love", // love Merchant Law Group LLP + "lpl", // lpl LPL Holdings, Inc. + "lplfinancial", // lplfinancial LPL Holdings, Inc. + "ltd", // ltd Over Corner, LLC + "ltda", // ltda InterNetX Corp. + "lundbeck", // lundbeck H. Lundbeck A/S + "lupin", // lupin LUPIN LIMITED + "luxe", // luxe Top Level Domain Holdings Limited + "luxury", // luxury Luxury Partners LLC + "macys", // macys Macys, Inc. + "madrid", // madrid Comunidad de Madrid + "maif", // maif Mutuelle Assurance Instituteur France (MAIF) + "maison", // maison Victor Frostbite, LLC + "makeup", // makeup L'Oréal + "man", // man MAN SE + "management", // management John Goodbye, LLC + "mango", // mango PUNTO FA S.L. + "market", // market Unitied TLD Holdco, Ltd + "marketing", // marketing Fern Pass, LLC + "markets", // markets DOTMARKETS REGISTRY LTD + "marriott", // marriott Marriott Worldwide Corporation + "marshalls", // marshalls The TJX Companies, Inc. + "maserati", // maserati Fiat Chrysler Automobiles N.V. + "mattel", // mattel Mattel Sites, Inc. + "mba", // mba Lone Hollow, LLC + "mcd", // mcd McDonald’s Corporation + "mcdonalds", // mcdonalds McDonald’s Corporation + "mckinsey", // mckinsey McKinsey Holdings, Inc. + "med", // med Medistry LLC + "media", // media Grand Glen, LLC + "meet", // meet Afilias Limited + "melbourne", // melbourne The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation + "meme", // meme Charleston Road Registry Inc. + "memorial", // memorial Dog Beach, LLC + "men", // men Exclusive Registry Limited + "menu", // menu Wedding TLD2, LLC + "meo", // meo PT Comunicacoes S.A. + "metlife", // metlife MetLife Services and Solutions, LLC + "miami", // miami Top Level Domain Holdings Limited + "microsoft", // microsoft Microsoft Corporation + "mil", // mil DoD Network Information Center + "mini", // mini Bayerische Motoren Werke Aktiengesellschaft + "mint", // mint Intuit Administrative Services, Inc. + "mit", // mit Massachusetts Institute of Technology + "mitsubishi", // mitsubishi Mitsubishi Corporation + "mlb", // mlb MLB Advanced Media DH, LLC + "mls", // mls The Canadian Real Estate Association + "mma", // mma MMA IARD + "mobi", // mobi Afilias Technologies Limited dba dotMobi + "mobile", // mobile Dish DBS Corporation + "mobily", // mobily GreenTech Consultancy Company W.L.L. + "moda", // moda United TLD Holdco Ltd. + "moe", // moe Interlink Co., Ltd. + "moi", // moi Amazon Registry Services, Inc. + "mom", // mom Uniregistry, Corp. + "monash", // monash Monash University + "money", // money Outer McCook, LLC + "monster", // monster Monster Worldwide, Inc. + "montblanc", // montblanc Richemont DNS Inc. + "mopar", // mopar FCA US LLC. + "mormon", // mormon IRI Domain Management, LLC ("Applicant") + "mortgage", // mortgage United TLD Holdco, Ltd + "moscow", // moscow Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) + "moto", // moto Motorola Trademark Holdings, LLC + "motorcycles", // motorcycles DERMotorcycles, LLC + "mov", // mov Charleston Road Registry Inc. + "movie", // movie New Frostbite, LLC + "movistar", // movistar Telefónica S.A. + "msd", // msd MSD Registry Holdings, Inc. + "mtn", // mtn MTN Dubai Limited + "mtpc", // mtpc Mitsubishi Tanabe Pharma Corporation + "mtr", // mtr MTR Corporation Limited + "museum", // museum Museum Domain Management Association + "mutual", // mutual Northwestern Mutual MU TLD Registry, LLC +// "mutuelle", // mutuelle Fédération Nationale de la Mutualité Française (Retired) + "nab", // nab National Australia Bank Limited + "nadex", // nadex Nadex Domains, Inc + "nagoya", // nagoya GMO Registry, Inc. + "name", // name VeriSign Information Services, Inc. + "nationwide", // nationwide Nationwide Mutual Insurance Company + "natura", // natura NATURA COSMÉTICOS S.A. + "navy", // navy United TLD Holdco Ltd. + "nba", // nba NBA REGISTRY, LLC + "nec", // nec NEC Corporation + "net", // net VeriSign Global Registry Services + "netbank", // netbank COMMONWEALTH BANK OF AUSTRALIA + "netflix", // netflix Netflix, Inc. + "network", // network Trixy Manor, LLC + "neustar", // neustar NeuStar, Inc. + "new", // new Charleston Road Registry Inc. + "newholland", // newholland CNH Industrial N.V. + "news", // news United TLD Holdco Ltd. + "next", // next Next plc + "nextdirect", // nextdirect Next plc + "nexus", // nexus Charleston Road Registry Inc. + "nfl", // nfl NFL Reg Ops LLC + "ngo", // ngo Public Interest Registry + "nhk", // nhk Japan Broadcasting Corporation (NHK) + "nico", // nico DWANGO Co., Ltd. + "nike", // nike NIKE, Inc. + "nikon", // nikon NIKON CORPORATION + "ninja", // ninja United TLD Holdco Ltd. + "nissan", // nissan NISSAN MOTOR CO., LTD. + "nissay", // nissay Nippon Life Insurance Company + "nokia", // nokia Nokia Corporation + "northwesternmutual", // northwesternmutual Northwestern Mutual Registry, LLC + "norton", // norton Symantec Corporation + "now", // now Amazon Registry Services, Inc. + "nowruz", // nowruz Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "nowtv", // nowtv Starbucks (HK) Limited + "nra", // nra NRA Holdings Company, INC. + "nrw", // nrw Minds + Machines GmbH + "ntt", // ntt NIPPON TELEGRAPH AND TELEPHONE CORPORATION + "nyc", // nyc The City of New York by and through the New York City Department of Information Technology & Telecommunications + "obi", // obi OBI Group Holding SE & Co. KGaA + "observer", // observer Top Level Spectrum, Inc. + "off", // off Johnson Shareholdings, Inc. + "office", // office Microsoft Corporation + "okinawa", // okinawa BusinessRalliart inc. + "olayan", // olayan Crescent Holding GmbH + "olayangroup", // olayangroup Crescent Holding GmbH + "oldnavy", // oldnavy The Gap, Inc. + "ollo", // ollo Dish DBS Corporation + "omega", // omega The Swatch Group Ltd + "one", // one One.com A/S + "ong", // ong Public Interest Registry + "onl", // onl I-REGISTRY Ltd., Niederlassung Deutschland + "online", // online DotOnline Inc. + "onyourside", // onyourside Nationwide Mutual Insurance Company + "ooo", // ooo INFIBEAM INCORPORATION LIMITED + "open", // open American Express Travel Related Services Company, Inc. + "oracle", // oracle Oracle Corporation + "orange", // orange Orange Brand Services Limited + "org", // org Public Interest Registry (PIR) + "organic", // organic Afilias Limited + "orientexpress", // orientexpress Orient Express + "origins", // origins The Estée Lauder Companies Inc. + "osaka", // osaka Interlink Co., Ltd. + "otsuka", // otsuka Otsuka Holdings Co., Ltd. + "ott", // ott Dish DBS Corporation + "ovh", // ovh OVH SAS + "page", // page Charleston Road Registry Inc. + "pamperedchef", // pamperedchef The Pampered Chef, Ltd. + "panasonic", // panasonic Panasonic Corporation + "panerai", // panerai Richemont DNS Inc. + "paris", // paris City of Paris + "pars", // pars Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "partners", // partners Magic Glen, LLC + "parts", // parts Sea Goodbye, LLC + "party", // party Blue Sky Registry Limited + "passagens", // passagens Travel Reservations SRL + "pay", // pay Amazon Registry Services, Inc. + "pccw", // pccw PCCW Enterprises Limited + "pet", // pet Afilias plc + "pfizer", // pfizer Pfizer Inc. + "pharmacy", // pharmacy National Association of Boards of Pharmacy + "philips", // philips Koninklijke Philips N.V. + "phone", // phone Dish DBS Corporation + "photo", // photo Uniregistry, Corp. + "photography", // photography Sugar Glen, LLC + "photos", // photos Sea Corner, LLC + "physio", // physio PhysBiz Pty Ltd + "piaget", // piaget Richemont DNS Inc. + "pics", // pics Uniregistry, Corp. + "pictet", // pictet Pictet Europe S.A. + "pictures", // pictures Foggy Sky, LLC + "pid", // pid Top Level Spectrum, Inc. + "pin", // pin Amazon Registry Services, Inc. + "ping", // ping Ping Registry Provider, Inc. + "pink", // pink Afilias Limited + "pioneer", // pioneer Pioneer Corporation + "pizza", // pizza Foggy Moon, LLC + "place", // place Snow Galley, LLC + "play", // play Charleston Road Registry Inc. + "playstation", // playstation Sony Computer Entertainment Inc. + "plumbing", // plumbing Spring Tigers, LLC + "plus", // plus Sugar Mill, LLC + "pnc", // pnc PNC Domain Co., LLC + "pohl", // pohl Deutsche Vermögensberatung Aktiengesellschaft DVAG + "poker", // poker Afilias Domains No. 5 Limited + "politie", // politie Politie Nederland + "porn", // porn ICM Registry PN LLC + "post", // post Universal Postal Union + "pramerica", // pramerica Prudential Financial, Inc. + "praxi", // praxi Praxi S.p.A. + "press", // press DotPress Inc. + "prime", // prime Amazon Registry Services, Inc. + "pro", // pro Registry Services Corporation dba RegistryPro + "prod", // prod Charleston Road Registry Inc. + "productions", // productions Magic Birch, LLC + "prof", // prof Charleston Road Registry Inc. + "progressive", // progressive Progressive Casualty Insurance Company + "promo", // promo Afilias plc + "properties", // properties Big Pass, LLC + "property", // property Uniregistry, Corp. + "protection", // protection XYZ.COM LLC + "pru", // pru Prudential Financial, Inc. + "prudential", // prudential Prudential Financial, Inc. + "pub", // pub United TLD Holdco Ltd. + "pwc", // pwc PricewaterhouseCoopers LLP + "qpon", // qpon dotCOOL, Inc. + "quebec", // quebec PointQuébec Inc + "quest", // quest Quest ION Limited + "qvc", // qvc QVC, Inc. + "racing", // racing Premier Registry Limited + "radio", // radio European Broadcasting Union (EBU) + "raid", // raid Johnson Shareholdings, Inc. + "read", // read Amazon Registry Services, Inc. + "realestate", // realestate dotRealEstate LLC + "realtor", // realtor Real Estate Domains LLC + "realty", // realty Fegistry, LLC + "recipes", // recipes Grand Island, LLC + "red", // red Afilias Limited + "redstone", // redstone Redstone Haute Couture Co., Ltd. + "redumbrella", // redumbrella Travelers TLD, LLC + "rehab", // rehab United TLD Holdco Ltd. + "reise", // reise Foggy Way, LLC + "reisen", // reisen New Cypress, LLC + "reit", // reit National Association of Real Estate Investment Trusts, Inc. + "reliance", // reliance Reliance Industries Limited + "ren", // ren Beijing Qianxiang Wangjing Technology Development Co., Ltd. + "rent", // rent XYZ.COM LLC + "rentals", // rentals Big Hollow,LLC + "repair", // repair Lone Sunset, LLC + "report", // report Binky Glen, LLC + "republican", // republican United TLD Holdco Ltd. + "rest", // rest Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable + "restaurant", // restaurant Snow Avenue, LLC + "review", // review dot Review Limited + "reviews", // reviews United TLD Holdco, Ltd. + "rexroth", // rexroth Robert Bosch GMBH + "rich", // rich I-REGISTRY Ltd., Niederlassung Deutschland + "richardli", // richardli Pacific Century Asset Management (HK) Limited + "ricoh", // ricoh Ricoh Company, Ltd. + "rightathome", // rightathome Johnson Shareholdings, Inc. + "ril", // ril Reliance Industries Limited + "rio", // rio Empresa Municipal de Informática SA - IPLANRIO + "rip", // rip United TLD Holdco Ltd. + "rmit", // rmit Royal Melbourne Institute of Technology + "rocher", // rocher Ferrero Trading Lux S.A. + "rocks", // rocks United TLD Holdco, LTD. + "rodeo", // rodeo Top Level Domain Holdings Limited + "rogers", // rogers Rogers Communications Canada Inc. + "room", // room Amazon Registry Services, Inc. + "rsvp", // rsvp Charleston Road Registry Inc. + "ruhr", // ruhr regiodot GmbH & Co. KG + "run", // run Snow Park, LLC + "rwe", // rwe RWE AG + "ryukyu", // ryukyu BusinessRalliart inc. + "saarland", // saarland dotSaarland GmbH + "safe", // safe Amazon Registry Services, Inc. + "safety", // safety Safety Registry Services, LLC. + "sakura", // sakura SAKURA Internet Inc. + "sale", // sale United TLD Holdco, Ltd + "salon", // salon Outer Orchard, LLC + "samsclub", // samsclub Wal-Mart Stores, Inc. + "samsung", // samsung SAMSUNG SDS CO., LTD + "sandvik", // sandvik Sandvik AB + "sandvikcoromant", // sandvikcoromant Sandvik AB + "sanofi", // sanofi Sanofi + "sap", // sap SAP AG + "sapo", // sapo PT Comunicacoes S.A. + "sarl", // sarl Delta Orchard, LLC + "sas", // sas Research IP LLC + "save", // save Amazon Registry Services, Inc. + "saxo", // saxo Saxo Bank A/S + "sbi", // sbi STATE BANK OF INDIA + "sbs", // sbs SPECIAL BROADCASTING SERVICE CORPORATION + "sca", // sca SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) + "scb", // scb The Siam Commercial Bank Public Company Limited ("SCB") + "schaeffler", // schaeffler Schaeffler Technologies AG & Co. KG + "schmidt", // schmidt SALM S.A.S. + "scholarships", // scholarships Scholarships.com, LLC + "school", // school Little Galley, LLC + "schule", // schule Outer Moon, LLC + "schwarz", // schwarz Schwarz Domains und Services GmbH & Co. KG + "science", // science dot Science Limited + "scjohnson", // scjohnson Johnson Shareholdings, Inc. + "scor", // scor SCOR SE + "scot", // scot Dot Scot Registry Limited + "seat", // seat SEAT, S.A. (Sociedad Unipersonal) + "secure", // secure Amazon Registry Services, Inc. + "security", // security XYZ.COM LLC + "seek", // seek Seek Limited + "select", // select iSelect Ltd + "sener", // sener Sener Ingeniería y Sistemas, S.A. + "services", // services Fox Castle, LLC + "ses", // ses SES + "seven", // seven Seven West Media Ltd + "sew", // sew SEW-EURODRIVE GmbH & Co KG + "sex", // sex ICM Registry SX LLC + "sexy", // sexy Uniregistry, Corp. + "sfr", // sfr Societe Francaise du Radiotelephone - SFR + "shangrila", // shangrila Shangri‐La International Hotel Management Limited + "sharp", // sharp Sharp Corporation + "shaw", // shaw Shaw Cablesystems G.P. + "shell", // shell Shell Information Technology International Inc + "shia", // shia Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "shiksha", // shiksha Afilias Limited + "shoes", // shoes Binky Galley, LLC + "shop", // shop GMO Registry, Inc. + "shopping", // shopping Over Keep, LLC + "shouji", // shouji QIHOO 360 TECHNOLOGY CO. LTD. + "show", // show Snow Beach, LLC + "showtime", // showtime CBS Domains Inc. + "shriram", // shriram Shriram Capital Ltd. + "silk", // silk Amazon Registry Services, Inc. + "sina", // sina Sina Corporation + "singles", // singles Fern Madison, LLC + "site", // site DotSite Inc. + "ski", // ski STARTING DOT LIMITED + "skin", // skin L'Oréal + "sky", // sky Sky International AG + "skype", // skype Microsoft Corporation + "sling", // sling Hughes Satellite Systems Corporation + "smart", // smart Smart Communications, Inc. (SMART) + "smile", // smile Amazon Registry Services, Inc. + "sncf", // sncf SNCF (Société Nationale des Chemins de fer Francais) + "soccer", // soccer Foggy Shadow, LLC + "social", // social United TLD Holdco Ltd. + "softbank", // softbank SoftBank Group Corp. + "software", // software United TLD Holdco, Ltd + "sohu", // sohu Sohu.com Limited + "solar", // solar Ruby Town, LLC + "solutions", // solutions Silver Cover, LLC + "song", // song Amazon Registry Services, Inc. + "sony", // sony Sony Corporation + "soy", // soy Charleston Road Registry Inc. + "space", // space DotSpace Inc. + "spiegel", // spiegel SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG + "spot", // spot Amazon Registry Services, Inc. + "spreadbetting", // spreadbetting DOTSPREADBETTING REGISTRY LTD + "srl", // srl InterNetX Corp. + "srt", // srt FCA US LLC. + "stada", // stada STADA Arzneimittel AG + "staples", // staples Staples, Inc. + "star", // star Star India Private Limited + "starhub", // starhub StarHub Limited + "statebank", // statebank STATE BANK OF INDIA + "statefarm", // statefarm State Farm Mutual Automobile Insurance Company + "statoil", // statoil Statoil ASA + "stc", // stc Saudi Telecom Company + "stcgroup", // stcgroup Saudi Telecom Company + "stockholm", // stockholm Stockholms kommun + "storage", // storage Self Storage Company LLC + "store", // store DotStore Inc. + "stream", // stream dot Stream Limited + "studio", // studio United TLD Holdco Ltd. + "study", // study OPEN UNIVERSITIES AUSTRALIA PTY LTD + "style", // style Binky Moon, LLC + "sucks", // sucks Vox Populi Registry Ltd. + "supplies", // supplies Atomic Fields, LLC + "supply", // supply Half Falls, LLC + "support", // support Grand Orchard, LLC + "surf", // surf Top Level Domain Holdings Limited + "surgery", // surgery Tin Avenue, LLC + "suzuki", // suzuki SUZUKI MOTOR CORPORATION + "swatch", // swatch The Swatch Group Ltd + "swiftcover", // swiftcover Swiftcover Insurance Services Limited + "swiss", // swiss Swiss Confederation + "sydney", // sydney State of New South Wales, Department of Premier and Cabinet + "symantec", // symantec Symantec Corporation + "systems", // systems Dash Cypress, LLC + "tab", // tab Tabcorp Holdings Limited + "taipei", // taipei Taipei City Government + "talk", // talk Amazon Registry Services, Inc. + "taobao", // taobao Alibaba Group Holding Limited + "target", // target Target Domain Holdings, LLC + "tatamotors", // tatamotors Tata Motors Ltd + "tatar", // tatar Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" + "tattoo", // tattoo Uniregistry, Corp. + "tax", // tax Storm Orchard, LLC + "taxi", // taxi Pine Falls, LLC + "tci", // tci Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "tdk", // tdk TDK Corporation + "team", // team Atomic Lake, LLC + "tech", // tech Dot Tech LLC + "technology", // technology Auburn Falls, LLC + "tel", // tel Telnic Ltd. + "telecity", // telecity TelecityGroup International Limited + "telefonica", // telefonica Telefónica S.A. + "temasek", // temasek Temasek Holdings (Private) Limited + "tennis", // tennis Cotton Bloom, LLC + "teva", // teva Teva Pharmaceutical Industries Limited + "thd", // thd Homer TLC, Inc. + "theater", // theater Blue Tigers, LLC + "theatre", // theatre XYZ.COM LLC + "tiaa", // tiaa Teachers Insurance and Annuity Association of America + "tickets", // tickets Accent Media Limited + "tienda", // tienda Victor Manor, LLC + "tiffany", // tiffany Tiffany and Company + "tips", // tips Corn Willow, LLC + "tires", // tires Dog Edge, LLC + "tirol", // tirol punkt Tirol GmbH + "tjmaxx", // tjmaxx The TJX Companies, Inc. + "tjx", // tjx The TJX Companies, Inc. + "tkmaxx", // tkmaxx The TJX Companies, Inc. + "tmall", // tmall Alibaba Group Holding Limited + "today", // today Pearl Woods, LLC + "tokyo", // tokyo GMO Registry, Inc. + "tools", // tools Pioneer North, LLC + "top", // top Jiangsu Bangning Science & Technology Co.,Ltd. + "toray", // toray Toray Industries, Inc. + "toshiba", // toshiba TOSHIBA Corporation + "total", // total Total SA + "tours", // tours Sugar Station, LLC + "town", // town Koko Moon, LLC + "toyota", // toyota TOYOTA MOTOR CORPORATION + "toys", // toys Pioneer Orchard, LLC + "trade", // trade Elite Registry Limited + "trading", // trading DOTTRADING REGISTRY LTD + "training", // training Wild Willow, LLC + "travel", // travel Tralliance Registry Management Company, LLC. + "travelchannel", // travelchannel Lifestyle Domain Holdings, Inc. + "travelers", // travelers Travelers TLD, LLC + "travelersinsurance", // travelersinsurance Travelers TLD, LLC + "trust", // trust Artemis Internet Inc + "trv", // trv Travelers TLD, LLC + "tube", // tube Latin American Telecom LLC + "tui", // tui TUI AG + "tunes", // tunes Amazon Registry Services, Inc. + "tushu", // tushu Amazon Registry Services, Inc. + "tvs", // tvs T V SUNDRAM IYENGAR & SONS PRIVATE LIMITED + "ubank", // ubank National Australia Bank Limited + "ubs", // ubs UBS AG + "uconnect", // uconnect FCA US LLC. + "unicom", // unicom China United Network Communications Corporation Limited + "university", // university Little Station, LLC + "uno", // uno Dot Latin LLC + "uol", // uol UBN INTERNET LTDA. + "ups", // ups UPS Market Driver, Inc. + "vacations", // vacations Atomic Tigers, LLC + "vana", // vana Lifestyle Domain Holdings, Inc. + "vanguard", // vanguard The Vanguard Group, Inc. + "vegas", // vegas Dot Vegas, Inc. + "ventures", // ventures Binky Lake, LLC + "verisign", // verisign VeriSign, Inc. + "versicherung", // versicherung dotversicherung-registry GmbH + "vet", // vet United TLD Holdco, Ltd + "viajes", // viajes Black Madison, LLC + "video", // video United TLD Holdco, Ltd + "vig", // vig VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe + "viking", // viking Viking River Cruises (Bermuda) Ltd. + "villas", // villas New Sky, LLC + "vin", // vin Holly Shadow, LLC + "vip", // vip Minds + Machines Group Limited + "virgin", // virgin Virgin Enterprises Limited + "visa", // visa Visa Worldwide Pte. Limited + "vision", // vision Koko Station, LLC + "vista", // vista Vistaprint Limited + "vistaprint", // vistaprint Vistaprint Limited + "viva", // viva Saudi Telecom Company + "vivo", // vivo Telefonica Brasil S.A. + "vlaanderen", // vlaanderen DNS.be vzw + "vodka", // vodka Top Level Domain Holdings Limited + "volkswagen", // volkswagen Volkswagen Group of America Inc. + "volvo", // volvo Volvo Holding Sverige Aktiebolag + "vote", // vote Monolith Registry LLC + "voting", // voting Valuetainment Corp. + "voto", // voto Monolith Registry LLC + "voyage", // voyage Ruby House, LLC + "vuelos", // vuelos Travel Reservations SRL + "wales", // wales Nominet UK + "walmart", // walmart Wal-Mart Stores, Inc. + "walter", // walter Sandvik AB + "wang", // wang Zodiac Registry Limited + "wanggou", // wanggou Amazon Registry Services, Inc. + "warman", // warman Weir Group IP Limited + "watch", // watch Sand Shadow, LLC + "watches", // watches Richemont DNS Inc. + "weather", // weather The Weather Channel, LLC + "weatherchannel", // weatherchannel The Weather Channel, LLC + "webcam", // webcam dot Webcam Limited + "weber", // weber Saint-Gobain Weber SA + "website", // website DotWebsite Inc. + "wed", // wed Atgron, Inc. + "wedding", // wedding Top Level Domain Holdings Limited + "weibo", // weibo Sina Corporation + "weir", // weir Weir Group IP Limited + "whoswho", // whoswho Who's Who Registry + "wien", // wien punkt.wien GmbH + "wiki", // wiki Top Level Design, LLC + "williamhill", // williamhill William Hill Organization Limited + "win", // win First Registry Limited + "windows", // windows Microsoft Corporation + "wine", // wine June Station, LLC + "winners", // winners The TJX Companies, Inc. + "wme", // wme William Morris Endeavor Entertainment, LLC + "wolterskluwer", // wolterskluwer Wolters Kluwer N.V. + "woodside", // woodside Woodside Petroleum Limited + "work", // work Top Level Domain Holdings Limited + "works", // works Little Dynamite, LLC + "world", // world Bitter Fields, LLC + "wow", // wow Amazon Registry Services, Inc. + "wtc", // wtc World Trade Centers Association, Inc. + "wtf", // wtf Hidden Way, LLC + "xbox", // xbox Microsoft Corporation + "xerox", // xerox Xerox DNHC LLC + "xfinity", // xfinity Comcast IP Holdings I, LLC + "xihuan", // xihuan QIHOO 360 TECHNOLOGY CO. LTD. + "xin", // xin Elegant Leader Limited + "xn--11b4c3d", // कॉम VeriSign Sarl + "xn--1ck2e1b", // セール Amazon Registry Services, Inc. + "xn--1qqw23a", // 佛山 Guangzhou YU Wei Information Technology Co., Ltd. + "xn--30rr7y", // 慈善 Excellent First Limited + "xn--3bst00m", // 集团 Eagle Horizon Limited + "xn--3ds443g", // 在线 TLD REGISTRY LIMITED + "xn--3oq18vl8pn36a", // 大众汽车 Volkswagen (China) Investment Co., Ltd. + "xn--3pxu8k", // 点看 VeriSign Sarl + "xn--42c2d9a", // คอม VeriSign Sarl + "xn--45q11c", // 八卦 Zodiac Scorpio Limited + "xn--4gbrim", // موقع Suhub Electronic Establishment + "xn--55qw42g", // 公益 China Organizational Name Administration Center + "xn--55qx5d", // 公司 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) + "xn--5su34j936bgsg", // 香格里拉 Shangri‐La International Hotel Management Limited + "xn--5tzm5g", // 网站 Global Website TLD Asia Limited + "xn--6frz82g", // 移动 Afilias Limited + "xn--6qq986b3xl", // 我爱你 Tycoon Treasure Limited + "xn--80adxhks", // москва Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) + "xn--80aqecdr1a", // католик Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "xn--80asehdb", // онлайн CORE Association + "xn--80aswg", // сайт CORE Association + "xn--8y0a063a", // 联通 China United Network Communications Corporation Limited + "xn--90ae", // бг Imena.BG Plc (NAMES.BG Plc) + "xn--9dbq2a", // קום VeriSign Sarl + "xn--9et52u", // 时尚 RISE VICTORY LIMITED + "xn--9krt00a", // 微博 Sina Corporation + "xn--b4w605ferd", // 淡马锡 Temasek Holdings (Private) Limited + "xn--bck1b9a5dre4c", // ファッション Amazon Registry Services, Inc. + "xn--c1avg", // орг Public Interest Registry + "xn--c2br7g", // नेट VeriSign Sarl + "xn--cck2b3b", // ストア Amazon Registry Services, Inc. + "xn--cg4bki", // 삼성 SAMSUNG SDS CO., LTD + "xn--czr694b", // 商标 HU YI GLOBAL INFORMATION RESOURCES(HOLDING) COMPANY.HONGKONG LIMITED + "xn--czrs0t", // 商店 Wild Island, LLC + "xn--czru2d", // 商城 Zodiac Aquarius Limited + "xn--d1acj3b", // дети The Foundation for Network Initiatives “The Smart Internet” + "xn--eckvdtc9d", // ポイント Amazon Registry Services, Inc. + "xn--efvy88h", // 新闻 Xinhua News Agency Guangdong Branch 新华通讯社广东分社 + "xn--estv75g", // 工行 Industrial and Commercial Bank of China Limited + "xn--fct429k", // 家電 Amazon Registry Services, Inc. + "xn--fhbei", // كوم VeriSign Sarl + "xn--fiq228c5hs", // 中文网 TLD REGISTRY LIMITED + "xn--fiq64b", // 中信 CITIC Group Corporation + "xn--fjq720a", // 娱乐 Will Bloom, LLC + "xn--flw351e", // 谷歌 Charleston Road Registry Inc. + "xn--fzys8d69uvgm", // 電訊盈科 PCCW Enterprises Limited + "xn--g2xx48c", // 购物 Minds + Machines Group Limited + "xn--gckr3f0f", // クラウド Amazon Registry Services, Inc. + "xn--gk3at1e", // 通販 Amazon Registry Services, Inc. + "xn--hxt814e", // 网店 Zodiac Libra Limited + "xn--i1b6b1a6a2e", // संगठन Public Interest Registry + "xn--imr513n", // 餐厅 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED + "xn--io0a7i", // 网络 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) + "xn--j1aef", // ком VeriSign Sarl + "xn--jlq61u9w7b", // 诺基亚 Nokia Corporation + "xn--jvr189m", // 食品 Amazon Registry Services, Inc. + "xn--kcrx77d1x4a", // 飞利浦 Koninklijke Philips N.V. + "xn--kpu716f", // 手表 Richemont DNS Inc. + "xn--kput3i", // 手机 Beijing RITT-Net Technology Development Co., Ltd + "xn--mgba3a3ejt", // ارامكو Aramco Services Company + "xn--mgba7c0bbn0a", // العليان Crescent Holding GmbH + "xn--mgbab2bd", // بازار CORE Association + "xn--mgbb9fbpob", // موبايلي GreenTech Consultancy Company W.L.L. + "xn--mgbca7dzdo", // ابوظبي Abu Dhabi Systems and Information Centre + "xn--mgbi4ecexp", // كاثوليك Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "xn--mgbt3dhd", // همراه Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "xn--mk1bu44c", // 닷컴 VeriSign Sarl + "xn--mxtq1m", // 政府 Net-Chinese Co., Ltd. + "xn--ngbc5azd", // شبكة International Domain Registry Pty. Ltd. + "xn--ngbe9e0a", // بيتك Kuwait Finance House + "xn--nqv7f", // 机构 Public Interest Registry + "xn--nqv7fs00ema", // 组织机构 Public Interest Registry + "xn--nyqy26a", // 健康 Stable Tone Limited + "xn--p1acf", // рус Rusnames Limited + "xn--pbt977c", // 珠宝 Richemont DNS Inc. + "xn--pssy2u", // 大拿 VeriSign Sarl + "xn--q9jyb4c", // みんな Charleston Road Registry Inc. + "xn--qcka1pmc", // グーグル Charleston Road Registry Inc. + "xn--rhqv96g", // 世界 Stable Tone Limited + "xn--rovu88b", // 書籍 Amazon EU S.à r.l. + "xn--ses554g", // 网址 KNET Co., Ltd + "xn--t60b56a", // 닷넷 VeriSign Sarl + "xn--tckwe", // コム VeriSign Sarl + "xn--tiq49xqyj", // 天主教 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "xn--unup4y", // 游戏 Spring Fields, LLC + "xn--vermgensberater-ctb", // VERMöGENSBERATER Deutsche Vermögensberatung Aktiengesellschaft DVAG + "xn--vermgensberatung-pwb", // VERMöGENSBERATUNG Deutsche Vermögensberatung Aktiengesellschaft DVAG + "xn--vhquv", // 企业 Dash McCook, LLC + "xn--vuq861b", // 信息 Beijing Tele-info Network Technology Co., Ltd. + "xn--w4r85el8fhu5dnra", // 嘉里大酒店 Kerry Trading Co. Limited + "xn--w4rs40l", // 嘉里 Kerry Trading Co. Limited + "xn--xhq521b", // 广东 Guangzhou YU Wei Information Technology Co., Ltd. + "xn--zfr164b", // 政务 China Organizational Name Administration Center + "xperia", // xperia Sony Mobile Communications AB + "xxx", // xxx ICM Registry LLC + "xyz", // xyz XYZ.COM LLC + "yachts", // yachts DERYachts, LLC + "yahoo", // yahoo Yahoo! Domain Services Inc. + "yamaxun", // yamaxun Amazon Registry Services, Inc. + "yandex", // yandex YANDEX, LLC + "yodobashi", // yodobashi YODOBASHI CAMERA CO.,LTD. + "yoga", // yoga Top Level Domain Holdings Limited + "yokohama", // yokohama GMO Registry, Inc. + "you", // you Amazon Registry Services, Inc. + "youtube", // youtube Charleston Road Registry Inc. + "yun", // yun QIHOO 360 TECHNOLOGY CO. LTD. + "zappos", // zappos Amazon Registry Services, Inc. + "zara", // zara Industria de Diseño Textil, S.A. (INDITEX, S.A.) + "zero", // zero Amazon Registry Services, Inc. + "zip", // zip Charleston Road Registry Inc. + "zippo", // zippo Zadco Company + "zone", // zone Outer Falls, LLC + "zuerich", // zuerich Kanton Zürich (Canton of Zurich) +}; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] COUNTRY_CODE_TLDS = new String[] { + "ac", // Ascension Island + "ad", // Andorra + "ae", // United Arab Emirates + "af", // Afghanistan + "ag", // Antigua and Barbuda + "ai", // Anguilla + "al", // Albania + "am", // Armenia +// "an", // Netherlands Antilles (retired) + "ao", // Angola + "aq", // Antarctica + "ar", // Argentina + "as", // American Samoa + "at", // Austria + "au", // Australia (includes Ashmore and Cartier Islands and Coral Sea Islands) + "aw", // Aruba + "ax", // Åland + "az", // Azerbaijan + "ba", // Bosnia and Herzegovina + "bb", // Barbados + "bd", // Bangladesh + "be", // Belgium + "bf", // Burkina Faso + "bg", // Bulgaria + "bh", // Bahrain + "bi", // Burundi + "bj", // Benin + "bm", // Bermuda + "bn", // Brunei Darussalam + "bo", // Bolivia + "br", // Brazil + "bs", // Bahamas + "bt", // Bhutan + "bv", // Bouvet Island + "bw", // Botswana + "by", // Belarus + "bz", // Belize + "ca", // Canada + "cc", // Cocos (Keeling) Islands + "cd", // Democratic Republic of the Congo (formerly Zaire) + "cf", // Central African Republic + "cg", // Republic of the Congo + "ch", // Switzerland + "ci", // Côte d'Ivoire + "ck", // Cook Islands + "cl", // Chile + "cm", // Cameroon + "cn", // China, mainland + "co", // Colombia + "cr", // Costa Rica + "cu", // Cuba + "cv", // Cape Verde + "cw", // Curaçao + "cx", // Christmas Island + "cy", // Cyprus + "cz", // Czech Republic + "de", // Germany + "dj", // Djibouti + "dk", // Denmark + "dm", // Dominica + "do", // Dominican Republic + "dz", // Algeria + "ec", // Ecuador + "ee", // Estonia + "eg", // Egypt + "er", // Eritrea + "es", // Spain + "et", // Ethiopia + "eu", // European Union + "fi", // Finland + "fj", // Fiji + "fk", // Falkland Islands + "fm", // Federated States of Micronesia + "fo", // Faroe Islands + "fr", // France + "ga", // Gabon + "gb", // Great Britain (United Kingdom) + "gd", // Grenada + "ge", // Georgia + "gf", // French Guiana + "gg", // Guernsey + "gh", // Ghana + "gi", // Gibraltar + "gl", // Greenland + "gm", // The Gambia + "gn", // Guinea + "gp", // Guadeloupe + "gq", // Equatorial Guinea + "gr", // Greece + "gs", // South Georgia and the South Sandwich Islands + "gt", // Guatemala + "gu", // Guam + "gw", // Guinea-Bissau + "gy", // Guyana + "hk", // Hong Kong + "hm", // Heard Island and McDonald Islands + "hn", // Honduras + "hr", // Croatia (Hrvatska) + "ht", // Haiti + "hu", // Hungary + "id", // Indonesia + "ie", // Ireland (Éire) + "il", // Israel + "im", // Isle of Man + "in", // India + "io", // British Indian Ocean Territory + "iq", // Iraq + "ir", // Iran + "is", // Iceland + "it", // Italy + "je", // Jersey + "jm", // Jamaica + "jo", // Jordan + "jp", // Japan + "ke", // Kenya + "kg", // Kyrgyzstan + "kh", // Cambodia (Khmer) + "ki", // Kiribati + "km", // Comoros + "kn", // Saint Kitts and Nevis + "kp", // North Korea + "kr", // South Korea + "kw", // Kuwait + "ky", // Cayman Islands + "kz", // Kazakhstan + "la", // Laos (currently being marketed as the official domain for Los Angeles) + "lb", // Lebanon + "lc", // Saint Lucia + "li", // Liechtenstein + "lk", // Sri Lanka + "lr", // Liberia + "ls", // Lesotho + "lt", // Lithuania + "lu", // Luxembourg + "lv", // Latvia + "ly", // Libya + "ma", // Morocco + "mc", // Monaco + "md", // Moldova + "me", // Montenegro + "mg", // Madagascar + "mh", // Marshall Islands + "mk", // Republic of Macedonia + "ml", // Mali + "mm", // Myanmar + "mn", // Mongolia + "mo", // Macau + "mp", // Northern Mariana Islands + "mq", // Martinique + "mr", // Mauritania + "ms", // Montserrat + "mt", // Malta + "mu", // Mauritius + "mv", // Maldives + "mw", // Malawi + "mx", // Mexico + "my", // Malaysia + "mz", // Mozambique + "na", // Namibia + "nc", // New Caledonia + "ne", // Niger + "nf", // Norfolk Island + "ng", // Nigeria + "ni", // Nicaragua + "nl", // Netherlands + "no", // Norway + "np", // Nepal + "nr", // Nauru + "nu", // Niue + "nz", // New Zealand + "om", // Oman + "pa", // Panama + "pe", // Peru + "pf", // French Polynesia With Clipperton Island + "pg", // Papua New Guinea + "ph", // Philippines + "pk", // Pakistan + "pl", // Poland + "pm", // Saint-Pierre and Miquelon + "pn", // Pitcairn Islands + "pr", // Puerto Rico + "ps", // Palestinian territories (PA-controlled West Bank and Gaza Strip) + "pt", // Portugal + "pw", // Palau + "py", // Paraguay + "qa", // Qatar + "re", // Réunion + "ro", // Romania + "rs", // Serbia + "ru", // Russia + "rw", // Rwanda + "sa", // Saudi Arabia + "sb", // Solomon Islands + "sc", // Seychelles + "sd", // Sudan + "se", // Sweden + "sg", // Singapore + "sh", // Saint Helena + "si", // Slovenia + "sj", // Svalbard and Jan Mayen Islands Not in use (Norwegian dependencies; see .no) + "sk", // Slovakia + "sl", // Sierra Leone + "sm", // San Marino + "sn", // Senegal + "so", // Somalia + "sr", // Suriname + "st", // São Tomé and Príncipe + "su", // Soviet Union (deprecated) + "sv", // El Salvador + "sx", // Sint Maarten + "sy", // Syria + "sz", // Swaziland + "tc", // Turks and Caicos Islands + "td", // Chad + "tf", // French Southern and Antarctic Lands + "tg", // Togo + "th", // Thailand + "tj", // Tajikistan + "tk", // Tokelau + "tl", // East Timor (deprecated old code) + "tm", // Turkmenistan + "tn", // Tunisia + "to", // Tonga +// "tp", // East Timor (Retired) + "tr", // Turkey + "tt", // Trinidad and Tobago + "tv", // Tuvalu + "tw", // Taiwan, Republic of China + "tz", // Tanzania + "ua", // Ukraine + "ug", // Uganda + "uk", // United Kingdom + "us", // United States of America + "uy", // Uruguay + "uz", // Uzbekistan + "va", // Vatican City State + "vc", // Saint Vincent and the Grenadines + "ve", // Venezuela + "vg", // British Virgin Islands + "vi", // U.S. Virgin Islands + "vn", // Vietnam + "vu", // Vanuatu + "wf", // Wallis and Futuna + "ws", // Samoa (formerly Western Samoa) + "xn--3e0b707e", // 한국 KISA (Korea Internet & Security Agency) + "xn--45brj9c", // ভারত National Internet Exchange of India + "xn--54b7fta0cc", // বাংলা Posts and Telecommunications Division + "xn--80ao21a", // қаз Association of IT Companies of Kazakhstan + "xn--90a3ac", // срб Serbian National Internet Domain Registry (RNIDS) + "xn--90ais", // ??? Reliable Software Inc. + "xn--clchc0ea0b2g2a9gcd", // சிங்கப்பூர் Singapore Network Information Centre (SGNIC) Pte Ltd + "xn--d1alf", // мкд Macedonian Academic Research Network Skopje + "xn--e1a4c", // ею EURid vzw/asbl + "xn--fiqs8s", // 中国 China Internet Network Information Center + "xn--fiqz9s", // 中國 China Internet Network Information Center + "xn--fpcrj9c3d", // భారత్ National Internet Exchange of India + "xn--fzc2c9e2c", // ලංකා LK Domain Registry + "xn--gecrj9c", // ભારત National Internet Exchange of India + "xn--h2brj9c", // भारत National Internet Exchange of India + "xn--j1amh", // укр Ukrainian Network Information Centre (UANIC), Inc. + "xn--j6w193g", // 香港 Hong Kong Internet Registration Corporation Ltd. + "xn--kprw13d", // 台湾 Taiwan Network Information Center (TWNIC) + "xn--kpry57d", // 台灣 Taiwan Network Information Center (TWNIC) + "xn--l1acc", // мон Datacom Co.,Ltd + "xn--lgbbat1ad8j", // الجزائر CERIST + "xn--mgb9awbf", // عمان Telecommunications Regulatory Authority (TRA) + "xn--mgba3a4f16a", // ایران Institute for Research in Fundamental Sciences (IPM) + "xn--mgbaam7a8h", // امارات Telecommunications Regulatory Authority (TRA) + "xn--mgbayh7gpa", // الاردن National Information Technology Center (NITC) + "xn--mgbbh1a71e", // بھارت National Internet Exchange of India + "xn--mgbc0a9azcg", // المغرب Agence Nationale de Réglementation des Télécommunications (ANRT) + "xn--mgberp4a5d4ar", // السعودية Communications and Information Technology Commission + "xn--mgbpl2fh", // ????? Sudan Internet Society + "xn--mgbtx2b", // عراق Communications and Media Commission (CMC) + "xn--mgbx4cd0ab", // مليسيا MYNIC Berhad + "xn--mix891f", // 澳門 Bureau of Telecommunications Regulation (DSRT) + "xn--node", // გე Information Technologies Development Center (ITDC) + "xn--o3cw4h", // ไทย Thai Network Information Center Foundation + "xn--ogbpf8fl", // سورية National Agency for Network Services (NANS) + "xn--p1ai", // рф Coordination Center for TLD RU + "xn--pgbs0dh", // تونس Agence Tunisienne d'Internet + "xn--qxam", // ελ ICS-FORTH GR + "xn--s9brj9c", // ਭਾਰਤ National Internet Exchange of India + "xn--wgbh1c", // مصر National Telecommunication Regulatory Authority - NTRA + "xn--wgbl6a", // قطر Communications Regulatory Authority + "xn--xkc2al3hye2a", // இலங்கை LK Domain Registry + "xn--xkc2dl3a5ee0h", // இந்தியா National Internet Exchange of India + "xn--y9a3aq", // ??? Internet Society + "xn--yfro4i67o", // 新加坡 Singapore Network Information Centre (SGNIC) Pte Ltd + "xn--ygbi2ammx", // فلسطين Ministry of Telecom & Information Technology (MTIT) + "ye", // Yemen + "yt", // Mayotte + "za", // South Africa + "zm", // Zambia + "zw", // Zimbabwe + }; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] LOCAL_TLDS = new String[] { + "localdomain", // Also widely used as localhost.localdomain + "localhost", // RFC2606 defined + }; + + // Additional arrays to supplement or override the built in ones. + // The PLUS arrays are valid keys, the MINUS arrays are invalid keys + + /* + * This field is used to detect whether the getInstance has been called. + * After this, the method updateTLDOverride is not allowed to be called. + * This field does not need to be volatile since it is only accessed from + * synchronized methods. + */ + private static boolean inUse = false; + + /* + * These arrays are mutable, but they don't need to be volatile. + * They can only be updated by the updateTLDOverride method, and any readers must get an instance + * using the getInstance methods which are all (now) synchronised. + */ + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static volatile String[] countryCodeTLDsPlus = EMPTY_STRING_ARRAY; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static volatile String[] genericTLDsPlus = EMPTY_STRING_ARRAY; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static volatile String[] countryCodeTLDsMinus = EMPTY_STRING_ARRAY; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static volatile String[] genericTLDsMinus = EMPTY_STRING_ARRAY; + + /** + * enum used by {@link DomainValidator#updateTLDOverride(ArrayType, String[])} + * to determine which override array to update / fetch + * @since 1.5.0 + * @since 1.5.1 made public and added read-only array references + */ + public enum ArrayType { + /** Update (or get a copy of) the GENERIC_TLDS_PLUS table containing additonal generic TLDs */ + GENERIC_PLUS, + /** Update (or get a copy of) the GENERIC_TLDS_MINUS table containing deleted generic TLDs */ + GENERIC_MINUS, + /** Update (or get a copy of) the COUNTRY_CODE_TLDS_PLUS table containing additonal country code TLDs */ + COUNTRY_CODE_PLUS, + /** Update (or get a copy of) the COUNTRY_CODE_TLDS_MINUS table containing deleted country code TLDs */ + COUNTRY_CODE_MINUS, + /** Get a copy of the generic TLDS table */ + GENERIC_RO, + /** Get a copy of the country code table */ + COUNTRY_CODE_RO, + /** Get a copy of the infrastructure table */ + INFRASTRUCTURE_RO, + /** Get a copy of the local table */ + LOCAL_RO + ; + }; + + // For use by unit test code only + static synchronized void clearTLDOverrides() { + inUse = false; + countryCodeTLDsPlus = EMPTY_STRING_ARRAY; + countryCodeTLDsMinus = EMPTY_STRING_ARRAY; + genericTLDsPlus = EMPTY_STRING_ARRAY; + genericTLDsMinus = EMPTY_STRING_ARRAY; + } + /** + * Update one of the TLD override arrays. + * This must only be done at program startup, before any instances are accessed using getInstance. + *

+ * For example: + *

+ * {@code DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, new String[]{"apache"})} + *

+ * To clear an override array, provide an empty array. + * + * @param table the table to update, see {@link DomainValidator.ArrayType} + * Must be one of the following + *

    + *
  • COUNTRY_CODE_MINUS
  • + *
  • COUNTRY_CODE_PLUS
  • + *
  • GENERIC_MINUS
  • + *
  • GENERIC_PLUS
  • + *
+ * @param tlds the array of TLDs, must not be null + * @throws IllegalStateException if the method is called after getInstance + * @throws IllegalArgumentException if one of the read-only tables is requested + * @since 1.5.0 + */ + public static synchronized void updateTLDOverride(ArrayType table, String [] tlds) { + if (inUse) { + throw new IllegalStateException("Can only invoke this method before calling getInstance"); + } + String [] copy = new String[tlds.length]; + // Comparisons are always done with lower-case entries + for (int i = 0; i < tlds.length; i++) { + copy[i] = tlds[i].toLowerCase(Locale.ENGLISH); + } + Arrays.sort(copy); + switch(table) { + case COUNTRY_CODE_MINUS: + countryCodeTLDsMinus = copy; + break; + case COUNTRY_CODE_PLUS: + countryCodeTLDsPlus = copy; + break; + case GENERIC_MINUS: + genericTLDsMinus = copy; + break; + case GENERIC_PLUS: + genericTLDsPlus = copy; + break; + case COUNTRY_CODE_RO: + case GENERIC_RO: + case INFRASTRUCTURE_RO: + case LOCAL_RO: + throw new IllegalArgumentException("Cannot update the table: " + table); + default: + throw new IllegalArgumentException("Unexpected enum value: " + table); + } + } + + /** + * Get a copy of the internal array. + * @param table the array type (any of the enum values) + * @return a copy of the array + * @throws IllegalArgumentException if the table type is unexpected (should not happen) + * @since 1.5.1 + */ + public static String [] getTLDEntries(ArrayType table) { + final String array[]; + switch(table) { + case COUNTRY_CODE_MINUS: + array = countryCodeTLDsMinus; + break; + case COUNTRY_CODE_PLUS: + array = countryCodeTLDsPlus; + break; + case GENERIC_MINUS: + array = genericTLDsMinus; + break; + case GENERIC_PLUS: + array = genericTLDsPlus; + break; + case GENERIC_RO: + array = GENERIC_TLDS; + break; + case COUNTRY_CODE_RO: + array = COUNTRY_CODE_TLDS; + break; + case INFRASTRUCTURE_RO: + array = INFRASTRUCTURE_TLDS; + break; + case LOCAL_RO: + array = LOCAL_TLDS; + break; + default: + throw new IllegalArgumentException("Unexpected enum value: " + table); + } + return Arrays.copyOf(array, array.length); // clone the array + } + + /** + * Converts potentially Unicode input to punycode. + * If conversion fails, returns the original input. + * + * @param input the string to convert, not null + * @return converted input, or original input if conversion fails + */ + // Needed by UrlValidator + static String unicodeToASCII(String input) { + if (isOnlyASCII(input)) { // skip possibly expensive processing + return input; + } + try { + final String ascii = IDN.toASCII(input); + if (IDNBUGHOLDER.IDN_TOASCII_PRESERVES_TRAILING_DOTS) { + return ascii; + } + final int length = input.length(); + if (length == 0) {// check there is a last character + return input; + } + // RFC3490 3.1. 1) + // Whenever dots are used as label separators, the following + // characters MUST be recognized as dots: U+002E (full stop), U+3002 + // (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61 + // (halfwidth ideographic full stop). + char lastChar = input.charAt(length-1);// fetch original last char + switch(lastChar) { + case '\u002E': // "." full stop + case '\u3002': // ideographic full stop + case '\uFF0E': // fullwidth full stop + case '\uFF61': // halfwidth ideographic full stop + return ascii + "."; // restore the missing stop + default: + return ascii; + } + } catch (IllegalArgumentException e) { // input is not valid + return input; + } + } + + private static class IDNBUGHOLDER { + private static boolean keepsTrailingDot() { + final String input = "a."; // must be a valid name + return input.equals(IDN.toASCII(input)); + } + private static final boolean IDN_TOASCII_PRESERVES_TRAILING_DOTS = keepsTrailingDot(); + } + + /* + * Check if input contains only ASCII + * Treats null as all ASCII + */ + private static boolean isOnlyASCII(String input) { + if (input == null) { + return true; + } + for(int i=0; i < input.length(); i++) { + if (input.charAt(i) > 0x7F) { // CHECKSTYLE IGNORE MagicNumber + return false; + } + } + return true; + } + + /** + * Check if a sorted array contains the specified key + * + * @param sortedArray the array to search + * @param key the key to find + * @return {@code true} if the array contains the key + */ + private static boolean arrayContains(String[] sortedArray, String key) { + return Arrays.binarySearch(sortedArray, key) >= 0; + } +} diff --git a/projects/bleckw/FinalProject/URLValidatorCorrect/src/InetAddressValidator.java b/projects/bleckw/FinalProject/URLValidatorCorrect/src/InetAddressValidator.java new file mode 100644 index 00000000..bf93d47c --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorCorrect/src/InetAddressValidator.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + *

InetAddress validation and conversion routines (java.net.InetAddress).

+ * + *

This class provides methods to validate a candidate IP address. + * + *

+ * This class is a Singleton; you can retrieve the instance via the {@link #getInstance()} method. + *

+ * + * @version $Revision: 1783032 $ + * @since Validator 1.4 + */ +public class InetAddressValidator implements Serializable { + + private static final int IPV4_MAX_OCTET_VALUE = 255; + + private static final int MAX_UNSIGNED_SHORT = 0xffff; + + private static final int BASE_16 = 16; + + private static final long serialVersionUID = -919201640201914789L; + + private static final String IPV4_REGEX = + "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"; + + // Max number of hex groups (separated by :) in an IPV6 address + private static final int IPV6_MAX_HEX_GROUPS = 8; + + // Max hex digits in each IPv6 group + private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4; + + /** + * Singleton instance of this class. + */ + private static final InetAddressValidator VALIDATOR = new InetAddressValidator(); + + /** IPv4 RegexValidator */ + private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX); + + /** + * Returns the singleton instance of this validator. + * @return the singleton instance of this validator + */ + public static InetAddressValidator getInstance() { + return VALIDATOR; + } + + /** + * Checks if the specified string is a valid IP address. + * @param inetAddress the string to validate + * @return true if the string validates as an IP address + */ + public boolean isValid(String inetAddress) { + return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress); + } + + /** + * Validates an IPv4 address. Returns true if valid. + * @param inet4Address the IPv4 address to validate + * @return true if the argument contains a valid IPv4 address + */ + public boolean isValidInet4Address(String inet4Address) { + // verify that address conforms to generic IPv4 format + String[] groups = ipv4Validator.match(inet4Address); + + if (groups == null) { + return false; + } + + // verify that address subgroups are legal + for (String ipSegment : groups) { + if (ipSegment == null || ipSegment.length() == 0) { + return false; + } + + int iIpSegment = 0; + + try { + iIpSegment = Integer.parseInt(ipSegment); + } catch(NumberFormatException e) { + return false; + } + + if (iIpSegment > IPV4_MAX_OCTET_VALUE) { + return false; + } + + if (ipSegment.length() > 1 && ipSegment.startsWith("0")) { + return false; + } + + } + + return true; + } + + /** + * Validates an IPv6 address. Returns true if valid. + * @param inet6Address the IPv6 address to validate + * @return true if the argument contains a valid IPv6 address + * + * @since 1.4.1 + */ + public boolean isValidInet6Address(String inet6Address) { + boolean containsCompressedZeroes = inet6Address.contains("::"); + if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) { + return false; + } + if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::")) + || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) { + return false; + } + String[] octets = inet6Address.split(":"); + if (containsCompressedZeroes) { + List octetList = new ArrayList(Arrays.asList(octets)); + if (inet6Address.endsWith("::")) { + // String.split() drops ending empty segments + octetList.add(""); + } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) { + octetList.remove(0); + } + octets = octetList.toArray(new String[octetList.size()]); + } + if (octets.length > IPV6_MAX_HEX_GROUPS) { + return false; + } + int validOctets = 0; + int emptyOctets = 0; // consecutive empty chunks + for (int index = 0; index < octets.length; index++) { + String octet = octets[index]; + if (octet.length() == 0) { + emptyOctets++; + if (emptyOctets > 1) { + return false; + } + } else { + emptyOctets = 0; + // Is last chunk an IPv4 address? + if (index == octets.length - 1 && octet.contains(".")) { + if (!isValidInet4Address(octet)) { + return false; + } + validOctets += 2; + continue; + } + if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) { + return false; + } + int octetInt = 0; + try { + octetInt = Integer.parseInt(octet, BASE_16); + } catch (NumberFormatException e) { + return false; + } + if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) { + return false; + } + } + validOctets++; + } + if (validOctets > IPV6_MAX_HEX_GROUPS || (validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes)) { + return false; + } + return true; + } +} diff --git a/projects/bleckw/FinalProject/URLValidatorCorrect/src/RegexValidator.java b/projects/bleckw/FinalProject/URLValidatorCorrect/src/RegexValidator.java new file mode 100644 index 00000000..9f49087b --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorCorrect/src/RegexValidator.java @@ -0,0 +1,229 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Regular Expression validation (using JDK 1.4+ regex support). + *

+ * Construct the validator either for a single regular expression or a set (array) of + * regular expressions. By default validation is case sensitive but constructors + * are provided to allow case in-sensitive validation. For example to create + * a validator which does case in-sensitive validation for a set of regular + * expressions: + *

+ *
+ * 
+ * String[] regexs = new String[] {...};
+ * RegexValidator validator = new RegexValidator(regexs, false);
+ * 
+ * 
+ * + *
    + *
  • Validate true or false:
  • + *
  • + *
      + *
    • boolean valid = validator.isValid(value);
    • + *
    + *
  • + *
  • Validate returning an aggregated String of the matched groups:
  • + *
  • + *
      + *
    • String result = validator.validate(value);
    • + *
    + *
  • + *
  • Validate returning the matched groups:
  • + *
  • + *
      + *
    • String[] result = validator.match(value);
    • + *
    + *
  • + *
+ * + * Note that patterns are matched against the entire input. + * + *

+ * Cached instances pre-compile and re-use {@link Pattern}(s) - which according + * to the {@link Pattern} API are safe to use in a multi-threaded environment. + *

+ * + * @version $Revision: 1739356 $ + * @since Validator 1.4 + */ +public class RegexValidator implements Serializable { + + private static final long serialVersionUID = -8832409930574867162L; + + private final Pattern[] patterns; + + /** + * Construct a case sensitive validator for a single + * regular expression. + * + * @param regex The regular expression this validator will + * validate against + */ + public RegexValidator(String regex) { + this(regex, true); + } + + /** + * Construct a validator for a single regular expression + * with the specified case sensitivity. + * + * @param regex The regular expression this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String regex, boolean caseSensitive) { + this(new String[] {regex}, caseSensitive); + } + + /** + * Construct a case sensitive validator that matches any one + * of the set of regular expressions. + * + * @param regexs The set of regular expressions this validator will + * validate against + */ + public RegexValidator(String[] regexs) { + this(regexs, true); + } + + /** + * Construct a validator that matches any one of the set of regular + * expressions with the specified case sensitivity. + * + * @param regexs The set of regular expressions this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String[] regexs, boolean caseSensitive) { + if (regexs == null || regexs.length == 0) { + throw new IllegalArgumentException("Regular expressions are missing"); + } + patterns = new Pattern[regexs.length]; + int flags = (caseSensitive ? 0: Pattern.CASE_INSENSITIVE); + for (int i = 0; i < regexs.length; i++) { + if (regexs[i] == null || regexs[i].length() == 0) { + throw new IllegalArgumentException("Regular expression[" + i + "] is missing"); + } + patterns[i] = Pattern.compile(regexs[i], flags); + } + } + + /** + * Validate a value against the set of regular expressions. + * + * @param value The value to validate. + * @return true if the value is valid + * otherwise false. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + for (int i = 0; i < patterns.length; i++) { + if (patterns[i].matcher(value).matches()) { + return true; + } + } + return false; + } + + /** + * Validate a value against the set of regular expressions + * returning the array of matched groups. + * + * @param value The value to validate. + * @return String array of the groups matched if + * valid or null if invalid + */ + public String[] match(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + String[] groups = new String[count]; + for (int j = 0; j < count; j++) { + groups[j] = matcher.group(j+1); + } + return groups; + } + } + return null; + } + + + /** + * Validate a value against the set of regular expressions + * returning a String value of the aggregated groups. + * + * @param value The value to validate. + * @return Aggregated String value comprised of the + * groups matched if valid or null if invalid + */ + public String validate(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + if (count == 1) { + return matcher.group(1); + } + StringBuilder buffer = new StringBuilder(); + for (int j = 0; j < count; j++) { + String component = matcher.group(j+1); + if (component != null) { + buffer.append(component); + } + } + return buffer.toString(); + } + } + return null; + } + + /** + * Provide a String representation of this validator. + * @return A String representation of this validator + */ + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RegexValidator{"); + for (int i = 0; i < patterns.length; i++) { + if (i > 0) { + buffer.append(","); + } + buffer.append(patterns[i].pattern()); + } + buffer.append("}"); + return buffer.toString(); + } + +} diff --git a/projects/bleckw/FinalProject/URLValidatorCorrect/src/ResultPair.java b/projects/bleckw/FinalProject/URLValidatorCorrect/src/ResultPair.java new file mode 100644 index 00000000..01d6b682 --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorCorrect/src/ResultPair.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/** + * Groups tests and expected results. + * + * @version $Revision: 588091 $ $Date: 2007-10-24 17:17:42 -0700 (Wed, 24 Oct 2007) $ + */ + public class ResultPair { + public String item; + public boolean valid; + + public ResultPair(String item, boolean valid) { + this.item = item; + this.valid = valid; //Weather the individual part of url is valid. + } + } diff --git a/projects/bleckw/FinalProject/URLValidatorCorrect/src/UrlValidator.java b/projects/bleckw/FinalProject/URLValidatorCorrect/src/UrlValidator.java new file mode 100644 index 00000000..01e759f6 --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorCorrect/src/UrlValidator.java @@ -0,0 +1,543 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *

URL Validation routines.

+ * Behavior of validation is modified by passing in options: + *
    + *
  • ALLOW_2_SLASHES - [FALSE] Allows double '/' characters in the path + * component.
  • + *
  • NO_FRAGMENT- [FALSE] By default fragments are allowed, if this option is + * included then fragments are flagged as illegal.
  • + *
  • ALLOW_ALL_SCHEMES - [FALSE] By default only http, https, and ftp are + * considered valid schemes. Enabling this option will let any scheme pass validation.
  • + *
+ * + *

Originally based in on php script by Debbie Dyer, validation.php v1.2b, Date: 03/07/02, + * http://javascript.internet.com. However, this validation now bears little resemblance + * to the php original.

+ *
+ *   Example of usage:
+ *   Construct a UrlValidator with valid schemes of "http", and "https".
+ *
+ *    String[] schemes = {"http","https"}.
+ *    UrlValidator urlValidator = new UrlValidator(schemes);
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *    prints "url is invalid"
+ *   If instead the default constructor is used.
+ *
+ *    UrlValidator urlValidator = new UrlValidator();
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *   prints out "url is valid"
+ *  
+ * + * @see + * + * Uniform Resource Identifiers (URI): Generic Syntax + * + * + * @version $Revision: 1783203 $ + * @since Validator 1.4 + */ +public class UrlValidator implements Serializable { + + private static final long serialVersionUID = 7557161713937335013L; + + private static final int MAX_UNSIGNED_16_BIT_INT = 0xFFFF; // port max + + /** + * Allows all validly formatted schemes to pass validation instead of + * supplying a set of valid schemes. + */ + public static final long ALLOW_ALL_SCHEMES = 1 << 0; + + /** + * Allow two slashes in the path component of the URL. + */ + public static final long ALLOW_2_SLASHES = 1 << 1; + + /** + * Enabling this options disallows any URL fragments. + */ + public static final long NO_FRAGMENTS = 1 << 2; + + /** + * Allow local URLs, such as http://localhost/ or http://machine/ . + * This enables a broad-brush check, for complex local machine name + * validation requirements you should create your validator with + * a {@link RegexValidator} instead ({@link #UrlValidator(RegexValidator, long)}) + */ + public static final long ALLOW_LOCAL_URLS = 1 << 3; // CHECKSTYLE IGNORE MagicNumber + + /** + * This expression derived/taken from the BNF for URI (RFC2396). + */ + private static final String URL_REGEX = + "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"; + // 12 3 4 5 6 7 8 9 + private static final Pattern URL_PATTERN = Pattern.compile(URL_REGEX); + + /** + * Schema/Protocol (ie. http:, ftp:, file:, etc). + */ + private static final int PARSE_URL_SCHEME = 2; + + /** + * Includes hostname/ip and port number. + */ + private static final int PARSE_URL_AUTHORITY = 4; + + private static final int PARSE_URL_PATH = 5; + + private static final int PARSE_URL_QUERY = 7; + + private static final int PARSE_URL_FRAGMENT = 9; + + /** + * Protocol scheme (e.g. http, ftp, https). + */ + private static final String SCHEME_REGEX = "^\\p{Alpha}[\\p{Alnum}\\+\\-\\.]*"; + private static final Pattern SCHEME_PATTERN = Pattern.compile(SCHEME_REGEX); + + // Drop numeric, and "+-." for now + // TODO does not allow for optional userinfo. + // Validation of character set is done by isValidAuthority + private static final String AUTHORITY_CHARS_REGEX = "\\p{Alnum}\\-\\."; // allows for IPV4 but not IPV6 + private static final String IPV6_REGEX = "[0-9a-fA-F:]+"; // do this as separate match because : could cause ambiguity with port prefix + + // userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + // We assume that password has the same valid chars as user info + private static final String USERINFO_CHARS_REGEX = "[a-zA-Z0-9%-._~!$&'()*+,;=]"; + // since neither ':' nor '@' are allowed chars, we don't need to use non-greedy matching + private static final String USERINFO_FIELD_REGEX = + USERINFO_CHARS_REGEX + "+" + // At least one character for the name + "(?::" + USERINFO_CHARS_REGEX + "*)?@"; // colon and password may be absent + private static final String AUTHORITY_REGEX = + "(?:\\[("+IPV6_REGEX+")\\]|(?:(?:"+USERINFO_FIELD_REGEX+")?([" + AUTHORITY_CHARS_REGEX + "]*)))(?::(\\d*))?(.*)?"; + // 1 e.g. user:pass@ 2 3 4 + private static final Pattern AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEX); + + private static final int PARSE_AUTHORITY_IPV6 = 1; + + private static final int PARSE_AUTHORITY_HOST_IP = 2; // excludes userinfo, if present + + private static final int PARSE_AUTHORITY_PORT = 3; // excludes leading colon + + /** + * Should always be empty. The code currently allows spaces. + */ + private static final int PARSE_AUTHORITY_EXTRA = 4; + + private static final String PATH_REGEX = "^(/[-\\w:@&?=+,.!/~*'%$_;\\(\\)]*)?$"; + private static final Pattern PATH_PATTERN = Pattern.compile(PATH_REGEX); + + private static final String QUERY_REGEX = "^(\\S*)$"; + private static final Pattern QUERY_PATTERN = Pattern.compile(QUERY_REGEX); + + /** + * Holds the set of current validation options. + */ + private final long options; + + /** + * The set of schemes that are allowed to be in a URL. + */ + private final Set allowedSchemes; // Must be lower-case + + /** + * Regular expressions used to manually validate authorities if IANA + * domain name validation isn't desired. + */ + private final RegexValidator authorityValidator; + + /** + * If no schemes are provided, default to this set. + */ + private static final String[] DEFAULT_SCHEMES = {"http", "https", "ftp"}; // Must be lower-case + + /** + * Singleton instance of this class with default schemes and options. + */ + private static final UrlValidator DEFAULT_URL_VALIDATOR = new UrlValidator(); + + /** + * Returns the singleton instance of this class with default schemes and options. + * @return singleton instance with default schemes and options + */ + public static UrlValidator getInstance() { + return DEFAULT_URL_VALIDATOR; + } + + /** + * Create a UrlValidator with default properties. + */ + public UrlValidator() { + this(null); + } + + /** + * Behavior of validation is modified by passing in several strings options: + * @param schemes Pass in one or more url schemes to consider valid, passing in + * a null will default to "http,https,ftp" being valid. + * If a non-null schemes is specified then all valid schemes must + * be specified. Setting the ALLOW_ALL_SCHEMES option will + * ignore the contents of schemes. + */ + public UrlValidator(String[] schemes) { + this(schemes, 0L); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(long options) { + this(null, null, options); + } + + /** + * Behavior of validation is modified by passing in options: + * @param schemes The set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(String[] schemes, long options) { + this(schemes, null, options); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param authorityValidator Regular expression validator used to validate the authority part + * This allows the user to override the standard set of domains. + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(RegexValidator authorityValidator, long options) { + this(null, authorityValidator, options); + } + + /** + * Customizable constructor. Validation behavior is modifed by passing in options. + * @param schemes the set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param authorityValidator Regular expression validator used to validate the authority part + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(String[] schemes, RegexValidator authorityValidator, long options) { + this.options = options; + + if (isOn(ALLOW_ALL_SCHEMES)) { + allowedSchemes = Collections.emptySet(); + } else { + if (schemes == null) { + schemes = DEFAULT_SCHEMES; + } + allowedSchemes = new HashSet(schemes.length); + for(int i=0; i < schemes.length; i++) { + allowedSchemes.add(schemes[i].toLowerCase(Locale.ENGLISH)); + } + } + + this.authorityValidator = authorityValidator; + } + + /** + *

Checks if a field has a valid url address.

+ * + * Note that the method calls #isValidAuthority() + * which checks that the domain is valid. + * + * @param value The value validation is being performed on. A null + * value is considered invalid. + * @return true if the url is valid. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + + // Check the whole url address structure + Matcher urlMatcher = URL_PATTERN.matcher(value); + if (!urlMatcher.matches()) { + return false; + } + + String scheme = urlMatcher.group(PARSE_URL_SCHEME); + if (!isValidScheme(scheme)) { + return false; + } + + String authority = urlMatcher.group(PARSE_URL_AUTHORITY); + if ("file".equals(scheme)) {// Special case - file: allows an empty authority + if (authority != null) { + if (authority.contains(":")) { // but cannot allow trailing : + return false; + } + } + // drop through to continue validation + } else { // not file: + // Validate the authority + if (!isValidAuthority(authority)) { + return false; + } + } + + if (!isValidPath(urlMatcher.group(PARSE_URL_PATH))) { + return false; + } + + if (!isValidQuery(urlMatcher.group(PARSE_URL_QUERY))) { + return false; + } + + if (!isValidFragment(urlMatcher.group(PARSE_URL_FRAGMENT))) { + return false; + } + + return true; + } + + /** + * Validate scheme. If schemes[] was initialized to a non null, + * then only those schemes are allowed. + * Otherwise the default schemes are "http", "https", "ftp". + * Matching is case-blind. + * @param scheme The scheme to validate. A null value is considered + * invalid. + * @return true if valid. + */ + protected boolean isValidScheme(String scheme) { + if (scheme == null) { + return false; + } + + // TODO could be removed if external schemes were checked in the ctor before being stored + if (!SCHEME_PATTERN.matcher(scheme).matches()) { + return false; + } + + if (isOff(ALLOW_ALL_SCHEMES) && !allowedSchemes.contains(scheme.toLowerCase(Locale.ENGLISH))) { + return false; + } + + return true; + } + + /** + * Returns true if the authority is properly formatted. An authority is the combination + * of hostname and port. A null authority value is considered invalid. + * Note: this implementation validates the domain unless a RegexValidator was provided. + * If a RegexValidator was supplied and it matches, then the authority is regarded + * as valid with no further checks, otherwise the method checks against the + * AUTHORITY_PATTERN and the DomainValidator (ALLOW_LOCAL_URLS) + * @param authority Authority value to validate, alllows IDN + * @return true if authority (hostname and port) is valid. + */ + protected boolean isValidAuthority(String authority) { + if (authority == null) { + return false; + } + + // check manual authority validation if specified + if (authorityValidator != null && authorityValidator.isValid(authority)) { + return true; + } + // convert to ASCII if possible + final String authorityASCII = DomainValidator.unicodeToASCII(authority); + + Matcher authorityMatcher = AUTHORITY_PATTERN.matcher(authorityASCII); + if (!authorityMatcher.matches()) { + return false; + } + + // We have to process IPV6 separately because that is parsed in a different group + String ipv6 = authorityMatcher.group(PARSE_AUTHORITY_IPV6); + if (ipv6 != null) { + InetAddressValidator inetAddressValidator = InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet6Address(ipv6)) { + return false; + } + } else { + String hostLocation = authorityMatcher.group(PARSE_AUTHORITY_HOST_IP); + // check if authority is hostname or IP address: + // try a hostname first since that's much more likely + DomainValidator domainValidator = DomainValidator.getInstance(isOn(ALLOW_LOCAL_URLS)); + if (!domainValidator.isValid(hostLocation)) { + // try an IPv4 address + InetAddressValidator inetAddressValidator = InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet4Address(hostLocation)) { + // isn't IPv4, so the URL is invalid + return false; + } + } + String port = authorityMatcher.group(PARSE_AUTHORITY_PORT); + if (port != null && port.length() > 0) { + try { + int iPort = Integer.parseInt(port); + if (iPort < 0 || iPort > MAX_UNSIGNED_16_BIT_INT) { + return false; + } + } catch (NumberFormatException nfe) { + return false; // this can happen for big numbers + } + } + } + + String extra = authorityMatcher.group(PARSE_AUTHORITY_EXTRA); + if (extra != null && extra.trim().length() > 0){ + return false; + } + + return true; + } + + /** + * Returns true if the path is valid. A null value is considered invalid. + * @param path Path value to validate. + * @return true if path is valid. + */ + protected boolean isValidPath(String path) { + if (path == null) { + return false; + } + + if (!PATH_PATTERN.matcher(path).matches()) { + return false; + } + + try { + URI uri = new URI(null,null,path,null); + String norm = uri.normalize().getPath(); + if (norm.startsWith("/../") // Trying to go via the parent dir + || norm.equals("/..")) { // Trying to go to the parent dir + return false; + } + } catch (URISyntaxException e) { + return false; + } + + int slash2Count = countToken("//", path); + if (isOff(ALLOW_2_SLASHES) && (slash2Count > 0)) { + return false; + } + + return true; + } + + /** + * Returns true if the query is null or it's a properly formatted query string. + * @param query Query value to validate. + * @return true if query is valid. + */ + protected boolean isValidQuery(String query) { + if (query == null) { + return true; + } + + return QUERY_PATTERN.matcher(query).matches(); + } + + /** + * Returns true if the given fragment is null or fragments are allowed. + * @param fragment Fragment value to validate. + * @return true if fragment is valid. + */ + protected boolean isValidFragment(String fragment) { + if (fragment == null) { + return true; + } + + return isOff(NO_FRAGMENTS); + } + + /** + * Returns the number of times the token appears in the target. + * @param token Token value to be counted. + * @param target Target value to count tokens in. + * @return the number of tokens. + */ + protected int countToken(String token, String target) { + int tokenIndex = 0; + int count = 0; + while (tokenIndex != -1) { + tokenIndex = target.indexOf(token, tokenIndex); + if (tokenIndex > -1) { + tokenIndex++; + count++; + } + } + return count; + } + + /** + * Tests whether the given flag is on. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is on. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is on. + */ + private boolean isOn(long flag) { + return (options & flag) > 0; + } + + /** + * Tests whether the given flag is off. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is off. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is off. + */ + private boolean isOff(long flag) { + return (options & flag) == 0; + } + + // Unit test access to pattern matcher + Matcher matchURL(String value) { + return URL_PATTERN.matcher(value); + } +} diff --git a/projects/bleckw/FinalProject/URLValidatorCorrect/test/UrlValidatorTest.java b/projects/bleckw/FinalProject/URLValidatorCorrect/test/UrlValidatorTest.java new file mode 100644 index 00000000..f6dad84e --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorCorrect/test/UrlValidatorTest.java @@ -0,0 +1,600 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import junit.framework.TestCase; + +/** + * Performs Validation Test for url validations. + * + * @version $Revision$ + */ +public class UrlValidatorTest extends TestCase { + + private final boolean printStatus = false; + private final boolean printIndex = false;//print index that indicates current scheme,host,port,path, query test were using. + + public UrlValidatorTest(String testName) { + super(testName); + } + + @Override +protected void setUp() { + for (int index = 0; index < testPartsIndex.length - 1; index++) { + testPartsIndex[index] = 0; + } + } + + public void testIsValid() { + testIsValid(testUrlParts, UrlValidator.ALLOW_ALL_SCHEMES); + setUp(); + long options = + UrlValidator.ALLOW_2_SLASHES + + UrlValidator.ALLOW_ALL_SCHEMES + + UrlValidator.NO_FRAGMENTS; + + testIsValid(testUrlPartsOptions, options); + } + + public void testIsValidScheme() { + if (printStatus) { + System.out.print("\n testIsValidScheme() "); + } + //UrlValidator urlVal = new UrlValidator(schemes,false,false,false); + UrlValidator urlVal = new UrlValidator(schemes, 0); + for (int sIndex = 0; sIndex < testScheme.length; sIndex++) { + ResultPair testPair = testScheme[sIndex]; + boolean result = urlVal.isValidScheme(testPair.item); + assertEquals(testPair.item, testPair.valid, result); + if (printStatus) { + if (result == testPair.valid) { + System.out.print('.'); + } else { + System.out.print('X'); + } + } + } + if (printStatus) { + System.out.println(); + } + + } + + /** + * Create set of tests by taking the testUrlXXX arrays and + * running through all possible permutations of their combinations. + * + * @param testObjects Used to create a url. + */ + public void testIsValid(Object[] testObjects, long options) { + UrlValidator urlVal = new UrlValidator(null, null, options); + assertTrue(urlVal.isValid("http://www.google.com")); + assertTrue(urlVal.isValid("http://www.google.com/")); + int statusPerLine = 60; + int printed = 0; + if (printIndex) { + statusPerLine = 6; + } + do { + StringBuilder testBuffer = new StringBuilder(); + boolean expected = true; + for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) { + int index = testPartsIndex[testPartsIndexIndex]; + ResultPair[] part = (ResultPair[]) testObjects[testPartsIndexIndex]; + testBuffer.append(part[index].item); + expected &= part[index].valid; + } + String url = testBuffer.toString(); + boolean result = urlVal.isValid(url); + assertEquals(url, expected, result); + if (printStatus) { + if (printIndex) { + System.out.print(testPartsIndextoString()); + } else { + if (result == expected) { + System.out.print('.'); + } else { + System.out.print('X'); + } + } + printed++; + if (printed == statusPerLine) { + System.out.println(); + printed = 0; + } + } + } while (incrementTestPartsIndex(testPartsIndex, testObjects)); + if (printStatus) { + System.out.println(); + } + } + + public void testValidator202() { + String[] schemes = {"http","https"}; + UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.NO_FRAGMENTS); + assertTrue(urlValidator.isValid("http://l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.org")); + } + + public void testValidator204() { + String[] schemes = {"http","https"}; + UrlValidator urlValidator = new UrlValidator(schemes); + assertTrue(urlValidator.isValid("http://tech.yahoo.com/rc/desktops/102;_ylt=Ao8yevQHlZ4On0O3ZJGXLEQFLZA5")); + } + + public void testValidator218() { + UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_2_SLASHES); + assertTrue("parentheses should be valid in URLs", + validator.isValid("http://somewhere.com/pathxyz/file(1).html")); + } + + public void testValidator235() { + String version = System.getProperty("java.version"); + if (version.compareTo("1.6") < 0) { + System.out.println("Cannot run Unicode IDN tests"); + return; // Cannot run the test + } + UrlValidator validator = new UrlValidator(); + assertTrue("xn--d1abbgf6aiiy.xn--p1ai should validate", validator.isValid("http://xn--d1abbgf6aiiy.xn--p1ai")); + assertTrue("президент.рф should validate", validator.isValid("http://президент.рф")); + assertTrue("www.b\u00fccher.ch should validate", validator.isValid("http://www.b\u00fccher.ch")); + assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("http://www.\uFFFD.ch")); + assertTrue("www.b\u00fccher.ch should validate", validator.isValid("ftp://www.b\u00fccher.ch")); + assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("ftp://www.\uFFFD.ch")); + } + + public void testValidator248() { + RegexValidator regex = new RegexValidator(new String[] {"localhost", ".*\\.my-testing"}); + UrlValidator validator = new UrlValidator(regex, 0); + + assertTrue("localhost URL should validate", + validator.isValid("http://localhost/test/index.html")); + assertTrue("first.my-testing should validate", + validator.isValid("http://first.my-testing/test/index.html")); + assertTrue("sup3r.my-testing should validate", + validator.isValid("http://sup3r.my-testing/test/index.html")); + + assertFalse("broke.my-test should not validate", + validator.isValid("http://broke.my-test/test/index.html")); + + assertTrue("www.apache.org should still validate", + validator.isValid("http://www.apache.org/test/index.html")); + + // Now check using options + validator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS); + + assertTrue("localhost URL should validate", + validator.isValid("http://localhost/test/index.html")); + + assertTrue("machinename URL should validate", + validator.isValid("http://machinename/test/index.html")); + + assertTrue("www.apache.org should still validate", + validator.isValid("http://www.apache.org/test/index.html")); + } + + public void testValidator288() { + UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS); + + assertTrue("hostname should validate", + validator.isValid("http://hostname")); + + assertTrue("hostname with path should validate", + validator.isValid("http://hostname/test/index.html")); + + assertTrue("localhost URL should validate", + validator.isValid("http://localhost/test/index.html")); + + assertFalse("first.my-testing should not validate", + validator.isValid("http://first.my-testing/test/index.html")); + + assertFalse("broke.hostname should not validate", + validator.isValid("http://broke.hostname/test/index.html")); + + assertTrue("www.apache.org should still validate", + validator.isValid("http://www.apache.org/test/index.html")); + + // Turn it off, and check + validator = new UrlValidator(0); + + assertFalse("hostname should no longer validate", + validator.isValid("http://hostname")); + + assertFalse("localhost URL should no longer validate", + validator.isValid("http://localhost/test/index.html")); + + assertTrue("www.apache.org should still validate", + validator.isValid("http://www.apache.org/test/index.html")); + } + + public void testValidator276() { + // file:// isn't allowed by default + UrlValidator validator = new UrlValidator(); + + assertTrue("http://apache.org/ should be allowed by default", + validator.isValid("http://www.apache.org/test/index.html")); + + assertFalse("file:///c:/ shouldn't be allowed by default", + validator.isValid("file:///C:/some.file")); + + assertFalse("file:///c:\\ shouldn't be allowed by default", + validator.isValid("file:///C:\\some.file")); + + assertFalse("file:///etc/ shouldn't be allowed by default", + validator.isValid("file:///etc/hosts")); + + assertFalse("file://localhost/etc/ shouldn't be allowed by default", + validator.isValid("file://localhost/etc/hosts")); + + assertFalse("file://localhost/c:/ shouldn't be allowed by default", + validator.isValid("file://localhost/c:/some.file")); + + // Turn it on, and check + // Note - we need to enable local urls when working with file: + validator = new UrlValidator(new String[] {"http","file"}, UrlValidator.ALLOW_LOCAL_URLS); + + assertTrue("http://apache.org/ should be allowed by default", + validator.isValid("http://www.apache.org/test/index.html")); + + assertTrue("file:///c:/ should now be allowed", + validator.isValid("file:///C:/some.file")); + + // Currently, we don't support the c:\ form + assertFalse("file:///c:\\ shouldn't be allowed", + validator.isValid("file:///C:\\some.file")); + + assertTrue("file:///etc/ should now be allowed", + validator.isValid("file:///etc/hosts")); + + assertTrue("file://localhost/etc/ should now be allowed", + validator.isValid("file://localhost/etc/hosts")); + + assertTrue("file://localhost/c:/ should now be allowed", + validator.isValid("file://localhost/c:/some.file")); + + // These are never valid + assertFalse("file://c:/ shouldn't ever be allowed, needs file:///c:/", + validator.isValid("file://C:/some.file")); + + assertFalse("file://c:\\ shouldn't ever be allowed, needs file:///c:/", + validator.isValid("file://C:\\some.file")); + } + + public void testValidator391OK() { + String[] schemes = {"file"}; + UrlValidator urlValidator = new UrlValidator(schemes); + assertTrue(urlValidator.isValid("file:///C:/path/to/dir/")); + } + + public void testValidator391FAILS() { + String[] schemes = {"file"}; + UrlValidator urlValidator = new UrlValidator(schemes); + assertTrue(urlValidator.isValid("file:/C:/path/to/dir/")); + } + + public void testValidator309() { + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://sample.ondemand.com/")); + assertTrue(urlValidator.isValid("hTtP://sample.ondemand.CoM/")); + assertTrue(urlValidator.isValid("httpS://SAMPLE.ONEMAND.COM/")); + urlValidator = new UrlValidator(new String[] {"HTTP","HTTPS"}); + assertTrue(urlValidator.isValid("http://sample.ondemand.com/")); + assertTrue(urlValidator.isValid("hTtP://sample.ondemand.CoM/")); + assertTrue(urlValidator.isValid("httpS://SAMPLE.ONEMAND.COM/")); + } + + public void testValidator339(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://www.cnn.com/WORLD/?hpt=sitenav")); // without + assertTrue(urlValidator.isValid("http://www.cnn.com./WORLD/?hpt=sitenav")); // with + assertFalse(urlValidator.isValid("http://www.cnn.com../")); // doubly dotty + assertFalse(urlValidator.isValid("http://www.cnn.invalid/")); + assertFalse(urlValidator.isValid("http://www.cnn.invalid./")); // check . does not affect invalid domains + } + + public void testValidator339IDN(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://президент.рф/WORLD/?hpt=sitenav")); // without + assertTrue(urlValidator.isValid("http://президент.рф./WORLD/?hpt=sitenav")); // with + assertFalse(urlValidator.isValid("http://президент.рф..../")); // very dotty + assertFalse(urlValidator.isValid("http://президент.рф.../")); // triply dotty + assertFalse(urlValidator.isValid("http://президент.рф../")); // doubly dotty + } + + public void testValidator342(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://example.rocks/")); + assertTrue(urlValidator.isValid("http://example.rocks")); + } + + public void testValidator411(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://example.rocks:/")); + assertTrue(urlValidator.isValid("http://example.rocks:0/")); + assertTrue(urlValidator.isValid("http://example.rocks:65535/")); + assertFalse(urlValidator.isValid("http://example.rocks:65536/")); + assertFalse(urlValidator.isValid("http://example.rocks:100000/")); + } + + static boolean incrementTestPartsIndex(int[] testPartsIndex, Object[] testParts) { + boolean carry = true; //add 1 to lowest order part. + boolean maxIndex = true; + for (int testPartsIndexIndex = testPartsIndex.length - 1; testPartsIndexIndex >= 0; --testPartsIndexIndex) { + int index = testPartsIndex[testPartsIndexIndex]; + ResultPair[] part = (ResultPair[]) testParts[testPartsIndexIndex]; + maxIndex &= (index == (part.length - 1)); + if (carry) { + if (index < part.length - 1) { + index++; + testPartsIndex[testPartsIndexIndex] = index; + carry = false; + } else { + testPartsIndex[testPartsIndexIndex] = 0; + carry = true; + } + } + } + + + return (!maxIndex); + } + + private String testPartsIndextoString() { + StringBuilder carryMsg = new StringBuilder("{"); + for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) { + carryMsg.append(testPartsIndex[testPartsIndexIndex]); + if (testPartsIndexIndex < testPartsIndex.length - 1) { + carryMsg.append(','); + } else { + carryMsg.append('}'); + } + } + return carryMsg.toString(); + + } + + public void testValidateUrl() { + assertTrue(true); + } + + public void testValidator290() { + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("http://xn--h1acbxfam.idn.icann.org/")); +// assertTrue(validator.isValid("http://xn--e1afmkfd.xn--80akhbyknj4f")); + // Internationalized country code top-level domains + assertTrue(validator.isValid("http://test.xn--lgbbat1ad8j")); //Algeria + assertTrue(validator.isValid("http://test.xn--fiqs8s")); // China + assertTrue(validator.isValid("http://test.xn--fiqz9s")); // China + assertTrue(validator.isValid("http://test.xn--wgbh1c")); // Egypt + assertTrue(validator.isValid("http://test.xn--j6w193g")); // Hong Kong + assertTrue(validator.isValid("http://test.xn--h2brj9c")); // India + assertTrue(validator.isValid("http://test.xn--mgbbh1a71e")); // India + assertTrue(validator.isValid("http://test.xn--fpcrj9c3d")); // India + assertTrue(validator.isValid("http://test.xn--gecrj9c")); // India + assertTrue(validator.isValid("http://test.xn--s9brj9c")); // India + assertTrue(validator.isValid("http://test.xn--xkc2dl3a5ee0h")); // India + assertTrue(validator.isValid("http://test.xn--45brj9c")); // India + assertTrue(validator.isValid("http://test.xn--mgba3a4f16a")); // Iran + assertTrue(validator.isValid("http://test.xn--mgbayh7gpa")); // Jordan + assertTrue(validator.isValid("http://test.xn--mgbc0a9azcg")); // Morocco + assertTrue(validator.isValid("http://test.xn--ygbi2ammx")); // Palestinian Territory + assertTrue(validator.isValid("http://test.xn--wgbl6a")); // Qatar + assertTrue(validator.isValid("http://test.xn--p1ai")); // Russia + assertTrue(validator.isValid("http://test.xn--mgberp4a5d4ar")); // Saudi Arabia + assertTrue(validator.isValid("http://test.xn--90a3ac")); // Serbia + assertTrue(validator.isValid("http://test.xn--yfro4i67o")); // Singapore + assertTrue(validator.isValid("http://test.xn--clchc0ea0b2g2a9gcd")); // Singapore + assertTrue(validator.isValid("http://test.xn--3e0b707e")); // South Korea + assertTrue(validator.isValid("http://test.xn--fzc2c9e2c")); // Sri Lanka + assertTrue(validator.isValid("http://test.xn--xkc2al3hye2a")); // Sri Lanka + assertTrue(validator.isValid("http://test.xn--ogbpf8fl")); // Syria + assertTrue(validator.isValid("http://test.xn--kprw13d")); // Taiwan + assertTrue(validator.isValid("http://test.xn--kpry57d")); // Taiwan + assertTrue(validator.isValid("http://test.xn--o3cw4h")); // Thailand + assertTrue(validator.isValid("http://test.xn--pgbs0dh")); // Tunisia + assertTrue(validator.isValid("http://test.xn--mgbaam7a8h")); // United Arab Emirates + // Proposed internationalized ccTLDs +// assertTrue(validator.isValid("http://test.xn--54b7fta0cc")); // Bangladesh +// assertTrue(validator.isValid("http://test.xn--90ae")); // Bulgaria +// assertTrue(validator.isValid("http://test.xn--node")); // Georgia +// assertTrue(validator.isValid("http://test.xn--4dbrk0ce")); // Israel +// assertTrue(validator.isValid("http://test.xn--mgb9awbf")); // Oman +// assertTrue(validator.isValid("http://test.xn--j1amh")); // Ukraine +// assertTrue(validator.isValid("http://test.xn--mgb2ddes")); // Yemen + // Test TLDs +// assertTrue(validator.isValid("http://test.xn--kgbechtv")); // Arabic +// assertTrue(validator.isValid("http://test.xn--hgbk6aj7f53bba")); // Persian +// assertTrue(validator.isValid("http://test.xn--0zwm56d")); // Chinese +// assertTrue(validator.isValid("http://test.xn--g6w251d")); // Chinese +// assertTrue(validator.isValid("http://test.xn--80akhbyknj4f")); // Russian +// assertTrue(validator.isValid("http://test.xn--11b5bs3a9aj6g")); // Hindi +// assertTrue(validator.isValid("http://test.xn--jxalpdlp")); // Greek +// assertTrue(validator.isValid("http://test.xn--9t4b11yi5a")); // Korean +// assertTrue(validator.isValid("http://test.xn--deba0ad")); // Yiddish +// assertTrue(validator.isValid("http://test.xn--zckzah")); // Japanese +// assertTrue(validator.isValid("http://test.xn--hlcj6aya9esc7a")); // Tamil + } + + public void testValidator361() { + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("http://hello.tokyo/")); + } + + public void testValidator363(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://www.example.org/a/b/hello..world")); + assertTrue(urlValidator.isValid("http://www.example.org/a/hello..world")); + assertTrue(urlValidator.isValid("http://www.example.org/hello.world/")); + assertTrue(urlValidator.isValid("http://www.example.org/hello..world/")); + assertTrue(urlValidator.isValid("http://www.example.org/hello.world")); + assertTrue(urlValidator.isValid("http://www.example.org/hello..world")); + assertTrue(urlValidator.isValid("http://www.example.org/..world")); + assertTrue(urlValidator.isValid("http://www.example.org/.../world")); + assertFalse(urlValidator.isValid("http://www.example.org/../world")); + assertFalse(urlValidator.isValid("http://www.example.org/..")); + assertFalse(urlValidator.isValid("http://www.example.org/../")); + assertFalse(urlValidator.isValid("http://www.example.org/./..")); + assertFalse(urlValidator.isValid("http://www.example.org/././..")); + assertTrue(urlValidator.isValid("http://www.example.org/...")); + assertTrue(urlValidator.isValid("http://www.example.org/.../")); + assertTrue(urlValidator.isValid("http://www.example.org/.../..")); + } + + public void testValidator375() { + UrlValidator validator = new UrlValidator(); + String url = "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html"; + assertTrue("IPv6 address URL should validate: " + url, validator.isValid(url)); + url = "http://[::1]:80/index.html"; + assertTrue("IPv6 address URL should validate: " + url, validator.isValid(url)); + url = "http://FEDC:BA98:7654:3210:FEDC:BA98:7654:3210:80/index.html"; + assertFalse("IPv6 address without [] should not validate: " + url, validator.isValid(url)); + } + + + public void testValidator353() { // userinfo + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("http://www.apache.org:80/path")); + assertTrue(validator.isValid("http://user:pass@www.apache.org:80/path")); + assertTrue(validator.isValid("http://user:@www.apache.org:80/path")); + assertTrue(validator.isValid("http://user@www.apache.org:80/path")); + assertTrue(validator.isValid("http://us%00er:-._~!$&'()*+,;=@www.apache.org:80/path")); + assertFalse(validator.isValid("http://:pass@www.apache.org:80/path")); + assertFalse(validator.isValid("http://:@www.apache.org:80/path")); + assertFalse(validator.isValid("http://user:pa:ss@www.apache.org/path")); + assertFalse(validator.isValid("http://user:pa@ss@www.apache.org/path")); + } + + public void testValidator382() { + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("ftp://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose")); + } + + public void testValidator380() { + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("http://www.apache.org:80/path")); + assertTrue(validator.isValid("http://www.apache.org:8/path")); + assertTrue(validator.isValid("http://www.apache.org:/path")); + } + + public void testValidator420() { + UrlValidator validator = new UrlValidator(); + assertFalse(validator.isValid("http://example.com/serach?address=Main Avenue")); + assertTrue(validator.isValid("http://example.com/serach?address=Main%20Avenue")); + assertTrue(validator.isValid("http://example.com/serach?address=Main+Avenue")); + } + + //-------------------- Test data for creating a composite URL + /** + * The data given below approximates the 4 parts of a URL + * ://? except that the port number + * is broken out of authority to increase the number of permutations. + * A complete URL is composed of a scheme+authority+port+path+query, + * all of which must be individually valid for the entire URL to be considered + * valid. + */ + ResultPair[] testUrlScheme = {new ResultPair("http://", true), + new ResultPair("ftp://", true), + new ResultPair("h3t://", true), + new ResultPair("3ht://", false), + new ResultPair("http:/", false), + new ResultPair("http:", false), + new ResultPair("http/", false), + new ResultPair("://", false)}; + + ResultPair[] testUrlAuthority = {new ResultPair("www.google.com", true), + new ResultPair("www.google.com.", true), + new ResultPair("go.com", true), + new ResultPair("go.au", true), + new ResultPair("0.0.0.0", true), + new ResultPair("255.255.255.255", true), + new ResultPair("256.256.256.256", false), + new ResultPair("255.com", true), + new ResultPair("1.2.3.4.5", false), + new ResultPair("1.2.3.4.", false), + new ResultPair("1.2.3", false), + new ResultPair(".1.2.3.4", false), + new ResultPair("go.a", false), + new ResultPair("go.a1a", false), + new ResultPair("go.cc", true), + new ResultPair("go.1aa", false), + new ResultPair("aaa.", false), + new ResultPair(".aaa", false), + new ResultPair("aaa", false), + new ResultPair("", false) + }; + ResultPair[] testUrlPort = {new ResultPair(":80", true), + new ResultPair(":65535", true), // max possible + new ResultPair(":65536", false), // max possible +1 + new ResultPair(":0", true), + new ResultPair("", true), + new ResultPair(":-1", false), + new ResultPair(":65636", false), + new ResultPair(":999999999999999999", false), + new ResultPair(":65a", false) + }; + ResultPair[] testPath = {new ResultPair("/test1", true), + new ResultPair("/t123", true), + new ResultPair("/$23", true), + new ResultPair("/..", false), + new ResultPair("/../", false), + new ResultPair("/test1/", true), + new ResultPair("", true), + new ResultPair("/test1/file", true), + new ResultPair("/..//file", false), + new ResultPair("/test1//file", false) + }; + //Test allow2slash, noFragment + ResultPair[] testUrlPathOptions = {new ResultPair("/test1", true), + new ResultPair("/t123", true), + new ResultPair("/$23", true), + new ResultPair("/..", false), + new ResultPair("/../", false), + new ResultPair("/test1/", true), + new ResultPair("/#", false), + new ResultPair("", true), + new ResultPair("/test1/file", true), + new ResultPair("/t123/file", true), + new ResultPair("/$23/file", true), + new ResultPair("/../file", false), + new ResultPair("/..//file", false), + new ResultPair("/test1//file", true), + new ResultPair("/#/file", false) + }; + + ResultPair[] testUrlQuery = {new ResultPair("?action=view", true), + new ResultPair("?action=edit&mode=up", true), + new ResultPair("", true) + }; + + Object[] testUrlParts = {testUrlScheme, testUrlAuthority, testUrlPort, testPath, testUrlQuery}; + Object[] testUrlPartsOptions = {testUrlScheme, testUrlAuthority, testUrlPort, testUrlPathOptions, testUrlQuery}; + int[] testPartsIndex = {0, 0, 0, 0, 0}; + + //---------------- Test data for individual url parts ---------------- + private final String[] schemes = {"http", "gopher", "g0-To+.", + "not_valid" // TODO this will need to be dropped if the ctor validates schemes + }; + + ResultPair[] testScheme = {new ResultPair("http", true), + new ResultPair("ftp", false), + new ResultPair("httpd", false), + new ResultPair("gopher", true), + new ResultPair("g0-to+.", true), + new ResultPair("not_valid", false), // underscore not allowed + new ResultPair("HtTp", true), + new ResultPair("telnet", false)}; + + +} diff --git a/projects/bleckw/FinalProject/URLValidatorInCorrect/src/DomainValidator.java b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/DomainValidator.java new file mode 100644 index 00000000..a8e8a793 --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/DomainValidator.java @@ -0,0 +1,2064 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.net.IDN; +import java.util.Arrays; +import java.util.Locale; + +/** + *

Domain name validation routines.

+ * + *

+ * This validator provides methods for validating Internet domain names + * and top-level domains. + *

+ * + *

Domain names are evaluated according + * to the standards RFC1034, + * section 3, and RFC1123, + * section 2.1. No accommodation is provided for the specialized needs of + * other applications; if the domain name has been URL-encoded, for example, + * validation will fail even though the equivalent plaintext version of the + * same name would have passed. + *

+ * + *

+ * Validation is also provided for top-level domains (TLDs) as defined and + * maintained by the Internet Assigned Numbers Authority (IANA): + *

+ * + *
    + *
  • {@link #isValidInfrastructureTld} - validates infrastructure TLDs + * (.arpa, etc.)
  • + *
  • {@link #isValidGenericTld} - validates generic TLDs + * (.com, .org, etc.)
  • + *
  • {@link #isValidCountryCodeTld} - validates country code TLDs + * (.us, .uk, .cn, etc.)
  • + *
+ * + *

+ * (NOTE: This class does not provide IP address lookup for domain names or + * methods to ensure that a given domain name matches a specific IP; see + * {@link java.net.InetAddress} for that functionality.) + *

+ * + * @version $Revision: 1781829 $ + * @since Validator 1.4 + */ +public class DomainValidator implements Serializable { + + private static final int MAX_DOMAIN_LENGTH = 253; + + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private static final long serialVersionUID = -4407125112880174009L; + + // Regular expression strings for hostnames (derived from RFC2396 and RFC 1123) + + // RFC2396: domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum + // Max 63 characters + private static final String DOMAIN_LABEL_REGEX = "\\p{Alnum}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?"; + + // RFC2396 toplabel = alpha | alpha *( alphanum | "-" ) alphanum + // Max 63 characters + private static final String TOP_LABEL_REGEX = "\\p{Alpha}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?"; + + // RFC2396 hostname = *( domainlabel "." ) toplabel [ "." ] + // Note that the regex currently requires both a domain label and a top level label, whereas + // the RFC does not. This is because the regex is used to detect if a TLD is present. + // If the match fails, input is checked against DOMAIN_LABEL_REGEX (hostnameRegex) + // RFC1123 sec 2.1 allows hostnames to start with a digit + private static final String DOMAIN_NAME_REGEX = + "^(?:" + DOMAIN_LABEL_REGEX + "\\.)+" + "(" + TOP_LABEL_REGEX + ")\\.?$"; + + private final boolean allowLocal; + + /** + * Singleton instance of this validator, which + * doesn't consider local addresses as valid. + */ + private static final DomainValidator DOMAIN_VALIDATOR = new DomainValidator(false); + + /** + * Singleton instance of this validator, which does + * consider local addresses valid. + */ + private static final DomainValidator DOMAIN_VALIDATOR_WITH_LOCAL = new DomainValidator(true); + + /** + * RegexValidator for matching domains. + */ + private final RegexValidator domainRegex = + new RegexValidator(DOMAIN_NAME_REGEX); + /** + * RegexValidator for matching a local hostname + */ + // RFC1123 sec 2.1 allows hostnames to start with a digit + private final RegexValidator hostnameRegex = + new RegexValidator(DOMAIN_LABEL_REGEX); + + /** + * Returns the singleton instance of this validator. It + * will not consider local addresses as valid. + * @return the singleton instance of this validator + */ + public static synchronized DomainValidator getInstance() { + inUse = true; + return DOMAIN_VALIDATOR; + } + + /** + * Returns the singleton instance of this validator, + * with local validation as required. + * @param allowLocal Should local addresses be considered valid? + * @return the singleton instance of this validator + */ + public static synchronized DomainValidator getInstance(boolean allowLocal) { + inUse = true; + if(allowLocal) { + return DOMAIN_VALIDATOR_WITH_LOCAL; + } + return DOMAIN_VALIDATOR; + } + + /** Private constructor. */ + private DomainValidator(boolean allowLocal) { + this.allowLocal = allowLocal; + } + + /** + * Returns true if the specified String parses + * as a valid domain name with a recognized top-level domain. + * The parsing is case-insensitive. + * @param domain the parameter to check for domain name syntax + * @return true if the parameter is a valid domain name + */ + public boolean isValid(String domain) { + if (domain == null) { + return false; + } + domain = unicodeToASCII(domain); + // hosts must be equally reachable via punycode and Unicode; + // Unicode is never shorter than punycode, so check punycode + // if domain did not convert, then it will be caught by ASCII + // checks in the regexes below + if (domain.length() > MAX_DOMAIN_LENGTH) { + return false; + } + String[] groups = domainRegex.match(domain); + if (groups != null && groups.length > 0) { + return isValidTld(groups[0]); + } + return allowLocal && hostnameRegex.isValid(domain); + } + + // package protected for unit test access + // must agree with isValid() above + final boolean isValidDomainSyntax(String domain) { + if (domain == null) { + return false; + } + domain = unicodeToASCII(domain); + // hosts must be equally reachable via punycode and Unicode; + // Unicode is never shorter than punycode, so check punycode + // if domain did not convert, then it will be caught by ASCII + // checks in the regexes below + if (domain.length() > MAX_DOMAIN_LENGTH) { + return false; + } + String[] groups = domainRegex.match(domain); + return (groups != null && groups.length > 0) + || hostnameRegex.isValid(domain); + } + + /** + * Returns true if the specified String matches any + * IANA-defined top-level domain. Leading dots are ignored if present. + * The search is case-insensitive. + * @param tld the parameter to check for TLD status, not null + * @return true if the parameter is a TLD + */ + public boolean isValidTld(String tld) { + tld = unicodeToASCII(tld); + if(allowLocal && isValidLocalTld(tld)) { + return true; + } + return isValidInfrastructureTld(tld) + || isValidGenericTld(tld) + || isValidCountryCodeTld(tld); + } + + /** + * Returns true if the specified String matches any + * IANA-defined infrastructure top-level domain. Leading dots are + * ignored if present. The search is case-insensitive. + * @param iTld the parameter to check for infrastructure TLD status, not null + * @return true if the parameter is an infrastructure TLD + */ + public boolean isValidInfrastructureTld(String iTld) { + final String key = chompLeadingDot(unicodeToASCII(iTld).toLowerCase(Locale.ENGLISH)); + return arrayContains(INFRASTRUCTURE_TLDS, key); + } + + /** + * Returns true if the specified String matches any + * IANA-defined generic top-level domain. Leading dots are ignored + * if present. The search is case-insensitive. + * @param gTld the parameter to check for generic TLD status, not null + * @return true if the parameter is a generic TLD + */ + public boolean isValidGenericTld(String gTld) { + final String key = chompLeadingDot(unicodeToASCII(gTld).toLowerCase(Locale.ENGLISH)); + return (arrayContains(GENERIC_TLDS, key) || arrayContains(genericTLDsPlus, key)) + && !arrayContains(genericTLDsMinus, key); + } + + /** + * Returns true if the specified String matches any + * IANA-defined country code top-level domain. Leading dots are + * ignored if present. The search is case-insensitive. + * @param ccTld the parameter to check for country code TLD status, not null + * @return true if the parameter is a country code TLD + */ + public boolean isValidCountryCodeTld(String ccTld) { + final String key = chompLeadingDot(unicodeToASCII(ccTld).toLowerCase(Locale.ENGLISH)); + return (arrayContains(COUNTRY_CODE_TLDS, key) || arrayContains(countryCodeTLDsPlus, key)) + && !arrayContains(countryCodeTLDsMinus, key); + } + + /** + * Returns true if the specified String matches any + * widely used "local" domains (localhost or localdomain). Leading dots are + * ignored if present. The search is case-insensitive. + * @param lTld the parameter to check for local TLD status, not null + * @return true if the parameter is an local TLD + */ + public boolean isValidLocalTld(String lTld) { + final String key = chompLeadingDot(unicodeToASCII(lTld).toLowerCase(Locale.ENGLISH)); + return arrayContains(LOCAL_TLDS, key); + } + + private String chompLeadingDot(String str) { + if (str.startsWith(".")) { + return str.substring(1); + } + return str; + } + + // --------------------------------------------- + // ----- TLDs defined by IANA + // ----- Authoritative and comprehensive list at: + // ----- http://data.iana.org/TLD/tlds-alpha-by-domain.txt + + // Note that the above list is in UPPER case. + // The code currently converts strings to lower case (as per the tables below) + + // IANA also provide an HTML list at http://www.iana.org/domains/root/db + // Note that this contains several country code entries which are NOT in + // the text file. These all have the "Not assigned" in the "Sponsoring Organisation" column + // For example (as of 2015-01-02): + // .bl country-code Not assigned + // .um country-code Not assigned + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] INFRASTRUCTURE_TLDS = new String[] { + "arpa", // internet infrastructure + }; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] GENERIC_TLDS = new String[] { + // Taken from Version 2017020400, Last Updated Sat Feb 4 07:07:01 2017 UTC + "aaa", // aaa American Automobile Association, Inc. + "aarp", // aarp AARP + "abarth", // abarth Fiat Chrysler Automobiles N.V. + "abb", // abb ABB Ltd + "abbott", // abbott Abbott Laboratories, Inc. + "abbvie", // abbvie AbbVie Inc. + "abc", // abc Disney Enterprises, Inc. + "able", // able Able Inc. + "abogado", // abogado Top Level Domain Holdings Limited + "abudhabi", // abudhabi Abu Dhabi Systems and Information Centre + "academy", // academy Half Oaks, LLC + "accenture", // accenture Accenture plc + "accountant", // accountant dot Accountant Limited + "accountants", // accountants Knob Town, LLC + "aco", // aco ACO Severin Ahlmann GmbH & Co. KG + "active", // active The Active Network, Inc + "actor", // actor United TLD Holdco Ltd. + "adac", // adac Allgemeiner Deutscher Automobil-Club e.V. (ADAC) + "ads", // ads Charleston Road Registry Inc. + "adult", // adult ICM Registry AD LLC + "aeg", // aeg Aktiebolaget Electrolux + "aero", // aero Societe Internationale de Telecommunications Aeronautique (SITA INC USA) + "aetna", // aetna Aetna Life Insurance Company + "afamilycompany", // afamilycompany Johnson Shareholdings, Inc. + "afl", // afl Australian Football League + "agakhan", // agakhan Fondation Aga Khan (Aga Khan Foundation) + "agency", // agency Steel Falls, LLC + "aig", // aig American International Group, Inc. + "aigo", // aigo aigo Digital Technology Co,Ltd. + "airbus", // airbus Airbus S.A.S. + "airforce", // airforce United TLD Holdco Ltd. + "airtel", // airtel Bharti Airtel Limited + "akdn", // akdn Fondation Aga Khan (Aga Khan Foundation) + "alfaromeo", // alfaromeo Fiat Chrysler Automobiles N.V. + "alibaba", // alibaba Alibaba Group Holding Limited + "alipay", // alipay Alibaba Group Holding Limited + "allfinanz", // allfinanz Allfinanz Deutsche Vermögensberatung Aktiengesellschaft + "allstate", // allstate Allstate Fire and Casualty Insurance Company + "ally", // ally Ally Financial Inc. + "alsace", // alsace REGION D ALSACE + "alstom", // alstom ALSTOM + "americanexpress", // americanexpress American Express Travel Related Services Company, Inc. + "americanfamily", // americanfamily AmFam, Inc. + "amex", // amex American Express Travel Related Services Company, Inc. + "amfam", // amfam AmFam, Inc. + "amica", // amica Amica Mutual Insurance Company + "amsterdam", // amsterdam Gemeente Amsterdam + "analytics", // analytics Campus IP LLC + "android", // android Charleston Road Registry Inc. + "anquan", // anquan QIHOO 360 TECHNOLOGY CO. LTD. + "anz", // anz Australia and New Zealand Banking Group Limited + "aol", // aol AOL Inc. + "apartments", // apartments June Maple, LLC + "app", // app Charleston Road Registry Inc. + "apple", // apple Apple Inc. + "aquarelle", // aquarelle Aquarelle.com + "aramco", // aramco Aramco Services Company + "archi", // archi STARTING DOT LIMITED + "army", // army United TLD Holdco Ltd. + "art", // art UK Creative Ideas Limited + "arte", // arte Association Relative à la Télévision Européenne G.E.I.E. + "asda", // asda Wal-Mart Stores, Inc. + "asia", // asia DotAsia Organisation Ltd. + "associates", // associates Baxter Hill, LLC + "athleta", // athleta The Gap, Inc. + "attorney", // attorney United TLD Holdco, Ltd + "auction", // auction United TLD HoldCo, Ltd. + "audi", // audi AUDI Aktiengesellschaft + "audible", // audible Amazon Registry Services, Inc. + "audio", // audio Uniregistry, Corp. + "auspost", // auspost Australian Postal Corporation + "author", // author Amazon Registry Services, Inc. + "auto", // auto Uniregistry, Corp. + "autos", // autos DERAutos, LLC + "avianca", // avianca Aerovias del Continente Americano S.A. Avianca + "aws", // aws Amazon Registry Services, Inc. + "axa", // axa AXA SA + "azure", // azure Microsoft Corporation + "baby", // baby Johnson & Johnson Services, Inc. + "baidu", // baidu Baidu, Inc. + "banamex", // banamex Citigroup Inc. + "bananarepublic", // bananarepublic The Gap, Inc. + "band", // band United TLD Holdco, Ltd + "bank", // bank fTLD Registry Services, LLC + "bar", // bar Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable + "barcelona", // barcelona Municipi de Barcelona + "barclaycard", // barclaycard Barclays Bank PLC + "barclays", // barclays Barclays Bank PLC + "barefoot", // barefoot Gallo Vineyards, Inc. + "bargains", // bargains Half Hallow, LLC + "baseball", // baseball MLB Advanced Media DH, LLC + "basketball", // basketball Fédération Internationale de Basketball (FIBA) + "bauhaus", // bauhaus Werkhaus GmbH + "bayern", // bayern Bayern Connect GmbH + "bbc", // bbc British Broadcasting Corporation + "bbt", // bbt BB&T Corporation + "bbva", // bbva BANCO BILBAO VIZCAYA ARGENTARIA, S.A. + "bcg", // bcg The Boston Consulting Group, Inc. + "bcn", // bcn Municipi de Barcelona + "beats", // beats Beats Electronics, LLC + "beauty", // beauty L'Oréal + "beer", // beer Top Level Domain Holdings Limited + "bentley", // bentley Bentley Motors Limited + "berlin", // berlin dotBERLIN GmbH & Co. KG + "best", // best BestTLD Pty Ltd + "bestbuy", // bestbuy BBY Solutions, Inc. + "bet", // bet Afilias plc + "bharti", // bharti Bharti Enterprises (Holding) Private Limited + "bible", // bible American Bible Society + "bid", // bid dot Bid Limited + "bike", // bike Grand Hollow, LLC + "bing", // bing Microsoft Corporation + "bingo", // bingo Sand Cedar, LLC + "bio", // bio STARTING DOT LIMITED + "biz", // biz Neustar, Inc. + "black", // black Afilias Limited + "blackfriday", // blackfriday Uniregistry, Corp. + "blanco", // blanco BLANCO GmbH + Co KG + "blockbuster", // blockbuster Dish DBS Corporation + "blog", // blog Knock Knock WHOIS There, LLC + "bloomberg", // bloomberg Bloomberg IP Holdings LLC + "blue", // blue Afilias Limited + "bms", // bms Bristol-Myers Squibb Company + "bmw", // bmw Bayerische Motoren Werke Aktiengesellschaft + "bnl", // bnl Banca Nazionale del Lavoro + "bnpparibas", // bnpparibas BNP Paribas + "boats", // boats DERBoats, LLC + "boehringer", // boehringer Boehringer Ingelheim International GmbH + "bofa", // bofa NMS Services, Inc. + "bom", // bom Núcleo de Informação e Coordenação do Ponto BR - NIC.br + "bond", // bond Bond University Limited + "boo", // boo Charleston Road Registry Inc. + "book", // book Amazon Registry Services, Inc. + "booking", // booking Booking.com B.V. + "boots", // boots THE BOOTS COMPANY PLC + "bosch", // bosch Robert Bosch GMBH + "bostik", // bostik Bostik SA + "boston", // boston Boston TLD Management, LLC + "bot", // bot Amazon Registry Services, Inc. + "boutique", // boutique Over Galley, LLC + "box", // box NS1 Limited + "bradesco", // bradesco Banco Bradesco S.A. + "bridgestone", // bridgestone Bridgestone Corporation + "broadway", // broadway Celebrate Broadway, Inc. + "broker", // broker DOTBROKER REGISTRY LTD + "brother", // brother Brother Industries, Ltd. + "brussels", // brussels DNS.be vzw + "budapest", // budapest Top Level Domain Holdings Limited + "bugatti", // bugatti Bugatti International SA + "build", // build Plan Bee LLC + "builders", // builders Atomic Madison, LLC + "business", // business Spring Cross, LLC + "buy", // buy Amazon Registry Services, INC + "buzz", // buzz DOTSTRATEGY CO. + "bzh", // bzh Association www.bzh + "cab", // cab Half Sunset, LLC + "cafe", // cafe Pioneer Canyon, LLC + "cal", // cal Charleston Road Registry Inc. + "call", // call Amazon Registry Services, Inc. + "calvinklein", // calvinklein PVH gTLD Holdings LLC + "cam", // cam AC Webconnecting Holding B.V. + "camera", // camera Atomic Maple, LLC + "camp", // camp Delta Dynamite, LLC + "cancerresearch", // cancerresearch Australian Cancer Research Foundation + "canon", // canon Canon Inc. + "capetown", // capetown ZA Central Registry NPC trading as ZA Central Registry + "capital", // capital Delta Mill, LLC + "capitalone", // capitalone Capital One Financial Corporation + "car", // car Cars Registry Limited + "caravan", // caravan Caravan International, Inc. + "cards", // cards Foggy Hollow, LLC + "care", // care Goose Cross, LLC + "career", // career dotCareer LLC + "careers", // careers Wild Corner, LLC + "cars", // cars Uniregistry, Corp. + "cartier", // cartier Richemont DNS Inc. + "casa", // casa Top Level Domain Holdings Limited + "case", // case CNH Industrial N.V. + "caseih", // caseih CNH Industrial N.V. + "cash", // cash Delta Lake, LLC + "casino", // casino Binky Sky, LLC + "cat", // cat Fundacio puntCAT + "catering", // catering New Falls. LLC + "catholic", // catholic Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "cba", // cba COMMONWEALTH BANK OF AUSTRALIA + "cbn", // cbn The Christian Broadcasting Network, Inc. + "cbre", // cbre CBRE, Inc. + "cbs", // cbs CBS Domains Inc. + "ceb", // ceb The Corporate Executive Board Company + "center", // center Tin Mill, LLC + "ceo", // ceo CEOTLD Pty Ltd + "cern", // cern European Organization for Nuclear Research ("CERN") + "cfa", // cfa CFA Institute + "cfd", // cfd DOTCFD REGISTRY LTD + "chanel", // chanel Chanel International B.V. + "channel", // channel Charleston Road Registry Inc. + "chase", // chase JPMorgan Chase & Co. + "chat", // chat Sand Fields, LLC + "cheap", // cheap Sand Cover, LLC + "chintai", // chintai CHINTAI Corporation + "chloe", // chloe Richemont DNS Inc. + "christmas", // christmas Uniregistry, Corp. + "chrome", // chrome Charleston Road Registry Inc. + "chrysler", // chrysler FCA US LLC. + "church", // church Holly Fileds, LLC + "cipriani", // cipriani Hotel Cipriani Srl + "circle", // circle Amazon Registry Services, Inc. + "cisco", // cisco Cisco Technology, Inc. + "citadel", // citadel Citadel Domain LLC + "citi", // citi Citigroup Inc. + "citic", // citic CITIC Group Corporation + "city", // city Snow Sky, LLC + "cityeats", // cityeats Lifestyle Domain Holdings, Inc. + "claims", // claims Black Corner, LLC + "cleaning", // cleaning Fox Shadow, LLC + "click", // click Uniregistry, Corp. + "clinic", // clinic Goose Park, LLC + "clinique", // clinique The Estée Lauder Companies Inc. + "clothing", // clothing Steel Lake, LLC + "cloud", // cloud ARUBA S.p.A. + "club", // club .CLUB DOMAINS, LLC + "clubmed", // clubmed Club Méditerranée S.A. + "coach", // coach Koko Island, LLC + "codes", // codes Puff Willow, LLC + "coffee", // coffee Trixy Cover, LLC + "college", // college XYZ.COM LLC + "cologne", // cologne NetCologne Gesellschaft für Telekommunikation mbH + "com", // com VeriSign Global Registry Services + "comcast", // comcast Comcast IP Holdings I, LLC + "commbank", // commbank COMMONWEALTH BANK OF AUSTRALIA + "community", // community Fox Orchard, LLC + "company", // company Silver Avenue, LLC + "compare", // compare iSelect Ltd + "computer", // computer Pine Mill, LLC + "comsec", // comsec VeriSign, Inc. + "condos", // condos Pine House, LLC + "construction", // construction Fox Dynamite, LLC + "consulting", // consulting United TLD Holdco, LTD. + "contact", // contact Top Level Spectrum, Inc. + "contractors", // contractors Magic Woods, LLC + "cooking", // cooking Top Level Domain Holdings Limited + "cookingchannel", // cookingchannel Lifestyle Domain Holdings, Inc. + "cool", // cool Koko Lake, LLC + "coop", // coop DotCooperation LLC + "corsica", // corsica Collectivité Territoriale de Corse + "country", // country Top Level Domain Holdings Limited + "coupon", // coupon Amazon Registry Services, Inc. + "coupons", // coupons Black Island, LLC + "courses", // courses OPEN UNIVERSITIES AUSTRALIA PTY LTD + "credit", // credit Snow Shadow, LLC + "creditcard", // creditcard Binky Frostbite, LLC + "creditunion", // creditunion CUNA Performance Resources, LLC + "cricket", // cricket dot Cricket Limited + "crown", // crown Crown Equipment Corporation + "crs", // crs Federated Co-operatives Limited + "cruise", // cruise Viking River Cruises (Bermuda) Ltd. + "cruises", // cruises Spring Way, LLC + "csc", // csc Alliance-One Services, Inc. + "cuisinella", // cuisinella SALM S.A.S. + "cymru", // cymru Nominet UK + "cyou", // cyou Beijing Gamease Age Digital Technology Co., Ltd. + "dabur", // dabur Dabur India Limited + "dad", // dad Charleston Road Registry Inc. + "dance", // dance United TLD Holdco Ltd. + "data", // data Dish DBS Corporation + "date", // date dot Date Limited + "dating", // dating Pine Fest, LLC + "datsun", // datsun NISSAN MOTOR CO., LTD. + "day", // day Charleston Road Registry Inc. + "dclk", // dclk Charleston Road Registry Inc. + "dds", // dds Minds + Machines Group Limited + "deal", // deal Amazon Registry Services, Inc. + "dealer", // dealer Dealer Dot Com, Inc. + "deals", // deals Sand Sunset, LLC + "degree", // degree United TLD Holdco, Ltd + "delivery", // delivery Steel Station, LLC + "dell", // dell Dell Inc. + "deloitte", // deloitte Deloitte Touche Tohmatsu + "delta", // delta Delta Air Lines, Inc. + "democrat", // democrat United TLD Holdco Ltd. + "dental", // dental Tin Birch, LLC + "dentist", // dentist United TLD Holdco, Ltd + "desi", // desi Desi Networks LLC + "design", // design Top Level Design, LLC + "dev", // dev Charleston Road Registry Inc. + "dhl", // dhl Deutsche Post AG + "diamonds", // diamonds John Edge, LLC + "diet", // diet Uniregistry, Corp. + "digital", // digital Dash Park, LLC + "direct", // direct Half Trail, LLC + "directory", // directory Extra Madison, LLC + "discount", // discount Holly Hill, LLC + "discover", // discover Discover Financial Services + "dish", // dish Dish DBS Corporation + "diy", // diy Lifestyle Domain Holdings, Inc. + "dnp", // dnp Dai Nippon Printing Co., Ltd. + "docs", // docs Charleston Road Registry Inc. + "doctor", // doctor Brice Trail, LLC + "dodge", // dodge FCA US LLC. + "dog", // dog Koko Mill, LLC + "doha", // doha Communications Regulatory Authority (CRA) + "domains", // domains Sugar Cross, LLC +// "doosan", // doosan Doosan Corporation (retired) + "dot", // dot Dish DBS Corporation + "download", // download dot Support Limited + "drive", // drive Charleston Road Registry Inc. + "dtv", // dtv Dish DBS Corporation + "dubai", // dubai Dubai Smart Government Department + "duck", // duck Johnson Shareholdings, Inc. + "dunlop", // dunlop The Goodyear Tire & Rubber Company + "duns", // duns The Dun & Bradstreet Corporation + "dupont", // dupont E. I. du Pont de Nemours and Company + "durban", // durban ZA Central Registry NPC trading as ZA Central Registry + "dvag", // dvag Deutsche Vermögensberatung Aktiengesellschaft DVAG + "dvr", // dvr Hughes Satellite Systems Corporation + "earth", // earth Interlink Co., Ltd. + "eat", // eat Charleston Road Registry Inc. + "eco", // eco Big Room Inc. + "edeka", // edeka EDEKA Verband kaufmännischer Genossenschaften e.V. + "edu", // edu EDUCAUSE + "education", // education Brice Way, LLC + "email", // email Spring Madison, LLC + "emerck", // emerck Merck KGaA + "energy", // energy Binky Birch, LLC + "engineer", // engineer United TLD Holdco Ltd. + "engineering", // engineering Romeo Canyon + "enterprises", // enterprises Snow Oaks, LLC + "epost", // epost Deutsche Post AG + "epson", // epson Seiko Epson Corporation + "equipment", // equipment Corn Station, LLC + "ericsson", // ericsson Telefonaktiebolaget L M Ericsson + "erni", // erni ERNI Group Holding AG + "esq", // esq Charleston Road Registry Inc. + "estate", // estate Trixy Park, LLC + "esurance", // esurance Esurance Insurance Company + "eurovision", // eurovision European Broadcasting Union (EBU) + "eus", // eus Puntueus Fundazioa + "events", // events Pioneer Maple, LLC + "everbank", // everbank EverBank + "exchange", // exchange Spring Falls, LLC + "expert", // expert Magic Pass, LLC + "exposed", // exposed Victor Beach, LLC + "express", // express Sea Sunset, LLC + "extraspace", // extraspace Extra Space Storage LLC + "fage", // fage Fage International S.A. + "fail", // fail Atomic Pipe, LLC + "fairwinds", // fairwinds FairWinds Partners, LLC + "faith", // faith dot Faith Limited + "family", // family United TLD Holdco Ltd. + "fan", // fan Asiamix Digital Ltd + "fans", // fans Asiamix Digital Limited + "farm", // farm Just Maple, LLC + "farmers", // farmers Farmers Insurance Exchange + "fashion", // fashion Top Level Domain Holdings Limited + "fast", // fast Amazon Registry Services, Inc. + "fedex", // fedex Federal Express Corporation + "feedback", // feedback Top Level Spectrum, Inc. + "ferrari", // ferrari Fiat Chrysler Automobiles N.V. + "ferrero", // ferrero Ferrero Trading Lux S.A. + "fiat", // fiat Fiat Chrysler Automobiles N.V. + "fidelity", // fidelity Fidelity Brokerage Services LLC + "fido", // fido Rogers Communications Canada Inc. + "film", // film Motion Picture Domain Registry Pty Ltd + "final", // final Núcleo de Informação e Coordenação do Ponto BR - NIC.br + "finance", // finance Cotton Cypress, LLC + "financial", // financial Just Cover, LLC + "fire", // fire Amazon Registry Services, Inc. + "firestone", // firestone Bridgestone Corporation + "firmdale", // firmdale Firmdale Holdings Limited + "fish", // fish Fox Woods, LLC + "fishing", // fishing Top Level Domain Holdings Limited + "fit", // fit Minds + Machines Group Limited + "fitness", // fitness Brice Orchard, LLC + "flickr", // flickr Yahoo! Domain Services Inc. + "flights", // flights Fox Station, LLC + "flir", // flir FLIR Systems, Inc. + "florist", // florist Half Cypress, LLC + "flowers", // flowers Uniregistry, Corp. +// "flsmidth", // flsmidth FLSmidth A/S retired 2016-07-22 + "fly", // fly Charleston Road Registry Inc. + "foo", // foo Charleston Road Registry Inc. + "food", // food Lifestyle Domain Holdings, Inc. + "foodnetwork", // foodnetwork Lifestyle Domain Holdings, Inc. + "football", // football Foggy Farms, LLC + "ford", // ford Ford Motor Company + "forex", // forex DOTFOREX REGISTRY LTD + "forsale", // forsale United TLD Holdco, LLC + "forum", // forum Fegistry, LLC + "foundation", // foundation John Dale, LLC + "fox", // fox FOX Registry, LLC + "free", // free Amazon Registry Services, Inc. + "fresenius", // fresenius Fresenius Immobilien-Verwaltungs-GmbH + "frl", // frl FRLregistry B.V. + "frogans", // frogans OP3FT + "frontdoor", // frontdoor Lifestyle Domain Holdings, Inc. + "frontier", // frontier Frontier Communications Corporation + "ftr", // ftr Frontier Communications Corporation + "fujitsu", // fujitsu Fujitsu Limited + "fujixerox", // fujixerox Xerox DNHC LLC + "fun", // fun DotSpace, Inc. + "fund", // fund John Castle, LLC + "furniture", // furniture Lone Fields, LLC + "futbol", // futbol United TLD Holdco, Ltd. + "fyi", // fyi Silver Tigers, LLC + "gal", // gal Asociación puntoGAL + "gallery", // gallery Sugar House, LLC + "gallo", // gallo Gallo Vineyards, Inc. + "gallup", // gallup Gallup, Inc. + "game", // game Uniregistry, Corp. + "games", // games United TLD Holdco Ltd. + "gap", // gap The Gap, Inc. + "garden", // garden Top Level Domain Holdings Limited + "gbiz", // gbiz Charleston Road Registry Inc. + "gdn", // gdn Joint Stock Company "Navigation-information systems" + "gea", // gea GEA Group Aktiengesellschaft + "gent", // gent COMBELL GROUP NV/SA + "genting", // genting Resorts World Inc. Pte. Ltd. + "george", // george Wal-Mart Stores, Inc. + "ggee", // ggee GMO Internet, Inc. + "gift", // gift Uniregistry, Corp. + "gifts", // gifts Goose Sky, LLC + "gives", // gives United TLD Holdco Ltd. + "giving", // giving Giving Limited + "glade", // glade Johnson Shareholdings, Inc. + "glass", // glass Black Cover, LLC + "gle", // gle Charleston Road Registry Inc. + "global", // global Dot Global Domain Registry Limited + "globo", // globo Globo Comunicação e Participações S.A + "gmail", // gmail Charleston Road Registry Inc. + "gmbh", // gmbh Extra Dynamite, LLC + "gmo", // gmo GMO Internet, Inc. + "gmx", // gmx 1&1 Mail & Media GmbH + "godaddy", // godaddy Go Daddy East, LLC + "gold", // gold June Edge, LLC + "goldpoint", // goldpoint YODOBASHI CAMERA CO.,LTD. + "golf", // golf Lone Falls, LLC + "goo", // goo NTT Resonant Inc. + "goodhands", // goodhands Allstate Fire and Casualty Insurance Company + "goodyear", // goodyear The Goodyear Tire & Rubber Company + "goog", // goog Charleston Road Registry Inc. + "google", // google Charleston Road Registry Inc. + "gop", // gop Republican State Leadership Committee, Inc. + "got", // got Amazon Registry Services, Inc. + "gov", // gov General Services Administration Attn: QTDC, 2E08 (.gov Domain Registration) + "grainger", // grainger Grainger Registry Services, LLC + "graphics", // graphics Over Madison, LLC + "gratis", // gratis Pioneer Tigers, LLC + "green", // green Afilias Limited + "gripe", // gripe Corn Sunset, LLC + "group", // group Romeo Town, LLC + "guardian", // guardian The Guardian Life Insurance Company of America + "gucci", // gucci Guccio Gucci S.p.a. + "guge", // guge Charleston Road Registry Inc. + "guide", // guide Snow Moon, LLC + "guitars", // guitars Uniregistry, Corp. + "guru", // guru Pioneer Cypress, LLC + "hair", // hair L'Oreal + "hamburg", // hamburg Hamburg Top-Level-Domain GmbH + "hangout", // hangout Charleston Road Registry Inc. + "haus", // haus United TLD Holdco, LTD. + "hbo", // hbo HBO Registry Services, Inc. + "hdfc", // hdfc HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED + "hdfcbank", // hdfcbank HDFC Bank Limited + "health", // health DotHealth, LLC + "healthcare", // healthcare Silver Glen, LLC + "help", // help Uniregistry, Corp. + "helsinki", // helsinki City of Helsinki + "here", // here Charleston Road Registry Inc. + "hermes", // hermes Hermes International + "hgtv", // hgtv Lifestyle Domain Holdings, Inc. + "hiphop", // hiphop Uniregistry, Corp. + "hisamitsu", // hisamitsu Hisamitsu Pharmaceutical Co.,Inc. + "hitachi", // hitachi Hitachi, Ltd. + "hiv", // hiv dotHIV gemeinnuetziger e.V. + "hkt", // hkt PCCW-HKT DataCom Services Limited + "hockey", // hockey Half Willow, LLC + "holdings", // holdings John Madison, LLC + "holiday", // holiday Goose Woods, LLC + "homedepot", // homedepot Homer TLC, Inc. + "homegoods", // homegoods The TJX Companies, Inc. + "homes", // homes DERHomes, LLC + "homesense", // homesense The TJX Companies, Inc. + "honda", // honda Honda Motor Co., Ltd. + "honeywell", // honeywell Honeywell GTLD LLC + "horse", // horse Top Level Domain Holdings Limited + "hospital", // hospital Ruby Pike, LLC + "host", // host DotHost Inc. + "hosting", // hosting Uniregistry, Corp. + "hot", // hot Amazon Registry Services, Inc. + "hoteles", // hoteles Travel Reservations SRL + "hotmail", // hotmail Microsoft Corporation + "house", // house Sugar Park, LLC + "how", // how Charleston Road Registry Inc. + "hsbc", // hsbc HSBC Holdings PLC + "htc", // htc HTC corporation + "hughes", // hughes Hughes Satellite Systems Corporation + "hyatt", // hyatt Hyatt GTLD, L.L.C. + "hyundai", // hyundai Hyundai Motor Company + "ibm", // ibm International Business Machines Corporation + "icbc", // icbc Industrial and Commercial Bank of China Limited + "ice", // ice IntercontinentalExchange, Inc. + "icu", // icu One.com A/S + "ieee", // ieee IEEE Global LLC + "ifm", // ifm ifm electronic gmbh +// "iinet", // iinet Connect West Pty. Ltd. (Retired) + "ikano", // ikano Ikano S.A. + "imamat", // imamat Fondation Aga Khan (Aga Khan Foundation) + "imdb", // imdb Amazon Registry Services, Inc. + "immo", // immo Auburn Bloom, LLC + "immobilien", // immobilien United TLD Holdco Ltd. + "industries", // industries Outer House, LLC + "infiniti", // infiniti NISSAN MOTOR CO., LTD. + "info", // info Afilias Limited + "ing", // ing Charleston Road Registry Inc. + "ink", // ink Top Level Design, LLC + "institute", // institute Outer Maple, LLC + "insurance", // insurance fTLD Registry Services LLC + "insure", // insure Pioneer Willow, LLC + "int", // int Internet Assigned Numbers Authority + "intel", // intel Intel Corporation + "international", // international Wild Way, LLC + "intuit", // intuit Intuit Administrative Services, Inc. + "investments", // investments Holly Glen, LLC + "ipiranga", // ipiranga Ipiranga Produtos de Petroleo S.A. + "irish", // irish Dot-Irish LLC + "iselect", // iselect iSelect Ltd + "ismaili", // ismaili Fondation Aga Khan (Aga Khan Foundation) + "ist", // ist Istanbul Metropolitan Municipality + "istanbul", // istanbul Istanbul Metropolitan Municipality / Medya A.S. + "itau", // itau Itau Unibanco Holding S.A. + "itv", // itv ITV Services Limited + "iveco", // iveco CNH Industrial N.V. + "iwc", // iwc Richemont DNS Inc. + "jaguar", // jaguar Jaguar Land Rover Ltd + "java", // java Oracle Corporation + "jcb", // jcb JCB Co., Ltd. + "jcp", // jcp JCP Media, Inc. + "jeep", // jeep FCA US LLC. + "jetzt", // jetzt New TLD Company AB + "jewelry", // jewelry Wild Bloom, LLC + "jio", // jio Affinity Names, Inc. + "jlc", // jlc Richemont DNS Inc. + "jll", // jll Jones Lang LaSalle Incorporated + "jmp", // jmp Matrix IP LLC + "jnj", // jnj Johnson & Johnson Services, Inc. + "jobs", // jobs Employ Media LLC + "joburg", // joburg ZA Central Registry NPC trading as ZA Central Registry + "jot", // jot Amazon Registry Services, Inc. + "joy", // joy Amazon Registry Services, Inc. + "jpmorgan", // jpmorgan JPMorgan Chase & Co. + "jprs", // jprs Japan Registry Services Co., Ltd. + "juegos", // juegos Uniregistry, Corp. + "juniper", // juniper JUNIPER NETWORKS, INC. + "kaufen", // kaufen United TLD Holdco Ltd. + "kddi", // kddi KDDI CORPORATION + "kerryhotels", // kerryhotels Kerry Trading Co. Limited + "kerrylogistics", // kerrylogistics Kerry Trading Co. Limited + "kerryproperties", // kerryproperties Kerry Trading Co. Limited + "kfh", // kfh Kuwait Finance House + "kia", // kia KIA MOTORS CORPORATION + "kim", // kim Afilias Limited + "kinder", // kinder Ferrero Trading Lux S.A. + "kindle", // kindle Amazon Registry Services, Inc. + "kitchen", // kitchen Just Goodbye, LLC + "kiwi", // kiwi DOT KIWI LIMITED + "koeln", // koeln NetCologne Gesellschaft für Telekommunikation mbH + "komatsu", // komatsu Komatsu Ltd. + "kosher", // kosher Kosher Marketing Assets LLC + "kpmg", // kpmg KPMG International Cooperative (KPMG International Genossenschaft) + "kpn", // kpn Koninklijke KPN N.V. + "krd", // krd KRG Department of Information Technology + "kred", // kred KredTLD Pty Ltd + "kuokgroup", // kuokgroup Kerry Trading Co. Limited + "kyoto", // kyoto Academic Institution: Kyoto Jyoho Gakuen + "lacaixa", // lacaixa CAIXA D'ESTALVIS I PENSIONS DE BARCELONA + "ladbrokes", // ladbrokes LADBROKES INTERNATIONAL PLC + "lamborghini", // lamborghini Automobili Lamborghini S.p.A. + "lamer", // lamer The Estée Lauder Companies Inc. + "lancaster", // lancaster LANCASTER + "lancia", // lancia Fiat Chrysler Automobiles N.V. + "lancome", // lancome L'Oréal + "land", // land Pine Moon, LLC + "landrover", // landrover Jaguar Land Rover Ltd + "lanxess", // lanxess LANXESS Corporation + "lasalle", // lasalle Jones Lang LaSalle Incorporated + "lat", // lat ECOM-LAC Federación de Latinoamérica y el Caribe para Internet y el Comercio Electrónico + "latino", // latino Dish DBS Corporation + "latrobe", // latrobe La Trobe University + "law", // law Minds + Machines Group Limited + "lawyer", // lawyer United TLD Holdco, Ltd + "lds", // lds IRI Domain Management, LLC + "lease", // lease Victor Trail, LLC + "leclerc", // leclerc A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc + "lefrak", // lefrak LeFrak Organization, Inc. + "legal", // legal Blue Falls, LLC + "lego", // lego LEGO Juris A/S + "lexus", // lexus TOYOTA MOTOR CORPORATION + "lgbt", // lgbt Afilias Limited + "liaison", // liaison Liaison Technologies, Incorporated + "lidl", // lidl Schwarz Domains und Services GmbH & Co. KG + "life", // life Trixy Oaks, LLC + "lifeinsurance", // lifeinsurance American Council of Life Insurers + "lifestyle", // lifestyle Lifestyle Domain Holdings, Inc. + "lighting", // lighting John McCook, LLC + "like", // like Amazon Registry Services, Inc. + "lilly", // lilly Eli Lilly and Company + "limited", // limited Big Fest, LLC + "limo", // limo Hidden Frostbite, LLC + "lincoln", // lincoln Ford Motor Company + "linde", // linde Linde Aktiengesellschaft + "link", // link Uniregistry, Corp. + "lipsy", // lipsy Lipsy Ltd + "live", // live United TLD Holdco Ltd. + "living", // living Lifestyle Domain Holdings, Inc. + "lixil", // lixil LIXIL Group Corporation + "loan", // loan dot Loan Limited + "loans", // loans June Woods, LLC + "locker", // locker Dish DBS Corporation + "locus", // locus Locus Analytics LLC + "loft", // loft Annco, Inc. + "lol", // lol Uniregistry, Corp. + "london", // london Dot London Domains Limited + "lotte", // lotte Lotte Holdings Co., Ltd. + "lotto", // lotto Afilias Limited + "love", // love Merchant Law Group LLP + "lpl", // lpl LPL Holdings, Inc. + "lplfinancial", // lplfinancial LPL Holdings, Inc. + "ltd", // ltd Over Corner, LLC + "ltda", // ltda InterNetX Corp. + "lundbeck", // lundbeck H. Lundbeck A/S + "lupin", // lupin LUPIN LIMITED + "luxe", // luxe Top Level Domain Holdings Limited + "luxury", // luxury Luxury Partners LLC + "macys", // macys Macys, Inc. + "madrid", // madrid Comunidad de Madrid + "maif", // maif Mutuelle Assurance Instituteur France (MAIF) + "maison", // maison Victor Frostbite, LLC + "makeup", // makeup L'Oréal + "man", // man MAN SE + "management", // management John Goodbye, LLC + "mango", // mango PUNTO FA S.L. + "market", // market Unitied TLD Holdco, Ltd + "marketing", // marketing Fern Pass, LLC + "markets", // markets DOTMARKETS REGISTRY LTD + "marriott", // marriott Marriott Worldwide Corporation + "marshalls", // marshalls The TJX Companies, Inc. + "maserati", // maserati Fiat Chrysler Automobiles N.V. + "mattel", // mattel Mattel Sites, Inc. + "mba", // mba Lone Hollow, LLC + "mcd", // mcd McDonald’s Corporation + "mcdonalds", // mcdonalds McDonald’s Corporation + "mckinsey", // mckinsey McKinsey Holdings, Inc. + "med", // med Medistry LLC + "media", // media Grand Glen, LLC + "meet", // meet Afilias Limited + "melbourne", // melbourne The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation + "meme", // meme Charleston Road Registry Inc. + "memorial", // memorial Dog Beach, LLC + "men", // men Exclusive Registry Limited + "menu", // menu Wedding TLD2, LLC + "meo", // meo PT Comunicacoes S.A. + "metlife", // metlife MetLife Services and Solutions, LLC + "miami", // miami Top Level Domain Holdings Limited + "microsoft", // microsoft Microsoft Corporation + "mil", // mil DoD Network Information Center + "mini", // mini Bayerische Motoren Werke Aktiengesellschaft + "mint", // mint Intuit Administrative Services, Inc. + "mit", // mit Massachusetts Institute of Technology + "mitsubishi", // mitsubishi Mitsubishi Corporation + "mlb", // mlb MLB Advanced Media DH, LLC + "mls", // mls The Canadian Real Estate Association + "mma", // mma MMA IARD + "mobi", // mobi Afilias Technologies Limited dba dotMobi + "mobile", // mobile Dish DBS Corporation + "mobily", // mobily GreenTech Consultancy Company W.L.L. + "moda", // moda United TLD Holdco Ltd. + "moe", // moe Interlink Co., Ltd. + "moi", // moi Amazon Registry Services, Inc. + "mom", // mom Uniregistry, Corp. + "monash", // monash Monash University + "money", // money Outer McCook, LLC + "monster", // monster Monster Worldwide, Inc. + "montblanc", // montblanc Richemont DNS Inc. + "mopar", // mopar FCA US LLC. + "mormon", // mormon IRI Domain Management, LLC ("Applicant") + "mortgage", // mortgage United TLD Holdco, Ltd + "moscow", // moscow Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) + "moto", // moto Motorola Trademark Holdings, LLC + "motorcycles", // motorcycles DERMotorcycles, LLC + "mov", // mov Charleston Road Registry Inc. + "movie", // movie New Frostbite, LLC + "movistar", // movistar Telefónica S.A. + "msd", // msd MSD Registry Holdings, Inc. + "mtn", // mtn MTN Dubai Limited + "mtpc", // mtpc Mitsubishi Tanabe Pharma Corporation + "mtr", // mtr MTR Corporation Limited + "museum", // museum Museum Domain Management Association + "mutual", // mutual Northwestern Mutual MU TLD Registry, LLC +// "mutuelle", // mutuelle Fédération Nationale de la Mutualité Française (Retired) + "nab", // nab National Australia Bank Limited + "nadex", // nadex Nadex Domains, Inc + "nagoya", // nagoya GMO Registry, Inc. + "name", // name VeriSign Information Services, Inc. + "nationwide", // nationwide Nationwide Mutual Insurance Company + "natura", // natura NATURA COSMÉTICOS S.A. + "navy", // navy United TLD Holdco Ltd. + "nba", // nba NBA REGISTRY, LLC + "nec", // nec NEC Corporation + "net", // net VeriSign Global Registry Services + "netbank", // netbank COMMONWEALTH BANK OF AUSTRALIA + "netflix", // netflix Netflix, Inc. + "network", // network Trixy Manor, LLC + "neustar", // neustar NeuStar, Inc. + "new", // new Charleston Road Registry Inc. + "newholland", // newholland CNH Industrial N.V. + "news", // news United TLD Holdco Ltd. + "next", // next Next plc + "nextdirect", // nextdirect Next plc + "nexus", // nexus Charleston Road Registry Inc. + "nfl", // nfl NFL Reg Ops LLC + "ngo", // ngo Public Interest Registry + "nhk", // nhk Japan Broadcasting Corporation (NHK) + "nico", // nico DWANGO Co., Ltd. + "nike", // nike NIKE, Inc. + "nikon", // nikon NIKON CORPORATION + "ninja", // ninja United TLD Holdco Ltd. + "nissan", // nissan NISSAN MOTOR CO., LTD. + "nissay", // nissay Nippon Life Insurance Company + "nokia", // nokia Nokia Corporation + "northwesternmutual", // northwesternmutual Northwestern Mutual Registry, LLC + "norton", // norton Symantec Corporation + "now", // now Amazon Registry Services, Inc. + "nowruz", // nowruz Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "nowtv", // nowtv Starbucks (HK) Limited + "nra", // nra NRA Holdings Company, INC. + "nrw", // nrw Minds + Machines GmbH + "ntt", // ntt NIPPON TELEGRAPH AND TELEPHONE CORPORATION + "nyc", // nyc The City of New York by and through the New York City Department of Information Technology & Telecommunications + "obi", // obi OBI Group Holding SE & Co. KGaA + "observer", // observer Top Level Spectrum, Inc. + "off", // off Johnson Shareholdings, Inc. + "office", // office Microsoft Corporation + "okinawa", // okinawa BusinessRalliart inc. + "olayan", // olayan Crescent Holding GmbH + "olayangroup", // olayangroup Crescent Holding GmbH + "oldnavy", // oldnavy The Gap, Inc. + "ollo", // ollo Dish DBS Corporation + "omega", // omega The Swatch Group Ltd + "one", // one One.com A/S + "ong", // ong Public Interest Registry + "onl", // onl I-REGISTRY Ltd., Niederlassung Deutschland + "online", // online DotOnline Inc. + "onyourside", // onyourside Nationwide Mutual Insurance Company + "ooo", // ooo INFIBEAM INCORPORATION LIMITED + "open", // open American Express Travel Related Services Company, Inc. + "oracle", // oracle Oracle Corporation + "orange", // orange Orange Brand Services Limited + "org", // org Public Interest Registry (PIR) + "organic", // organic Afilias Limited + "orientexpress", // orientexpress Orient Express + "origins", // origins The Estée Lauder Companies Inc. + "osaka", // osaka Interlink Co., Ltd. + "otsuka", // otsuka Otsuka Holdings Co., Ltd. + "ott", // ott Dish DBS Corporation + "ovh", // ovh OVH SAS + "page", // page Charleston Road Registry Inc. + "pamperedchef", // pamperedchef The Pampered Chef, Ltd. + "panasonic", // panasonic Panasonic Corporation + "panerai", // panerai Richemont DNS Inc. + "paris", // paris City of Paris + "pars", // pars Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "partners", // partners Magic Glen, LLC + "parts", // parts Sea Goodbye, LLC + "party", // party Blue Sky Registry Limited + "passagens", // passagens Travel Reservations SRL + "pay", // pay Amazon Registry Services, Inc. + "pccw", // pccw PCCW Enterprises Limited + "pet", // pet Afilias plc + "pfizer", // pfizer Pfizer Inc. + "pharmacy", // pharmacy National Association of Boards of Pharmacy + "philips", // philips Koninklijke Philips N.V. + "phone", // phone Dish DBS Corporation + "photo", // photo Uniregistry, Corp. + "photography", // photography Sugar Glen, LLC + "photos", // photos Sea Corner, LLC + "physio", // physio PhysBiz Pty Ltd + "piaget", // piaget Richemont DNS Inc. + "pics", // pics Uniregistry, Corp. + "pictet", // pictet Pictet Europe S.A. + "pictures", // pictures Foggy Sky, LLC + "pid", // pid Top Level Spectrum, Inc. + "pin", // pin Amazon Registry Services, Inc. + "ping", // ping Ping Registry Provider, Inc. + "pink", // pink Afilias Limited + "pioneer", // pioneer Pioneer Corporation + "pizza", // pizza Foggy Moon, LLC + "place", // place Snow Galley, LLC + "play", // play Charleston Road Registry Inc. + "playstation", // playstation Sony Computer Entertainment Inc. + "plumbing", // plumbing Spring Tigers, LLC + "plus", // plus Sugar Mill, LLC + "pnc", // pnc PNC Domain Co., LLC + "pohl", // pohl Deutsche Vermögensberatung Aktiengesellschaft DVAG + "poker", // poker Afilias Domains No. 5 Limited + "politie", // politie Politie Nederland + "porn", // porn ICM Registry PN LLC + "post", // post Universal Postal Union + "pramerica", // pramerica Prudential Financial, Inc. + "praxi", // praxi Praxi S.p.A. + "press", // press DotPress Inc. + "prime", // prime Amazon Registry Services, Inc. + "pro", // pro Registry Services Corporation dba RegistryPro + "prod", // prod Charleston Road Registry Inc. + "productions", // productions Magic Birch, LLC + "prof", // prof Charleston Road Registry Inc. + "progressive", // progressive Progressive Casualty Insurance Company + "promo", // promo Afilias plc + "properties", // properties Big Pass, LLC + "property", // property Uniregistry, Corp. + "protection", // protection XYZ.COM LLC + "pru", // pru Prudential Financial, Inc. + "prudential", // prudential Prudential Financial, Inc. + "pub", // pub United TLD Holdco Ltd. + "pwc", // pwc PricewaterhouseCoopers LLP + "qpon", // qpon dotCOOL, Inc. + "quebec", // quebec PointQuébec Inc + "quest", // quest Quest ION Limited + "qvc", // qvc QVC, Inc. + "racing", // racing Premier Registry Limited + "radio", // radio European Broadcasting Union (EBU) + "raid", // raid Johnson Shareholdings, Inc. + "read", // read Amazon Registry Services, Inc. + "realestate", // realestate dotRealEstate LLC + "realtor", // realtor Real Estate Domains LLC + "realty", // realty Fegistry, LLC + "recipes", // recipes Grand Island, LLC + "red", // red Afilias Limited + "redstone", // redstone Redstone Haute Couture Co., Ltd. + "redumbrella", // redumbrella Travelers TLD, LLC + "rehab", // rehab United TLD Holdco Ltd. + "reise", // reise Foggy Way, LLC + "reisen", // reisen New Cypress, LLC + "reit", // reit National Association of Real Estate Investment Trusts, Inc. + "reliance", // reliance Reliance Industries Limited + "ren", // ren Beijing Qianxiang Wangjing Technology Development Co., Ltd. + "rent", // rent XYZ.COM LLC + "rentals", // rentals Big Hollow,LLC + "repair", // repair Lone Sunset, LLC + "report", // report Binky Glen, LLC + "republican", // republican United TLD Holdco Ltd. + "rest", // rest Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable + "restaurant", // restaurant Snow Avenue, LLC + "review", // review dot Review Limited + "reviews", // reviews United TLD Holdco, Ltd. + "rexroth", // rexroth Robert Bosch GMBH + "rich", // rich I-REGISTRY Ltd., Niederlassung Deutschland + "richardli", // richardli Pacific Century Asset Management (HK) Limited + "ricoh", // ricoh Ricoh Company, Ltd. + "rightathome", // rightathome Johnson Shareholdings, Inc. + "ril", // ril Reliance Industries Limited + "rio", // rio Empresa Municipal de Informática SA - IPLANRIO + "rip", // rip United TLD Holdco Ltd. + "rmit", // rmit Royal Melbourne Institute of Technology + "rocher", // rocher Ferrero Trading Lux S.A. + "rocks", // rocks United TLD Holdco, LTD. + "rodeo", // rodeo Top Level Domain Holdings Limited + "rogers", // rogers Rogers Communications Canada Inc. + "room", // room Amazon Registry Services, Inc. + "rsvp", // rsvp Charleston Road Registry Inc. + "ruhr", // ruhr regiodot GmbH & Co. KG + "run", // run Snow Park, LLC + "rwe", // rwe RWE AG + "ryukyu", // ryukyu BusinessRalliart inc. + "saarland", // saarland dotSaarland GmbH + "safe", // safe Amazon Registry Services, Inc. + "safety", // safety Safety Registry Services, LLC. + "sakura", // sakura SAKURA Internet Inc. + "sale", // sale United TLD Holdco, Ltd + "salon", // salon Outer Orchard, LLC + "samsclub", // samsclub Wal-Mart Stores, Inc. + "samsung", // samsung SAMSUNG SDS CO., LTD + "sandvik", // sandvik Sandvik AB + "sandvikcoromant", // sandvikcoromant Sandvik AB + "sanofi", // sanofi Sanofi + "sap", // sap SAP AG + "sapo", // sapo PT Comunicacoes S.A. + "sarl", // sarl Delta Orchard, LLC + "sas", // sas Research IP LLC + "save", // save Amazon Registry Services, Inc. + "saxo", // saxo Saxo Bank A/S + "sbi", // sbi STATE BANK OF INDIA + "sbs", // sbs SPECIAL BROADCASTING SERVICE CORPORATION + "sca", // sca SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) + "scb", // scb The Siam Commercial Bank Public Company Limited ("SCB") + "schaeffler", // schaeffler Schaeffler Technologies AG & Co. KG + "schmidt", // schmidt SALM S.A.S. + "scholarships", // scholarships Scholarships.com, LLC + "school", // school Little Galley, LLC + "schule", // schule Outer Moon, LLC + "schwarz", // schwarz Schwarz Domains und Services GmbH & Co. KG + "science", // science dot Science Limited + "scjohnson", // scjohnson Johnson Shareholdings, Inc. + "scor", // scor SCOR SE + "scot", // scot Dot Scot Registry Limited + "seat", // seat SEAT, S.A. (Sociedad Unipersonal) + "secure", // secure Amazon Registry Services, Inc. + "security", // security XYZ.COM LLC + "seek", // seek Seek Limited + "select", // select iSelect Ltd + "sener", // sener Sener Ingeniería y Sistemas, S.A. + "services", // services Fox Castle, LLC + "ses", // ses SES + "seven", // seven Seven West Media Ltd + "sew", // sew SEW-EURODRIVE GmbH & Co KG + "sex", // sex ICM Registry SX LLC + "sexy", // sexy Uniregistry, Corp. + "sfr", // sfr Societe Francaise du Radiotelephone - SFR + "shangrila", // shangrila Shangri‐La International Hotel Management Limited + "sharp", // sharp Sharp Corporation + "shaw", // shaw Shaw Cablesystems G.P. + "shell", // shell Shell Information Technology International Inc + "shia", // shia Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "shiksha", // shiksha Afilias Limited + "shoes", // shoes Binky Galley, LLC + "shop", // shop GMO Registry, Inc. + "shopping", // shopping Over Keep, LLC + "shouji", // shouji QIHOO 360 TECHNOLOGY CO. LTD. + "show", // show Snow Beach, LLC + "showtime", // showtime CBS Domains Inc. + "shriram", // shriram Shriram Capital Ltd. + "silk", // silk Amazon Registry Services, Inc. + "sina", // sina Sina Corporation + "singles", // singles Fern Madison, LLC + "site", // site DotSite Inc. + "ski", // ski STARTING DOT LIMITED + "skin", // skin L'Oréal + "sky", // sky Sky International AG + "skype", // skype Microsoft Corporation + "sling", // sling Hughes Satellite Systems Corporation + "smart", // smart Smart Communications, Inc. (SMART) + "smile", // smile Amazon Registry Services, Inc. + "sncf", // sncf SNCF (Société Nationale des Chemins de fer Francais) + "soccer", // soccer Foggy Shadow, LLC + "social", // social United TLD Holdco Ltd. + "softbank", // softbank SoftBank Group Corp. + "software", // software United TLD Holdco, Ltd + "sohu", // sohu Sohu.com Limited + "solar", // solar Ruby Town, LLC + "solutions", // solutions Silver Cover, LLC + "song", // song Amazon Registry Services, Inc. + "sony", // sony Sony Corporation + "soy", // soy Charleston Road Registry Inc. + "space", // space DotSpace Inc. + "spiegel", // spiegel SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG + "spot", // spot Amazon Registry Services, Inc. + "spreadbetting", // spreadbetting DOTSPREADBETTING REGISTRY LTD + "srl", // srl InterNetX Corp. + "srt", // srt FCA US LLC. + "stada", // stada STADA Arzneimittel AG + "staples", // staples Staples, Inc. + "star", // star Star India Private Limited + "starhub", // starhub StarHub Limited + "statebank", // statebank STATE BANK OF INDIA + "statefarm", // statefarm State Farm Mutual Automobile Insurance Company + "statoil", // statoil Statoil ASA + "stc", // stc Saudi Telecom Company + "stcgroup", // stcgroup Saudi Telecom Company + "stockholm", // stockholm Stockholms kommun + "storage", // storage Self Storage Company LLC + "store", // store DotStore Inc. + "stream", // stream dot Stream Limited + "studio", // studio United TLD Holdco Ltd. + "study", // study OPEN UNIVERSITIES AUSTRALIA PTY LTD + "style", // style Binky Moon, LLC + "sucks", // sucks Vox Populi Registry Ltd. + "supplies", // supplies Atomic Fields, LLC + "supply", // supply Half Falls, LLC + "support", // support Grand Orchard, LLC + "surf", // surf Top Level Domain Holdings Limited + "surgery", // surgery Tin Avenue, LLC + "suzuki", // suzuki SUZUKI MOTOR CORPORATION + "swatch", // swatch The Swatch Group Ltd + "swiftcover", // swiftcover Swiftcover Insurance Services Limited + "swiss", // swiss Swiss Confederation + "sydney", // sydney State of New South Wales, Department of Premier and Cabinet + "symantec", // symantec Symantec Corporation + "systems", // systems Dash Cypress, LLC + "tab", // tab Tabcorp Holdings Limited + "taipei", // taipei Taipei City Government + "talk", // talk Amazon Registry Services, Inc. + "taobao", // taobao Alibaba Group Holding Limited + "target", // target Target Domain Holdings, LLC + "tatamotors", // tatamotors Tata Motors Ltd + "tatar", // tatar Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" + "tattoo", // tattoo Uniregistry, Corp. + "tax", // tax Storm Orchard, LLC + "taxi", // taxi Pine Falls, LLC + "tci", // tci Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "tdk", // tdk TDK Corporation + "team", // team Atomic Lake, LLC + "tech", // tech Dot Tech LLC + "technology", // technology Auburn Falls, LLC + "tel", // tel Telnic Ltd. + "telecity", // telecity TelecityGroup International Limited + "telefonica", // telefonica Telefónica S.A. + "temasek", // temasek Temasek Holdings (Private) Limited + "tennis", // tennis Cotton Bloom, LLC + "teva", // teva Teva Pharmaceutical Industries Limited + "thd", // thd Homer TLC, Inc. + "theater", // theater Blue Tigers, LLC + "theatre", // theatre XYZ.COM LLC + "tiaa", // tiaa Teachers Insurance and Annuity Association of America + "tickets", // tickets Accent Media Limited + "tienda", // tienda Victor Manor, LLC + "tiffany", // tiffany Tiffany and Company + "tips", // tips Corn Willow, LLC + "tires", // tires Dog Edge, LLC + "tirol", // tirol punkt Tirol GmbH + "tjmaxx", // tjmaxx The TJX Companies, Inc. + "tjx", // tjx The TJX Companies, Inc. + "tkmaxx", // tkmaxx The TJX Companies, Inc. + "tmall", // tmall Alibaba Group Holding Limited + "today", // today Pearl Woods, LLC + "tokyo", // tokyo GMO Registry, Inc. + "tools", // tools Pioneer North, LLC + "top", // top Jiangsu Bangning Science & Technology Co.,Ltd. + "toray", // toray Toray Industries, Inc. + "toshiba", // toshiba TOSHIBA Corporation + "total", // total Total SA + "tours", // tours Sugar Station, LLC + "town", // town Koko Moon, LLC + "toyota", // toyota TOYOTA MOTOR CORPORATION + "toys", // toys Pioneer Orchard, LLC + "trade", // trade Elite Registry Limited + "trading", // trading DOTTRADING REGISTRY LTD + "training", // training Wild Willow, LLC + "travel", // travel Tralliance Registry Management Company, LLC. + "travelchannel", // travelchannel Lifestyle Domain Holdings, Inc. + "travelers", // travelers Travelers TLD, LLC + "travelersinsurance", // travelersinsurance Travelers TLD, LLC + "trust", // trust Artemis Internet Inc + "trv", // trv Travelers TLD, LLC + "tube", // tube Latin American Telecom LLC + "tui", // tui TUI AG + "tunes", // tunes Amazon Registry Services, Inc. + "tushu", // tushu Amazon Registry Services, Inc. + "tvs", // tvs T V SUNDRAM IYENGAR & SONS PRIVATE LIMITED + "ubank", // ubank National Australia Bank Limited + "ubs", // ubs UBS AG + "uconnect", // uconnect FCA US LLC. + "unicom", // unicom China United Network Communications Corporation Limited + "university", // university Little Station, LLC + "uno", // uno Dot Latin LLC + "uol", // uol UBN INTERNET LTDA. + "ups", // ups UPS Market Driver, Inc. + "vacations", // vacations Atomic Tigers, LLC + "vana", // vana Lifestyle Domain Holdings, Inc. + "vanguard", // vanguard The Vanguard Group, Inc. + "vegas", // vegas Dot Vegas, Inc. + "ventures", // ventures Binky Lake, LLC + "verisign", // verisign VeriSign, Inc. + "versicherung", // versicherung dotversicherung-registry GmbH + "vet", // vet United TLD Holdco, Ltd + "viajes", // viajes Black Madison, LLC + "video", // video United TLD Holdco, Ltd + "vig", // vig VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe + "viking", // viking Viking River Cruises (Bermuda) Ltd. + "villas", // villas New Sky, LLC + "vin", // vin Holly Shadow, LLC + "vip", // vip Minds + Machines Group Limited + "virgin", // virgin Virgin Enterprises Limited + "visa", // visa Visa Worldwide Pte. Limited + "vision", // vision Koko Station, LLC + "vista", // vista Vistaprint Limited + "vistaprint", // vistaprint Vistaprint Limited + "viva", // viva Saudi Telecom Company + "vivo", // vivo Telefonica Brasil S.A. + "vlaanderen", // vlaanderen DNS.be vzw + "vodka", // vodka Top Level Domain Holdings Limited + "volkswagen", // volkswagen Volkswagen Group of America Inc. + "volvo", // volvo Volvo Holding Sverige Aktiebolag + "vote", // vote Monolith Registry LLC + "voting", // voting Valuetainment Corp. + "voto", // voto Monolith Registry LLC + "voyage", // voyage Ruby House, LLC + "vuelos", // vuelos Travel Reservations SRL + "wales", // wales Nominet UK + "walmart", // walmart Wal-Mart Stores, Inc. + "walter", // walter Sandvik AB + "wang", // wang Zodiac Registry Limited + "wanggou", // wanggou Amazon Registry Services, Inc. + "warman", // warman Weir Group IP Limited + "watch", // watch Sand Shadow, LLC + "watches", // watches Richemont DNS Inc. + "weather", // weather The Weather Channel, LLC + "weatherchannel", // weatherchannel The Weather Channel, LLC + "webcam", // webcam dot Webcam Limited + "weber", // weber Saint-Gobain Weber SA + "website", // website DotWebsite Inc. + "wed", // wed Atgron, Inc. + "wedding", // wedding Top Level Domain Holdings Limited + "weibo", // weibo Sina Corporation + "weir", // weir Weir Group IP Limited + "whoswho", // whoswho Who's Who Registry + "wien", // wien punkt.wien GmbH + "wiki", // wiki Top Level Design, LLC + "williamhill", // williamhill William Hill Organization Limited + "win", // win First Registry Limited + "windows", // windows Microsoft Corporation + "wine", // wine June Station, LLC + "winners", // winners The TJX Companies, Inc. + "wme", // wme William Morris Endeavor Entertainment, LLC + "wolterskluwer", // wolterskluwer Wolters Kluwer N.V. + "woodside", // woodside Woodside Petroleum Limited + "work", // work Top Level Domain Holdings Limited + "works", // works Little Dynamite, LLC + "world", // world Bitter Fields, LLC + "wow", // wow Amazon Registry Services, Inc. + "wtc", // wtc World Trade Centers Association, Inc. + "wtf", // wtf Hidden Way, LLC + "xbox", // xbox Microsoft Corporation + "xerox", // xerox Xerox DNHC LLC + "xfinity", // xfinity Comcast IP Holdings I, LLC + "xihuan", // xihuan QIHOO 360 TECHNOLOGY CO. LTD. + "xin", // xin Elegant Leader Limited + "xn--11b4c3d", // कॉम VeriSign Sarl + "xn--1ck2e1b", // セール Amazon Registry Services, Inc. + "xn--1qqw23a", // 佛山 Guangzhou YU Wei Information Technology Co., Ltd. + "xn--30rr7y", // 慈善 Excellent First Limited + "xn--3bst00m", // 集团 Eagle Horizon Limited + "xn--3ds443g", // 在线 TLD REGISTRY LIMITED + "xn--3oq18vl8pn36a", // 大众汽车 Volkswagen (China) Investment Co., Ltd. + "xn--3pxu8k", // 点看 VeriSign Sarl + "xn--42c2d9a", // คอม VeriSign Sarl + "xn--45q11c", // 八卦 Zodiac Scorpio Limited + "xn--4gbrim", // موقع Suhub Electronic Establishment + "xn--55qw42g", // 公益 China Organizational Name Administration Center + "xn--55qx5d", // 公司 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) + "xn--5su34j936bgsg", // 香格里拉 Shangri‐La International Hotel Management Limited + "xn--5tzm5g", // 网站 Global Website TLD Asia Limited + "xn--6frz82g", // 移动 Afilias Limited + "xn--6qq986b3xl", // 我爱你 Tycoon Treasure Limited + "xn--80adxhks", // москва Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) + "xn--80aqecdr1a", // католик Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "xn--80asehdb", // онлайн CORE Association + "xn--80aswg", // сайт CORE Association + "xn--8y0a063a", // 联通 China United Network Communications Corporation Limited + "xn--90ae", // бг Imena.BG Plc (NAMES.BG Plc) + "xn--9dbq2a", // קום VeriSign Sarl + "xn--9et52u", // 时尚 RISE VICTORY LIMITED + "xn--9krt00a", // 微博 Sina Corporation + "xn--b4w605ferd", // 淡马锡 Temasek Holdings (Private) Limited + "xn--bck1b9a5dre4c", // ファッション Amazon Registry Services, Inc. + "xn--c1avg", // орг Public Interest Registry + "xn--c2br7g", // नेट VeriSign Sarl + "xn--cck2b3b", // ストア Amazon Registry Services, Inc. + "xn--cg4bki", // 삼성 SAMSUNG SDS CO., LTD + "xn--czr694b", // 商标 HU YI GLOBAL INFORMATION RESOURCES(HOLDING) COMPANY.HONGKONG LIMITED + "xn--czrs0t", // 商店 Wild Island, LLC + "xn--czru2d", // 商城 Zodiac Aquarius Limited + "xn--d1acj3b", // дети The Foundation for Network Initiatives “The Smart Internet” + "xn--eckvdtc9d", // ポイント Amazon Registry Services, Inc. + "xn--efvy88h", // 新闻 Xinhua News Agency Guangdong Branch 新华通讯社广东分社 + "xn--estv75g", // 工行 Industrial and Commercial Bank of China Limited + "xn--fct429k", // 家電 Amazon Registry Services, Inc. + "xn--fhbei", // كوم VeriSign Sarl + "xn--fiq228c5hs", // 中文网 TLD REGISTRY LIMITED + "xn--fiq64b", // 中信 CITIC Group Corporation + "xn--fjq720a", // 娱乐 Will Bloom, LLC + "xn--flw351e", // 谷歌 Charleston Road Registry Inc. + "xn--fzys8d69uvgm", // 電訊盈科 PCCW Enterprises Limited + "xn--g2xx48c", // 购物 Minds + Machines Group Limited + "xn--gckr3f0f", // クラウド Amazon Registry Services, Inc. + "xn--gk3at1e", // 通販 Amazon Registry Services, Inc. + "xn--hxt814e", // 网店 Zodiac Libra Limited + "xn--i1b6b1a6a2e", // संगठन Public Interest Registry + "xn--imr513n", // 餐厅 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED + "xn--io0a7i", // 网络 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) + "xn--j1aef", // ком VeriSign Sarl + "xn--jlq61u9w7b", // 诺基亚 Nokia Corporation + "xn--jvr189m", // 食品 Amazon Registry Services, Inc. + "xn--kcrx77d1x4a", // 飞利浦 Koninklijke Philips N.V. + "xn--kpu716f", // 手表 Richemont DNS Inc. + "xn--kput3i", // 手机 Beijing RITT-Net Technology Development Co., Ltd + "xn--mgba3a3ejt", // ارامكو Aramco Services Company + "xn--mgba7c0bbn0a", // العليان Crescent Holding GmbH + "xn--mgbab2bd", // بازار CORE Association + "xn--mgbb9fbpob", // موبايلي GreenTech Consultancy Company W.L.L. + "xn--mgbca7dzdo", // ابوظبي Abu Dhabi Systems and Information Centre + "xn--mgbi4ecexp", // كاثوليك Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "xn--mgbt3dhd", // همراه Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. + "xn--mk1bu44c", // 닷컴 VeriSign Sarl + "xn--mxtq1m", // 政府 Net-Chinese Co., Ltd. + "xn--ngbc5azd", // شبكة International Domain Registry Pty. Ltd. + "xn--ngbe9e0a", // بيتك Kuwait Finance House + "xn--nqv7f", // 机构 Public Interest Registry + "xn--nqv7fs00ema", // 组织机构 Public Interest Registry + "xn--nyqy26a", // 健康 Stable Tone Limited + "xn--p1acf", // рус Rusnames Limited + "xn--pbt977c", // 珠宝 Richemont DNS Inc. + "xn--pssy2u", // 大拿 VeriSign Sarl + "xn--q9jyb4c", // みんな Charleston Road Registry Inc. + "xn--qcka1pmc", // グーグル Charleston Road Registry Inc. + "xn--rhqv96g", // 世界 Stable Tone Limited + "xn--rovu88b", // 書籍 Amazon EU S.à r.l. + "xn--ses554g", // 网址 KNET Co., Ltd + "xn--t60b56a", // 닷넷 VeriSign Sarl + "xn--tckwe", // コム VeriSign Sarl + "xn--tiq49xqyj", // 天主教 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) + "xn--unup4y", // 游戏 Spring Fields, LLC + "xn--vermgensberater-ctb", // VERMöGENSBERATER Deutsche Vermögensberatung Aktiengesellschaft DVAG + "xn--vermgensberatung-pwb", // VERMöGENSBERATUNG Deutsche Vermögensberatung Aktiengesellschaft DVAG + "xn--vhquv", // 企业 Dash McCook, LLC + "xn--vuq861b", // 信息 Beijing Tele-info Network Technology Co., Ltd. + "xn--w4r85el8fhu5dnra", // 嘉里大酒店 Kerry Trading Co. Limited + "xn--w4rs40l", // 嘉里 Kerry Trading Co. Limited + "xn--xhq521b", // 广东 Guangzhou YU Wei Information Technology Co., Ltd. + "xn--zfr164b", // 政务 China Organizational Name Administration Center + "xperia", // xperia Sony Mobile Communications AB + "xxx", // xxx ICM Registry LLC + "xyz", // xyz XYZ.COM LLC + "yachts", // yachts DERYachts, LLC + "yahoo", // yahoo Yahoo! Domain Services Inc. + "yamaxun", // yamaxun Amazon Registry Services, Inc. + "yandex", // yandex YANDEX, LLC + "yodobashi", // yodobashi YODOBASHI CAMERA CO.,LTD. + "yoga", // yoga Top Level Domain Holdings Limited + "yokohama", // yokohama GMO Registry, Inc. + "you", // you Amazon Registry Services, Inc. + "youtube", // youtube Charleston Road Registry Inc. + "yun", // yun QIHOO 360 TECHNOLOGY CO. LTD. + "zappos", // zappos Amazon Registry Services, Inc. + "zara", // zara Industria de Diseño Textil, S.A. (INDITEX, S.A.) + "zero", // zero Amazon Registry Services, Inc. + "zip", // zip Charleston Road Registry Inc. + "zippo", // zippo Zadco Company + "zone", // zone Outer Falls, LLC + "zuerich", // zuerich Kanton Zürich (Canton of Zurich) +}; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] COUNTRY_CODE_TLDS = new String[] { + "ac", // Ascension Island + "ad", // Andorra + "ae", // United Arab Emirates + "af", // Afghanistan + "ag", // Antigua and Barbuda + "ai", // Anguilla + "al", // Albania + "am", // Armenia +// "an", // Netherlands Antilles (retired) + "ao", // Angola + "aq", // Antarctica + "ar", // Argentina + "as", // American Samoa + "at", // Austria + "au", // Australia (includes Ashmore and Cartier Islands and Coral Sea Islands) + "aw", // Aruba + "ax", // Åland + "az", // Azerbaijan + "ba", // Bosnia and Herzegovina + "bb", // Barbados + "bd", // Bangladesh + "be", // Belgium + "bf", // Burkina Faso + "bg", // Bulgaria + "bh", // Bahrain + "bi", // Burundi + "bj", // Benin + "bm", // Bermuda + "bn", // Brunei Darussalam + "bo", // Bolivia + "br", // Brazil + "bs", // Bahamas + "bt", // Bhutan + "bv", // Bouvet Island + "bw", // Botswana + "by", // Belarus + "bz", // Belize + "ca", // Canada + "cc", // Cocos (Keeling) Islands + "cd", // Democratic Republic of the Congo (formerly Zaire) + "cf", // Central African Republic + "cg", // Republic of the Congo + "ch", // Switzerland + "ci", // Côte d'Ivoire + "ck", // Cook Islands + "cl", // Chile + "cm", // Cameroon + "cn", // China, mainland + "co", // Colombia + "cr", // Costa Rica + "cu", // Cuba + "cv", // Cape Verde + "cw", // Curaçao + "cx", // Christmas Island + "cy", // Cyprus + "cz", // Czech Republic + "de", // Germany + "dj", // Djibouti + "dk", // Denmark + "dm", // Dominica + "do", // Dominican Republic + "dz", // Algeria + "ec", // Ecuador + "ee", // Estonia + "eg", // Egypt + "er", // Eritrea + "es", // Spain + "et", // Ethiopia + "eu", // European Union + "fi", // Finland + "fj", // Fiji + "fk", // Falkland Islands + "fm", // Federated States of Micronesia + "fo", // Faroe Islands + "fr", // France + "ga", // Gabon + "gb", // Great Britain (United Kingdom) + "gd", // Grenada + "ge", // Georgia + "gf", // French Guiana + "gg", // Guernsey + "gh", // Ghana + "gi", // Gibraltar + "gl", // Greenland + "gm", // The Gambia + "gn", // Guinea + "gp", // Guadeloupe + "gq", // Equatorial Guinea + "gr", // Greece + "gs", // South Georgia and the South Sandwich Islands + "gt", // Guatemala + "gu", // Guam + "gw", // Guinea-Bissau + "gy", // Guyana + "hk", // Hong Kong + "hm", // Heard Island and McDonald Islands + "hn", // Honduras + "hr", // Croatia (Hrvatska) + "ht", // Haiti + "hu", // Hungary + "id", // Indonesia + "ie", // Ireland (Éire) + "il", // Israel + "im", // Isle of Man + "in", // India + "io", // British Indian Ocean Territory + "iq", // Iraq + "ir", // Iran + "is", // Iceland + "it", // Italy + "je", // Jersey + "jm", // Jamaica + "jo", // Jordan + "jp", // Japan + "ke", // Kenya + "kg", // Kyrgyzstan + "kh", // Cambodia (Khmer) + "ki", // Kiribati + "km", // Comoros + "kn", // Saint Kitts and Nevis + "kp", // North Korea + "kr", // South Korea + "kw", // Kuwait + "ky", // Cayman Islands + "kz", // Kazakhstan + "la", // Laos (currently being marketed as the official domain for Los Angeles) + "lb", // Lebanon + "lc", // Saint Lucia + "li", // Liechtenstein + "lk", // Sri Lanka + "lr", // Liberia + "ls", // Lesotho + "lt", // Lithuania + "lu", // Luxembourg + "lv", // Latvia + "ly", // Libya + "ma", // Morocco + "mc", // Monaco + "md", // Moldova + "me", // Montenegro + "mg", // Madagascar + "mh", // Marshall Islands + "mk", // Republic of Macedonia + "ml", // Mali + "mm", // Myanmar + "mn", // Mongolia + "mo", // Macau + "mp", // Northern Mariana Islands + "mq", // Martinique + "mr", // Mauritania + "ms", // Montserrat + "mt", // Malta + "mu", // Mauritius + "mv", // Maldives + "mw", // Malawi + "mx", // Mexico + "my", // Malaysia + "mz", // Mozambique + "na", // Namibia + "nc", // New Caledonia + "ne", // Niger + "nf", // Norfolk Island + "ng", // Nigeria + "ni", // Nicaragua + "nl", // Netherlands + "no", // Norway + "np", // Nepal + "nr", // Nauru + "nu", // Niue + "nz", // New Zealand + "om", // Oman + "pa", // Panama + "pe", // Peru + "pf", // French Polynesia With Clipperton Island + "pg", // Papua New Guinea + "ph", // Philippines + "pk", // Pakistan + "pl", // Poland + "pm", // Saint-Pierre and Miquelon + "pn", // Pitcairn Islands + "pr", // Puerto Rico + "ps", // Palestinian territories (PA-controlled West Bank and Gaza Strip) + "pt", // Portugal + "pw", // Palau + "py", // Paraguay + "qa", // Qatar + "re", // Réunion + "ro", // Romania + "rs", // Serbia + "ru", // Russia + "rw", // Rwanda + "sa", // Saudi Arabia + "sb", // Solomon Islands + "sc", // Seychelles + "sd", // Sudan + "se", // Sweden + "sg", // Singapore + "sh", // Saint Helena + "si", // Slovenia + "sj", // Svalbard and Jan Mayen Islands Not in use (Norwegian dependencies; see .no) + "sk", // Slovakia + "sl", // Sierra Leone + "sm", // San Marino + "sn", // Senegal + "so", // Somalia + "sr", // Suriname + "st", // São Tomé and Príncipe + "su", // Soviet Union (deprecated) + "sv", // El Salvador + "sx", // Sint Maarten + "sy", // Syria + "sz", // Swaziland + "tc", // Turks and Caicos Islands + "td", // Chad + "tf", // French Southern and Antarctic Lands + "tg", // Togo + "th", // Thailand + "tj", // Tajikistan + "tk", // Tokelau + "tl", // East Timor (deprecated old code) + "tm", // Turkmenistan + "tn", // Tunisia + "to", // Tonga +// "tp", // East Timor (Retired) + "tr", // Turkey + "tt", // Trinidad and Tobago + "tv", // Tuvalu + "tw", // Taiwan, Republic of China + "tz", // Tanzania + "ua", // Ukraine + "ug", // Uganda + "uk", // United Kingdom + "us", // United States of America + "uy", // Uruguay + "uz", // Uzbekistan + "va", // Vatican City State + "vc", // Saint Vincent and the Grenadines + "ve", // Venezuela + "vg", // British Virgin Islands + "vi", // U.S. Virgin Islands + "vn", // Vietnam + "vu", // Vanuatu + "wf", // Wallis and Futuna + "ws", // Samoa (formerly Western Samoa) + "xn--3e0b707e", // 한국 KISA (Korea Internet & Security Agency) + "xn--45brj9c", // ভারত National Internet Exchange of India + "xn--54b7fta0cc", // বাংলা Posts and Telecommunications Division + "xn--80ao21a", // қаз Association of IT Companies of Kazakhstan + "xn--90a3ac", // срб Serbian National Internet Domain Registry (RNIDS) + "xn--90ais", // ??? Reliable Software Inc. + "xn--clchc0ea0b2g2a9gcd", // சிங்கப்பூர் Singapore Network Information Centre (SGNIC) Pte Ltd + "xn--d1alf", // мкд Macedonian Academic Research Network Skopje + "xn--e1a4c", // ею EURid vzw/asbl + "xn--fiqs8s", // 中国 China Internet Network Information Center + "xn--fiqz9s", // 中國 China Internet Network Information Center + "xn--fpcrj9c3d", // భారత్ National Internet Exchange of India + "xn--fzc2c9e2c", // ලංකා LK Domain Registry + "xn--gecrj9c", // ભારત National Internet Exchange of India + "xn--h2brj9c", // भारत National Internet Exchange of India + "xn--j1amh", // укр Ukrainian Network Information Centre (UANIC), Inc. + "xn--j6w193g", // 香港 Hong Kong Internet Registration Corporation Ltd. + "xn--kprw13d", // 台湾 Taiwan Network Information Center (TWNIC) + "xn--kpry57d", // 台灣 Taiwan Network Information Center (TWNIC) + "xn--l1acc", // мон Datacom Co.,Ltd + "xn--lgbbat1ad8j", // الجزائر CERIST + "xn--mgb9awbf", // عمان Telecommunications Regulatory Authority (TRA) + "xn--mgba3a4f16a", // ایران Institute for Research in Fundamental Sciences (IPM) + "xn--mgbaam7a8h", // امارات Telecommunications Regulatory Authority (TRA) + "xn--mgbayh7gpa", // الاردن National Information Technology Center (NITC) + "xn--mgbbh1a71e", // بھارت National Internet Exchange of India + "xn--mgbc0a9azcg", // المغرب Agence Nationale de Réglementation des Télécommunications (ANRT) + "xn--mgberp4a5d4ar", // السعودية Communications and Information Technology Commission + "xn--mgbpl2fh", // ????? Sudan Internet Society + "xn--mgbtx2b", // عراق Communications and Media Commission (CMC) + "xn--mgbx4cd0ab", // مليسيا MYNIC Berhad + "xn--mix891f", // 澳門 Bureau of Telecommunications Regulation (DSRT) + "xn--node", // გე Information Technologies Development Center (ITDC) + "xn--o3cw4h", // ไทย Thai Network Information Center Foundation + "xn--ogbpf8fl", // سورية National Agency for Network Services (NANS) + "xn--p1ai", // рф Coordination Center for TLD RU + "xn--pgbs0dh", // تونس Agence Tunisienne d'Internet + "xn--qxam", // ελ ICS-FORTH GR + "xn--s9brj9c", // ਭਾਰਤ National Internet Exchange of India + "xn--wgbh1c", // مصر National Telecommunication Regulatory Authority - NTRA + "xn--wgbl6a", // قطر Communications Regulatory Authority + "xn--xkc2al3hye2a", // இலங்கை LK Domain Registry + "xn--xkc2dl3a5ee0h", // இந்தியா National Internet Exchange of India + "xn--y9a3aq", // ??? Internet Society + "xn--yfro4i67o", // 新加坡 Singapore Network Information Centre (SGNIC) Pte Ltd + "xn--ygbi2ammx", // فلسطين Ministry of Telecom & Information Technology (MTIT) + "ye", // Yemen + "yt", // Mayotte + "za", // South Africa + "zm", // Zambia + "zw", // Zimbabwe + }; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static final String[] LOCAL_TLDS = new String[] { + "localdomain", // Also widely used as localhost.localdomain + "localhost", // RFC2606 defined + }; + + // Additional arrays to supplement or override the built in ones. + // The PLUS arrays are valid keys, the MINUS arrays are invalid keys + + /* + * This field is used to detect whether the getInstance has been called. + * After this, the method updateTLDOverride is not allowed to be called. + * This field does not need to be volatile since it is only accessed from + * synchronized methods. + */ + private static boolean inUse = false; + + /* + * These arrays are mutable, but they don't need to be volatile. + * They can only be updated by the updateTLDOverride method, and any readers must get an instance + * using the getInstance methods which are all (now) synchronised. + */ + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static volatile String[] countryCodeTLDsPlus = EMPTY_STRING_ARRAY; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static volatile String[] genericTLDsPlus = EMPTY_STRING_ARRAY; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static volatile String[] countryCodeTLDsMinus = EMPTY_STRING_ARRAY; + + // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search + private static volatile String[] genericTLDsMinus = EMPTY_STRING_ARRAY; + + /** + * enum used by {@link DomainValidator#updateTLDOverride(ArrayType, String[])} + * to determine which override array to update / fetch + * @since 1.5.0 + * @since 1.5.1 made public and added read-only array references + */ + public enum ArrayType { + /** Update (or get a copy of) the GENERIC_TLDS_PLUS table containing additonal generic TLDs */ + GENERIC_PLUS, + /** Update (or get a copy of) the GENERIC_TLDS_MINUS table containing deleted generic TLDs */ + GENERIC_MINUS, + /** Update (or get a copy of) the COUNTRY_CODE_TLDS_PLUS table containing additonal country code TLDs */ + COUNTRY_CODE_PLUS, + /** Update (or get a copy of) the COUNTRY_CODE_TLDS_MINUS table containing deleted country code TLDs */ + COUNTRY_CODE_MINUS, + /** Get a copy of the generic TLDS table */ + GENERIC_RO, + /** Get a copy of the country code table */ + COUNTRY_CODE_RO, + /** Get a copy of the infrastructure table */ + INFRASTRUCTURE_RO, + /** Get a copy of the local table */ + LOCAL_RO + ; + }; + + // For use by unit test code only + static synchronized void clearTLDOverrides() { + inUse = false; + countryCodeTLDsPlus = EMPTY_STRING_ARRAY; + countryCodeTLDsMinus = EMPTY_STRING_ARRAY; + genericTLDsPlus = EMPTY_STRING_ARRAY; + genericTLDsMinus = EMPTY_STRING_ARRAY; + } + /** + * Update one of the TLD override arrays. + * This must only be done at program startup, before any instances are accessed using getInstance. + *

+ * For example: + *

+ * {@code DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, new String[]{"apache"})} + *

+ * To clear an override array, provide an empty array. + * + * @param table the table to update, see {@link DomainValidator.ArrayType} + * Must be one of the following + *

    + *
  • COUNTRY_CODE_MINUS
  • + *
  • COUNTRY_CODE_PLUS
  • + *
  • GENERIC_MINUS
  • + *
  • GENERIC_PLUS
  • + *
+ * @param tlds the array of TLDs, must not be null + * @throws IllegalStateException if the method is called after getInstance + * @throws IllegalArgumentException if one of the read-only tables is requested + * @since 1.5.0 + */ + public static synchronized void updateTLDOverride(ArrayType table, String [] tlds) { + if (inUse) { + throw new IllegalStateException("Can only invoke this method before calling getInstance"); + } + String [] copy = new String[tlds.length]; + // Comparisons are always done with lower-case entries + for (int i = 0; i < tlds.length; i++) { + copy[i] = tlds[i].toLowerCase(Locale.ENGLISH); + } + Arrays.sort(copy); + switch(table) { + case COUNTRY_CODE_MINUS: + countryCodeTLDsMinus = copy; + break; + case COUNTRY_CODE_PLUS: + countryCodeTLDsPlus = copy; + break; + case GENERIC_MINUS: + genericTLDsMinus = copy; + break; + case GENERIC_PLUS: + genericTLDsPlus = copy; + break; + case COUNTRY_CODE_RO: + case GENERIC_RO: + case INFRASTRUCTURE_RO: + case LOCAL_RO: + throw new IllegalArgumentException("Cannot update the table: " + table); + default: + throw new IllegalArgumentException("Unexpected enum value: " + table); + } + } + + /** + * Get a copy of the internal array. + * @param table the array type (any of the enum values) + * @return a copy of the array + * @throws IllegalArgumentException if the table type is unexpected (should not happen) + * @since 1.5.1 + */ + public static String [] getTLDEntries(ArrayType table) { + final String array[]; + switch(table) { + case COUNTRY_CODE_MINUS: + array = countryCodeTLDsMinus; + break; + case COUNTRY_CODE_PLUS: + array = countryCodeTLDsPlus; + break; + case GENERIC_MINUS: + array = genericTLDsMinus; + break; + case GENERIC_PLUS: + array = genericTLDsPlus; + break; + case GENERIC_RO: + array = GENERIC_TLDS; + break; + case COUNTRY_CODE_RO: + array = COUNTRY_CODE_TLDS; + break; + case INFRASTRUCTURE_RO: + array = INFRASTRUCTURE_TLDS; + break; + case LOCAL_RO: + array = LOCAL_TLDS; + break; + default: + throw new IllegalArgumentException("Unexpected enum value: " + table); + } + return Arrays.copyOf(array, array.length); // clone the array + } + + /** + * Converts potentially Unicode input to punycode. + * If conversion fails, returns the original input. + * + * @param input the string to convert, not null + * @return converted input, or original input if conversion fails + */ + // Needed by UrlValidator + static String unicodeToASCII(String input) { + if (isOnlyASCII(input)) { // skip possibly expensive processing + return input; + } + try { + final String ascii = IDN.toASCII(input); + if (IDNBUGHOLDER.IDN_TOASCII_PRESERVES_TRAILING_DOTS) { + return ascii; + } + final int length = input.length(); + if (length == 0) {// check there is a last character + return input; + } + // RFC3490 3.1. 1) + // Whenever dots are used as label separators, the following + // characters MUST be recognized as dots: U+002E (full stop), U+3002 + // (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61 + // (halfwidth ideographic full stop). + char lastChar = input.charAt(length-1);// fetch original last char + switch(lastChar) { + case '\u002E': // "." full stop + case '\u3002': // ideographic full stop + case '\uFF0E': // fullwidth full stop + case '\uFF61': // halfwidth ideographic full stop + return ascii + "."; // restore the missing stop + default: + return ascii; + } + } catch (IllegalArgumentException e) { // input is not valid + return input; + } + } + + private static class IDNBUGHOLDER { + private static boolean keepsTrailingDot() { + final String input = "a."; // must be a valid name + return input.equals(IDN.toASCII(input)); + } + private static final boolean IDN_TOASCII_PRESERVES_TRAILING_DOTS = keepsTrailingDot(); + } + + /* + * Check if input contains only ASCII + * Treats null as all ASCII + */ + private static boolean isOnlyASCII(String input) { + if (input == null) { + return true; + } + for(int i=0; i < input.length(); i++) { + if (input.charAt(i) > 0x7F) { // CHECKSTYLE IGNORE MagicNumber + return false; + } + } + return true; + } + + /** + * Check if a sorted array contains the specified key + * + * @param sortedArray the array to search + * @param key the key to find + * @return {@code true} if the array contains the key + */ + private static boolean arrayContains(String[] sortedArray, String key) { + return Arrays.binarySearch(sortedArray, key) >= 0; + } +} diff --git a/projects/bleckw/FinalProject/URLValidatorInCorrect/src/InetAddressValidator.java b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/InetAddressValidator.java new file mode 100644 index 00000000..bf93d47c --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/InetAddressValidator.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + *

InetAddress validation and conversion routines (java.net.InetAddress).

+ * + *

This class provides methods to validate a candidate IP address. + * + *

+ * This class is a Singleton; you can retrieve the instance via the {@link #getInstance()} method. + *

+ * + * @version $Revision: 1783032 $ + * @since Validator 1.4 + */ +public class InetAddressValidator implements Serializable { + + private static final int IPV4_MAX_OCTET_VALUE = 255; + + private static final int MAX_UNSIGNED_SHORT = 0xffff; + + private static final int BASE_16 = 16; + + private static final long serialVersionUID = -919201640201914789L; + + private static final String IPV4_REGEX = + "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"; + + // Max number of hex groups (separated by :) in an IPV6 address + private static final int IPV6_MAX_HEX_GROUPS = 8; + + // Max hex digits in each IPv6 group + private static final int IPV6_MAX_HEX_DIGITS_PER_GROUP = 4; + + /** + * Singleton instance of this class. + */ + private static final InetAddressValidator VALIDATOR = new InetAddressValidator(); + + /** IPv4 RegexValidator */ + private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX); + + /** + * Returns the singleton instance of this validator. + * @return the singleton instance of this validator + */ + public static InetAddressValidator getInstance() { + return VALIDATOR; + } + + /** + * Checks if the specified string is a valid IP address. + * @param inetAddress the string to validate + * @return true if the string validates as an IP address + */ + public boolean isValid(String inetAddress) { + return isValidInet4Address(inetAddress) || isValidInet6Address(inetAddress); + } + + /** + * Validates an IPv4 address. Returns true if valid. + * @param inet4Address the IPv4 address to validate + * @return true if the argument contains a valid IPv4 address + */ + public boolean isValidInet4Address(String inet4Address) { + // verify that address conforms to generic IPv4 format + String[] groups = ipv4Validator.match(inet4Address); + + if (groups == null) { + return false; + } + + // verify that address subgroups are legal + for (String ipSegment : groups) { + if (ipSegment == null || ipSegment.length() == 0) { + return false; + } + + int iIpSegment = 0; + + try { + iIpSegment = Integer.parseInt(ipSegment); + } catch(NumberFormatException e) { + return false; + } + + if (iIpSegment > IPV4_MAX_OCTET_VALUE) { + return false; + } + + if (ipSegment.length() > 1 && ipSegment.startsWith("0")) { + return false; + } + + } + + return true; + } + + /** + * Validates an IPv6 address. Returns true if valid. + * @param inet6Address the IPv6 address to validate + * @return true if the argument contains a valid IPv6 address + * + * @since 1.4.1 + */ + public boolean isValidInet6Address(String inet6Address) { + boolean containsCompressedZeroes = inet6Address.contains("::"); + if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) { + return false; + } + if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::")) + || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) { + return false; + } + String[] octets = inet6Address.split(":"); + if (containsCompressedZeroes) { + List octetList = new ArrayList(Arrays.asList(octets)); + if (inet6Address.endsWith("::")) { + // String.split() drops ending empty segments + octetList.add(""); + } else if (inet6Address.startsWith("::") && !octetList.isEmpty()) { + octetList.remove(0); + } + octets = octetList.toArray(new String[octetList.size()]); + } + if (octets.length > IPV6_MAX_HEX_GROUPS) { + return false; + } + int validOctets = 0; + int emptyOctets = 0; // consecutive empty chunks + for (int index = 0; index < octets.length; index++) { + String octet = octets[index]; + if (octet.length() == 0) { + emptyOctets++; + if (emptyOctets > 1) { + return false; + } + } else { + emptyOctets = 0; + // Is last chunk an IPv4 address? + if (index == octets.length - 1 && octet.contains(".")) { + if (!isValidInet4Address(octet)) { + return false; + } + validOctets += 2; + continue; + } + if (octet.length() > IPV6_MAX_HEX_DIGITS_PER_GROUP) { + return false; + } + int octetInt = 0; + try { + octetInt = Integer.parseInt(octet, BASE_16); + } catch (NumberFormatException e) { + return false; + } + if (octetInt < 0 || octetInt > MAX_UNSIGNED_SHORT) { + return false; + } + } + validOctets++; + } + if (validOctets > IPV6_MAX_HEX_GROUPS || (validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes)) { + return false; + } + return true; + } +} diff --git a/projects/bleckw/FinalProject/URLValidatorInCorrect/src/RegexValidator.java b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/RegexValidator.java new file mode 100644 index 00000000..9f49087b --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/RegexValidator.java @@ -0,0 +1,229 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** + * Regular Expression validation (using JDK 1.4+ regex support). + *

+ * Construct the validator either for a single regular expression or a set (array) of + * regular expressions. By default validation is case sensitive but constructors + * are provided to allow case in-sensitive validation. For example to create + * a validator which does case in-sensitive validation for a set of regular + * expressions: + *

+ *
+ * 
+ * String[] regexs = new String[] {...};
+ * RegexValidator validator = new RegexValidator(regexs, false);
+ * 
+ * 
+ * + *
    + *
  • Validate true or false:
  • + *
  • + *
      + *
    • boolean valid = validator.isValid(value);
    • + *
    + *
  • + *
  • Validate returning an aggregated String of the matched groups:
  • + *
  • + *
      + *
    • String result = validator.validate(value);
    • + *
    + *
  • + *
  • Validate returning the matched groups:
  • + *
  • + *
      + *
    • String[] result = validator.match(value);
    • + *
    + *
  • + *
+ * + * Note that patterns are matched against the entire input. + * + *

+ * Cached instances pre-compile and re-use {@link Pattern}(s) - which according + * to the {@link Pattern} API are safe to use in a multi-threaded environment. + *

+ * + * @version $Revision: 1739356 $ + * @since Validator 1.4 + */ +public class RegexValidator implements Serializable { + + private static final long serialVersionUID = -8832409930574867162L; + + private final Pattern[] patterns; + + /** + * Construct a case sensitive validator for a single + * regular expression. + * + * @param regex The regular expression this validator will + * validate against + */ + public RegexValidator(String regex) { + this(regex, true); + } + + /** + * Construct a validator for a single regular expression + * with the specified case sensitivity. + * + * @param regex The regular expression this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String regex, boolean caseSensitive) { + this(new String[] {regex}, caseSensitive); + } + + /** + * Construct a case sensitive validator that matches any one + * of the set of regular expressions. + * + * @param regexs The set of regular expressions this validator will + * validate against + */ + public RegexValidator(String[] regexs) { + this(regexs, true); + } + + /** + * Construct a validator that matches any one of the set of regular + * expressions with the specified case sensitivity. + * + * @param regexs The set of regular expressions this validator will + * validate against + * @param caseSensitive when true matching is case + * sensitive, otherwise matching is case in-sensitive + */ + public RegexValidator(String[] regexs, boolean caseSensitive) { + if (regexs == null || regexs.length == 0) { + throw new IllegalArgumentException("Regular expressions are missing"); + } + patterns = new Pattern[regexs.length]; + int flags = (caseSensitive ? 0: Pattern.CASE_INSENSITIVE); + for (int i = 0; i < regexs.length; i++) { + if (regexs[i] == null || regexs[i].length() == 0) { + throw new IllegalArgumentException("Regular expression[" + i + "] is missing"); + } + patterns[i] = Pattern.compile(regexs[i], flags); + } + } + + /** + * Validate a value against the set of regular expressions. + * + * @param value The value to validate. + * @return true if the value is valid + * otherwise false. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + for (int i = 0; i < patterns.length; i++) { + if (patterns[i].matcher(value).matches()) { + return true; + } + } + return false; + } + + /** + * Validate a value against the set of regular expressions + * returning the array of matched groups. + * + * @param value The value to validate. + * @return String array of the groups matched if + * valid or null if invalid + */ + public String[] match(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + String[] groups = new String[count]; + for (int j = 0; j < count; j++) { + groups[j] = matcher.group(j+1); + } + return groups; + } + } + return null; + } + + + /** + * Validate a value against the set of regular expressions + * returning a String value of the aggregated groups. + * + * @param value The value to validate. + * @return Aggregated String value comprised of the + * groups matched if valid or null if invalid + */ + public String validate(String value) { + if (value == null) { + return null; + } + for (int i = 0; i < patterns.length; i++) { + Matcher matcher = patterns[i].matcher(value); + if (matcher.matches()) { + int count = matcher.groupCount(); + if (count == 1) { + return matcher.group(1); + } + StringBuilder buffer = new StringBuilder(); + for (int j = 0; j < count; j++) { + String component = matcher.group(j+1); + if (component != null) { + buffer.append(component); + } + } + return buffer.toString(); + } + } + return null; + } + + /** + * Provide a String representation of this validator. + * @return A String representation of this validator + */ + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RegexValidator{"); + for (int i = 0; i < patterns.length; i++) { + if (i > 0) { + buffer.append(","); + } + buffer.append(patterns[i].pattern()); + } + buffer.append("}"); + return buffer.toString(); + } + +} diff --git a/projects/bleckw/FinalProject/URLValidatorInCorrect/src/ResultPair.java b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/ResultPair.java new file mode 100644 index 00000000..01d6b682 --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/ResultPair.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/** + * Groups tests and expected results. + * + * @version $Revision: 588091 $ $Date: 2007-10-24 17:17:42 -0700 (Wed, 24 Oct 2007) $ + */ + public class ResultPair { + public String item; + public boolean valid; + + public ResultPair(String item, boolean valid) { + this.item = item; + this.valid = valid; //Weather the individual part of url is valid. + } + } diff --git a/projects/bleckw/FinalProject/URLValidatorInCorrect/src/UrlValidator.java b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/UrlValidator.java new file mode 100644 index 00000000..01e759f6 --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorInCorrect/src/UrlValidator.java @@ -0,0 +1,543 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + *

URL Validation routines.

+ * Behavior of validation is modified by passing in options: + *
    + *
  • ALLOW_2_SLASHES - [FALSE] Allows double '/' characters in the path + * component.
  • + *
  • NO_FRAGMENT- [FALSE] By default fragments are allowed, if this option is + * included then fragments are flagged as illegal.
  • + *
  • ALLOW_ALL_SCHEMES - [FALSE] By default only http, https, and ftp are + * considered valid schemes. Enabling this option will let any scheme pass validation.
  • + *
+ * + *

Originally based in on php script by Debbie Dyer, validation.php v1.2b, Date: 03/07/02, + * http://javascript.internet.com. However, this validation now bears little resemblance + * to the php original.

+ *
+ *   Example of usage:
+ *   Construct a UrlValidator with valid schemes of "http", and "https".
+ *
+ *    String[] schemes = {"http","https"}.
+ *    UrlValidator urlValidator = new UrlValidator(schemes);
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *    prints "url is invalid"
+ *   If instead the default constructor is used.
+ *
+ *    UrlValidator urlValidator = new UrlValidator();
+ *    if (urlValidator.isValid("ftp://foo.bar.com/")) {
+ *       System.out.println("url is valid");
+ *    } else {
+ *       System.out.println("url is invalid");
+ *    }
+ *
+ *   prints out "url is valid"
+ *  
+ * + * @see + * + * Uniform Resource Identifiers (URI): Generic Syntax + * + * + * @version $Revision: 1783203 $ + * @since Validator 1.4 + */ +public class UrlValidator implements Serializable { + + private static final long serialVersionUID = 7557161713937335013L; + + private static final int MAX_UNSIGNED_16_BIT_INT = 0xFFFF; // port max + + /** + * Allows all validly formatted schemes to pass validation instead of + * supplying a set of valid schemes. + */ + public static final long ALLOW_ALL_SCHEMES = 1 << 0; + + /** + * Allow two slashes in the path component of the URL. + */ + public static final long ALLOW_2_SLASHES = 1 << 1; + + /** + * Enabling this options disallows any URL fragments. + */ + public static final long NO_FRAGMENTS = 1 << 2; + + /** + * Allow local URLs, such as http://localhost/ or http://machine/ . + * This enables a broad-brush check, for complex local machine name + * validation requirements you should create your validator with + * a {@link RegexValidator} instead ({@link #UrlValidator(RegexValidator, long)}) + */ + public static final long ALLOW_LOCAL_URLS = 1 << 3; // CHECKSTYLE IGNORE MagicNumber + + /** + * This expression derived/taken from the BNF for URI (RFC2396). + */ + private static final String URL_REGEX = + "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?"; + // 12 3 4 5 6 7 8 9 + private static final Pattern URL_PATTERN = Pattern.compile(URL_REGEX); + + /** + * Schema/Protocol (ie. http:, ftp:, file:, etc). + */ + private static final int PARSE_URL_SCHEME = 2; + + /** + * Includes hostname/ip and port number. + */ + private static final int PARSE_URL_AUTHORITY = 4; + + private static final int PARSE_URL_PATH = 5; + + private static final int PARSE_URL_QUERY = 7; + + private static final int PARSE_URL_FRAGMENT = 9; + + /** + * Protocol scheme (e.g. http, ftp, https). + */ + private static final String SCHEME_REGEX = "^\\p{Alpha}[\\p{Alnum}\\+\\-\\.]*"; + private static final Pattern SCHEME_PATTERN = Pattern.compile(SCHEME_REGEX); + + // Drop numeric, and "+-." for now + // TODO does not allow for optional userinfo. + // Validation of character set is done by isValidAuthority + private static final String AUTHORITY_CHARS_REGEX = "\\p{Alnum}\\-\\."; // allows for IPV4 but not IPV6 + private static final String IPV6_REGEX = "[0-9a-fA-F:]+"; // do this as separate match because : could cause ambiguity with port prefix + + // userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + // We assume that password has the same valid chars as user info + private static final String USERINFO_CHARS_REGEX = "[a-zA-Z0-9%-._~!$&'()*+,;=]"; + // since neither ':' nor '@' are allowed chars, we don't need to use non-greedy matching + private static final String USERINFO_FIELD_REGEX = + USERINFO_CHARS_REGEX + "+" + // At least one character for the name + "(?::" + USERINFO_CHARS_REGEX + "*)?@"; // colon and password may be absent + private static final String AUTHORITY_REGEX = + "(?:\\[("+IPV6_REGEX+")\\]|(?:(?:"+USERINFO_FIELD_REGEX+")?([" + AUTHORITY_CHARS_REGEX + "]*)))(?::(\\d*))?(.*)?"; + // 1 e.g. user:pass@ 2 3 4 + private static final Pattern AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEX); + + private static final int PARSE_AUTHORITY_IPV6 = 1; + + private static final int PARSE_AUTHORITY_HOST_IP = 2; // excludes userinfo, if present + + private static final int PARSE_AUTHORITY_PORT = 3; // excludes leading colon + + /** + * Should always be empty. The code currently allows spaces. + */ + private static final int PARSE_AUTHORITY_EXTRA = 4; + + private static final String PATH_REGEX = "^(/[-\\w:@&?=+,.!/~*'%$_;\\(\\)]*)?$"; + private static final Pattern PATH_PATTERN = Pattern.compile(PATH_REGEX); + + private static final String QUERY_REGEX = "^(\\S*)$"; + private static final Pattern QUERY_PATTERN = Pattern.compile(QUERY_REGEX); + + /** + * Holds the set of current validation options. + */ + private final long options; + + /** + * The set of schemes that are allowed to be in a URL. + */ + private final Set allowedSchemes; // Must be lower-case + + /** + * Regular expressions used to manually validate authorities if IANA + * domain name validation isn't desired. + */ + private final RegexValidator authorityValidator; + + /** + * If no schemes are provided, default to this set. + */ + private static final String[] DEFAULT_SCHEMES = {"http", "https", "ftp"}; // Must be lower-case + + /** + * Singleton instance of this class with default schemes and options. + */ + private static final UrlValidator DEFAULT_URL_VALIDATOR = new UrlValidator(); + + /** + * Returns the singleton instance of this class with default schemes and options. + * @return singleton instance with default schemes and options + */ + public static UrlValidator getInstance() { + return DEFAULT_URL_VALIDATOR; + } + + /** + * Create a UrlValidator with default properties. + */ + public UrlValidator() { + this(null); + } + + /** + * Behavior of validation is modified by passing in several strings options: + * @param schemes Pass in one or more url schemes to consider valid, passing in + * a null will default to "http,https,ftp" being valid. + * If a non-null schemes is specified then all valid schemes must + * be specified. Setting the ALLOW_ALL_SCHEMES option will + * ignore the contents of schemes. + */ + public UrlValidator(String[] schemes) { + this(schemes, 0L); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(long options) { + this(null, null, options); + } + + /** + * Behavior of validation is modified by passing in options: + * @param schemes The set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param options The options should be set using the public constants declared in + * this class. To set multiple options you simply add them together. For example, + * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options. + */ + public UrlValidator(String[] schemes, long options) { + this(schemes, null, options); + } + + /** + * Initialize a UrlValidator with the given validation options. + * @param authorityValidator Regular expression validator used to validate the authority part + * This allows the user to override the standard set of domains. + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(RegexValidator authorityValidator, long options) { + this(null, authorityValidator, options); + } + + /** + * Customizable constructor. Validation behavior is modifed by passing in options. + * @param schemes the set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set. + * @param authorityValidator Regular expression validator used to validate the authority part + * @param options Validation options. Set using the public constants of this class. + * To set multiple options, simply add them together: + *

ALLOW_2_SLASHES + NO_FRAGMENTS

+ * enables both of those options. + */ + public UrlValidator(String[] schemes, RegexValidator authorityValidator, long options) { + this.options = options; + + if (isOn(ALLOW_ALL_SCHEMES)) { + allowedSchemes = Collections.emptySet(); + } else { + if (schemes == null) { + schemes = DEFAULT_SCHEMES; + } + allowedSchemes = new HashSet(schemes.length); + for(int i=0; i < schemes.length; i++) { + allowedSchemes.add(schemes[i].toLowerCase(Locale.ENGLISH)); + } + } + + this.authorityValidator = authorityValidator; + } + + /** + *

Checks if a field has a valid url address.

+ * + * Note that the method calls #isValidAuthority() + * which checks that the domain is valid. + * + * @param value The value validation is being performed on. A null + * value is considered invalid. + * @return true if the url is valid. + */ + public boolean isValid(String value) { + if (value == null) { + return false; + } + + // Check the whole url address structure + Matcher urlMatcher = URL_PATTERN.matcher(value); + if (!urlMatcher.matches()) { + return false; + } + + String scheme = urlMatcher.group(PARSE_URL_SCHEME); + if (!isValidScheme(scheme)) { + return false; + } + + String authority = urlMatcher.group(PARSE_URL_AUTHORITY); + if ("file".equals(scheme)) {// Special case - file: allows an empty authority + if (authority != null) { + if (authority.contains(":")) { // but cannot allow trailing : + return false; + } + } + // drop through to continue validation + } else { // not file: + // Validate the authority + if (!isValidAuthority(authority)) { + return false; + } + } + + if (!isValidPath(urlMatcher.group(PARSE_URL_PATH))) { + return false; + } + + if (!isValidQuery(urlMatcher.group(PARSE_URL_QUERY))) { + return false; + } + + if (!isValidFragment(urlMatcher.group(PARSE_URL_FRAGMENT))) { + return false; + } + + return true; + } + + /** + * Validate scheme. If schemes[] was initialized to a non null, + * then only those schemes are allowed. + * Otherwise the default schemes are "http", "https", "ftp". + * Matching is case-blind. + * @param scheme The scheme to validate. A null value is considered + * invalid. + * @return true if valid. + */ + protected boolean isValidScheme(String scheme) { + if (scheme == null) { + return false; + } + + // TODO could be removed if external schemes were checked in the ctor before being stored + if (!SCHEME_PATTERN.matcher(scheme).matches()) { + return false; + } + + if (isOff(ALLOW_ALL_SCHEMES) && !allowedSchemes.contains(scheme.toLowerCase(Locale.ENGLISH))) { + return false; + } + + return true; + } + + /** + * Returns true if the authority is properly formatted. An authority is the combination + * of hostname and port. A null authority value is considered invalid. + * Note: this implementation validates the domain unless a RegexValidator was provided. + * If a RegexValidator was supplied and it matches, then the authority is regarded + * as valid with no further checks, otherwise the method checks against the + * AUTHORITY_PATTERN and the DomainValidator (ALLOW_LOCAL_URLS) + * @param authority Authority value to validate, alllows IDN + * @return true if authority (hostname and port) is valid. + */ + protected boolean isValidAuthority(String authority) { + if (authority == null) { + return false; + } + + // check manual authority validation if specified + if (authorityValidator != null && authorityValidator.isValid(authority)) { + return true; + } + // convert to ASCII if possible + final String authorityASCII = DomainValidator.unicodeToASCII(authority); + + Matcher authorityMatcher = AUTHORITY_PATTERN.matcher(authorityASCII); + if (!authorityMatcher.matches()) { + return false; + } + + // We have to process IPV6 separately because that is parsed in a different group + String ipv6 = authorityMatcher.group(PARSE_AUTHORITY_IPV6); + if (ipv6 != null) { + InetAddressValidator inetAddressValidator = InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet6Address(ipv6)) { + return false; + } + } else { + String hostLocation = authorityMatcher.group(PARSE_AUTHORITY_HOST_IP); + // check if authority is hostname or IP address: + // try a hostname first since that's much more likely + DomainValidator domainValidator = DomainValidator.getInstance(isOn(ALLOW_LOCAL_URLS)); + if (!domainValidator.isValid(hostLocation)) { + // try an IPv4 address + InetAddressValidator inetAddressValidator = InetAddressValidator.getInstance(); + if (!inetAddressValidator.isValidInet4Address(hostLocation)) { + // isn't IPv4, so the URL is invalid + return false; + } + } + String port = authorityMatcher.group(PARSE_AUTHORITY_PORT); + if (port != null && port.length() > 0) { + try { + int iPort = Integer.parseInt(port); + if (iPort < 0 || iPort > MAX_UNSIGNED_16_BIT_INT) { + return false; + } + } catch (NumberFormatException nfe) { + return false; // this can happen for big numbers + } + } + } + + String extra = authorityMatcher.group(PARSE_AUTHORITY_EXTRA); + if (extra != null && extra.trim().length() > 0){ + return false; + } + + return true; + } + + /** + * Returns true if the path is valid. A null value is considered invalid. + * @param path Path value to validate. + * @return true if path is valid. + */ + protected boolean isValidPath(String path) { + if (path == null) { + return false; + } + + if (!PATH_PATTERN.matcher(path).matches()) { + return false; + } + + try { + URI uri = new URI(null,null,path,null); + String norm = uri.normalize().getPath(); + if (norm.startsWith("/../") // Trying to go via the parent dir + || norm.equals("/..")) { // Trying to go to the parent dir + return false; + } + } catch (URISyntaxException e) { + return false; + } + + int slash2Count = countToken("//", path); + if (isOff(ALLOW_2_SLASHES) && (slash2Count > 0)) { + return false; + } + + return true; + } + + /** + * Returns true if the query is null or it's a properly formatted query string. + * @param query Query value to validate. + * @return true if query is valid. + */ + protected boolean isValidQuery(String query) { + if (query == null) { + return true; + } + + return QUERY_PATTERN.matcher(query).matches(); + } + + /** + * Returns true if the given fragment is null or fragments are allowed. + * @param fragment Fragment value to validate. + * @return true if fragment is valid. + */ + protected boolean isValidFragment(String fragment) { + if (fragment == null) { + return true; + } + + return isOff(NO_FRAGMENTS); + } + + /** + * Returns the number of times the token appears in the target. + * @param token Token value to be counted. + * @param target Target value to count tokens in. + * @return the number of tokens. + */ + protected int countToken(String token, String target) { + int tokenIndex = 0; + int count = 0; + while (tokenIndex != -1) { + tokenIndex = target.indexOf(token, tokenIndex); + if (tokenIndex > -1) { + tokenIndex++; + count++; + } + } + return count; + } + + /** + * Tests whether the given flag is on. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is on. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is on. + */ + private boolean isOn(long flag) { + return (options & flag) > 0; + } + + /** + * Tests whether the given flag is off. If the flag is not a power of 2 + * (ie. 3) this tests whether the combination of flags is off. + * + * @param flag Flag value to check. + * + * @return whether the specified flag value is off. + */ + private boolean isOff(long flag) { + return (options & flag) == 0; + } + + // Unit test access to pattern matcher + Matcher matchURL(String value) { + return URL_PATTERN.matcher(value); + } +} diff --git a/projects/bleckw/FinalProject/URLValidatorInCorrect/test/UrlValidatorTest.java b/projects/bleckw/FinalProject/URLValidatorInCorrect/test/UrlValidatorTest.java new file mode 100644 index 00000000..f6dad84e --- /dev/null +++ b/projects/bleckw/FinalProject/URLValidatorInCorrect/test/UrlValidatorTest.java @@ -0,0 +1,600 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import junit.framework.TestCase; + +/** + * Performs Validation Test for url validations. + * + * @version $Revision$ + */ +public class UrlValidatorTest extends TestCase { + + private final boolean printStatus = false; + private final boolean printIndex = false;//print index that indicates current scheme,host,port,path, query test were using. + + public UrlValidatorTest(String testName) { + super(testName); + } + + @Override +protected void setUp() { + for (int index = 0; index < testPartsIndex.length - 1; index++) { + testPartsIndex[index] = 0; + } + } + + public void testIsValid() { + testIsValid(testUrlParts, UrlValidator.ALLOW_ALL_SCHEMES); + setUp(); + long options = + UrlValidator.ALLOW_2_SLASHES + + UrlValidator.ALLOW_ALL_SCHEMES + + UrlValidator.NO_FRAGMENTS; + + testIsValid(testUrlPartsOptions, options); + } + + public void testIsValidScheme() { + if (printStatus) { + System.out.print("\n testIsValidScheme() "); + } + //UrlValidator urlVal = new UrlValidator(schemes,false,false,false); + UrlValidator urlVal = new UrlValidator(schemes, 0); + for (int sIndex = 0; sIndex < testScheme.length; sIndex++) { + ResultPair testPair = testScheme[sIndex]; + boolean result = urlVal.isValidScheme(testPair.item); + assertEquals(testPair.item, testPair.valid, result); + if (printStatus) { + if (result == testPair.valid) { + System.out.print('.'); + } else { + System.out.print('X'); + } + } + } + if (printStatus) { + System.out.println(); + } + + } + + /** + * Create set of tests by taking the testUrlXXX arrays and + * running through all possible permutations of their combinations. + * + * @param testObjects Used to create a url. + */ + public void testIsValid(Object[] testObjects, long options) { + UrlValidator urlVal = new UrlValidator(null, null, options); + assertTrue(urlVal.isValid("http://www.google.com")); + assertTrue(urlVal.isValid("http://www.google.com/")); + int statusPerLine = 60; + int printed = 0; + if (printIndex) { + statusPerLine = 6; + } + do { + StringBuilder testBuffer = new StringBuilder(); + boolean expected = true; + for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) { + int index = testPartsIndex[testPartsIndexIndex]; + ResultPair[] part = (ResultPair[]) testObjects[testPartsIndexIndex]; + testBuffer.append(part[index].item); + expected &= part[index].valid; + } + String url = testBuffer.toString(); + boolean result = urlVal.isValid(url); + assertEquals(url, expected, result); + if (printStatus) { + if (printIndex) { + System.out.print(testPartsIndextoString()); + } else { + if (result == expected) { + System.out.print('.'); + } else { + System.out.print('X'); + } + } + printed++; + if (printed == statusPerLine) { + System.out.println(); + printed = 0; + } + } + } while (incrementTestPartsIndex(testPartsIndex, testObjects)); + if (printStatus) { + System.out.println(); + } + } + + public void testValidator202() { + String[] schemes = {"http","https"}; + UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.NO_FRAGMENTS); + assertTrue(urlValidator.isValid("http://l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.org")); + } + + public void testValidator204() { + String[] schemes = {"http","https"}; + UrlValidator urlValidator = new UrlValidator(schemes); + assertTrue(urlValidator.isValid("http://tech.yahoo.com/rc/desktops/102;_ylt=Ao8yevQHlZ4On0O3ZJGXLEQFLZA5")); + } + + public void testValidator218() { + UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_2_SLASHES); + assertTrue("parentheses should be valid in URLs", + validator.isValid("http://somewhere.com/pathxyz/file(1).html")); + } + + public void testValidator235() { + String version = System.getProperty("java.version"); + if (version.compareTo("1.6") < 0) { + System.out.println("Cannot run Unicode IDN tests"); + return; // Cannot run the test + } + UrlValidator validator = new UrlValidator(); + assertTrue("xn--d1abbgf6aiiy.xn--p1ai should validate", validator.isValid("http://xn--d1abbgf6aiiy.xn--p1ai")); + assertTrue("президент.рф should validate", validator.isValid("http://президент.рф")); + assertTrue("www.b\u00fccher.ch should validate", validator.isValid("http://www.b\u00fccher.ch")); + assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("http://www.\uFFFD.ch")); + assertTrue("www.b\u00fccher.ch should validate", validator.isValid("ftp://www.b\u00fccher.ch")); + assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("ftp://www.\uFFFD.ch")); + } + + public void testValidator248() { + RegexValidator regex = new RegexValidator(new String[] {"localhost", ".*\\.my-testing"}); + UrlValidator validator = new UrlValidator(regex, 0); + + assertTrue("localhost URL should validate", + validator.isValid("http://localhost/test/index.html")); + assertTrue("first.my-testing should validate", + validator.isValid("http://first.my-testing/test/index.html")); + assertTrue("sup3r.my-testing should validate", + validator.isValid("http://sup3r.my-testing/test/index.html")); + + assertFalse("broke.my-test should not validate", + validator.isValid("http://broke.my-test/test/index.html")); + + assertTrue("www.apache.org should still validate", + validator.isValid("http://www.apache.org/test/index.html")); + + // Now check using options + validator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS); + + assertTrue("localhost URL should validate", + validator.isValid("http://localhost/test/index.html")); + + assertTrue("machinename URL should validate", + validator.isValid("http://machinename/test/index.html")); + + assertTrue("www.apache.org should still validate", + validator.isValid("http://www.apache.org/test/index.html")); + } + + public void testValidator288() { + UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS); + + assertTrue("hostname should validate", + validator.isValid("http://hostname")); + + assertTrue("hostname with path should validate", + validator.isValid("http://hostname/test/index.html")); + + assertTrue("localhost URL should validate", + validator.isValid("http://localhost/test/index.html")); + + assertFalse("first.my-testing should not validate", + validator.isValid("http://first.my-testing/test/index.html")); + + assertFalse("broke.hostname should not validate", + validator.isValid("http://broke.hostname/test/index.html")); + + assertTrue("www.apache.org should still validate", + validator.isValid("http://www.apache.org/test/index.html")); + + // Turn it off, and check + validator = new UrlValidator(0); + + assertFalse("hostname should no longer validate", + validator.isValid("http://hostname")); + + assertFalse("localhost URL should no longer validate", + validator.isValid("http://localhost/test/index.html")); + + assertTrue("www.apache.org should still validate", + validator.isValid("http://www.apache.org/test/index.html")); + } + + public void testValidator276() { + // file:// isn't allowed by default + UrlValidator validator = new UrlValidator(); + + assertTrue("http://apache.org/ should be allowed by default", + validator.isValid("http://www.apache.org/test/index.html")); + + assertFalse("file:///c:/ shouldn't be allowed by default", + validator.isValid("file:///C:/some.file")); + + assertFalse("file:///c:\\ shouldn't be allowed by default", + validator.isValid("file:///C:\\some.file")); + + assertFalse("file:///etc/ shouldn't be allowed by default", + validator.isValid("file:///etc/hosts")); + + assertFalse("file://localhost/etc/ shouldn't be allowed by default", + validator.isValid("file://localhost/etc/hosts")); + + assertFalse("file://localhost/c:/ shouldn't be allowed by default", + validator.isValid("file://localhost/c:/some.file")); + + // Turn it on, and check + // Note - we need to enable local urls when working with file: + validator = new UrlValidator(new String[] {"http","file"}, UrlValidator.ALLOW_LOCAL_URLS); + + assertTrue("http://apache.org/ should be allowed by default", + validator.isValid("http://www.apache.org/test/index.html")); + + assertTrue("file:///c:/ should now be allowed", + validator.isValid("file:///C:/some.file")); + + // Currently, we don't support the c:\ form + assertFalse("file:///c:\\ shouldn't be allowed", + validator.isValid("file:///C:\\some.file")); + + assertTrue("file:///etc/ should now be allowed", + validator.isValid("file:///etc/hosts")); + + assertTrue("file://localhost/etc/ should now be allowed", + validator.isValid("file://localhost/etc/hosts")); + + assertTrue("file://localhost/c:/ should now be allowed", + validator.isValid("file://localhost/c:/some.file")); + + // These are never valid + assertFalse("file://c:/ shouldn't ever be allowed, needs file:///c:/", + validator.isValid("file://C:/some.file")); + + assertFalse("file://c:\\ shouldn't ever be allowed, needs file:///c:/", + validator.isValid("file://C:\\some.file")); + } + + public void testValidator391OK() { + String[] schemes = {"file"}; + UrlValidator urlValidator = new UrlValidator(schemes); + assertTrue(urlValidator.isValid("file:///C:/path/to/dir/")); + } + + public void testValidator391FAILS() { + String[] schemes = {"file"}; + UrlValidator urlValidator = new UrlValidator(schemes); + assertTrue(urlValidator.isValid("file:/C:/path/to/dir/")); + } + + public void testValidator309() { + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://sample.ondemand.com/")); + assertTrue(urlValidator.isValid("hTtP://sample.ondemand.CoM/")); + assertTrue(urlValidator.isValid("httpS://SAMPLE.ONEMAND.COM/")); + urlValidator = new UrlValidator(new String[] {"HTTP","HTTPS"}); + assertTrue(urlValidator.isValid("http://sample.ondemand.com/")); + assertTrue(urlValidator.isValid("hTtP://sample.ondemand.CoM/")); + assertTrue(urlValidator.isValid("httpS://SAMPLE.ONEMAND.COM/")); + } + + public void testValidator339(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://www.cnn.com/WORLD/?hpt=sitenav")); // without + assertTrue(urlValidator.isValid("http://www.cnn.com./WORLD/?hpt=sitenav")); // with + assertFalse(urlValidator.isValid("http://www.cnn.com../")); // doubly dotty + assertFalse(urlValidator.isValid("http://www.cnn.invalid/")); + assertFalse(urlValidator.isValid("http://www.cnn.invalid./")); // check . does not affect invalid domains + } + + public void testValidator339IDN(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://президент.рф/WORLD/?hpt=sitenav")); // without + assertTrue(urlValidator.isValid("http://президент.рф./WORLD/?hpt=sitenav")); // with + assertFalse(urlValidator.isValid("http://президент.рф..../")); // very dotty + assertFalse(urlValidator.isValid("http://президент.рф.../")); // triply dotty + assertFalse(urlValidator.isValid("http://президент.рф../")); // doubly dotty + } + + public void testValidator342(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://example.rocks/")); + assertTrue(urlValidator.isValid("http://example.rocks")); + } + + public void testValidator411(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://example.rocks:/")); + assertTrue(urlValidator.isValid("http://example.rocks:0/")); + assertTrue(urlValidator.isValid("http://example.rocks:65535/")); + assertFalse(urlValidator.isValid("http://example.rocks:65536/")); + assertFalse(urlValidator.isValid("http://example.rocks:100000/")); + } + + static boolean incrementTestPartsIndex(int[] testPartsIndex, Object[] testParts) { + boolean carry = true; //add 1 to lowest order part. + boolean maxIndex = true; + for (int testPartsIndexIndex = testPartsIndex.length - 1; testPartsIndexIndex >= 0; --testPartsIndexIndex) { + int index = testPartsIndex[testPartsIndexIndex]; + ResultPair[] part = (ResultPair[]) testParts[testPartsIndexIndex]; + maxIndex &= (index == (part.length - 1)); + if (carry) { + if (index < part.length - 1) { + index++; + testPartsIndex[testPartsIndexIndex] = index; + carry = false; + } else { + testPartsIndex[testPartsIndexIndex] = 0; + carry = true; + } + } + } + + + return (!maxIndex); + } + + private String testPartsIndextoString() { + StringBuilder carryMsg = new StringBuilder("{"); + for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) { + carryMsg.append(testPartsIndex[testPartsIndexIndex]); + if (testPartsIndexIndex < testPartsIndex.length - 1) { + carryMsg.append(','); + } else { + carryMsg.append('}'); + } + } + return carryMsg.toString(); + + } + + public void testValidateUrl() { + assertTrue(true); + } + + public void testValidator290() { + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("http://xn--h1acbxfam.idn.icann.org/")); +// assertTrue(validator.isValid("http://xn--e1afmkfd.xn--80akhbyknj4f")); + // Internationalized country code top-level domains + assertTrue(validator.isValid("http://test.xn--lgbbat1ad8j")); //Algeria + assertTrue(validator.isValid("http://test.xn--fiqs8s")); // China + assertTrue(validator.isValid("http://test.xn--fiqz9s")); // China + assertTrue(validator.isValid("http://test.xn--wgbh1c")); // Egypt + assertTrue(validator.isValid("http://test.xn--j6w193g")); // Hong Kong + assertTrue(validator.isValid("http://test.xn--h2brj9c")); // India + assertTrue(validator.isValid("http://test.xn--mgbbh1a71e")); // India + assertTrue(validator.isValid("http://test.xn--fpcrj9c3d")); // India + assertTrue(validator.isValid("http://test.xn--gecrj9c")); // India + assertTrue(validator.isValid("http://test.xn--s9brj9c")); // India + assertTrue(validator.isValid("http://test.xn--xkc2dl3a5ee0h")); // India + assertTrue(validator.isValid("http://test.xn--45brj9c")); // India + assertTrue(validator.isValid("http://test.xn--mgba3a4f16a")); // Iran + assertTrue(validator.isValid("http://test.xn--mgbayh7gpa")); // Jordan + assertTrue(validator.isValid("http://test.xn--mgbc0a9azcg")); // Morocco + assertTrue(validator.isValid("http://test.xn--ygbi2ammx")); // Palestinian Territory + assertTrue(validator.isValid("http://test.xn--wgbl6a")); // Qatar + assertTrue(validator.isValid("http://test.xn--p1ai")); // Russia + assertTrue(validator.isValid("http://test.xn--mgberp4a5d4ar")); // Saudi Arabia + assertTrue(validator.isValid("http://test.xn--90a3ac")); // Serbia + assertTrue(validator.isValid("http://test.xn--yfro4i67o")); // Singapore + assertTrue(validator.isValid("http://test.xn--clchc0ea0b2g2a9gcd")); // Singapore + assertTrue(validator.isValid("http://test.xn--3e0b707e")); // South Korea + assertTrue(validator.isValid("http://test.xn--fzc2c9e2c")); // Sri Lanka + assertTrue(validator.isValid("http://test.xn--xkc2al3hye2a")); // Sri Lanka + assertTrue(validator.isValid("http://test.xn--ogbpf8fl")); // Syria + assertTrue(validator.isValid("http://test.xn--kprw13d")); // Taiwan + assertTrue(validator.isValid("http://test.xn--kpry57d")); // Taiwan + assertTrue(validator.isValid("http://test.xn--o3cw4h")); // Thailand + assertTrue(validator.isValid("http://test.xn--pgbs0dh")); // Tunisia + assertTrue(validator.isValid("http://test.xn--mgbaam7a8h")); // United Arab Emirates + // Proposed internationalized ccTLDs +// assertTrue(validator.isValid("http://test.xn--54b7fta0cc")); // Bangladesh +// assertTrue(validator.isValid("http://test.xn--90ae")); // Bulgaria +// assertTrue(validator.isValid("http://test.xn--node")); // Georgia +// assertTrue(validator.isValid("http://test.xn--4dbrk0ce")); // Israel +// assertTrue(validator.isValid("http://test.xn--mgb9awbf")); // Oman +// assertTrue(validator.isValid("http://test.xn--j1amh")); // Ukraine +// assertTrue(validator.isValid("http://test.xn--mgb2ddes")); // Yemen + // Test TLDs +// assertTrue(validator.isValid("http://test.xn--kgbechtv")); // Arabic +// assertTrue(validator.isValid("http://test.xn--hgbk6aj7f53bba")); // Persian +// assertTrue(validator.isValid("http://test.xn--0zwm56d")); // Chinese +// assertTrue(validator.isValid("http://test.xn--g6w251d")); // Chinese +// assertTrue(validator.isValid("http://test.xn--80akhbyknj4f")); // Russian +// assertTrue(validator.isValid("http://test.xn--11b5bs3a9aj6g")); // Hindi +// assertTrue(validator.isValid("http://test.xn--jxalpdlp")); // Greek +// assertTrue(validator.isValid("http://test.xn--9t4b11yi5a")); // Korean +// assertTrue(validator.isValid("http://test.xn--deba0ad")); // Yiddish +// assertTrue(validator.isValid("http://test.xn--zckzah")); // Japanese +// assertTrue(validator.isValid("http://test.xn--hlcj6aya9esc7a")); // Tamil + } + + public void testValidator361() { + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("http://hello.tokyo/")); + } + + public void testValidator363(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://www.example.org/a/b/hello..world")); + assertTrue(urlValidator.isValid("http://www.example.org/a/hello..world")); + assertTrue(urlValidator.isValid("http://www.example.org/hello.world/")); + assertTrue(urlValidator.isValid("http://www.example.org/hello..world/")); + assertTrue(urlValidator.isValid("http://www.example.org/hello.world")); + assertTrue(urlValidator.isValid("http://www.example.org/hello..world")); + assertTrue(urlValidator.isValid("http://www.example.org/..world")); + assertTrue(urlValidator.isValid("http://www.example.org/.../world")); + assertFalse(urlValidator.isValid("http://www.example.org/../world")); + assertFalse(urlValidator.isValid("http://www.example.org/..")); + assertFalse(urlValidator.isValid("http://www.example.org/../")); + assertFalse(urlValidator.isValid("http://www.example.org/./..")); + assertFalse(urlValidator.isValid("http://www.example.org/././..")); + assertTrue(urlValidator.isValid("http://www.example.org/...")); + assertTrue(urlValidator.isValid("http://www.example.org/.../")); + assertTrue(urlValidator.isValid("http://www.example.org/.../..")); + } + + public void testValidator375() { + UrlValidator validator = new UrlValidator(); + String url = "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html"; + assertTrue("IPv6 address URL should validate: " + url, validator.isValid(url)); + url = "http://[::1]:80/index.html"; + assertTrue("IPv6 address URL should validate: " + url, validator.isValid(url)); + url = "http://FEDC:BA98:7654:3210:FEDC:BA98:7654:3210:80/index.html"; + assertFalse("IPv6 address without [] should not validate: " + url, validator.isValid(url)); + } + + + public void testValidator353() { // userinfo + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("http://www.apache.org:80/path")); + assertTrue(validator.isValid("http://user:pass@www.apache.org:80/path")); + assertTrue(validator.isValid("http://user:@www.apache.org:80/path")); + assertTrue(validator.isValid("http://user@www.apache.org:80/path")); + assertTrue(validator.isValid("http://us%00er:-._~!$&'()*+,;=@www.apache.org:80/path")); + assertFalse(validator.isValid("http://:pass@www.apache.org:80/path")); + assertFalse(validator.isValid("http://:@www.apache.org:80/path")); + assertFalse(validator.isValid("http://user:pa:ss@www.apache.org/path")); + assertFalse(validator.isValid("http://user:pa@ss@www.apache.org/path")); + } + + public void testValidator382() { + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("ftp://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose")); + } + + public void testValidator380() { + UrlValidator validator = new UrlValidator(); + assertTrue(validator.isValid("http://www.apache.org:80/path")); + assertTrue(validator.isValid("http://www.apache.org:8/path")); + assertTrue(validator.isValid("http://www.apache.org:/path")); + } + + public void testValidator420() { + UrlValidator validator = new UrlValidator(); + assertFalse(validator.isValid("http://example.com/serach?address=Main Avenue")); + assertTrue(validator.isValid("http://example.com/serach?address=Main%20Avenue")); + assertTrue(validator.isValid("http://example.com/serach?address=Main+Avenue")); + } + + //-------------------- Test data for creating a composite URL + /** + * The data given below approximates the 4 parts of a URL + * ://? except that the port number + * is broken out of authority to increase the number of permutations. + * A complete URL is composed of a scheme+authority+port+path+query, + * all of which must be individually valid for the entire URL to be considered + * valid. + */ + ResultPair[] testUrlScheme = {new ResultPair("http://", true), + new ResultPair("ftp://", true), + new ResultPair("h3t://", true), + new ResultPair("3ht://", false), + new ResultPair("http:/", false), + new ResultPair("http:", false), + new ResultPair("http/", false), + new ResultPair("://", false)}; + + ResultPair[] testUrlAuthority = {new ResultPair("www.google.com", true), + new ResultPair("www.google.com.", true), + new ResultPair("go.com", true), + new ResultPair("go.au", true), + new ResultPair("0.0.0.0", true), + new ResultPair("255.255.255.255", true), + new ResultPair("256.256.256.256", false), + new ResultPair("255.com", true), + new ResultPair("1.2.3.4.5", false), + new ResultPair("1.2.3.4.", false), + new ResultPair("1.2.3", false), + new ResultPair(".1.2.3.4", false), + new ResultPair("go.a", false), + new ResultPair("go.a1a", false), + new ResultPair("go.cc", true), + new ResultPair("go.1aa", false), + new ResultPair("aaa.", false), + new ResultPair(".aaa", false), + new ResultPair("aaa", false), + new ResultPair("", false) + }; + ResultPair[] testUrlPort = {new ResultPair(":80", true), + new ResultPair(":65535", true), // max possible + new ResultPair(":65536", false), // max possible +1 + new ResultPair(":0", true), + new ResultPair("", true), + new ResultPair(":-1", false), + new ResultPair(":65636", false), + new ResultPair(":999999999999999999", false), + new ResultPair(":65a", false) + }; + ResultPair[] testPath = {new ResultPair("/test1", true), + new ResultPair("/t123", true), + new ResultPair("/$23", true), + new ResultPair("/..", false), + new ResultPair("/../", false), + new ResultPair("/test1/", true), + new ResultPair("", true), + new ResultPair("/test1/file", true), + new ResultPair("/..//file", false), + new ResultPair("/test1//file", false) + }; + //Test allow2slash, noFragment + ResultPair[] testUrlPathOptions = {new ResultPair("/test1", true), + new ResultPair("/t123", true), + new ResultPair("/$23", true), + new ResultPair("/..", false), + new ResultPair("/../", false), + new ResultPair("/test1/", true), + new ResultPair("/#", false), + new ResultPair("", true), + new ResultPair("/test1/file", true), + new ResultPair("/t123/file", true), + new ResultPair("/$23/file", true), + new ResultPair("/../file", false), + new ResultPair("/..//file", false), + new ResultPair("/test1//file", true), + new ResultPair("/#/file", false) + }; + + ResultPair[] testUrlQuery = {new ResultPair("?action=view", true), + new ResultPair("?action=edit&mode=up", true), + new ResultPair("", true) + }; + + Object[] testUrlParts = {testUrlScheme, testUrlAuthority, testUrlPort, testPath, testUrlQuery}; + Object[] testUrlPartsOptions = {testUrlScheme, testUrlAuthority, testUrlPort, testUrlPathOptions, testUrlQuery}; + int[] testPartsIndex = {0, 0, 0, 0, 0}; + + //---------------- Test data for individual url parts ---------------- + private final String[] schemes = {"http", "gopher", "g0-To+.", + "not_valid" // TODO this will need to be dropped if the ctor validates schemes + }; + + ResultPair[] testScheme = {new ResultPair("http", true), + new ResultPair("ftp", false), + new ResultPair("httpd", false), + new ResultPair("gopher", true), + new ResultPair("g0-to+.", true), + new ResultPair("not_valid", false), // underscore not allowed + new ResultPair("HtTp", true), + new ResultPair("telnet", false)}; + + +} diff --git a/projects/bleckw/FinalProject/bin/DomainValidator$ArrayType.class b/projects/bleckw/FinalProject/bin/DomainValidator$ArrayType.class new file mode 100644 index 0000000000000000000000000000000000000000..aed791f12adb7079dfca36bee174141e405717ef GIT binary patch literal 1484 zcmaJ=ZF3S=6n?G?++}m4glaS|O|{Y{ppmAH_63>-39*bIx;K?sNZp^Ve$t>v$+}L11pHcjN_O+v^5T zy+JR^l%mKxZXQ4LC1L^>554DJzUzet`ARrE5>O8+wMwH}-g{)X9DxPC@od zYK^03%Jo*Q*>LyD^{vX7A^nbT9B7>;HtGVG-ict(OtrS%C^^kWtK4igDtqiR?RvRn z>*G|V*4oXqOLnV5MHio(+oM_Rbb~M$YzP=D*|tEe+m>M`0QXK7FBZ5tnEub`bit;nBVyHNE|=FOar-9k1K=qJXh>S}<^h1{(Yp^l66Y zUU%rzVQD3M-byTdgYP816-Z5tdfXrQM+yZL1(F_Xq|%AT`gLAf_0}EQJ~3O#>oMn7`luhH%p# z883191+Hl@AJbq#gOB4HENO5(p}`FeZb}U@8hmbQu&hBgbrP4;=yvKPa5ZKAL$!<% zt~qXOgayZqkFeypi4kr%t{frbxaJ7Uj+-J^jtu!$ofpXeNsV5>8vVCv0LX{1#~6j>7XQ=*pV&NWE-yh8NbNKIFK$5Wffm)MrNfKe6kYa zH}uM7?$+W-*iDL&Iptn+T^t=`4Gar!;FC%&=S5%TVik$deHdEQ-P;T68V z{f92dBWO0tIc*_Hy4@IaoJ_cdo3TiRA=Ih0BH0uNB#ockYR Cj5Oi^ literal 0 HcmV?d00001 diff --git a/projects/bleckw/FinalProject/bin/DomainValidator$IDNBUGHOLDER.class b/projects/bleckw/FinalProject/bin/DomainValidator$IDNBUGHOLDER.class new file mode 100644 index 0000000000000000000000000000000000000000..9989e60c32cf229d4a5fbf5118390f690d1ea1f2 GIT binary patch literal 838 zcmaJfgc5Ph4kOt1sY0HAmP9*5mHG)v9J;pha7r|HtwppxOTA}eiau$ zf{Ft_fFFZE+!3=*pe2#8WbbkozJ?u$4G%VxX# z_{Hwip4IO3IWi2zL-9t`J>ehJd*egt#0;AR8V!0ocFQzJ&-)#_(;s&1(V)L$T4r~5 z)b0&z2DZnLZ#tgqyYVB2bfr3E$h3lesexfxhmLbZ|4Pc^Xb=jQfCue>=n1*EM3D13 zvdGbDxxVa9j>a+^h_NRb3@dPiHx!|({%65lGpVE@jTIdR@>DH;=|&9e*8fyC^0>^9 z5;YB1vBq(YK~FUMGOm+S9oMnWz~dkh%&=9lPCc>Xkos;^7eg9u;1tm_|7$Pr_aoxBx}BcrJNfI+i^N$AKYt}#U%o2>YmJ!n?$9O3r6XgQ8G#=xbhJj zZ<8{rutw+L-;w4&{xYSpjN8}(ih1hz4^uheAw};|IL%*dypnKNv7NB1*6-pzwBOih Br04(u literal 0 HcmV?d00001 diff --git a/projects/bleckw/FinalProject/bin/DomainValidator.class b/projects/bleckw/FinalProject/bin/DomainValidator.class new file mode 100644 index 0000000000000000000000000000000000000000..5582d6d9af769374411ad5cf1e3a9a5dc53bae64 GIT binary patch literal 42956 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 literal 0 HcmV?d00001 diff --git a/projects/bleckw/FinalProject/bin/RegexValidator.class b/projects/bleckw/FinalProject/bin/RegexValidator.class new file mode 100644 index 0000000000000000000000000000000000000000..08e57657393980ab0cd609c9b5ad03ecd746993c GIT binary patch literal 3091 zcmZ`*U2GKB89moKyR%-_#w;vg#|8rd>|GWUf?a|G0gM3$g9!`fuN21XVLh;(U1n#A z3HebJ`q(Imln0O!m8y-?3aM10HY$N6ZAIEhmHN_$gd|mw`qt-4l}ep+@64{3u6fv* zxijB<-#OL zGp>%1z#?_m%6Fwr$71{|#z@X&a8WIXO{Zw(?IQ!b1jLI14SjjL=o+@m)Fm_c2TJ23rgPW>9UIJNjNGt6A|&D8)Z8(PsG0^J zmxNe?3LGodBGK{GV}f}AC9F0HYni~34xeT<0fnm}V-(G_X%{Wmx=1O-2}xp(Xh|ZZ zFc9CuIRYXGV707Afdd_#!#X+yR?fC@AeS? zF$HTtM^E|vDlvAJtlX&Sgt3|AYO$P*pd0Jtp*M=>v6VTELcz301zI}>I%`_ur|S*l z1%c?PcB?o`q#HYAj-3LjIn46pT(bJEDEhIR26ppalQ|L{wXgI>kiy<52EZxMGx_m? zCC6m_9QDfJ=k$N@Y|hBC-C}@0ivyK*jm-J|MnSn%$0}yGifVA5Fe4`yxR1v)_A(oQ~qSj$`HS)rLfI0w*hFh?_Q~or4$U z`17pF3#_d!ULNK-4Sf`6qA;X|B3UP2D)i+`wkvUDq8NotscuW|WgV+L#i4Dk*<8wO z_-;mKqmxt)sq#5CmRRL3$lPn@f?4A<%F>P1%ra6sdsa&8m#o53Hlskjv_jtI^o4PO zdlHRaweMaIL!zL~Qz%7oQ5sG6cgip(_~6&k%;8a<+TXm7I-!PG-Pzw6mhj zE=kowtx0>HP;*a!x)Q6HL?&D2B@=N%4HD|5#5A5x-bXlj?;0BJVD0f(=QNU^CX)B= zBK2EzwO)lDn1mMG7U^cJYXR z@S>@00mV6pmpqB^4)vGaOeViTFmNNVbrMSxq|>@FIfX-07`}?2cH>H&Xq9)#>7Ric z4EIPaqd|b5u;|A1X_Q*>VZEP64im7WywgOBP5s zoWhU%2Ckq2vcxfoPTZ8}`e)G{NGW_9cskvq#ibp$1Oq*xNi1v*#zU!iNINryk@S_2 zh==0Z^_hP)2X9tUxh-y1sPw3@xlSrSBbA?%$}b4{BT|{9tv+U-e#t)l3R`*JgBy5} zF~j(^qPW+?SfO~VLh*o4aWOx|4&y9kTgCs`tm;#O{U75x$lkTU;=PcPB88BWVg^q` zR}E}o6Oa0hoIk@^_xjqxzDl{y;k+-`5DSD!sW>awnHstFmF3cYiux3-JaSVydm1@k zytcA%Tl8lAKISzCn{|5qXhp_{%|RN!TFDQpl-!L4gzyQKyh}!(QpwM#%;!|{_hkDA z8sm@X!hLMU7ubeBVK4qnmA=Fgu217HF!{~}{8cG?$fHwHwpdZtswg{DQFf=V>}D!D z&PfWQml}G??qz@TG@ha;Rg9F w2mJ4(@c_@^AJ~qERkPIZ%Mqp-B~3xWJE~@B9s-ZBND_)P@!=(ws>3Va13i3~^8f$< literal 0 HcmV?d00001 diff --git a/projects/bleckw/FinalProject/bin/ResultPair.class b/projects/bleckw/FinalProject/bin/ResultPair.class new file mode 100644 index 0000000000000000000000000000000000000000..f1e63614be0f9704302bfd790f32ff8d484def53 GIT binary patch literal 398 zcmZXQ&q~8U5XQer(#FQvXw<4u|Mb>YuorKN7r|3du@bPiO}f-AX##1|_wrB#4?cho zCC)}62QM@8&CbkkX1~5aJ^@_f$c901p5(GjibtVx8x~=EE>>cch;%l3h~_db2$m}3 zg5U@B)40f0I=dn?Rw7YT0!;|bYn7_vhS2H%FP#iRo^+c{r2`XNE?Q_4%>E#3fvGMU zXzIv!VPk{f1uB*I#vxpL@`B^NIP~=MMzob>XswKe<>N9vNXPlLJEbo-=^XjJy zeF1umG5HG&_Dto7G_&%=dpWE(S-o(DuJeZPaEIq>4!UdXym89FE?XZK+b-K4;6(P6~{DhyST25ImCD+7l=XKqNo literal 0 HcmV?d00001 diff --git a/projects/bleckw/FinalProject/bin/UrlValidator.class b/projects/bleckw/FinalProject/bin/UrlValidator.class new file mode 100644 index 0000000000000000000000000000000000000000..87aeaff20e0cadb7a110a510710166e9c3f62f60 GIT binary patch literal 7447 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 literal 0 HcmV?d00001 diff --git a/projects/bleckw/FinalProject/bin/UrlValidatorTest.class b/projects/bleckw/FinalProject/bin/UrlValidatorTest.class new file mode 100644 index 0000000000000000000000000000000000000000..7ef9585bafcec36821f6ab257d931148e55e8eb9 GIT binary patch literal 17023 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 vt(CnAq->18tV{}aH`|Qm2F literal 0 HcmV?d00001 From 80811b2b4c1cb73b03cd6fc90feada33cadb620d Mon Sep 17 00:00:00 2001 From: Scott Hung Date: Wed, 24 Jul 2019 19:10:45 -0700 Subject: [PATCH 12/17] Added new file for Scott --- FinalProject/hungs.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 FinalProject/hungs.txt diff --git a/FinalProject/hungs.txt b/FinalProject/hungs.txt new file mode 100644 index 00000000..edf8f7f5 --- /dev/null +++ b/FinalProject/hungs.txt @@ -0,0 +1,2 @@ +Scott Hung +Hungs \ No newline at end of file From 805bea7e7724628ecdc44f480c9695e4481fb9ea Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Thu, 25 Jul 2019 10:00:34 -0700 Subject: [PATCH 13/17] Create bleckw.txt --- FinalProject/bleckw.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 FinalProject/bleckw.txt diff --git a/FinalProject/bleckw.txt b/FinalProject/bleckw.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/FinalProject/bleckw.txt @@ -0,0 +1 @@ + From 6070e90873e9d1b6b4b6e405cf84d4f67850be44 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 7 Aug 2019 08:19:37 -0700 Subject: [PATCH 14/17] Create delgarka.txt --- FinalProject/delgarka.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 FinalProject/delgarka.txt diff --git a/FinalProject/delgarka.txt b/FinalProject/delgarka.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/FinalProject/delgarka.txt @@ -0,0 +1 @@ + From 3056d0b1e5cfe1940558cf1dabf9ae2eb46077c1 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 7 Aug 2019 08:20:22 -0700 Subject: [PATCH 15/17] Create bleckw.txt --- projects/bleckw/FinalProject/bleckw.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 projects/bleckw/FinalProject/bleckw.txt diff --git a/projects/bleckw/FinalProject/bleckw.txt b/projects/bleckw/FinalProject/bleckw.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/projects/bleckw/FinalProject/bleckw.txt @@ -0,0 +1 @@ + From 53bcc47b6ba21852453ec377949ccc565285cbcf Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 7 Aug 2019 08:20:34 -0700 Subject: [PATCH 16/17] Create delgarka.txt --- projects/bleckw/FinalProject/delgarka.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 projects/bleckw/FinalProject/delgarka.txt diff --git a/projects/bleckw/FinalProject/delgarka.txt b/projects/bleckw/FinalProject/delgarka.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/projects/bleckw/FinalProject/delgarka.txt @@ -0,0 +1 @@ + From ce336451f01a5fe2c51843e06ceda07684acad12 Mon Sep 17 00:00:00 2001 From: Jordan Bleck Date: Wed, 7 Aug 2019 08:20:50 -0700 Subject: [PATCH 17/17] Rename bleckw.txt to hungs.txt --- projects/bleckw/FinalProject/hungs.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 projects/bleckw/FinalProject/hungs.txt diff --git a/projects/bleckw/FinalProject/hungs.txt b/projects/bleckw/FinalProject/hungs.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/projects/bleckw/FinalProject/hungs.txt @@ -0,0 +1 @@ +