diff options
author | Luke Shumaker <LukeShu@sbcglobal.net> | 2014-01-28 09:50:25 -0500 |
---|---|---|
committer | Luke Shumaker <LukeShu@sbcglobal.net> | 2014-01-28 09:50:25 -0500 |
commit | 5744df39e15f85c6cc8a9faf8924d77e76d2b216 (patch) | |
tree | a8c8dd40a94d1fa0d5377566aa5548ae55a163da /includes/upload/UploadBase.php | |
parent | 4bb2aeca1d198391ca856aa16c40b8559c68daec (diff) | |
parent | 224b22a051051f6c2e494c3a2fb4adb42898e2d1 (diff) |
Merge branch 'archwiki'
Conflicts:
extensions/FluxBBAuthPlugin.php
extensions/SyntaxHighlight_GeSHi/README
extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.class.php
extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.i18n.php
extensions/SyntaxHighlight_GeSHi/SyntaxHighlight_GeSHi.php
extensions/SyntaxHighlight_GeSHi/geshi/docs/CHANGES
extensions/SyntaxHighlight_GeSHi/geshi/docs/THANKS
extensions/SyntaxHighlight_GeSHi/geshi/docs/TODO
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractClass.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractClass_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateClass.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateClass_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/AbstractPrivateMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Class.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Class_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Constant.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Constructor.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Destructor.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Function.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Global.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/I.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Index.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Interface.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Interface_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/L.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Lminus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Lplus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Method.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Page.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Page_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateClass.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateClass_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/PrivateVariable.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/StaticMethod.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/StaticVariable.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/T.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Tminus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Tplus.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/Variable.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/blank.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/class_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/file.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/function_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/next_button.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/next_button_disabled.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/package.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/package_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/previous_button.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/previous_button_disabled.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/private_class_logo.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/tutorial.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/tutorial_folder.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/api/media/images/up_button.png
extensions/SyntaxHighlight_GeSHi/geshi/docs/geshi-doc.html
extensions/SyntaxHighlight_GeSHi/geshi/docs/geshi-doc.txt
extensions/SyntaxHighlight_GeSHi/geshi/geshi.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/4cs.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502acme.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502kickass.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/6502tasm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/68000devpac.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/abap.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/actionscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/actionscript3.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ada.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/algol68.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/apache.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/applescript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/apt_sources.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/asm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/asp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/autoconf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/autohotkey.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/autoit.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/avisynth.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/awk.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bascomavr.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bash.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/basic4gl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bibtex.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/blitzbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/bnf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/boo.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/c.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/c_loadrunner.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/c_mac.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/caddcl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cadlisp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cfdg.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cfm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/chaiscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cil.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/clojure.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cmake.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cobol.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/coffeescript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cpp-qt.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cpp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/csharp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/css.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/cuesheet.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/d.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/dcs.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/delphi.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/diff.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/div.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/dos.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/dot.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/e.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ecmascript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/eiffel.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/email.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/epc.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/erlang.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/euphoria.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/f1.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/falcon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/fo.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/fortran.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/freebasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/fsharp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gambas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gdb.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/genero.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/genie.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gettext.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/glsl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gnuplot.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/go.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/groovy.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/gwbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/haskell.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/hicest.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/hq9plus.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/html4strict.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/html5.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/icon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/idl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ini.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/inno.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/intercal.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/io.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/j.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/java.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/java5.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/javascript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/jquery.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/kixtart.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/klonec.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/klonecpp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/latex.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lb.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lisp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/llvm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/locobasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/logtalk.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lolcode.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lotusformulas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lotusscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lsl2.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/lua.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/m68k.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/magiksf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/make.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mapbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/matlab.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mirc.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mmix.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/modula2.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/modula3.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mpasm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mxml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/mysql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/newlisp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/nsis.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oberon2.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/objc.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/objeck.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ocaml-brief.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ocaml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oobas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oracle11.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oracle8.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oxygene.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/oz.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pascal.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pcre.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/per.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/perl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/perl6.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/php-brief.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/php.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pic16.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pike.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pixelbender.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pli.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/plsql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/postgresql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/povray.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/powerbuilder.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/powershell.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/proftpd.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/progress.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/prolog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/properties.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/providex.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/purebasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/pycon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/python.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/q.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/qbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rails.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rebol.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/reg.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/robots.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rpmspec.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/rsplus.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/ruby.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/sas.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/scala.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/scheme.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/scilab.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/sdlbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/smalltalk.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/smarty.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/sql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/systemverilog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/tcl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/teraterm.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/text.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/thinbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/tsql.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/typoscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/unicon.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/uscript.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vala.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vb.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vbnet.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/verilog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vhdl.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/vim.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/visualfoxpro.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/visualprolog.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/whitespace.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/whois.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/winbatch.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xbasic.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xorg_conf.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/xpp.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/yaml.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/z80.php
extensions/SyntaxHighlight_GeSHi/geshi/geshi/zxbasic.php
Diffstat (limited to 'includes/upload/UploadBase.php')
-rw-r--r-- | includes/upload/UploadBase.php | 400 |
1 files changed, 240 insertions, 160 deletions
diff --git a/includes/upload/UploadBase.php b/includes/upload/UploadBase.php index 0848780f..916ad6c1 100644 --- a/includes/upload/UploadBase.php +++ b/includes/upload/UploadBase.php @@ -65,24 +65,27 @@ abstract class UploadBase { const WINDOWS_NONASCII_FILENAME = 13; const FILENAME_TOO_LONG = 14; + const SESSION_STATUS_KEY = 'wsUploadStatusData'; + /** * @param $error int * @return string */ public function getVerificationErrorCode( $error ) { - $code_to_status = array(self::EMPTY_FILE => 'empty-file', - self::FILE_TOO_LARGE => 'file-too-large', - self::FILETYPE_MISSING => 'filetype-missing', - self::FILETYPE_BADTYPE => 'filetype-banned', - self::MIN_LENGTH_PARTNAME => 'filename-tooshort', - self::ILLEGAL_FILENAME => 'illegal-filename', - self::OVERWRITE_EXISTING_FILE => 'overwrite', - self::VERIFICATION_ERROR => 'verification-error', - self::HOOK_ABORTED => 'hookaborted', - self::WINDOWS_NONASCII_FILENAME => 'windows-nonascii-filename', - self::FILENAME_TOO_LONG => 'filename-toolong', + $code_to_status = array( + self::EMPTY_FILE => 'empty-file', + self::FILE_TOO_LARGE => 'file-too-large', + self::FILETYPE_MISSING => 'filetype-missing', + self::FILETYPE_BADTYPE => 'filetype-banned', + self::MIN_LENGTH_PARTNAME => 'filename-tooshort', + self::ILLEGAL_FILENAME => 'illegal-filename', + self::OVERWRITE_EXISTING_FILE => 'overwrite', + self::VERIFICATION_ERROR => 'verification-error', + self::HOOK_ABORTED => 'hookaborted', + self::WINDOWS_NONASCII_FILENAME => 'windows-nonascii-filename', + self::FILENAME_TOO_LONG => 'filename-toolong', ); - if( isset( $code_to_status[$error] ) ) { + if ( isset( $code_to_status[$error] ) ) { return $code_to_status[$error]; } @@ -108,7 +111,7 @@ abstract class UploadBase { /** * Returns true if the user can use this upload module or else a string * identifying the missing permission. - * Can be overriden by subclasses. + * Can be overridden by subclasses. * * @param $user User * @return bool @@ -135,7 +138,7 @@ abstract class UploadBase { public static function createFromRequest( &$request, $type = null ) { $type = $type ? $type : $request->getVal( 'wpSourceType', 'File' ); - if( !$type ) { + if ( !$type ) { return null; } @@ -148,18 +151,18 @@ abstract class UploadBase { if ( is_null( $className ) ) { $className = 'UploadFrom' . $type; wfDebug( __METHOD__ . ": class name: $className\n" ); - if( !in_array( $type, self::$uploadHandlers ) ) { + if ( !in_array( $type, self::$uploadHandlers ) ) { return null; } } // Check whether this upload class is enabled - if( !call_user_func( array( $className, 'isEnabled' ) ) ) { + if ( !call_user_func( array( $className, 'isEnabled' ) ) ) { return null; } // Check whether the request is valid - if( !call_user_func( array( $className, 'isValidRequest' ), $request ) ) { + if ( !call_user_func( array( $className, 'isValidRequest' ), $request ) ) { return null; } @@ -186,14 +189,16 @@ abstract class UploadBase { * @since 1.18 * @return string */ - public function getSourceType() { return null; } + public function getSourceType() { + return null; + } /** * Initialize the path information - * @param $name string the desired destination name - * @param $tempPath string the temporary path - * @param $fileSize int the file size - * @param $removeTempFile bool (false) remove the temporary file? + * @param string $name the desired destination name + * @param string $tempPath the temporary path + * @param int $fileSize the file size + * @param bool $removeTempFile (false) remove the temporary file? * @throws MWException */ public function initializePathInfo( $name, $tempPath, $fileSize, $removeTempFile = false ) { @@ -209,7 +214,7 @@ abstract class UploadBase { /** * Initialize from a WebRequest. Override this in a subclass. */ - public abstract function initializeFromRequest( &$request ); + abstract public function initializeFromRequest( &$request ); /** * Fetch the file. Usually a no-op @@ -236,22 +241,33 @@ abstract class UploadBase { } /** - * @param $srcPath String: the source path - * @return string the real path if it was a virtual URL + * Get the base 36 SHA1 of the file + * @return string + */ + public function getTempFileSha1Base36() { + return FSFile::getSha1Base36FromPath( $this->mTempPath ); + } + + /** + * @param string $srcPath the source path + * @return string|bool the real path if it was a virtual URL Returns false on failure */ function getRealPath( $srcPath ) { wfProfileIn( __METHOD__ ); $repo = RepoGroup::singleton()->getLocalRepo(); if ( $repo->isVirtualUrl( $srcPath ) ) { - // @TODO: just make uploads work with storage paths - // UploadFromStash loads files via virtuals URLs + // @todo just make uploads work with storage paths + // UploadFromStash loads files via virtual URLs $tmpFile = $repo->getLocalCopy( $srcPath ); - $tmpFile->bind( $this ); // keep alive with $thumb - wfProfileOut( __METHOD__ ); - return $tmpFile->getPath(); + if ( $tmpFile ) { + $tmpFile->bind( $this ); // keep alive with $this + } + $path = $tmpFile ? $tmpFile->getPath() : false; + } else { + $path = $srcPath; } wfProfileOut( __METHOD__ ); - return $srcPath; + return $path; } /** @@ -264,7 +280,7 @@ abstract class UploadBase { /** * If there was no filename or a zero size given, give up quick. */ - if( $this->isEmptyFile() ) { + if ( $this->isEmptyFile() ) { wfProfileOut( __METHOD__ ); return array( 'status' => self::EMPTY_FILE ); } @@ -273,7 +289,7 @@ abstract class UploadBase { * Honor $wgMaxUploadSize */ $maxSize = self::getMaxUploadSize( $this->getSourceType() ); - if( $this->mFileSize > $maxSize ) { + if ( $this->mFileSize > $maxSize ) { wfProfileOut( __METHOD__ ); return array( 'status' => self::FILE_TOO_LARGE, @@ -287,7 +303,7 @@ abstract class UploadBase { * probably not accept it. */ $verification = $this->verifyFile(); - if( $verification !== true ) { + if ( $verification !== true ) { wfProfileOut( __METHOD__ ); return array( 'status' => self::VERIFICATION_ERROR, @@ -299,13 +315,13 @@ abstract class UploadBase { * Make sure this file can be created */ $result = $this->validateName(); - if( $result !== true ) { + if ( $result !== true ) { wfProfileOut( __METHOD__ ); return $result; } $error = ''; - if( !wfRunHooks( 'UploadVerification', + if ( !wfRunHooks( 'UploadVerification', array( $this->mDestName, $this->mTempPath, &$error ) ) ) { wfProfileOut( __METHOD__ ); @@ -322,11 +338,11 @@ abstract class UploadBase { * @return mixed true if valid, otherwise and array with 'status' * and other keys **/ - protected function validateName() { + public function validateName() { $nt = $this->getTitle(); - if( is_null( $nt ) ) { + if ( is_null( $nt ) ) { $result = array( 'status' => $this->mTitleError ); - if( $this->mTitleError == self::ILLEGAL_FILENAME ) { + if ( $this->mTitleError == self::ILLEGAL_FILENAME ) { $result['filtered'] = $this->mFilteredName; } if ( $this->mTitleError == self::FILETYPE_BADTYPE ) { @@ -343,18 +359,18 @@ abstract class UploadBase { } /** - * Verify the mime type + * Verify the mime type. * * @note Only checks that it is not an evil mime. The does it have * correct extension given its mime type check is in verifyFile. - * @param $mime string representing the mime + * @param string $mime representing the mime * @return mixed true if the file is verified, an array otherwise */ protected function verifyMimeType( $mime ) { global $wgVerifyMimeType; wfProfileIn( __METHOD__ ); if ( $wgVerifyMimeType ) { - wfDebug ( "\n\nmime: <$mime> extension: <{$this->mFinalExtension}>\n\n"); + wfDebug( "\n\nmime: <$mime> extension: <{$this->mFinalExtension}>\n\n" ); global $wgMimeTypeBlacklist; if ( $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) { wfProfileOut( __METHOD__ ); @@ -381,6 +397,7 @@ abstract class UploadBase { return true; } + /** * Verifies that it's ok to include the uploaded file * @@ -396,10 +413,10 @@ abstract class UploadBase { return $status; } - if ( $wgVerifyMimeType ) { - $this->mFileProps = FSFile::getPropsFromPath( $this->mTempPath, $this->mFinalExtension ); - $mime = $this->mFileProps['file-mime']; + $this->mFileProps = FSFile::getPropsFromPath( $this->mTempPath, $this->mFinalExtension ); + $mime = $this->mFileProps['file-mime']; + if ( $wgVerifyMimeType ) { # XXX: Missing extension will be caught by validateName() via getTitle() if ( $this->mFinalExtension != '' && !$this->verifyExtension( $mime, $this->mFinalExtension ) ) { wfProfileOut( __METHOD__ ); @@ -407,6 +424,7 @@ abstract class UploadBase { } } + $handler = MediaHandler::getHandler( $mime ); if ( $handler ) { $handlerStatus = $handler->verifyUpload( $this->mTempPath ); @@ -440,14 +458,13 @@ abstract class UploadBase { global $wgAllowJavaUploads, $wgDisableUploadScriptChecks; wfProfileIn( __METHOD__ ); - # get the title, even though we are doing nothing with it, because - # we need to populate mFinalExtension + # getTitle() sets some internal parameters like $this->mFinalExtension $this->getTitle(); $this->mFileProps = FSFile::getPropsFromPath( $this->mTempPath, $this->mFinalExtension ); # check mime type, if desired - $mime = $this->mFileProps[ 'file-mime' ]; + $mime = $this->mFileProps['file-mime']; $status = $this->verifyMimeType( $mime ); if ( $status !== true ) { wfProfileOut( __METHOD__ ); @@ -456,14 +473,15 @@ abstract class UploadBase { # check for htmlish code and javascript if ( !$wgDisableUploadScriptChecks ) { - if( self::detectScript( $this->mTempPath, $mime, $this->mFinalExtension ) ) { + if ( self::detectScript( $this->mTempPath, $mime, $this->mFinalExtension ) ) { wfProfileOut( __METHOD__ ); return array( 'uploadscripted' ); } - if( $this->mFinalExtension == 'svg' || $mime == 'image/svg+xml' ) { - if( $this->detectScriptInSvg( $this->mTempPath ) ) { + if ( $this->mFinalExtension == 'svg' || $mime == 'image/svg+xml' ) { + $svgStatus = $this->detectScriptInSvg( $this->mTempPath ); + if ( $svgStatus !== false ) { wfProfileOut( __METHOD__ ); - return array( 'uploadscripted' ); + return $svgStatus; } } } @@ -550,7 +568,7 @@ abstract class UploadBase { * to modify it by uploading a new revision. */ $nt = $this->getTitle(); - if( is_null( $nt ) ) { + if ( is_null( $nt ) ) { return true; } $permErrors = $nt->getUserPermissionsErrors( 'edit', $user ); @@ -560,7 +578,7 @@ abstract class UploadBase { } else { $permErrorsCreate = array(); } - if( $permErrors || $permErrorsUpload || $permErrorsCreate ) { + if ( $permErrors || $permErrorsUpload || $permErrorsCreate ) { $permErrors = array_merge( $permErrors, wfArrayDiff2( $permErrorsUpload, $permErrors ) ); $permErrors = array_merge( $permErrors, wfArrayDiff2( $permErrorsCreate, $permErrors ) ); return $permErrors; @@ -575,7 +593,9 @@ abstract class UploadBase { } /** - * Check for non fatal problems with the file + * Check for non fatal problems with the file. + * + * This should not assume that mTempPath is set. * * @return Array of warnings */ @@ -595,22 +615,23 @@ abstract class UploadBase { $comparableName = str_replace( ' ', '_', $this->mDesiredDestName ); $comparableName = Title::capitalize( $comparableName, NS_FILE ); - if( $this->mDesiredDestName != $filename && $comparableName != $filename ) { + if ( $this->mDesiredDestName != $filename && $comparableName != $filename ) { $warnings['badfilename'] = $filename; } // Check whether the file extension is on the unwanted list global $wgCheckFileExtensions, $wgFileExtensions; if ( $wgCheckFileExtensions ) { - if ( !$this->checkFileExtension( $this->mFinalExtension, $wgFileExtensions ) ) { + $extensions = array_unique( $wgFileExtensions ); + if ( !$this->checkFileExtension( $this->mFinalExtension, $extensions ) ) { $warnings['filetype-unwanted-type'] = array( $this->mFinalExtension, - $wgLang->commaList( $wgFileExtensions ), count( $wgFileExtensions ) ); + $wgLang->commaList( $extensions ), count( $extensions ) ); } } global $wgUploadSizeWarning; if ( $wgUploadSizeWarning && ( $this->mFileSize > $wgUploadSizeWarning ) ) { - $warnings['large-file'] = $wgUploadSizeWarning; + $warnings['large-file'] = array( $wgUploadSizeWarning, $this->mFileSize ); } if ( $this->mFileSize == 0 ) { @@ -618,21 +639,21 @@ abstract class UploadBase { } $exists = self::getExistsWarning( $localFile ); - if( $exists !== false ) { + if ( $exists !== false ) { $warnings['exists'] = $exists; } // Check dupes against existing files - $hash = FSFile::getSha1Base36FromPath( $this->mTempPath ); + $hash = $this->getTempFileSha1Base36(); $dupes = RepoGroup::singleton()->findBySha1( $hash ); $title = $this->getTitle(); // Remove all matches against self foreach ( $dupes as $key => $dupe ) { - if( $title->equals( $dupe->getTitle() ) ) { + if ( $title->equals( $dupe->getTitle() ) ) { unset( $dupes[$key] ); } } - if( $dupes ) { + if ( $dupes ) { $warnings['duplicate'] = $dupes; } @@ -670,9 +691,9 @@ abstract class UploadBase { $user ); - if( $status->isGood() ) { + if ( $status->isGood() ) { if ( $watch ) { - $user->addWatch( $this->getLocalFile()->getTitle() ); + WatchAction::doWatch( $this->getLocalFile()->getTitle(), $user, WatchedItem::IGNORE_USER_RIGHTS ); } wfRunHooks( 'UploadComplete', array( &$this ) ); } @@ -691,7 +712,6 @@ abstract class UploadBase { if ( $this->mTitle !== false ) { return $this->mTitle; } - /* Assume that if a user specified File:Something.jpg, this is an error * and that the namespace prefix needs to be stripped of. */ @@ -717,21 +737,19 @@ abstract class UploadBase { $this->mFilteredName = wfStripIllegalFilenameChars( $this->mFilteredName ); /* Normalize to title form before we do any further processing */ $nt = Title::makeTitleSafe( NS_FILE, $this->mFilteredName ); - if( is_null( $nt ) ) { + if ( is_null( $nt ) ) { $this->mTitleError = self::ILLEGAL_FILENAME; return $this->mTitle = null; } $this->mFilteredName = $nt->getDBkey(); - - /** * We'll want to blacklist against *any* 'extension', and use * only the final one for the whitelist. */ list( $partname, $ext ) = $this->splitExtensions( $this->mFilteredName ); - if( count( $ext ) ) { + if ( count( $ext ) ) { $this->mFinalExtension = trim( $ext[count( $ext ) - 1] ); } else { $this->mFinalExtension = ''; @@ -752,7 +770,6 @@ abstract class UploadBase { $ext = array( $this->mFinalExtension ); } } - } /* Don't allow users to override the blacklist (check file extension) */ @@ -780,14 +797,14 @@ abstract class UploadBase { # If there was more than one "extension", reassemble the base # filename to prevent bogus complaints about length - if( count( $ext ) > 1 ) { - for( $i = 0; $i < count( $ext ) - 1; $i++ ) { + if ( count( $ext ) > 1 ) { + for ( $i = 0; $i < count( $ext ) - 1; $i++ ) { $partname .= '.' . $ext[$i]; } } - if( strlen( $partname ) < 1 ) { - $this->mTitleError = self::MIN_LENGTH_PARTNAME; + if ( strlen( $partname ) < 1 ) { + $this->mTitleError = self::MIN_LENGTH_PARTNAME; return $this->mTitle = null; } @@ -800,7 +817,7 @@ abstract class UploadBase { * @return LocalFile|null */ public function getLocalFile() { - if( is_null( $this->mLocalFile ) ) { + if ( is_null( $this->mLocalFile ) ) { $nt = $this->getTitle(); $this->mLocalFile = is_null( $nt ) ? null : wfLocalFile( $nt ); } @@ -816,13 +833,14 @@ abstract class UploadBase { * This method returns the file object, which also has a 'fileKey' property which can be passed through a form or * API request to find this stashed file again. * + * @param $user User * @return UploadStashFile stashed file */ - public function stashFile() { + public function stashFile( User $user = null ) { // was stashSessionFile wfProfileIn( __METHOD__ ); - $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash(); + $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash( $user ); $file = $stash->stashFile( $this->mTempPath, $this->getSourceType() ); $this->mLocalFile = $file; @@ -905,30 +923,36 @@ abstract class UploadBase { /** * Checks if the mime type of the uploaded file matches the file extension. * - * @param $mime String: the mime type of the uploaded file - * @param $extension String: the filename extension that the file is to be served with + * @param string $mime the mime type of the uploaded file + * @param string $extension the filename extension that the file is to be served with * @return Boolean */ public static function verifyExtension( $mime, $extension ) { $magic = MimeMagic::singleton(); - if ( !$mime || $mime == 'unknown' || $mime == 'unknown/unknown' ) + if ( !$mime || $mime == 'unknown' || $mime == 'unknown/unknown' ) { if ( !$magic->isRecognizableExtension( $extension ) ) { wfDebug( __METHOD__ . ": passing file with unknown detected mime type; " . "unrecognized extension '$extension', can't verify\n" ); return true; } else { - wfDebug( __METHOD__ . ": rejecting file with unknown detected mime type; ". + wfDebug( __METHOD__ . ": rejecting file with unknown detected mime type; " . "recognized extension '$extension', so probably invalid file\n" ); return false; } + } $match = $magic->isMatchingExtension( $extension, $mime ); if ( $match === null ) { - wfDebug( __METHOD__ . ": no file extension known for mime type $mime, passing file\n" ); - return true; - } elseif( $match === true ) { + if ( $magic->getTypesForExtension( $extension ) !== null ) { + wfDebug( __METHOD__ . ": No extension known for $mime, but we know a mime for $extension\n" ); + return false; + } else { + wfDebug( __METHOD__ . ": no file extension known for mime type $mime, passing file\n" ); + return true; + } + } elseif ( $match === true ) { wfDebug( __METHOD__ . ": mime type $mime matches extension $extension, passing file\n" ); #TODO: if it's a bitmap, make sure PHP or ImageMagic resp. can handle it! @@ -946,9 +970,9 @@ abstract class UploadBase { * potentially harmful. The present implementation will produce false * positives in some situations. * - * @param $file String: pathname to the temporary upload file - * @param $mime String: the mime type of the file - * @param $extension String: the extension of the file + * @param string $file pathname to the temporary upload file + * @param string $mime the mime type of the file + * @param string $extension the extension of the file * @return Boolean: true if the file contains something looking like embedded scripts */ public static function detectScript( $file, $mime, $extension ) { @@ -958,7 +982,7 @@ abstract class UploadBase { # ugly hack: for text files, always look at the entire file. # For binary field, just check the first K. - if( strpos( $mime,'text/' ) === 0 ) { + if ( strpos( $mime, 'text/' ) === 0 ) { $chunk = file_get_contents( $file ); } else { $fp = fopen( $file, 'rb' ); @@ -968,27 +992,27 @@ abstract class UploadBase { $chunk = strtolower( $chunk ); - if( !$chunk ) { + if ( !$chunk ) { wfProfileOut( __METHOD__ ); return false; } # decode from UTF-16 if needed (could be used for obfuscation). - if( substr( $chunk, 0, 2 ) == "\xfe\xff" ) { + if ( substr( $chunk, 0, 2 ) == "\xfe\xff" ) { $enc = 'UTF-16BE'; - } elseif( substr( $chunk, 0, 2 ) == "\xff\xfe" ) { + } elseif ( substr( $chunk, 0, 2 ) == "\xff\xfe" ) { $enc = 'UTF-16LE'; } else { $enc = null; } - if( $enc ) { + if ( $enc ) { $chunk = iconv( $enc, "ASCII//IGNORE", $chunk ); } $chunk = trim( $chunk ); - # @todo FIXME: Convert from UTF-16 if necessarry! + # @todo FIXME: Convert from UTF-16 if necessary! wfDebug( __METHOD__ . ": checking for embedded scripts and HTML stuff\n" ); # check for HTML doctype @@ -1032,12 +1056,12 @@ abstract class UploadBase { '<table' ); - if( !$wgAllowTitlesInSVG && $extension !== 'svg' && $mime !== 'image/svg' ) { + if ( !$wgAllowTitlesInSVG && $extension !== 'svg' && $mime !== 'image/svg' ) { $tags[] = '<title'; } - foreach( $tags as $tag ) { - if( false !== strpos( $chunk, $tag ) ) { + foreach ( $tags as $tag ) { + if ( false !== strpos( $chunk, $tag ) ) { wfDebug( __METHOD__ . ": found something that may make it be mistaken for html: $tag\n" ); wfProfileOut( __METHOD__ ); return true; @@ -1052,21 +1076,21 @@ abstract class UploadBase { $chunk = Sanitizer::decodeCharReferences( $chunk ); # look for script-types - if( preg_match( '!type\s*=\s*[\'"]?\s*(?:\w*/)?(?:ecma|java)!sim', $chunk ) ) { + if ( preg_match( '!type\s*=\s*[\'"]?\s*(?:\w*/)?(?:ecma|java)!sim', $chunk ) ) { wfDebug( __METHOD__ . ": found script types\n" ); wfProfileOut( __METHOD__ ); return true; } # look for html-style script-urls - if( preg_match( '!(?:href|src|data)\s*=\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) { + if ( preg_match( '!(?:href|src|data)\s*=\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) { wfDebug( __METHOD__ . ": found html-style script urls\n" ); wfProfileOut( __METHOD__ ); return true; } # look for css-style script-urls - if( preg_match( '!url\s*\(\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) { + if ( preg_match( '!url\s*\(\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) { wfDebug( __METHOD__ . ": found css-style script urls\n" ); wfProfileOut( __METHOD__ ); return true; @@ -1102,7 +1126,7 @@ abstract class UploadBase { // bytes. There shouldn't be a legitimate reason for this to happen. wfDebug( __METHOD__ . ": Unmatched XML declaration start\n" ); return true; - } elseif ( substr( $contents, 0, 4) == "\x4C\x6F\xA7\x94" ) { + } elseif ( substr( $contents, 0, 4 ) == "\x4C\x6F\xA7\x94" ) { // EBCDIC encoded XML wfDebug( __METHOD__ . ": EBCDIC Encoded XML\n" ); return true; @@ -1138,8 +1162,33 @@ abstract class UploadBase { * @return bool */ protected function detectScriptInSvg( $filename ) { - $check = new XmlTypeCheck( $filename, array( $this, 'checkSvgScriptCallback' ) ); - return $check->filterMatch; + $check = new XmlTypeCheck( + $filename, + array( $this, 'checkSvgScriptCallback' ), + true, + array( 'processing_instruction_handler' => 'UploadBase::checkSvgPICallback' ) + ); + if ( $check->wellFormed !== true ) { + // Invalid xml (bug 58553) + return array( 'uploadinvalidxml' ); + } elseif ( $check->filterMatch ) { + return array( 'uploadscripted' ); + } + return false; + } + + /** + * Callback to filter SVG Processing Instructions. + * @param $target string processing instruction name + * @param $data string processing instruction attribute and value + * @return bool (true if the filter identified something bad) + */ + public static function checkSvgPICallback( $target, $data ) { + // Don't allow external stylesheets (bug 57550) + if ( preg_match( '/xml-stylesheet/i', $target) ) { + return true; + } + return false; } /** @@ -1154,80 +1203,79 @@ abstract class UploadBase { /* * check for elements that can contain javascript */ - if( $strippedElement == 'script' ) { + if ( $strippedElement == 'script' ) { wfDebug( __METHOD__ . ": Found script element '$element' in uploaded file.\n" ); return true; } # e.g., <svg xmlns="http://www.w3.org/2000/svg"> <handler xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="load">alert(1)</handler> </svg> - if( $strippedElement == 'handler' ) { + if ( $strippedElement == 'handler' ) { wfDebug( __METHOD__ . ": Found scriptable element '$element' in uploaded file.\n" ); return true; } # SVG reported in Feb '12 that used xml:stylesheet to generate javascript block - if( $strippedElement == 'stylesheet' ) { + if ( $strippedElement == 'stylesheet' ) { wfDebug( __METHOD__ . ": Found scriptable element '$element' in uploaded file.\n" ); return true; } - foreach( $attribs as $attrib => $value ) { + foreach ( $attribs as $attrib => $value ) { $stripped = $this->stripXmlNamespace( $attrib ); - $value = strtolower($value); + $value = strtolower( $value ); - if( substr( $stripped, 0, 2 ) == 'on' ) { + if ( substr( $stripped, 0, 2 ) == 'on' ) { wfDebug( __METHOD__ . ": Found event-handler attribute '$attrib'='$value' in uploaded file.\n" ); return true; } # href with javascript target - if( $stripped == 'href' && strpos( strtolower( $value ), 'javascript:' ) !== false ) { + if ( $stripped == 'href' && strpos( strtolower( $value ), 'javascript:' ) !== false ) { wfDebug( __METHOD__ . ": Found script in href attribute '$attrib'='$value' in uploaded file.\n" ); return true; } - # href with embeded svg as target - if( $stripped == 'href' && preg_match( '!data:[^,]*image/svg[^,]*,!sim', $value ) ) { + # href with embedded svg as target + if ( $stripped == 'href' && preg_match( '!data:[^,]*image/svg[^,]*,!sim', $value ) ) { wfDebug( __METHOD__ . ": Found href to embedded svg \"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" ); return true; } - # href with embeded (text/xml) svg as target - if( $stripped == 'href' && preg_match( '!data:[^,]*text/xml[^,]*,!sim', $value ) ) { + # href with embedded (text/xml) svg as target + if ( $stripped == 'href' && preg_match( '!data:[^,]*text/xml[^,]*,!sim', $value ) ) { wfDebug( __METHOD__ . ": Found href to embedded svg \"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" ); return true; } # use set/animate to add event-handler attribute to parent - if( ( $strippedElement == 'set' || $strippedElement == 'animate' ) && $stripped == 'attributename' && substr( $value, 0, 2 ) == 'on' ) { + if ( ( $strippedElement == 'set' || $strippedElement == 'animate' ) && $stripped == 'attributename' && substr( $value, 0, 2 ) == 'on' ) { wfDebug( __METHOD__ . ": Found svg setting event-handler attribute with \"<$strippedElement $stripped='$value'...\" in uploaded file.\n" ); return true; } # use set to add href attribute to parent element - if( $strippedElement == 'set' && $stripped == 'attributename' && strpos( $value, 'href' ) !== false ) { - wfDebug( __METHOD__ . ": Found svg setting href attibute '$value' in uploaded file.\n" ); + if ( $strippedElement == 'set' && $stripped == 'attributename' && strpos( $value, 'href' ) !== false ) { + wfDebug( __METHOD__ . ": Found svg setting href attribute '$value' in uploaded file.\n" ); return true; } # use set to add a remote / data / script target to an element - if( $strippedElement == 'set' && $stripped == 'to' && preg_match( '!(http|https|data|script):!sim', $value ) ) { - wfDebug( __METHOD__ . ": Found svg setting attibute to '$value' in uploaded file.\n" ); + if ( $strippedElement == 'set' && $stripped == 'to' && preg_match( '!(http|https|data|script):!sim', $value ) ) { + wfDebug( __METHOD__ . ": Found svg setting attribute to '$value' in uploaded file.\n" ); return true; } - # use handler attribute with remote / data / script - if( $stripped == 'handler' && preg_match( '!(http|https|data|script):!sim', $value ) ) { + if ( $stripped == 'handler' && preg_match( '!(http|https|data|script):!sim', $value ) ) { wfDebug( __METHOD__ . ": Found svg setting handler with remote/data/script '$attrib'='$value' in uploaded file.\n" ); return true; } # use CSS styles to bring in remote code # catch url("http:..., url('http:..., url(http:..., but not url("#..., url('#..., url(#.... - if( $stripped == 'style' && preg_match_all( '!((?:font|clip-path|fill|filter|marker|marker-end|marker-mid|marker-start|mask|stroke)\s*:\s*url\s*\(\s*["\']?\s*[^#]+.*?\))!sim', $value, $matches ) ) { - foreach ($matches[1] as $match) { - if (!preg_match( '!(?:font|clip-path|fill|filter|marker|marker-end|marker-mid|marker-start|mask|stroke)\s*:\s*url\s*\(\s*(#|\'#|"#)!sim', $match ) ) { + if ( $stripped == 'style' && preg_match_all( '!((?:font|clip-path|fill|filter|marker|marker-end|marker-mid|marker-start|mask|stroke)\s*:\s*url\s*\(\s*["\']?\s*[^#]+.*?\))!sim', $value, $matches ) ) { + foreach ( $matches[1] as $match ) { + if ( !preg_match( '!(?:font|clip-path|fill|filter|marker|marker-end|marker-mid|marker-start|mask|stroke)\s*:\s*url\s*\(\s*(#|\'#|"#)!sim', $match ) ) { wfDebug( __METHOD__ . ": Found svg setting a style with remote url '$attrib'='$value' in uploaded file.\n" ); return true; } @@ -1235,7 +1283,7 @@ abstract class UploadBase { } # image filters can pull in url, which could be svg that executes scripts - if( $strippedElement == 'image' && $stripped == 'filter' && preg_match( '!url\s*\(!sim', $value ) ) { + if ( $strippedElement == 'image' && $stripped == 'filter' && preg_match( '!url\s*\(!sim', $value ) ) { wfDebug( __METHOD__ . ": Found image filter with url: \"<$strippedElement $stripped='$value'...\" in uploaded file.\n" ); return true; } @@ -1260,7 +1308,7 @@ abstract class UploadBase { * This relies on the $wgAntivirus and $wgAntivirusSetup variables. * $wgAntivirusRequired may be used to deny upload if the scan fails. * - * @param $file String: pathname to the temporary upload file + * @param string $file pathname to the temporary upload file * @return mixed false if not virus is found, NULL if the scan fails or is disabled, * or a string containing feedback from the virus scanner if a virus was found. * If textual feedback is missing but a virus was found, this function returns true. @@ -1305,7 +1353,7 @@ abstract class UploadBase { # NOTE: there's a 50 line workaround to make stderr redirection work on windows, too. # that does not seem to be worth the pain. # Ask me (Duesentrieb) about it if it's ever needed. - $output = wfShellExec( "$command 2>&1", $exitCode ); + $output = wfShellExecWithStderr( $command, $exitCode ); # map exit code to AV_xxx constants. $mappedCode = $exitCode; @@ -1317,27 +1365,22 @@ abstract class UploadBase { } } + /* NB: AV_NO_VIRUS is 0 but AV_SCAN_FAILED is false, + * so we need the strict equalities === and thus can't use a switch here + */ if ( $mappedCode === AV_SCAN_FAILED ) { # scan failed (code was mapped to false by $exitCodeMap) wfDebug( __METHOD__ . ": failed to scan $file (code $exitCode).\n" ); - if ( $wgAntivirusRequired ) { - wfProfileOut( __METHOD__ ); - return wfMessage( 'virus-scanfailed', array( $exitCode ) )->text(); - } else { - wfProfileOut( __METHOD__ ); - return null; - } + $output = $wgAntivirusRequired ? wfMessage( 'virus-scanfailed', array( $exitCode ) )->text() : null; } elseif ( $mappedCode === AV_SCAN_ABORTED ) { # scan failed because filetype is unknown (probably imune) wfDebug( __METHOD__ . ": unsupported file type $file (code $exitCode).\n" ); - wfProfileOut( __METHOD__ ); - return null; + $output = null; } elseif ( $mappedCode === AV_NO_VIRUS ) { # no virus found wfDebug( __METHOD__ . ": file passed virus scan.\n" ); - wfProfileOut( __METHOD__ ); - return false; + $output = false; } else { $output = trim( $output ); @@ -1353,9 +1396,10 @@ abstract class UploadBase { } wfDebug( __METHOD__ . ": FOUND VIRUS! scanner feedback: $output \n" ); - wfProfileOut( __METHOD__ ); - return $output; } + + wfProfileOut( __METHOD__ ); + return $output; } /** @@ -1369,8 +1413,8 @@ abstract class UploadBase { private function checkOverwrite( $user ) { // First check whether the local file can be overwritten $file = $this->getLocalFile(); - if( $file->exists() ) { - if( !self::userCanReUpload( $user, $file ) ) { + if ( $file->exists() ) { + if ( !self::userCanReUpload( $user, $file ) ) { return array( 'fileexists-forbidden', $file->getName() ); } else { return true; @@ -1392,17 +1436,17 @@ abstract class UploadBase { * Check if a user is the last uploader * * @param $user User object - * @param $img String: image name + * @param string $img image name * @return Boolean */ public static function userCanReUpload( User $user, $img ) { - if( $user->isAllowed( 'reupload' ) ) { + if ( $user->isAllowed( 'reupload' ) ) { return true; // non-conditional } - if( !$user->isAllowed( 'reupload-own' ) ) { + if ( !$user->isAllowed( 'reupload-own' ) ) { return false; } - if( is_string( $img ) ) { + if ( is_string( $img ) ) { $img = wfLocalFile( $img ); } if ( !( $img instanceof LocalFile ) ) { @@ -1424,11 +1468,11 @@ abstract class UploadBase { * @return mixed False if the file does not exists, else an array */ public static function getExistsWarning( $file ) { - if( $file->exists() ) { + if ( $file->exists() ) { return array( 'warning' => 'exists', 'file' => $file ); } - if( $file->getTitle()->getArticleID() ) { + if ( $file->getTitle()->getArticleID() ) { return array( 'warning' => 'page-exists', 'file' => $file ); } @@ -1436,7 +1480,7 @@ abstract class UploadBase { return array( 'warning' => 'was-deleted', 'file' => $file ); } - if( strpos( $file->getName(), '.' ) == false ) { + if ( strpos( $file->getName(), '.' ) == false ) { $partname = $file->getName(); $extension = ''; } else { @@ -1455,7 +1499,7 @@ abstract class UploadBase { $nt_lc = Title::makeTitle( NS_FILE, "{$partname}.{$normalizedExtension}" ); $file_lc = wfLocalFile( $nt_lc ); - if( $file_lc->exists() ) { + if ( $file_lc->exists() ) { return array( 'warning' => 'exists-normalized', 'file' => $file, @@ -1464,11 +1508,22 @@ abstract class UploadBase { } } + // Check for files with the same name but a different extension + $similarFiles = RepoGroup::singleton()->getLocalRepo()->findFilesByPrefix( + "{$partname}.", 1 ); + if ( count( $similarFiles ) ) { + return array( + 'warning' => 'exists-normalized', + 'file' => $file, + 'normalizedFile' => $similarFiles[0], + ); + } + if ( self::isThumbName( $file->getName() ) ) { # Check for filenames like 50px- or 180px-, these are mostly thumbnails - $nt_thb = Title::newFromText( substr( $partname , strpos( $partname , '-' ) +1 ) . '.' . $extension, NS_FILE ); + $nt_thb = Title::newFromText( substr( $partname, strpos( $partname, '-' ) + 1 ) . '.' . $extension, NS_FILE ); $file_thb = wfLocalFile( $nt_thb ); - if( $file_thb->exists() ) { + if ( $file_thb->exists() ) { return array( 'warning' => 'thumb', 'file' => $file, @@ -1484,8 +1539,7 @@ abstract class UploadBase { } } - - foreach( self::getFilenamePrefixBlacklist() as $prefix ) { + foreach ( self::getFilenamePrefixBlacklist() as $prefix ) { if ( substr( $partname, 0, strlen( $prefix ) ) == $prefix ) { return array( 'warning' => 'bad-prefix', @@ -1507,10 +1561,10 @@ abstract class UploadBase { $n = strrpos( $filename, '.' ); $partname = $n ? substr( $filename, 0, $n ) : $filename; return ( - substr( $partname , 3, 3 ) == 'px-' || - substr( $partname , 2, 3 ) == 'px-' + substr( $partname, 3, 3 ) == 'px-' || + substr( $partname, 2, 3 ) == 'px-' ) && - preg_match( "/[0-9]{2}/" , substr( $partname , 0, 2 ) ); + preg_match( "/[0-9]{2}/", substr( $partname, 0, 2 ) ); } /** @@ -1521,9 +1575,9 @@ abstract class UploadBase { public static function getFilenamePrefixBlacklist() { $blacklist = array(); $message = wfMessage( 'filename-prefix-blacklist' )->inContentLanguage(); - if( !$message->isDisabled() ) { + if ( !$message->isDisabled() ) { $lines = explode( "\n", $message->plain() ); - foreach( $lines as $line ) { + foreach ( $lines as $line ) { // Remove comment lines $comment = substr( trim( $line ), 0, 1 ); if ( $comment == '#' || $comment == '' ) { @@ -1532,7 +1586,7 @@ abstract class UploadBase { // Remove additional comments after a prefix $comment = strpos( $line, '#' ); if ( $comment > 0 ) { - $line = substr( $line, 0, $comment-1 ); + $line = substr( $line, 0, $comment - 1 ); } $blacklist[] = trim( $line ); } @@ -1590,6 +1644,32 @@ abstract class UploadBase { } else { return intval( $wgMaxUploadSize ); } + } + /** + * Get the current status of a chunked upload (used for polling). + * The status will be read from the *current* user session. + * @param $statusKey string + * @return Array|bool + */ + public static function getSessionStatus( $statusKey ) { + return isset( $_SESSION[self::SESSION_STATUS_KEY][$statusKey] ) + ? $_SESSION[self::SESSION_STATUS_KEY][$statusKey] + : false; + } + + /** + * Set the current status of a chunked upload (used for polling). + * The status will be stored in the *current* user session. + * @param $statusKey string + * @param $value array|false + * @return void + */ + public static function setSessionStatus( $statusKey, $value ) { + if ( $value === false ) { + unset( $_SESSION[self::SESSION_STATUS_KEY][$statusKey] ); + } else { + $_SESSION[self::SESSION_STATUS_KEY][$statusKey] = $value; + } } } |