PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/home/newgyandham.com/www/wp-content/plugins/nextgen-gallery/
Upload File :
Current File : /home/newgyandham.com/www/wp-content/plugins/nextgen-gallery/nggallery.php
<?php
if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You are not allowed to call this page directly.'); }

/**
 * Plugin Name: NextGEN Gallery
 * Description: The most popular gallery plugin for WordPress and one of the most popular plugins of all time with over 23 million downloads.
 * Version: 3.1.4
 * Author: Imagely
 * Plugin URI: https://www.imagely.com/wordpress-gallery-plugin/nextgen-gallery/
 * Author URI: https://www.imagely.com
 * License: GPLv2
 * Text Domain: nggallery
 * Domain Path: /products/photocrati_nextgen/modules/i18n/lang
 */

if (!class_exists('E_Clean_Exit')) { class E_Clean_Exit extends RuntimeException {} }
if (!class_exists('E_NggErrorException')) { class E_NggErrorException extends RuntimeException {} }

// This is a temporary function to replace the use of WP's esc_url which strips spaces away from URLs
// TODO: Move this to a better place
if (!function_exists('nextgen_esc_url')) {
	function nextgen_esc_url( $url, $protocols = null, $_context = 'display' ) {
		$original_url = $url;

		if ( '' == $url )
			return $url;
		$url = preg_replace('|[^a-z0-9 \\-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
		$strip = array('%0d', '%0a', '%0D', '%0A');
		$url = _deep_replace($strip, $url);
		$url = str_replace(';//', '://', $url);
		/* If the URL doesn't appear to contain a scheme, we
		 * presume it needs http:// appended (unless a relative
		 * link starting with /, # or ? or a php file).
		 */

		if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) &&
		     ! preg_match('/^[a-z0-9-]+?\.php/i', $url) )
			$url = 'http://' . $url;

		// Replace ampersands and single quotes only when displaying.
		if ( 'display' == $_context ) {
			$url = wp_kses_normalize_entities( $url );
			$url = str_replace( '&amp;', '&#038;', $url );
			$url = str_replace( "'", '&#039;', $url );
			$url = str_replace( ' ', '%20', $url );
		}

		if ( '/' === $url[0] ) {
			$good_protocol_url = $url;
		} else {
			if ( ! is_array( $protocols ) )
				$protocols = wp_allowed_protocols();
			$good_protocol_url = wp_kses_bad_protocol( $url, $protocols );
			if ( strtolower( $good_protocol_url ) != strtolower( $url ) )
				return '';
		}

		return apply_filters('clean_url', $good_protocol_url, $original_url, $_context);
	}
}

/**
 * NextGEN Gallery is built on top of the Pope Framework:
 * https://bitbucket.org/photocrati/pope-framework
 *
 * Pope constructs applications by assembling modules.
 *
 * The Bootstrapper. This class performs the following:
 * 1) Loads the Pope Framework
 * 2) Adds a path to the C_Component_Registry instance to search for products
 * 3) Loads all found Products. A Product is a collection of modules with some
 * additional meta data. A Product is responsible for loading any modules it
 * requires.
 * 4) Once all Products (and their associated modules) have been loaded (or in
 * otherwords, "included"), the modules are initialized.
 */
class C_NextGEN_Bootstrap
{
	var $_registry = NULL;
	var $_settings_option_name = 'ngg_options';
	var $_pope_loaded = FALSE;
	static $debug = FALSE;
	var $minimum_ngg_pro_version = '2.0.5';
    var $minimum_ngg_plus_version = '1.0.1';

	static function shutdown($exception=NULL)
	{
		if (is_null($exception))
		{
            $name = php_sapi_name();
            if (FALSE === strpos($name, 'cgi')
            &&  version_compare(PHP_VERSION, '5.3.3') >= 0)
            {
                $status = session_status();
                if (in_array($status, array(PHP_SESSION_DISABLED, PHP_SESSION_NONE), TRUE))
                    session_write_close();
                fastcgi_finish_request();
            }
            else {
                throw new E_Clean_Exit;
            }
        }
		elseif (!($exception instanceof E_Clean_Exit)) {
			ob_end_clean();
			self::print_exception($exception);
		}
	}

	static function print_exception($exception)
	{
		$klass = get_class($exception);
		echo "<h1>{$klass} thrown</h1>";
		echo "<p>{$exception->getMessage()}</p>";
		if (self::$debug OR (defined('NGG_DEBUG') AND NGG_DEBUG == TRUE)) {
			echo "<h3>Where:</h3>";
			echo "<p>On line <strong>{$exception->getLine()}</strong> of <strong>{$exception->getFile()}</strong></p>";
			echo "<h3>Trace:</h3>";
			echo "<pre>{$exception->getTraceAsString()}</pre>";
			if (method_exists($exception, 'getPrevious')) {
				if (($previous = $exception->getPrevious())) {
					self::print_exception($previous);
				}
			}
		}
	}

	static function get_backtrace($objects=FALSE, $remove_dynamic_calls=TRUE)
	{
		$trace = debug_backtrace($objects);
		if ($remove_dynamic_calls) {
			$skip_methods = array(
				'_exec_cached_method',
				'__call',
				'get_method_property',
				'set_method_property',
				'call_method'
			);
			foreach ($trace as $key => &$value) {
				if (isset($value['class']) && isset($value['function'])) {
					if ($value['class'] == 'ReflectionMethod' && $value['function'] == 'invokeArgs')
						unset($trace[$key]);

					else if ($value['class'] == 'ExtensibleObject' && in_array($value['function'], $skip_methods))
						unset($trace[$key]);
				}
			}
		}

		return $trace;
	}

	public function php_version_incompatible()
	{ ?>
		<div class="notice notice-error is-dismissible">
			<p><?php print __('We’ve detected you are running PHP versions 7.0.26 or 7.1.12. These versions of PHP have a bug that breaks NextGEN Gallery and causes server crashes in certain conditions. To protect your site, NextGEN Gallery will not load. We recommend asking your host to roll back to an earlier version of PHP. For details on the PHP bug, see: <a target="_blank" href="https://bugs.php.net/bug.php?id=75573">bugs.php.net/bug.php?id=75573</a>', 'nggallery'); ?></p>
		</div>
		<?php
	}

	function __construct()
	{
		set_exception_handler(__CLASS__.'::shutdown');

		// We only load the plugin if we're outside of the activation request, loaded in an iframe
		// by WordPress. Reason being, if WP_DEBUG is enabled, and another Pope-based plugin (such as
		// the photocrati theme or NextGEN Pro/Plus), then PHP will output strict warnings
		if ($this->is_not_activating()) {
			$this->_define_constants();
			$this->_load_non_pope();
			$this->_register_hooks();
			$this->_load_pope();
		}
	}

	function is_not_activating()
	{
		return !$this->is_activating();
	}

	function is_activating()
	{
        $retval =  strpos($_SERVER['REQUEST_URI'], 'plugins.php') !== FALSE && isset($_REQUEST['action']) && in_array($_REQUEST['action'], array('activate-selected'));

		if (!$retval && strpos($_SERVER['REQUEST_URI'], 'update.php') !== FALSE && isset($_REQUEST['action']) && $_REQUEST['action'] == 'install-plugin' && isset($_REQUEST['plugin']) && strpos($_REQUEST['plugin'], 'nextgen-gallery') === 0) {
			$retval = TRUE;
		}

		if (!$retval && strpos($_SERVER['REQUEST_URI'], 'update.php') !== FALSE && isset($_REQUEST['action']) && $_REQUEST['action'] == 'activate-plugin' && isset($_REQUEST['plugin']) && strpos($_REQUEST['plugin'], 'nextgen-gallery') === 0) {
			$retval = TRUE;
		}

		return $retval;
	}

	function _load_non_pope()
	{
		// Load caching component
		include_once('non_pope/class.photocrati_transient_manager.php');

		if (isset($_REQUEST['ngg_flush']))
		{
			C_Photocrati_Transient_Manager::flush();
			die("Flushed all caches");
		}

        if (isset($_REQUEST['ngg_flush_expired']))
        {
            C_Photocrati_Transient_Manager::get_instance()->flush_expired();
            die("Flushed all expired caches");
        }

		// Load Settings Manager
		include_once('non_pope/class.photocrati_settings_manager.php');
		include_once('non_pope/class.nextgen_settings.php');
		C_Photocrati_Global_Settings_Manager::$option_name = $this->_settings_option_name;
		C_Photocrati_Settings_Manager::$option_name = $this->_settings_option_name;

		// Load the installer
		include_once('non_pope/class.photocrati_installer.php');

		// Load the resource manager
		include_once('non_pope/class.photocrati_resource_manager.php');
		C_Photocrati_Resource_Manager::init();

		// Load the style manager
		include_once('non_pope/class.nextgen_style_manager.php');

		// Load the shortcode manager
		include_once('non_pope/class.nextgen_shortcode_manager.php');
		C_NextGen_Shortcode_Manager::get_instance();
	}

	function fix_loading_order()
	{
        // If a plugin wasn't activated/deactivated siliently, we can listen for these things
	    if (did_action('activate_plugin') || did_action('deactivate_plugin')) return;
	    else if (strpos($_SERVER['REQUEST_URI'], 'plugins') !== FALSE) return;
	    else if (!$this->is_page_request()) return;

		$plugins = get_option('active_plugins');

		// Remove NGG from the list
        $ngg = basename(dirname(__FILE__)).'/'.basename(__FILE__);
        $order = array();
        foreach ($plugins as $plugin) {
            if ($plugin != $ngg) $order[] = $plugin;
        }


        // Get the position of either NGG Pro or NGG Plus
        $insert_at = FALSE;
        for($i=0; $i<count($order); $i++) {
            $plugin = $order[$i];
            if (strpos($plugin, 'nggallery-pro') !== FALSE) $insert_at = $i+1;
            else if (strpos($plugin, 'ngg-plus') !== FALSE) $insert_at = $i+1;
        }

        // Re-insert NGG after Pro or Plus
        if ($insert_at === FALSE || $insert_at === count($order)) $order[] = $ngg;
        elseif ($insert_at === 0) array_unshift($order, $ngg);
        else array_splice($order, $insert_at, 0, array($ngg));
		
		if ($order != $plugins) {
		    $order = array_filter($order);
			update_option('active_plugins', $order);
		}
	}

	/**
	 * Loads the Pope Framework
	 */
	function _load_pope()
	{
		// No need to initialize pope again
		if ($this->_pope_loaded) return;

		// Pope requires a a higher limit
		$tmp = ini_get('xdebug.max_nesting_level');
		if ($tmp && (int)$tmp <= 300) @ini_set('xdebug.max_nesting_level', 300);

		// Include pope framework
		require_once(implode(
			DIRECTORY_SEPARATOR, array(NGG_PLUGIN_DIR, 'pope','lib','autoload.php')
		));

		// Enable/disable pope caching. For now, the pope cache will not be used in multisite environments
		if (class_exists('C_Pope_Cache')) {
			if ((C_Pope_Cache::$enabled = NGG_POPE_CACHE)) {
				$blogid = (is_multisite() ? get_current_blog_id() : NULL);
				if (isset($_SERVER['SERVER_ADDR']))
					$cache_key_prefix = abs(crc32((implode('|', array($blogid, site_url(), AUTH_KEY, $_SERVER['SERVER_ADDR'])))));
				else
					$cache_key_prefix = abs(crc32(implode('|', array($blogid, site_url(), AUTH_KEY))));

				C_Pope_Cache::set_driver('C_Pope_Cache_SingleFile');
				C_Pope_Cache::add_key_prefix($cache_key_prefix);
			}
		}

		// Enforce interfaces
		if (property_exists('ExtensibleObject', 'enforce_interfaces')) ExtensibleObject::$enforce_interfaces = EXTENSIBLE_OBJECT_ENFORCE_INTERFACES;

		// Get the component registry
		$this->_registry = C_Component_Registry::get_instance();

		// Add the default Pope factory utility, C_Component_Factory
		$this->_registry->add_utility('I_Component_Factory', 'C_Component_Factory');

		// Blacklist any modules which are known NOT to work with this version of NextGEN Gallery
		// We need to check if we have this ability as it's only available with Pope 0.9
		if (method_exists($this->_registry, 'blacklist_module_file')) {
			$this->_registry->blacklist_module_file('module.nextgen_pro_lightbox_legacy.php');
			$this->_registry->blacklist_module_file('module.protect_image.php');
			// TODO: Add module id for protect image
		}

		// If Pro is incompatible, then we need to blacklist all of Pro's modules
		// TODO: Pope needs a better way of introspecting into a product's list of provided modules
		if ($this->is_pro_incompatible()) {
			$pro_modules = array(
				'photocrati-comments',
				'photocrati-galleria',
				'photocrati-nextgen_pro_slideshow',
				'photocrati-nextgen_pro_horizontal_filmstrip',
				'photocrati-nextgen_pro_thumbnail_grid',
				'photocrati-nextgen_pro_blog_gallery',
				'photocrati-nextgen_pro_film',
				'photocrati-nextgen_pro_masonry',
				'photocrati-nextgen_pro_albums',
				'photocrati-nextgen_pro_lightbox',
				'photocrati-nextgen_pro_lightbox_legacy',
				'photocrati-nextgen_pro_ecommerce',
				'photocrati-paypal_express_checkout',
				'photocrati-paypal_standard',
				'photocrati-stripe'
			);
			foreach ($pro_modules as $mod) $this->_registry->blacklist_module_file($mod);
		}

		// Load embedded products. Each product is expected to load any
		// modules required
		$this->_registry->add_module_path(NGG_PRODUCT_DIR, 2, false);
		$this->_registry->load_all_products();

		// Give third-party plugins that opportunity to include their own products
		// and modules
		do_action('load_nextgen_gallery_modules', $this->_registry);

		// Initializes all loaded modules
		$this->_registry->initialize_all_modules();

		$this->_pope_loaded = TRUE;
	}

	function is_pro_compatible()
	{
		$retval = TRUE;

        if (defined('NEXTGEN_GALLERY_PRO_VERSION')) $retval = FALSE;
        if (defined('NEXTGEN_GALLERY_PRO_PLUGIN_BASENAME') && !defined('NGG_PRO_PLUGIN_VERSION')) $retval = FALSE; // 1.0 - 1.0.6
		if (defined('NGG_PRO_PLUGIN_VERSION')  && version_compare(NGG_PRO_PLUGIN_VERSION,  $this->minimum_ngg_pro_version)  < 0) $retval = FALSE;
        if (defined('NGG_PLUS_PLUGIN_VERSION') && version_compare(NGG_PLUS_PLUGIN_VERSION, $this->minimum_ngg_plus_version) < 0) $retval = FALSE;

		return $retval;
	}

	function is_pro_incompatible()
	{
		return !$this->is_pro_compatible();
	}

	function render_incompatibility_warning()
	{
		echo '<div class="updated error"><p>';
		echo esc_html(
			sprintf(
				__("NextGEN Gallery %s is incompatible with this version of NextGEN Pro. Please update NextGEN Pro to version %s or higher to restore NextGEN Pro functionality.",
					'nggallery'
				),
				NGG_PLUGIN_VERSION, $this->minimum_ngg_pro_version
			));
		echo '</p></div>';
	}


	/**
	 * Registers hooks for the WordPress framework necessary for instantiating
	 * the plugin
	 */
	function _register_hooks()
	{
		// Register the deactivation routines
		add_action('deactivate_'.NGG_PLUGIN_BASENAME, array(get_class(), 'deactivate'));

		// Register our test suite
		add_filter('simpletest_suites', array(&$this, 'add_testsuite'));

		// Ensure that settings manager is saved as an array
		add_filter('pre_update_option_' . $this->_settings_option_name, array($this, 'persist_settings'));
		add_filter('pre_update_site_option_' . $this->_settings_option_name, array($this, 'persist_settings'));

		// This plugin uses jQuery extensively
		if (NGG_FIX_JQUERY) {
			add_action('wp_enqueue_scripts', array(&$this, 'fix_jquery'));
			add_action('wp_print_scripts', array(&$this, 'fix_jquery'));
		}

		// If the selected stylesheet is using an unsafe path, then notify the user
		add_action('all_admin_notices', array(&$this, 'display_stylesheet_notice'));

		// Delete displayed gallery transients periodically
		if (NGG_CRON_ENABLED) {
			add_filter('cron_schedules', array(&$this, 'add_ngg_schedule'));
			add_action('ngg_delete_expired_transients', array($this, 'delete_expired_transients'));
			add_action('wp', array(&$this, 'schedule_cron_jobs'));
		}

		// Update modules
		add_action('init', array(&$this, 'update'), PHP_INT_MAX-2);

		// Start the plugin!
		add_action('init', array(&$this, 'route'), 11);

		// Flush pope cache
		add_action('init', array(&$this, 'flush_pope_cache'));

		// NGG extension plugins should be loaded in a specific order
        add_action('shutdown', array(&$this, 'fix_loading_order'));

		// Display a warning if an compatible version of NextGEN Pro is installed alongside this
		// version of NextGEN Gallery
		if ($this->is_pro_incompatible()) {
			add_filter('http_request_args', array(&$this, 'fix_autoupdate_api_requests'), 10, 2);
			add_action('all_admin_notices', array(&$this, 'render_incompatibility_warning'));
		}

		add_filter('ngg_load_frontend_logic', array($this, 'disable_frontend_logic'), -10, 2);
	}

	function disable_frontend_logic($enabled, $module_id)
	{
		if (is_admin())
		{
			$settings = C_NextGen_Settings::get_instance();
			if (!$settings->get('always_enable_frontend_logic'))
				$enabled = FALSE;
		}
		return $enabled;
	}

	function fix_autoupdate_api_requests($args, $url)
	{
		// Is this an HTTP request to the licensing server?
		if (preg_match("/api_act=/", $url)) {
			$args['autoupdate'] = TRUE;

			// If we're supposed to pass all Pro modules, then include them here
			if (preg_match("/api_act=(ckups|cklic)/", $url) && isset($args['body']) && is_array($args['body']) && isset($args['body']['module-list'])) {
				$pro_modules = array(
					'photocrati-comments',
					'photocrati-galleria',
					'photocrati-nextgen_pro_slideshow',
					'photocrati-nextgen_pro_horizontal_filmstrip',
					'photocrati-nextgen_pro_thumbnail_grid',
					'photocrati-nextgen_pro_blog_gallery',
					'photocrati-nextgen_pro_film',
					'photocrati-nextgen_pro_masonry',
					'photocrati-nextgen_pro_albums',
					'photocrati-auto_update',
					'photocrati-auto_update-admin',
					'photocrati-nextgen_pro_lightbox',
					'photocrati-nextgen_pro_lightbox_legacy',
					'photocrati-nextgen_pro_ecommerce',
					'photocrati-paypal_express_checkout',
					'photocrati-paypal_standard',
					'photocrati-stripe'
				);
				foreach ($pro_modules as $mod) {
					if (!isset($args['body']['module-list'][$mod])) $args['body']['module-list'][$mod] = '0.1';
				}
			}
		}
		return $args;
	}

	function flush_pope_cache()
	{
		if (is_user_logged_in() && current_user_can('manage_options') && isset($_REQUEST['ngg_flush_pope_cache'])) {
			C_Pope_Cache::get_instance()->flush();
			print "Flushed pope cache";
			exit;
		}
	}

	function schedule_cron_jobs()
	{
		if (!wp_next_scheduled('ngg_delete_expired_transients')) {
			wp_schedule_event(time(), 'ngg_custom', 'ngg_delete_expired_transients');
		}
	}

	/**
	 * Defines a new cron schedule
	 * @param $schedules
	 * @return mixed
	 */
	function add_ngg_schedule($schedules)
	{
		$schedules['ngg_custom'] = array(
			'interval'	=>	NGG_CRON_SCHEDULE,
			'display'	=>	sprintf(__('Every %d seconds', 'nggallery'), NGG_CRON_SCHEDULE)
		);

		return $schedules;
	}


	/**
	 * Flush all expires transients created by the plugin
	 */
	function delete_expired_transients()
	{
        C_Photocrati_Transient_Manager::get_instance()->flush_expired();
	}

	/**
	 * Ensure that C_Photocrati_Settings_Manager gets persisted as an array
	 * @param C_Photocrati_Settings_Manager_Base|array $settings
	 * @return array
	 */
	function persist_settings($settings = array())
	{
		if (is_object($settings) && $settings instanceof C_Photocrati_Settings_Manager_Base) {
			$settings = $settings->to_array();
		}
		return $settings;
	}

	/**
	 * Ensures that the version of JQuery used is expected for NextGEN Gallery
	 */
	function fix_jquery()
	{
		global $wp_scripts;

		// Determine which version of jQuery to include
		$src = '/wp-includes/js/jquery/jquery.js';

		// Ensure that jQuery is always set to the default
		if (isset($wp_scripts->registered['jquery'])) {
			$jquery = $wp_scripts->registered['jquery'];

			// There's an exception to the rule. We'll allow the same
			// version of jQuery as included with WP to be fetched from
			// Google AJAX libraries, as we have a systematic means of verifying
			// that won't cause any troubles
			$version = preg_quote($jquery->ver, '#');
			if (!preg_match("#ajax\\.googleapis\\.com/ajax/libs/jquery/{$version}/jquery\\.min\\.js#", $jquery->src)) {
				$jquery->src = FALSE;
				if (array_search('jquery-core', $jquery->deps) === FALSE) {
					$jquery->deps[] = 'jquery-core';
				}
				if (array_search('jquery-migrate', $jquery->deps) === FALSE) {
					$jquery->deps[] = 'jquery-migrate';
				}
			}
		}

		// Ensure that jquery-core is used, as WP intended
		if (isset($wp_scripts->registered['jquery-core'])) {
			$wp_scripts->registered['jquery-core']->src = $src;
		}

		wp_enqueue_script('jquery');
	}

	/**
	 * Displays a notice to the user that the current stylesheet location is unsafe
	 */
	function display_stylesheet_notice()
	{
		if (C_NextGen_Style_Manager::get_instance()->is_directory_unsafe()) {
			$styles		= C_NextGen_Style_Manager::get_instance();
			$filename	= $styles->get_selected_stylesheet();
			$abspath	= $styles->find_selected_stylesheet_abspath();
			$newpath	= $styles->new_dir;

			echo "<div class='updated error'>
                <h3>WARNING: NextGEN Gallery Stylesheet NOT Upgrade-safe</h3>
                <p>
                <strong>{$filename}</strong> is currently stored in <strong>{$abspath}</strong>, which isn't upgrade-safe. Please move the stylesheet to
                <strong>{$newpath}</strong> to ensure that your customizations persist after updates.
            </p></div>";
		}
	}

	/**
	 * Updates all modules
	 */
	function update()
	{
		if ((!(defined('DOING_AJAX') && DOING_AJAX)) && !isset($_REQUEST['doing_wp_cron'])) {

			$this->_load_pope();

			// Try updating all modules
			C_Photocrati_Installer::update();
		}
	}

	/**
	 * Routes access points using the Pope Router
	 * @return boolean
	 */
	function route()
	{
		$this->_load_pope();
		$router = C_Router::get_instance();

		// Set context to path if subdirectory install
		$parts     = parse_url($router->get_base_url(FALSE));
		$siteparts = parse_url(get_option('siteurl'));

        if (isset($parts['path']) && isset($siteparts['path']))
        {
            if (strpos($parts['path'], '/index.php') === FALSE)
            {
                $router->context = $siteparts['path'];
            }
            else {
                $new_parts = explode('/index.php', $parts['path']);
                if (!empty($new_parts[0]) && $new_parts[0] == $siteparts['path']) {
                    $router->context = array_shift($new_parts);
                }
            }
        }

        // Provide a means for modules/third-parties to configure routes
		do_action_ref_array('ngg_routes', array(&$router));

		// Serve the routes
		if (!$router->serve_request() && $router->has_parameter_segments()) {
			return $router->passthru();
		}
	}

    function is_page_request()
    {
        return !(defined('DOING_AJAX') && DOING_AJAX) && !(defined('DOING_CRON') && DOING_CRON) && !(defined('NGG_AJAX_SLUG') && strpos($_SERVER['REQUEST_URI'], NGG_AJAX_SLUG) !== FALSE);
    }

	/**
	 * Run the uninstaller
	 */
	static function deactivate()
	{
        include_once('products/photocrati_nextgen/class.nextgen_product_installer.php');
        C_Photocrati_Installer::add_handler(NGG_PLUGIN_BASENAME, 'C_NextGen_Product_Installer');
		C_Photocrati_Installer::uninstall(NGG_PLUGIN_BASENAME);
	}

	/**
	 * Defines necessary plugins for the plugin to load correctly
	 */
	function _define_constants()
	{
		define('NGG_PLUGIN', basename($this->directory_path()));
		define('NGG_PLUGIN_BASENAME', plugin_basename(__FILE__));
		define('NGG_PLUGIN_DIR', $this->directory_path());
		define('NGG_PLUGIN_URL', $this->path_uri());
		define('NGG_TESTS_DIR',   implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PLUGIN_DIR, "/\\"), 'tests')));
		define('NGG_PRODUCT_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PLUGIN_DIR, "/\\"), 'products')));
		define('NGG_MODULE_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PRODUCT_DIR, "/\\"), 'photocrati_nextgen', 'modules')));
		define('NGG_PRODUCT_URL', path_join(str_replace("\\" , '/', NGG_PLUGIN_URL), 'products'));
		define('NGG_MODULE_URL', path_join(str_replace("\\", '/', NGG_PRODUCT_URL), 'photocrati_nextgen/modules'));
		define('NGG_PLUGIN_STARTED_AT', microtime());
		define('NGG_PLUGIN_VERSION', '3.1.4');

		if (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG)
			define('NGG_SCRIPT_VERSION', (string)mt_rand(0, mt_getrandmax()));
		else
			define('NGG_SCRIPT_VERSION', NGG_PLUGIN_VERSION);

		if (!defined('NGG_HIDE_STRICT_ERRORS')) {
			define('NGG_HIDE_STRICT_ERRORS', TRUE);
		}

		// Should we display E_STRICT errors?
		if (NGG_HIDE_STRICT_ERRORS) {
			$level = error_reporting();
			if ($level != 0) error_reporting($level & ~E_STRICT);
		}

		// Should we display NGG debugging information?
		if (!defined('NGG_DEBUG')) {
			define('NGG_DEBUG', FALSE);
		}
		self::$debug = NGG_DEBUG;

		// User definable constants
		if (!defined('NGG_IMPORT_ROOT')) {
			$path = WP_CONTENT_DIR;
			if (defined('NEXTGEN_GALLERY_IMPORT_ROOT')) {
				$path = NEXTGEN_GALLERY_IMPORT_ROOT;
			}
			define('NGG_IMPORT_ROOT', $path);
		}

		// Should the Photocrati cache be enabled
		if (!defined('PHOTOCRATI_CACHE')) {
			define('PHOTOCRATI_CACHE', TRUE);
		}
		if (!defined('PHOTOCRATI_CACHE_TTL')) {
			define('PHOTOCRATI_CACHE_TTL', 1800);
		}

		// Cron job
		if (!defined('NGG_CRON_SCHEDULE')) {
			define('NGG_CRON_SCHEDULE', 900);
		}

		if (!defined('NGG_CRON_ENABLED')) {
			define('NGG_CRON_ENABLED', TRUE);
		}

		// Don't enforce interfaces
		if (!defined('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES')) {
			define('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES', FALSE);
		}

		// Fix jquery
		if (!defined('NGG_FIX_JQUERY')) {
			define('NGG_FIX_JQUERY', TRUE);
		}

		// Use Pope's new caching mechanism?
		if (!defined('NGG_POPE_CACHE')) {
			define('NGG_POPE_CACHE', FALSE);
		}
	}

	/**
	 * Defines the NextGEN Test Suite
	 * @param array $suites
	 * @return array
	 */
	function add_testsuite($suites=array())
	{
		$tests_dir = NGG_TESTS_DIR;

		if (file_exists($tests_dir)) {

			// Include mock objects
			// TODO: These mock objects should be moved to the appropriate
			// test folder
			require_once(path_join($tests_dir, 'mocks.php'));

			// Define the NextGEN Test Suite
			$suites['nextgen'] = array(
//                path_join($tests_dir, 'mvc'),
				path_join($tests_dir, 'datamapper'),
				path_join($tests_dir, 'nextgen_data'),
				path_join($tests_dir, 'gallery_display')
			);
		}

		return $suites;
	}


	/**
	 * Returns the path to a file within the plugin root folder
     *
	 * @param string $file_name
	 * @return string
	 */
	function file_path($file_name=NULL)
	{
		$path = dirname(__FILE__);
		if ($file_name != null)
			$path .= '/' . $file_name;

		return str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
	}

	/**
	 * Gets the directory path used by the plugin
     *
     * @param string|null $dir (optional)
	 * @return string
	 */
	function directory_path($dir=NULL)
	{
		return $this->file_path($dir);
	}

	/**
	 * Determines the location of the plugin - within a theme or plugin
	 * @return string
	 */
	function get_plugin_location()
	{
		$path = dirname(__FILE__);
		$gallery_dir = strtolower($path);
		$gallery_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $gallery_dir);

		$theme_dir = strtolower(get_stylesheet_directory());
		$theme_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $theme_dir);

		$plugin_dir = strtolower(WP_PLUGIN_DIR);
		$plugin_dir = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $plugin_dir);

		$common_dir_theme = substr($gallery_dir, 0, strlen($theme_dir));
		$common_dir_plugin = substr($gallery_dir, 0, strlen($plugin_dir));

		if ($common_dir_theme == $theme_dir)
		{
			return 'theme';
		}

		if ($common_dir_plugin == $plugin_dir)
		{
			return 'plugin';
		}

		$parent_dir = dirname($path);

		if (file_exists($parent_dir . DIRECTORY_SEPARATOR . 'style.css'))
		{
			return 'theme';
		}

		return 'plugin';
	}


	/**
	 * Gets the URI for a particular path
	 * @param string $path
	 * @param boolean $url_encode
	 * @return string
	 */
	function path_uri($path = null, $url_encode = false)
	{
		$location = $this->get_plugin_location();
		$uri = null;

		$path = str_replace(array('/', '\\'), '/', $path);

		if ($url_encode)
		{
			$path_list = explode('/', $path);

			foreach ($path_list as $index => $path_item)
			{
				$path_list[$index] = urlencode($path_item);
			}

			$path = implode('/', $path_list);
		}

		if ($location == 'theme')
		{
			$theme_uri = get_stylesheet_directory_uri();

			$uri = $theme_uri . 'nextgen-gallery';

			if ($path != null)
			{
				$uri .= '/' . $path;
			}
		}
		else
		{
			// XXX Note, paths could not match but STILL being contained in the theme (i.e. WordPress returns the wrong path for the theme directory, either with wrong formatting or wrong encoding)
			$base = basename(dirname(__FILE__));

			if ($base != 'nextgen-gallery')
			{
				// XXX this is needed when using symlinks, if the user renames the plugin folder everything will break though
				$base = 'nextgen-gallery';
			}

			if ($path != null)
			{
				$base .= '/' . $path;
			}

			$uri = plugins_url($base);
		}

		return $uri;
	}

	/**
	 * Returns the URI for a particular file
	 * @param string $file_name
	 * @return string
	 */
	function file_uri($file_name = NULL)
	{
		return $this->path($file_name);
	}
}

#region Freemius

/**
 * Customize the opt-in message.
 *
 * @author Vova Feldman (@svovaf)
 * @since 2.1.32
 *
 * @param string $message
 * @param string $user_first_name
 * @param string $plugin_title
 * @param string $user_login
 * @param string $site_link
 * @param string $freemius_link
 *
 * @return string
 */
function ngg_fs_custom_connect_message(
	$message,
	$user_first_name,
	$plugin_title,
	$user_login,
	$site_link,
	$freemius_link
) {
	return sprintf(
		__( 'Hey %s, ', 'nggallery' ) . '<br>' .
		__( 'Allow %6$s to collect some usage data with %5$s to make the plugin even more awesome. If you skip this, that\'s okay! %2$s will still work just fine.', 'nggallery' ),
		$user_first_name,
		'<b>' . __('NextGEN Gallery', 'nggallery') . '</b>',
		'<b>' . $user_login . '</b>',
		$site_link,
		$freemius_link,
		'<b>' . __('Imagely', 'nggallery') . '</b>'
	);
}

/**
 * Uninstall cleanup script.
 */
function ngg_fs_uninstall() {
	// Your cleanup script.
}

/**
 * Send custom event about 1st gallery creation.
 *
 * @author Vova Feldman (@svovaf)
 */
function fs_track_new_gallery() {
	global $ngg_fs;

	$galleries = C_Gallery_Mapper::get_instance()->count();
	if (1 == $galleries) {
		// Only track event on 1st gallery creation.
		$ngg_fs->track_event_once( 'new_gallery' );
	}
}

/**
 * Create a helper function for easy SDK access.
 *
 * @author Vova Feldman (@svovaf)
 * @since  2.1.32
 *
 * @param bool $activate_for_all If true, activate Freemius for all users. Was added for testing.
 *
 * @return bool|\Freemius
 */
function ngg_fs( $activate_for_all = false ) {
	global $ngg_fs;

	if ( ! $activate_for_all ) {
		$ngg_options      = get_option( 'ngg_options' );
		$ngg_run_freemius = get_option( 'ngg_run_freemius', null );

		if ( false === $ngg_options ) {
			// New plugin installation.

			if ( defined( 'WP_FS__DEV_MODE' ) && WP_FS__DEV_MODE ) {
				// Always run Freemius in development mode for new plugin installs.
				$run_freemius = true;
			} else {
				// Run Freemius code on 20% of the new installations.
			// $random = rand( 1, 10 );
			// $run_freemius = ( 1 <= $random && $random <= 2 );
            // Update 2016-08: run on all new instances
            $run_freemius = TRUE;
			}

			update_option( 'ngg_run_freemius', $run_freemius );

			// Compare both bool or string 0/1 because get_option() may give us either
		} else if ( ( is_bool( $ngg_run_freemius ) && $ngg_run_freemius ) || '1' === $ngg_run_freemius ) {
			// If runFreemius was set, use the value.
			$run_freemius = $ngg_run_freemius;
		} else {
			// Don't run Freemius for plugin updates.
			$run_freemius = false;
		if (is_null($ngg_run_freemius))
			update_option('ngg_run_freemius', FALSE);
		}

		if ( ! $run_freemius ) {
			return false;
		}
	}

	if ( ! isset( $ngg_fs ) ) {
		// Include Freemius SDK.
		require_once dirname( __FILE__ ) . '/freemius/start.php';

		$ngg_fs = fs_dynamic_init( array(
			'id'             => '266',
			'slug'           => 'nextgen-gallery',
			'public_key'     => 'pk_009356711cd548837f074e1ef60a4',
			'is_premium'     => false,
			'has_addons'     => false,
			'has_paid_plans' => false,
			'menu'           => array(
				'slug'    => 'nextgen-gallery',
				'account' => false,
				'contact' => false,
				'support' => false,
			),
			'permissions'    => array(
				'newsletter' => true,
			),
		) );
	}

	/*
	// Optional button override.
	if ( function_exists( 'fs_override_i18n' ) ) {
		fs_override_i18n( array(
			'opt-in-connect' => __('OK - I\'m in!', 'nggallery'),
		), 'nextgen-gallery' );
	}
	*/

	// Hook to the custom message filter.
	$ngg_fs->add_action( 'after_uninstall', 'ngg_fs_uninstall' );

	// Hook to new gallery creation event.
	add_action( 'ngg_created_new_gallery', 'fs_track_new_gallery' );

	return $ngg_fs;
}

// Init Freemius.
ngg_fs();

#endregion Freemius

new C_NextGEN_Bootstrap();