diff options
Diffstat (limited to 'src/application')
| -rw-r--r-- | src/application/assets/mimetypes | 771 | ||||
| -rw-r--r-- | src/application/assets/user-fallback.jpg | bin | 0 -> 812 bytes | |||
| -rw-r--r-- | src/application/fetch-mime-types.php | 22 | ||||
| -rw-r--r-- | src/application/mystic/forum/orm/User.php | 3 | ||||
| -rw-r--r-- | src/application/mystic/forum/utils/FileUtils.php | 33 | ||||
| -rw-r--r-- | src/application/mystic/forum/utils/RequestUtils.php | 7 | ||||
| -rw-r--r-- | src/application/mystic/forum/utils/StringUtils.php | 4 | ||||
| -rw-r--r-- | src/application/views/form_addpost.php | 2 | ||||
| -rw-r--r-- | src/application/views/form_delete_post_confirm.php | 17 | ||||
| -rw-r--r-- | src/application/views/form_login.php | 2 | ||||
| -rw-r--r-- | src/application/views/template_end.php | 8 | ||||
| -rw-r--r-- | src/application/views/template_start.php | 4 | ||||
| -rw-r--r-- | src/application/views/view_post.php | 53 | ||||
| -rw-r--r-- | src/application/views/view_topic_start.php | 28 | ||||
| -rw-r--r-- | src/application/views/view_user.php | 154 | 
15 files changed, 1069 insertions, 39 deletions
| diff --git a/src/application/assets/mimetypes b/src/application/assets/mimetypes new file mode 100644 index 0000000..5440824 --- /dev/null +++ b/src/application/assets/mimetypes @@ -0,0 +1,771 @@ +application/andrew-inset			ez +application/applixware				aw +application/atom+xml				atom +application/atomcat+xml				atomcat +application/atomsvc+xml				atomsvc +application/ccxml+xml				ccxml +application/cdmi-capability			cdmia +application/cdmi-container			cdmic +application/cdmi-domain				cdmid +application/cdmi-object				cdmio +application/cdmi-queue				cdmiq +application/cu-seeme				cu +application/davmount+xml			davmount +application/docbook+xml				dbk +application/dssc+der				dssc +application/dssc+xml				xdssc +application/ecmascript				ecma +application/emma+xml				emma +application/epub+zip				epub +application/exi					exi +application/font-tdpfr				pfr +application/gml+xml				gml +application/gpx+xml				gpx +application/gxf					gxf +application/hyperstudio				stk +application/inkml+xml				ink inkml +application/ipfix				ipfix +application/java-archive			jar +application/java-serialized-object		ser +application/java-vm				class +application/json				json +application/jsonml+json				jsonml +application/lost+xml				lostxml +application/mac-binhex40			hqx +application/mac-compactpro			cpt +application/mads+xml				mads +application/marc				mrc +application/marcxml+xml				mrcx +application/mathematica				ma nb mb +application/mathml+xml				mathml +application/mbox				mbox +application/mediaservercontrol+xml		mscml +application/metalink+xml			metalink +application/metalink4+xml			meta4 +application/mets+xml				mets +application/mods+xml				mods +application/mp21				m21 mp21 +application/mp4					mp4s +application/msword				doc dot +application/mxf					mxf +application/octet-stream	bin dms lrf mar so dist distz pkg bpk dump elc deploy +application/oda					oda +application/oebps-package+xml			opf +application/ogg					ogx +application/omdoc+xml				omdoc +application/onenote				onetoc onetoc2 onetmp onepkg +application/oxps				oxps +application/patch-ops-error+xml			xer +application/pdf					pdf +application/pgp-encrypted			pgp +application/pgp-signature			asc sig +application/pics-rules				prf +application/pkcs10				p10 +application/pkcs7-mime				p7m p7c +application/pkcs7-signature			p7s +application/pkcs8				p8 +application/pkix-attr-cert			ac +application/pkix-cert				cer +application/pkix-crl				crl +application/pkix-pkipath			pkipath +application/pkixcmp				pki +application/pls+xml				pls +application/postscript				ai eps ps +application/prs.cww				cww +application/pskc+xml				pskcxml +application/rdf+xml				rdf +application/reginfo+xml				rif +application/relax-ng-compact-syntax		rnc +application/resource-lists+xml			rl +application/resource-lists-diff+xml		rld +application/rls-services+xml			rs +application/rpki-ghostbusters			gbr +application/rpki-manifest			mft +application/rpki-roa				roa +application/rsd+xml				rsd +application/rss+xml				rss +application/rtf					rtf +application/sbml+xml				sbml +application/scvp-cv-request			scq +application/scvp-cv-response			scs +application/scvp-vp-request			spq +application/scvp-vp-response			spp +application/sdp					sdp +application/set-payment-initiation		setpay +application/set-registration-initiation		setreg +application/shf+xml				shf +application/smil+xml				smi smil +application/sparql-query			rq +application/sparql-results+xml			srx +application/srgs				gram +application/srgs+xml				grxml +application/sru+xml				sru +application/ssdl+xml				ssdl +application/ssml+xml				ssml +application/tei+xml				tei teicorpus +application/thraud+xml				tfi +application/timestamped-data			tsd +application/vnd.3gpp.pic-bw-large		plb +application/vnd.3gpp.pic-bw-small		psb +application/vnd.3gpp.pic-bw-var			pvb +application/vnd.3gpp2.tcap			tcap +application/vnd.3m.post-it-notes		pwn +application/vnd.accpac.simply.aso		aso +application/vnd.accpac.simply.imp		imp +application/vnd.acucobol			acu +application/vnd.acucorp				atc acutc +application/vnd.adobe.air-application-installer-package+zip	air +application/vnd.adobe.formscentral.fcdt		fcdt +application/vnd.adobe.fxp			fxp fxpl +application/vnd.adobe.xdp+xml			xdp +application/vnd.adobe.xfdf			xfdf +application/vnd.ahead.space			ahead +application/vnd.airzip.filesecure.azf		azf +application/vnd.airzip.filesecure.azs		azs +application/vnd.amazon.ebook			azw +application/vnd.americandynamics.acc		acc +application/vnd.amiga.ami			ami +application/vnd.android.package-archive		apk +application/vnd.anser-web-certificate-issue-initiation	cii +application/vnd.anser-web-funds-transfer-initiation	fti +application/vnd.antix.game-component		atx +application/vnd.apple.installer+xml		mpkg +application/vnd.apple.mpegurl			m3u8 +application/vnd.aristanetworks.swi		swi +application/vnd.astraea-software.iota		iota +application/vnd.audiograph			aep +application/vnd.blueice.multipass		mpm +application/vnd.bmi				bmi +application/vnd.businessobjects			rep +application/vnd.chemdraw+xml			cdxml +application/vnd.chipnuts.karaoke-mmd		mmd +application/vnd.cinderella			cdy +application/vnd.claymore			cla +application/vnd.cloanto.rp9			rp9 +application/vnd.clonk.c4group			c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config		c11amc +application/vnd.cluetrust.cartomobile-config-pkg	c11amz +application/vnd.commonspace			csp +application/vnd.contact.cmsg			cdbcmsg +application/vnd.cosmocaller			cmc +application/vnd.crick.clicker			clkx +application/vnd.crick.clicker.keyboard		clkk +application/vnd.crick.clicker.palette		clkp +application/vnd.crick.clicker.template		clkt +application/vnd.crick.clicker.wordbank		clkw +application/vnd.criticaltools.wbs+xml		wbs +application/vnd.ctc-posml			pml +application/vnd.cups-ppd			ppd +application/vnd.curl.car			car +application/vnd.curl.pcurl			pcurl +application/vnd.dart				dart +application/vnd.data-vision.rdz			rdz +application/vnd.dece.data			uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml			uvt uvvt +application/vnd.dece.unspecified		uvx uvvx +application/vnd.dece.zip			uvz uvvz +application/vnd.denovo.fcselayout-link		fe_launch +application/vnd.dna				dna +application/vnd.dolby.mlp			mlp +application/vnd.dpgraph				dpg +application/vnd.dreamfactory			dfac +application/vnd.ds-keypoint			kpxx +application/vnd.dvb.ait				ait +application/vnd.dvb.service			svc +application/vnd.dynageo				geo +application/vnd.ecowin.chart			mag +application/vnd.enliven				nml +application/vnd.epson.esf			esf +application/vnd.epson.msf			msf +application/vnd.epson.quickanime		qam +application/vnd.epson.salt			slt +application/vnd.epson.ssf			ssf +application/vnd.eszigno3+xml			es3 et3 +application/vnd.ezpix-album			ez2 +application/vnd.ezpix-package			ez3 +application/vnd.fdf				fdf +application/vnd.fdsn.mseed			mseed +application/vnd.fdsn.seed			seed dataless +application/vnd.flographit			gph +application/vnd.fluxtime.clip			ftc +application/vnd.framemaker			fm frame maker book +application/vnd.frogans.fnc			fnc +application/vnd.frogans.ltf			ltf +application/vnd.fsc.weblaunch			fsc +application/vnd.fujitsu.oasys			oas +application/vnd.fujitsu.oasys2			oa2 +application/vnd.fujitsu.oasys3			oa3 +application/vnd.fujitsu.oasysgp			fg5 +application/vnd.fujitsu.oasysprs		bh2 +application/vnd.fujixerox.ddd			ddd +application/vnd.fujixerox.docuworks		xdw +application/vnd.fujixerox.docuworks.binder	xbd +application/vnd.fuzzysheet			fzs +application/vnd.genomatix.tuxedo		txd +application/vnd.geogebra.file			ggb +application/vnd.geogebra.slides		ggs +application/vnd.geogebra.tool			ggt +application/vnd.geometry-explorer		gex gre +application/vnd.geonext				gxt +application/vnd.geoplan				g2w +application/vnd.geospace			g3w +application/vnd.gmx				gmx +application/vnd.google-earth.kml+xml		kml +application/vnd.google-earth.kmz		kmz +application/vnd.grafeq				gqf gqs +application/vnd.groove-account			gac +application/vnd.groove-help			ghf +application/vnd.groove-identity-message		gim +application/vnd.groove-injector			grv +application/vnd.groove-tool-message		gtm +application/vnd.groove-tool-template		tpl +application/vnd.groove-vcard			vcg +application/vnd.hal+xml				hal +application/vnd.handheld-entertainment+xml	zmm +application/vnd.hbci				hbci +application/vnd.hhe.lesson-player		les +application/vnd.hp-hpgl				hpgl +application/vnd.hp-hpid				hpid +application/vnd.hp-hps				hps +application/vnd.hp-jlyt				jlt +application/vnd.hp-pcl				pcl +application/vnd.hp-pclxl			pclxl +application/vnd.hydrostatix.sof-data		sfd-hdstx +application/vnd.ibm.minipay			mpy +application/vnd.ibm.modcap			afp listafp list3820 +application/vnd.ibm.rights-management		irm +application/vnd.ibm.secure-container		sc +application/vnd.iccprofile			icc icm +application/vnd.igloader			igl +application/vnd.immervision-ivp			ivp +application/vnd.immervision-ivu			ivu +application/vnd.insors.igm			igm +application/vnd.intercon.formnet		xpw xpx +application/vnd.intergeo			i2g +application/vnd.intu.qbo			qbo +application/vnd.intu.qfx			qfx +application/vnd.ipunplugged.rcprofile		rcprofile +application/vnd.irepository.package+xml		irp +application/vnd.is-xpr				xpr +application/vnd.isac.fcs			fcs +application/vnd.jam				jam +application/vnd.jcp.javame.midlet-rms		rms +application/vnd.jisp				jisp +application/vnd.joost.joda-archive		joda +application/vnd.kahootz				ktz ktr +application/vnd.kde.karbon			karbon +application/vnd.kde.kchart			chrt +application/vnd.kde.kformula			kfo +application/vnd.kde.kivio			flw +application/vnd.kde.kontour			kon +application/vnd.kde.kpresenter			kpr kpt +application/vnd.kde.kspread			ksp +application/vnd.kde.kword			kwd kwt +application/vnd.kenameaapp			htke +application/vnd.kidspiration			kia +application/vnd.kinar				kne knp +application/vnd.koan				skp skd skt skm +application/vnd.kodak-descriptor		sse +application/vnd.las.las+xml			lasxml +application/vnd.llamagraphics.life-balance.desktop	lbd +application/vnd.llamagraphics.life-balance.exchange+xml	lbe +application/vnd.lotus-1-2-3			123 +application/vnd.lotus-approach			apr +application/vnd.lotus-freelance			pre +application/vnd.lotus-notes			nsf +application/vnd.lotus-organizer			org +application/vnd.lotus-screencam			scm +application/vnd.lotus-wordpro			lwp +application/vnd.macports.portpkg		portpkg +application/vnd.mcd				mcd +application/vnd.medcalcdata			mc1 +application/vnd.mediastation.cdkey		cdkey +application/vnd.mfer				mwf +application/vnd.mfmp				mfm +application/vnd.micrografx.flo			flo +application/vnd.micrografx.igx			igx +application/vnd.mif				mif +application/vnd.mobius.daf			daf +application/vnd.mobius.dis			dis +application/vnd.mobius.mbk			mbk +application/vnd.mobius.mqy			mqy +application/vnd.mobius.msl			msl +application/vnd.mobius.plc			plc +application/vnd.mobius.txf			txf +application/vnd.mophun.application		mpn +application/vnd.mophun.certificate		mpc +application/vnd.mozilla.xul+xml			xul +application/vnd.ms-artgalry			cil +application/vnd.ms-cab-compressed		cab +application/vnd.ms-excel			xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12		xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12	xlsb +application/vnd.ms-excel.sheet.macroenabled.12		xlsm +application/vnd.ms-excel.template.macroenabled.12	xltm +application/vnd.ms-fontobject			eot +application/vnd.ms-htmlhelp			chm +application/vnd.ms-ims				ims +application/vnd.ms-lrm				lrm +application/vnd.ms-officetheme			thmx +application/vnd.ms-pki.seccat			cat +application/vnd.ms-pki.stl			stl +application/vnd.ms-powerpoint			ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12		ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12	pptm +application/vnd.ms-powerpoint.slide.macroenabled.12		sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12		ppsm +application/vnd.ms-powerpoint.template.macroenabled.12		potm +application/vnd.ms-project			mpp mpt +application/vnd.ms-word.document.macroenabled.12	docm +application/vnd.ms-word.template.macroenabled.12	dotm +application/vnd.ms-works			wps wks wcm wdb +application/vnd.ms-wpl				wpl +application/vnd.ms-xpsdocument			xps +application/vnd.mseq				mseq +application/vnd.musician			mus +application/vnd.muvee.style			msty +application/vnd.mynfc				taglet +application/vnd.neurolanguage.nlu		nlu +application/vnd.nitf				ntf nitf +application/vnd.noblenet-directory		nnd +application/vnd.noblenet-sealer			nns +application/vnd.noblenet-web			nnw +application/vnd.nokia.n-gage.data		ngdat +application/vnd.nokia.n-gage.symbian.install	n-gage +application/vnd.nokia.radio-preset		rpst +application/vnd.nokia.radio-presets		rpss +application/vnd.novadigm.edm			edm +application/vnd.novadigm.edx			edx +application/vnd.novadigm.ext			ext +application/vnd.oasis.opendocument.chart		odc +application/vnd.oasis.opendocument.chart-template	otc +application/vnd.oasis.opendocument.database		odb +application/vnd.oasis.opendocument.formula		odf +application/vnd.oasis.opendocument.formula-template	odft +application/vnd.oasis.opendocument.graphics		odg +application/vnd.oasis.opendocument.graphics-template	otg +application/vnd.oasis.opendocument.image		odi +application/vnd.oasis.opendocument.image-template	oti +application/vnd.oasis.opendocument.presentation		odp +application/vnd.oasis.opendocument.presentation-template	otp +application/vnd.oasis.opendocument.spreadsheet		ods +application/vnd.oasis.opendocument.spreadsheet-template	ots +application/vnd.oasis.opendocument.text			odt +application/vnd.oasis.opendocument.text-master		odm +application/vnd.oasis.opendocument.text-template	ott +application/vnd.oasis.opendocument.text-web		oth +application/vnd.olpc-sugar			xo +application/vnd.oma.dd2+xml			dd2 +application/vnd.openofficeorg.extension		oxt +application/vnd.openxmlformats-officedocument.presentationml.presentation	pptx +application/vnd.openxmlformats-officedocument.presentationml.slide	sldx +application/vnd.openxmlformats-officedocument.presentationml.slideshow	ppsx +application/vnd.openxmlformats-officedocument.presentationml.template	potx +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet	xlsx +application/vnd.openxmlformats-officedocument.spreadsheetml.template	xltx +application/vnd.openxmlformats-officedocument.wordprocessingml.document	docx +application/vnd.openxmlformats-officedocument.wordprocessingml.template	dotx +application/vnd.osgeo.mapguide.package		mgp +application/vnd.osgi.dp				dp +application/vnd.osgi.subsystem			esa +application/vnd.palm				pdb pqa oprc +application/vnd.pawaafile			paw +application/vnd.pg.format			str +application/vnd.pg.osasli			ei6 +application/vnd.picsel				efif +application/vnd.pmi.widget			wg +application/vnd.pocketlearn			plf +application/vnd.powerbuilder6			pbd +application/vnd.previewsystems.box		box +application/vnd.proteus.magazine		mgz +application/vnd.publishare-delta-tree		qps +application/vnd.pvi.ptid1			ptid +application/vnd.quark.quarkxpress		qxd qxt qwd qwt qxl qxb +application/vnd.realvnc.bed			bed +application/vnd.recordare.musicxml		mxl +application/vnd.recordare.musicxml+xml		musicxml +application/vnd.rig.cryptonote			cryptonote +application/vnd.rim.cod				cod +application/vnd.rn-realmedia			rm +application/vnd.rn-realmedia-vbr		rmvb +application/vnd.route66.link66+xml		link66 +application/vnd.sailingtracker.track		st +application/vnd.seemail				see +application/vnd.sema				sema +application/vnd.semd				semd +application/vnd.semf				semf +application/vnd.shana.informed.formdata		ifm +application/vnd.shana.informed.formtemplate	itp +application/vnd.shana.informed.interchange	iif +application/vnd.shana.informed.package		ipk +application/vnd.simtech-mindmapper		twd twds +application/vnd.smaf				mmf +application/vnd.smart.teacher			teacher +application/vnd.solent.sdkm+xml			sdkm sdkd +application/vnd.spotfire.dxp			dxp +application/vnd.spotfire.sfs			sfs +application/vnd.stardivision.calc		sdc +application/vnd.stardivision.draw		sda +application/vnd.stardivision.impress		sdd +application/vnd.stardivision.math		smf +application/vnd.stardivision.writer		sdw vor +application/vnd.stardivision.writer-global	sgl +application/vnd.stepmania.package		smzip +application/vnd.stepmania.stepchart		sm +application/vnd.sun.xml.calc			sxc +application/vnd.sun.xml.calc.template		stc +application/vnd.sun.xml.draw			sxd +application/vnd.sun.xml.draw.template		std +application/vnd.sun.xml.impress			sxi +application/vnd.sun.xml.impress.template	sti +application/vnd.sun.xml.math			sxm +application/vnd.sun.xml.writer			sxw +application/vnd.sun.xml.writer.global		sxg +application/vnd.sun.xml.writer.template		stw +application/vnd.sus-calendar			sus susp +application/vnd.svd				svd +application/vnd.symbian.install			sis sisx +application/vnd.syncml+xml			xsm +application/vnd.syncml.dm+wbxml			bdm +application/vnd.syncml.dm+xml			xdm +application/vnd.tao.intent-module-archive	tao +application/vnd.tcpdump.pcap			pcap cap dmp +application/vnd.tmobile-livetv			tmo +application/vnd.trid.tpt			tpt +application/vnd.triscape.mxs			mxs +application/vnd.trueapp				tra +application/vnd.ufdl				ufd ufdl +application/vnd.uiq.theme			utz +application/vnd.umajin				umj +application/vnd.unity				unityweb +application/vnd.uoml+xml			uoml +application/vnd.vcx				vcx +application/vnd.visio				vsd vst vss vsw +application/vnd.visionary			vis +application/vnd.vsf				vsf +application/vnd.wap.wbxml			wbxml +application/vnd.wap.wmlc			wmlc +application/vnd.wap.wmlscriptc			wmlsc +application/vnd.webturbo			wtb +application/vnd.wolfram.player			nbp +application/vnd.wordperfect			wpd +application/vnd.wqd				wqd +application/vnd.wt.stf				stf +application/vnd.xara				xar +application/vnd.xfdl				xfdl +application/vnd.yamaha.hv-dic			hvd +application/vnd.yamaha.hv-script		hvs +application/vnd.yamaha.hv-voice			hvp +application/vnd.yamaha.openscoreformat			osf +application/vnd.yamaha.openscoreformat.osfpvg+xml	osfpvg +application/vnd.yamaha.smaf-audio		saf +application/vnd.yamaha.smaf-phrase		spf +application/vnd.yellowriver-custom-menu		cmp +application/vnd.zul				zir zirz +application/vnd.zzazz.deck+xml			zaz +application/voicexml+xml			vxml +application/wasm				wasm +application/widget				wgt +application/winhlp				hlp +application/wsdl+xml				wsdl +application/wspolicy+xml			wspolicy +application/x-7z-compressed			7z +application/x-abiword				abw +application/x-ace-compressed			ace +application/x-apple-diskimage			dmg +application/x-authorware-bin			aab x32 u32 vox +application/x-authorware-map			aam +application/x-authorware-seg			aas +application/x-bcpio				bcpio +application/x-bittorrent			torrent +application/x-blorb				blb blorb +application/x-bzip				bz +application/x-bzip2				bz2 boz +application/x-cbr				cbr cba cbt cbz cb7 +application/x-cdlink				vcd +application/x-cfs-compressed			cfs +application/x-chat				chat +application/x-chess-pgn				pgn +application/x-conference			nsc +application/x-cpio				cpio +application/x-csh				csh +application/x-debian-package			deb udeb +application/x-dgc-compressed			dgc +application/x-director			dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom				wad +application/x-dtbncx+xml			ncx +application/x-dtbook+xml			dtb +application/x-dtbresource+xml			res +application/x-dvi				dvi +application/x-envoy				evy +application/x-eva				eva +application/x-font-bdf				bdf +application/x-font-ghostscript			gsf +application/x-font-linux-psf			psf +application/x-font-pcf				pcf +application/x-font-snf				snf +application/x-font-type1			pfa pfb pfm afm +application/x-freearc				arc +application/x-futuresplash			spl +application/x-gca-compressed			gca +application/x-glulx				ulx +application/x-gnumeric				gnumeric +application/x-gramps-xml			gramps +application/x-gtar				gtar +application/x-hdf				hdf +application/x-install-instructions		install +application/x-iso9660-image			iso +application/x-java-jnlp-file			jnlp +application/x-latex				latex +application/x-lzh-compressed			lzh lha +application/x-mie				mie +application/x-mobipocket-ebook			prc mobi +application/x-ms-application			application +application/x-ms-shortcut			lnk +application/x-ms-wmd				wmd +application/x-ms-wmz				wmz +application/x-ms-xbap				xbap +application/x-msaccess				mdb +application/x-msbinder				obd +application/x-mscardfile			crd +application/x-msclip				clp +application/x-msdownload			exe dll com bat msi +application/x-msmediaview			mvb m13 m14 +application/x-msmetafile			wmf wmz emf emz +application/x-msmoney				mny +application/x-mspublisher			pub +application/x-msschedule			scd +application/x-msterminal			trm +application/x-mswrite				wri +application/x-netcdf				nc cdf +application/x-nzb				nzb +application/x-pkcs12				p12 pfx +application/x-pkcs7-certificates		p7b spc +application/x-pkcs7-certreqresp			p7r +application/x-rar-compressed			rar +application/x-research-info-systems		ris +application/x-sh				sh +application/x-shar				shar +application/x-shockwave-flash			swf +application/x-silverlight-app			xap +application/x-sql				sql +application/x-stuffit				sit +application/x-stuffitx				sitx +application/x-subrip				srt +application/x-sv4cpio				sv4cpio +application/x-sv4crc				sv4crc +application/x-t3vm-image			t3 +application/x-tads				gam +application/x-tar				tar +application/x-tcl				tcl +application/x-tex				tex +application/x-tex-tfm				tfm +application/x-texinfo				texinfo texi +application/x-tgif				obj +application/x-ustar				ustar +application/x-wais-source			src +application/x-x509-ca-cert			der crt +application/x-xfig				fig +application/x-xliff+xml				xlf +application/x-xpinstall				xpi +application/x-xz				xz +application/x-zmachine				z1 z2 z3 z4 z5 z6 z7 z8 +application/xaml+xml				xaml +application/xcap-diff+xml			xdf +application/xenc+xml				xenc +application/xhtml+xml				xhtml xht +application/xml					xml xsl +application/xml-dtd				dtd +application/xop+xml				xop +application/xproc+xml				xpl +application/xslt+xml				xslt +application/xspf+xml				xspf +application/xv+xml				mxml xhvml xvml xvm +application/yang				yang +application/yin+xml				yin +application/zip					zip +audio/adpcm					adp +audio/basic					au snd +audio/midi					mid midi kar rmi +audio/mp4					m4a mp4a +audio/mpeg					mpga mp2 mp2a mp3 m2a m3a +audio/ogg					oga ogg spx opus +audio/s3m					s3m +audio/silk					sil +audio/vnd.dece.audio				uva uvva +audio/vnd.digital-winds				eol +audio/vnd.dra					dra +audio/vnd.dts					dts +audio/vnd.dts.hd				dtshd +audio/vnd.lucent.voice				lvp +audio/vnd.ms-playready.media.pya		pya +audio/vnd.nuera.ecelp4800			ecelp4800 +audio/vnd.nuera.ecelp7470			ecelp7470 +audio/vnd.nuera.ecelp9600			ecelp9600 +audio/vnd.rip					rip +audio/webm					weba +audio/x-aac					aac +audio/x-aiff					aif aiff aifc +audio/x-caf					caf +audio/x-flac					flac +audio/x-matroska				mka +audio/x-mpegurl					m3u +audio/x-ms-wax					wax +audio/x-ms-wma					wma +audio/x-pn-realaudio				ram ra +audio/x-pn-realaudio-plugin			rmp +audio/x-wav					wav +audio/xm					xm +chemical/x-cdx					cdx +chemical/x-cif					cif +chemical/x-cmdf					cmdf +chemical/x-cml					cml +chemical/x-csml					csml +chemical/x-xyz					xyz +font/collection					ttc +font/otf					otf +font/ttf					ttf +font/woff					woff +font/woff2					woff2 +image/avif					avif +image/bmp					bmp +image/cgm					cgm +image/g3fax					g3 +image/gif					gif +image/ief					ief +image/jpeg					jpeg jpg jpe +image/jxl					jxl +image/ktx					ktx +image/png					png +image/prs.btif					btif +image/sgi					sgi +image/svg+xml					svg svgz +image/tiff					tiff tif +image/vnd.adobe.photoshop			psd +image/vnd.dece.graphic				uvi uvvi uvg uvvg +image/vnd.djvu					djvu djv +image/vnd.dvb.subtitle				sub +image/vnd.dwg					dwg +image/vnd.dxf					dxf +image/vnd.fastbidsheet				fbs +image/vnd.fpx					fpx +image/vnd.fst					fst +image/vnd.fujixerox.edmics-mmr			mmr +image/vnd.fujixerox.edmics-rlc			rlc +image/vnd.ms-modi				mdi +image/vnd.ms-photo				wdp +image/vnd.net-fpx				npx +image/vnd.wap.wbmp				wbmp +image/vnd.xiff					xif +image/webp					webp +image/x-3ds					3ds +image/x-cmu-raster				ras +image/x-cmx					cmx +image/x-freehand				fh fhc fh4 fh5 fh7 +image/x-icon					ico +image/x-mrsid-image				sid +image/x-pcx					pcx +image/x-pict					pic pct +image/x-portable-anymap				pnm +image/x-portable-bitmap				pbm +image/x-portable-graymap			pgm +image/x-portable-pixmap				ppm +image/x-rgb					rgb +image/x-tga					tga +image/x-xbitmap					xbm +image/x-xpixmap					xpm +image/x-xwindowdump				xwd +message/rfc822					eml mime +model/iges					igs iges +model/mesh					msh mesh silo +model/vnd.collada+xml				dae +model/vnd.dwf					dwf +model/vnd.gdl					gdl +model/vnd.gtw					gtw +model/vnd.vtu					vtu +model/vrml					wrl vrml +model/x3d+binary				x3db x3dbz +model/x3d+vrml					x3dv x3dvz +model/x3d+xml					x3d x3dz +text/cache-manifest				appcache +text/calendar					ics ifb +text/css					css +text/csv					csv +text/html					html htm +text/javascript					js mjs +text/n3						n3 +text/plain					txt text conf def list log in +text/prs.lines.tag				dsc +text/richtext					rtx +text/sgml					sgml sgm +text/tab-separated-values			tsv +text/troff					t tr roff man me ms +text/turtle					ttl +text/uri-list					uri uris urls +text/vcard					vcard +text/vnd.curl					curl +text/vnd.curl.dcurl				dcurl +text/vnd.curl.mcurl				mcurl +text/vnd.curl.scurl				scurl +text/vnd.dvb.subtitle				sub +text/vnd.fly					fly +text/vnd.fmi.flexstor				flx +text/vnd.graphviz				gv +text/vnd.in3d.3dml				3dml +text/vnd.in3d.spot				spot +text/vnd.sun.j2me.app-descriptor		jad +text/vnd.wap.wml				wml +text/vnd.wap.wmlscript				wmls +text/x-asm					s asm +text/x-c					c cc cxx cpp h hh dic +text/x-fortran					f for f77 f90 +text/x-java-source				java +text/x-nfo					nfo +text/x-opml					opml +text/x-pascal					p pas +text/x-setext					etx +text/x-sfv					sfv +text/x-uuencode					uu +text/x-vcalendar				vcs +text/x-vcard					vcf +video/3gpp					3gp +video/3gpp2					3g2 +video/h261					h261 +video/h263					h263 +video/h264					h264 +video/jpeg					jpgv +video/jpm					jpm jpgm +video/mj2					mj2 mjp2 +video/mp2t					ts m2t m2ts mts +video/mp4					mp4 mp4v mpg4 +video/mpeg					mpeg mpg mpe m1v m2v +video/ogg					ogv +video/quicktime					qt mov +video/vnd.dece.hd				uvh uvvh +video/vnd.dece.mobile				uvm uvvm +video/vnd.dece.pd				uvp uvvp +video/vnd.dece.sd				uvs uvvs +video/vnd.dece.video				uvv uvvv +video/vnd.dvb.file				dvb +video/vnd.fvt					fvt +video/vnd.mpegurl				mxu m4u +video/vnd.ms-playready.media.pyv		pyv +video/vnd.uvvu.mp4				uvu uvvu +video/vnd.vivo					viv +video/webm					webm +video/x-f4v					f4v +video/x-fli					fli +video/x-flv					flv +video/x-m4v					m4v +video/x-matroska				mkv mk3d mks +video/x-mng					mng +video/x-ms-asf					asf asx +video/x-ms-vob					vob +video/x-ms-wm					wm +video/x-ms-wmv					wmv +video/x-ms-wmx					wmx +video/x-ms-wvx					wvx +video/x-msvideo					avi +video/x-sgi-movie				movie +video/x-smv					smv +x-conference/x-cooltalk				ice diff --git a/src/application/assets/user-fallback.jpg b/src/application/assets/user-fallback.jpgBinary files differ new file mode 100644 index 0000000..e657866 --- /dev/null +++ b/src/application/assets/user-fallback.jpg diff --git a/src/application/fetch-mime-types.php b/src/application/fetch-mime-types.php new file mode 100644 index 0000000..2e49726 --- /dev/null +++ b/src/application/fetch-mime-types.php @@ -0,0 +1,22 @@ +<?php + +if (PHP_SAPI !== "cli") { +    http_response_code(400); +    echo "This script must be run from the command line"; +    exit; +} + +$input = "https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types"; +$output = __DIR__ . "/assets/mimetypes"; + +$hInput = fopen($input, "r") or die("Failed to open input file"); +$hOutput = fopen($output, "w") or die("Failed to open output file"); + +while (($ln = fgets($hInput)) !== false) { +    if (strpos($ln, "#") === 0) +        continue; +    fputs($hOutput, $ln); +} + +fclose($hInput); +fclose($hOutput); diff --git a/src/application/mystic/forum/orm/User.php b/src/application/mystic/forum/orm/User.php index 1db1d04..97acbaf 100644 --- a/src/application/mystic/forum/orm/User.php +++ b/src/application/mystic/forum/orm/User.php @@ -3,6 +3,7 @@ declare(strict_types=1);  namespace mystic\forum\orm; +use mystic\forum\attributes\Column;  use mystic\forum\attributes\PrimaryKey;  use mystic\forum\attributes\Table;  use mystic\forum\attributes\Unique; @@ -22,6 +23,8 @@ class User extends Entity {      public bool $passwordResetRequired;      public string $activationToken;      public bool $activated; +    #[Column(columnType: "bytea")] public ?string $profilePicture; +    public ?\DateTimeImmutable $nameLastChanged;      public function hasPermission(int $perm): bool {          if ($this->id === self::SUPERUSER_ID) diff --git a/src/application/mystic/forum/utils/FileUtils.php b/src/application/mystic/forum/utils/FileUtils.php new file mode 100644 index 0000000..1910f0c --- /dev/null +++ b/src/application/mystic/forum/utils/FileUtils.php @@ -0,0 +1,33 @@ +<?php +declare(strict_types=1); + +namespace mystic\forum\utils; + +final class FileUtils { +    use StaticClass; + +    private const MIME_FILE = __DIR__ . "/../../../assets/mimetypes"; +    public const DEFAULT_MIME_TYPE = "application/octet-stream"; + +    private static ?array $extToMime = null; + +    private static function ensureMimeMapping(): void { +        if (self::$extToMime !== null) +            return; + +        self::$extToMime = []; +         +        $hFile = fopen(self::MIME_FILE, "r"); +        while (($ln = fgets($hFile)) !== false) { +            [$mime, $extensions] = preg_split('/\t+/', $ln, 2); +            $extensions = explode(" ", strtolower($extensions)); +            foreach ($extensions as $ext) +                self::$extToMime[$ext] = $mime; +        } +    } + +    public static function getMimeTypeForExtension(string $extension, string $defaultMimeType = self::DEFAULT_MIME_TYPE): string { +        self::ensureMimeMapping(); +        return self::$extToMime[strtolower($extension)] ?? $defaultMimeType; +    } +} diff --git a/src/application/mystic/forum/utils/RequestUtils.php b/src/application/mystic/forum/utils/RequestUtils.php index f6ce3a3..6599052 100644 --- a/src/application/mystic/forum/utils/RequestUtils.php +++ b/src/application/mystic/forum/utils/RequestUtils.php @@ -30,9 +30,10 @@ final class RequestUtils {      public static function getRequiredField(string $field): string {          $fieldValue = $_POST[$field] ?? null;          if ($fieldValue === null) { -            http_response_code(400); -            Messaging::error("Missing required field $field"); -            exit; +            //http_response_code(400); +            //Messaging::error("Missing required field $field"); +            RequestUtils::triggerFormError("Missing required field '$field'"); +            //exit;          }          return $fieldValue;      } diff --git a/src/application/mystic/forum/utils/StringUtils.php b/src/application/mystic/forum/utils/StringUtils.php index 7d4bf9d..fd38915 100644 --- a/src/application/mystic/forum/utils/StringUtils.php +++ b/src/application/mystic/forum/utils/StringUtils.php @@ -21,4 +21,8 @@ final class StringUtils {          return ltrim($result, '_');      } + +    public static function truncate(string $str, int $maxLength, string $ellipsis = "…"): string { +        return mb_strimwidth($str, 0, $maxLength, $ellipsis); +    }  } diff --git a/src/application/views/form_addpost.php b/src/application/views/form_addpost.php index b3cd6ca..88eda27 100644 --- a/src/application/views/form_addpost.php +++ b/src/application/views/form_addpost.php @@ -20,7 +20,7 @@ if (($_formError = RequestUtils::getAndClearFormError()) !== null) {      <textarea class="form-control" id="i_message" name="message" required rows="12" cols="60" style="resize:vertical;max-height:499px"></textarea>  </div>  <div class="form-group"> -    <label for="i_files">Attachments:</label> +    <label for="i_files">Attachments: <small>(max. 4 files, max. 2 MiB each)</small></label>      <input type="file" name="files[]" id="i_files" multiple accept="*/*">  </div>  <button type="submit" class="btn btn-success">Post reply</button> diff --git a/src/application/views/form_delete_post_confirm.php b/src/application/views/form_delete_post_confirm.php index 9d04095..2dc417d 100644 --- a/src/application/views/form_delete_post_confirm.php +++ b/src/application/views/form_delete_post_confirm.php @@ -1,16 +1,21 @@  <div class="panel panel-danger">      <div class="panel-heading"> -        <h3 class="panel-title">Do you want to delete your post?</h3> +        <?php if ($postAuthor->id === $GLOBALS["currentUser"]->id): ?> +            <h3 class="panel-title">Do you want to delete your post?</h3> +        <?php else: ?> +            <h3 class="panel-title">Do you want to delete <?= htmlentities($postAuthor->displayName) ?>'s post?</h3> +        <?php endif; ?>      </div>      <div class="panel-body"> -        Are you sure you want to delete the following post: -        <div class="well"> -            <?= renderPost($post->content); ?> -        </div> +        Are you sure you want to delete the following post:<br> +        <?php _view("view_post", [ +                ...$___PARAMS, +                "hide_actions" => true +            ]) ?>      </div>      <div class="panel-footer">          <div class="text-right"> -            <form action="." method="get" class="seamless-inline"> +            <form action=".#post-<?= htmlentities(urlencode($post->id)) ?>" method="get" class="seamless-inline">                  <input type="hidden" name="_action" value="viewtopic">                  <input type="hidden" name="topic" value="<?= htmlentities($post->topicId) ?>">                  <button class="btn btn-default">Keep my post</button> diff --git a/src/application/views/form_login.php b/src/application/views/form_login.php index 0e98a24..8ddb22e 100644 --- a/src/application/views/form_login.php +++ b/src/application/views/form_login.php @@ -20,7 +20,7 @@ if (($_formError = RequestUtils::getAndClearFormError()) !== null) {  <form action="<?= htmlentities($_SERVER["REQUEST_URI"]) ?>" method="post">  <div class="form-group">      <label for="i_username">Username:</label> -    <input class="form-control" type="text" id="i_username" name="username" value="<?= htmlentities($lastForm["username"] ?? "") ?>" required> +    <input class="form-control" type="text" id="i_username" name="username" value="<?= htmlentities($lastForm["username"] ?? "") ?>" required autofocus>  </div>  <div class="form-group"> diff --git a/src/application/views/template_end.php b/src/application/views/template_end.php index f7f70a9..27fc3ba 100644 --- a/src/application/views/template_end.php +++ b/src/application/views/template_end.php @@ -15,6 +15,14 @@ $(function() {          var date = new Date($(e).text());          $(e).text(date.toLocaleString());      }); +    $("._date").each(function(i, e) { +        var date = new Date($(e).text()); +        $(e).text(date.toLocaleDateString()); +    }); +    $("._time-only").each(function(i, e) { +        var date = new Date($(e).text()); +        $(e).text(date.toLocaleTimeString()); +    });  });  </script> diff --git a/src/application/views/template_start.php b/src/application/views/template_start.php index e011f74..4cfdb74 100644 --- a/src/application/views/template_start.php +++ b/src/application/views/template_start.php @@ -8,9 +8,7 @@      <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">      <meta name="viewport" content="width=device-width,initial-scale=1">      <title><?= htmlentities($_title ?? "") ?></title> -    <link rel="stylesheet" href="/ui/dist/css/bootstrap.min.css"> -    <link rel="stylesheet" href="/ui/dist/css/bootstrap-theme.min.css"> -    <link rel="stylesheet" href="/ui/site.css"> +    <link rel="stylesheet" href="/ui/theme-default.css">      <script src="/ui/jquery-1.12.4.min.js"></script>      <script src="/ui/dist/js/bootstrap.min.js"></script>      <script src="/ui/modernizr-2.6.2.min.js"></script> diff --git a/src/application/views/view_post.php b/src/application/views/view_post.php index 0776fb5..5022d4a 100644 --- a/src/application/views/view_post.php +++ b/src/application/views/view_post.php @@ -11,36 +11,49 @@ $canReply = $GLOBALS["currentUser"]?->hasPermission(UserPermissions::CREATE_OWN_  $canDelete = ($GLOBALS["currentUser"]?->id === $postAuthor?->id && $postAuthor?->hasPermission(UserPermissions::DELETE_OWN_POST))            || ($GLOBALS["currentUser"]?->hasPermission(UserPermissions::DELETE_OTHER_POST)); +$hide_actions ??= false; +$hide_pfp ??= false; +$your_are_the_author = $GLOBALS["currentUser"]?->id === $postAuthor?->id; +  ?>  <?php if ($post->deleted): ?> -<div class="media"> +<div class="media" id="post-<?= htmlentities($post->id) ?>">  <div class="media-left hidden-sm hidden-xs">      <div class="media-object" style="width:64px"></div>  </div>  <div class="media-body"> -    <div class="well"> +    <div class="well icon-well text-warning"> +        <span class="glyphicon glyphicon-exclamation-sign color-warning" aria-hidden="true"></span>          <em>This post has been deleted</em>      </div>  </div>  </div>  <?php else: ?> -<div class="media"> +<div class="media" id="post-<?= htmlentities($post->id) ?>"> +<?php if (!$hide_pfp): ?>      <div class="media-left hidden-sm hidden-xs">          <?php if ($postAuthor): ?> -            <a href="?_action=viewuser&user=<?= htmlentities(urlencode($postAuthor->id)) ?>"> -                <img class="media-object" src="/ui/placeholder.svg" alt="" width="64" height="64"> -            </a> +            <?php if ($hide_actions): ?> +                <img class="media-object" alt="Profile picture" src="?_action=profilepicture&user=<?= htmlentities(urlencode($postAuthor->id)) ?>" alt="" width="64" height="64"> +            <?php else: ?> +                <a href="?_action=viewuser&user=<?= htmlentities(urlencode($postAuthor->id)) ?>"> +                    <img class="media-object" alt="Profile picture" src="?_action=profilepicture&user=<?= htmlentities(urlencode($postAuthor->id)) ?>" alt="" width="64" height="64"> +                </a> +            <?php endif; ?>          <?php else: ?>              <div class="media-object" style="width:64px;height:64px"></div>          <?php endif; ?>      </div> +<?php endif; ?>      <div class="media-body">          <div class="panel panel-default">              <div class="panel-heading">                  <h3 class="panel-title"> +                    <?php if (!$hide_actions): ?>                      <div class="pull-right">                          <?php if ($canReply): ?> +                        <a href="#post-<?= htmlentities(urlencode($post->id)) ?>" class="btn btn-default"><span class="glyphicon glyphicon-link" aria-hidden="true"></span><span class="sr-only">Permalink</span></a>                          <button data-text="<?= htmlentities($post->content) ?>" class="btn btn-default js-only _reply-post"><span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span><span class="sr-only">Reply to post</span></button>                          <?php endif; ?>                          <?php if ($canDelete): ?> @@ -50,8 +63,16 @@ $canDelete = ($GLOBALS["currentUser"]?->id === $postAuthor?->id && $postAuthor?-                              </form>                          <?php endif; ?>                      </div> +                    <?php endif; ?>                      <?php if ($postAuthor): ?> -                        <a href="?_action=viewuser&user=<?= htmlentities(urlencode($postAuthor->id)) ?>"><?= htmlentities($postAuthor->displayName) ?></a> +                        <?php if ($hide_actions): ?> +                            <?= htmlentities($postAuthor->displayName) ?> +                        <?php else: ?> +                            <a href="?_action=viewuser&user=<?= htmlentities(urlencode($postAuthor->id)) ?>"><?= htmlentities($postAuthor->displayName) ?></a> +                        <?php endif; ?> +                        <?php if ($your_are_the_author): ?> +                            <span class="text-normal label label-primary">You</span> +                        <?php endif; ?>                      <?php else: ?>                          <em class="text-muted">(deleted)</em>                      <?php endif; ?> @@ -63,9 +84,15 @@ $canDelete = ($GLOBALS["currentUser"]?->id === $postAuthor?->id && $postAuthor?-                  <?php if (count($imageAttachments) > 0): ?>                  <div class="post-images clearfix">                      <?php /** @var Attachment $attachment */ foreach ($imageAttachments as $attachment): ?> -                        <a class="image-attachment" href="?_action=attachment&attachment=<?= htmlentities(urlencode($attachment->id)) ?>" title="<?= htmlentities($attachment->name) ?>"> -                            <img class="image-attachment-image" src="?_action=thumb&attachment=<?= htmlentities(urlencode($attachment->id)) ?>" alt="" width="110"> -                        </a> +                        <?php if ($hide_actions): ?> +                            <span class="image-attachment" title="<?= htmlentities($attachment->name) ?>"> +                                <img class="image-attachment-image" src="?_action=thumb&attachment=<?= htmlentities(urlencode($attachment->id)) ?>" alt="" width="110"> +                            </span> +                        <?php else: ?> +                            <a class="image-attachment" href="?_action=attachment&attachment=<?= htmlentities(urlencode($attachment->id)) ?>" title="<?= htmlentities($attachment->name) ?>"> +                                <img class="image-attachment-image" src="?_action=thumb&attachment=<?= htmlentities(urlencode($attachment->id)) ?>" alt="" width="110"> +                            </a> +                        <?php endif; ?>                      <?php endforeach; ?>                  </div>              <?php endif; ?> @@ -74,7 +101,11 @@ $canDelete = ($GLOBALS["currentUser"]?->id === $postAuthor?->id && $postAuthor?-                  <div class="panel-footer">                      <div class="btn-group">                          <?php /** @var Attachment $attachment */ foreach ($fileAttachments as $attachment): ?> -                            <a class="btn btn-default" href="?_action=attachment&attachment=<?= htmlentities(urlencode($attachment->id)) ?>"><?= htmlentities($attachment->name) ?></a> +                            <?php if ($hide_actions): ?> +                                <button class="btn btn-default"><?= htmlentities($attachment->name) ?></button> +                            <?php else: ?> +                                <a class="btn btn-default" href="?_action=attachment&attachment=<?= htmlentities(urlencode($attachment->id)) ?>"><?= htmlentities($attachment->name) ?></a> +                            <?php endif; ?>                          <?php endforeach; ?>                      </div>                  </div> diff --git a/src/application/views/view_topic_start.php b/src/application/views/view_topic_start.php index 5818483..84a29de 100644 --- a/src/application/views/view_topic_start.php +++ b/src/application/views/view_topic_start.php @@ -6,19 +6,21 @@ $canReply = $GLOBALS["currentUser"]?->hasPermission(UserPermissions::CREATE_OWN_  $canDelete = ($GLOBALS["currentUser"]?->id === $topicAuthor->id && $topicAuthor->hasPermission(UserPermissions::DELETE_OWN_TOPIC))            || ($GLOBALS["currentUser"]?->hasPermission(UserPermissions::DELETE_OTHER_TOPIC));  ?> -<div role="heading" class="h1"> -<?= htmlentities($topic->title) ?> -<div class="pull-right"> -<?php if ($canReply): ?> -<button id="btn-reply" class="btn btn-default js-only"><span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> Reply</button> -<?php endif; ?> -<?php if ($canDelete): ?> -<form action="?_action=deletetopic" method="post" class="seamless-inline"> -<input type="hidden" name="topic" value="<?= htmlentities($topic->id) ?>"> -<button type="submit" class="btn btn-danger"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete topic</button> -</form> -<?php endif; ?> -</div> +<div class="page-header margin-top-0"> +    <div role="heading" class="h1 margin-top-0"> +        <?= htmlentities($topic->title) ?> +        <div class="pull-right"> +            <?php if ($canReply): ?> +                <button id="btn-reply" class="btn btn-default js-only"><span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> Reply</button> +            <?php endif; ?> +            <?php if ($canDelete): ?> +                <form action="?_action=deletetopic" method="post" class="seamless-inline"> +                    <input type="hidden" name="topic" value="<?= htmlentities($topic->id) ?>"> +                    <button type="submit" class="btn btn-danger"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete topic</button> +                </form> +            <?php endif; ?> +        </div> +    </div>  </div>  <p>  Started by diff --git a/src/application/views/view_user.php b/src/application/views/view_user.php index 334928b..23d2b71 100644 --- a/src/application/views/view_user.php +++ b/src/application/views/view_user.php @@ -1 +1,153 @@ -<h1><?= htmlentities($user->displayName) ?></h1> +<?php + +use mystic\forum\orm\UserPermissions; +use mystic\forum\utils\RequestUtils; +use mystic\forum\utils\StringUtils; + +/** @var mystic\forum\orm\User $user */ +/** @var bool $lastNameChangeTooRecent */ + +$canEdit = ($user->id === $GLOBALS["currentUser"]?->id && $user->hasPermission(UserPermissions::EDIT_OWN_USER)) +        || $GLOBALS["currentUser"]?->hasPermission(UserPermissions::EDIT_OTHER_USER); + +$isOwnProfile = $user->id === $GLOBALS["currentUser"]?->id; + +$sIsOwn_your = ""; +if ($isOwnProfile) +    $sIsOwn_your = " your"; + +$sUserPossessive = ""; +if ($isOwnProfile) +    $sUserPossessive = "Your"; +else +    $sUserPossessive = $user->displayName . "'s"; + +$dateJoined = DateTime::createFromImmutable($user->created); +$dateJoined->setTime(0, 0, 0, 0); +?> + +<div class="clearfix"> +    <img class="pull-left margin-right" src="?_action=profilepicture&user=<?= htmlentities(urlencode($user->id)) ?>"> +    <span class="h1"><?= htmlentities($user->displayName) ?></span> +    <?php if ($isOwnProfile): ?> +        <span class="label label-primary">You</span> +    <?php endif; ?><br> +    @<?= htmlentities($user->name) ?> • <span class="text-muted">Member since <span class="_date"><?= htmlentities($dateJoined->format("c")); ?></span> +</div> + +<?php if ($canEdit): ?> +<div class="row"> +<div class="col-md-9"> +<?php endif; ?> + +<h3><?= $sUserPossessive ?> posts</h3> + +<?php if (count($posts) > 0): ?> +    <div class="post-container"> +        <div class="post-container-posts"> +            <div class="list-group margin-top"> +                <?php foreach ($posts as $post): if ($post->deleted) continue; ?> +                    <a href="?_action=viewtopic&topic=<?= htmlentities(urlencode($post->topicId)) ?>#post-<?= htmlentities(urlencode($post->id)) ?>" class="list-group-item"> +                        <?= htmlentities(StringUtils::truncate(strip_tags(renderPost($post->content)), 100)) ?><br> +                        <span class="text-muted">posted on <span class="_time"><?= htmlentities($post->postDate->format("c")) ?></span> in <em><?= htmlentities($topics[$post->topicId]?->title ?? "unknown") ?></em></span> +                    </a> +                <?php endforeach; ?> +            </div> +        </div> +        <div class="post-container-controls"> +            <button class="btn btn-default">Show all posts</button> +        </div> +    </div> +<?php else: ?> +    <div class="well icon-well text-info margin-top margin-bottom"> +        <span class="glyphicon glyphicon-info-sign color-info" aria-hidden="true"></span> +        <em>This user has not posted anything yet</em> +    </div> +<?php endif; ?> + +<?php if ($canEdit): ?> +</div> + +<div class="col-md-3"> +<h3>Edit<?= $sIsOwn_your ?> profile</h3> +<?php +if (($_formError = RequestUtils::getAndClearFormError()) !== null) { +    _view("alert_error", ["message" => $_formError]); +} +?> +<form action="<?= htmlentities($_SERVER["REQUEST_URI"]) ?>" method="post" enctype="multipart/form-data"> +    <div class="form-group"> +        <label for="i_display_name">Display name:</label> +        <input required class="form-control" type="text" name="display_name" id="i_display_name" value="<?= htmlentities($user->displayName) ?>"> +    </div> +    <div class="form-group"> +        <label for="i_name">Login name:</label> +        <?php if ($lastNameChangeTooRecent): ?> +            <input required class="form-control" type="text" id="i_name" value="<?= htmlentities($user->name) ?>" disabled> +            <small class="text-danger"><strong>You can only change your username every 30 days!</strong></small> +        <?php else: ?> +            <input required class="form-control" type="text" name="name" id="i_name" value="<?= htmlentities($user->name) ?>"> +        <?php endif; ?> +    </div> +    <div class="form-group"> +        <label for="i_email">Email address:</label> +        <input required class="form-control" type="email" id="i_email" value="<?= htmlentities($user->email) ?>" disabled> +    </div> +    <div class="form-group"> +        <label>Profile picture:</label> +<?php +$_checkbox_disabled = empty($user->profilePicture); +$_checkbox_disabled_class = $_checkbox_disabled ? " disabled" : ""; +?> +        <div class="radio margin-top-0 <?= $_checkbox_disabled_class ?>"> +            <label> +                <input type="radio" name="pfp_action" id="pfp_action_1" value="keep"<?= !empty($user->profilePicture) ? ' checked' : ' disabled' ?>> +                Existing profile picture +            </label> +        </div> +        <div class="radio"> +            <label> +                <input type="radio" name="pfp_action" id="pfp_action_2" value="remove"<?= empty($user->profilePicture) ? ' checked' : '' ?>> +                No profile picture +            </label> +        </div> +        <div class="radio"> +            <label> +                <input type="radio" name="pfp_action" value="replace" id="pfp_action_3"> +                Upload new profile picture +            </label> +        </div> +        <input type="file" name="pfp" id="i_pfp" accept="image/png,image/jpeg" class="margin-left-3x"> +    </div> +    <div class="form-group"> +        <button type="submit" class="btn btn-success">Save changes</button> +    </div> +</form> +</div> + +</div> +<?php endif; ?> + +<script> +$(function() { +    $(".post-container").each(function(i, e) { +        if ($(e).height() > 900) { // more than 800 so it doesn't collapse just a few pixels +            $(e).addClass("collapsed"); +        } +        $(e).find(".post-container-controls button").click(function() { +            $(e).removeClass("collapsed"); +        }); +    }); +}); +<?php if ($canEdit): ?> +$(function() { +    $("#i_pfp").hide().prop("disabled", true).prop("required", false); +    $("[name='pfp_action']").on("change input check click", function() { +        if ($("#pfp_action_3").is(":checked")) +            $("#i_pfp").show().prop("disabled", false).prop("required", true); +        else +            $("#i_pfp").hide().prop("disabled", true).prop("required", false); +    }) +}); +<?php endif; ?> +</script> |