summaryrefslogtreecommitdiff
path: root/sites/all/modules/plupload
diff options
context:
space:
mode:
authorCtibor Brančík <ctibor@brancik.cz>2016-03-20 19:27:01 +0100
committerCtibor Brančík <ctibor@brancik.cz>2016-03-20 19:27:01 +0100
commit29a6913890a675ddf1a9239b4407f105e02dc95d (patch)
treedd9ba21b73e9e704952b49d5153616a9dfa9b98f /sites/all/modules/plupload
parent5ddacae6306ce071d4f7e4d438960d6d3a4c6bd8 (diff)
downloadbrdo-29a6913890a675ddf1a9239b4407f105e02dc95d.tar.gz
brdo-29a6913890a675ddf1a9239b4407f105e02dc95d.tar.bz2
Added drupal modules for site
Diffstat (limited to 'sites/all/modules/plupload')
-rw-r--r--sites/all/modules/plupload/CHANGELOG.txt70
-rw-r--r--sites/all/modules/plupload/LICENSE.txt339
-rw-r--r--sites/all/modules/plupload/README.txt89
-rw-r--r--sites/all/modules/plupload/images/add.pngbin0 -> 160 bytes
-rw-r--r--sites/all/modules/plupload/images/backgrounds.gifbin0 -> 2977 bytes
-rw-r--r--sites/all/modules/plupload/images/buttons-disabled.pngbin0 -> 1292 bytes
-rw-r--r--sites/all/modules/plupload/images/buttons.pngbin0 -> 1439 bytes
-rw-r--r--sites/all/modules/plupload/images/delete.gifbin0 -> 180 bytes
-rw-r--r--sites/all/modules/plupload/images/done.gifbin0 -> 1024 bytes
-rw-r--r--sites/all/modules/plupload/images/error.gifbin0 -> 994 bytes
-rwxr-xr-xsites/all/modules/plupload/images/icon-feed.pngbin0 -> 1360 bytes
-rw-r--r--sites/all/modules/plupload/images/throbber.gifbin0 -> 1922 bytes
-rw-r--r--sites/all/modules/plupload/images/transp50.pngbin0 -> 399 bytes
-rw-r--r--sites/all/modules/plupload/images/up_arrow.pngbin0 -> 218 bytes
-rw-r--r--sites/all/modules/plupload/images/up_arrow_disabled.pngbin0 -> 227 bytes
-rw-r--r--sites/all/modules/plupload/images/video-indicator.pngbin0 -> 231 bytes
-rw-r--r--sites/all/modules/plupload/js/i18n.js41
-rw-r--r--sites/all/modules/plupload/plupload.css204
-rw-r--r--sites/all/modules/plupload/plupload.info12
-rw-r--r--sites/all/modules/plupload/plupload.install122
-rw-r--r--sites/all/modules/plupload/plupload.js178
-rw-r--r--sites/all/modules/plupload/plupload.make9
-rw-r--r--sites/all/modules/plupload/plupload.module523
23 files changed, 1587 insertions, 0 deletions
diff --git a/sites/all/modules/plupload/CHANGELOG.txt b/sites/all/modules/plupload/CHANGELOG.txt
new file mode 100644
index 000000000..83b9c0705
--- /dev/null
+++ b/sites/all/modules/plupload/CHANGELOG.txt
@@ -0,0 +1,70 @@
+CHANGELOG for Plupload integration for Drupal 7
+
+Plupload integration 7.x-1.7
+=================================
+- #2370889 by znerol: Fixed Extra margin on file list due to insufficient specificity of CSS selector.
+- #2190007 by slashrsm | hswong3i: Kill Firefox 3.6 check and entire _requirements checks section.
+- #2241523 by K. Tadesse, si.mon: Add some more strings to i18n.js.
+- #2088143 by hswong3i, Chris Charlton | lsolesen: Add make file so dependencies are downloaded automatically.
+
+Plupload integration 7.x-1.6
+=================================
+- #2171575 by slashrsm | kreatIL: Plupload library not found (version 1.5.8).
+- #2098555 by slashrsm: Suggest using .zip instead of .tar.gz.
+
+Plupload integration 7.x-1.5
+=================================
+- by slashrsm: Update README.txt with new download links.
+- #2132373 by OnkelTem: Plupload doesn't support international file names.
+- #2098555 by slashrsm: Document library v2.0.0 incompatibility.
+
+Plupload integration 7.x-1.4
+=================================
+- #2065927 by vladan.me: Added Plupload events support.
+- #2081263 by hgneng: Fixed Check transliteration setting before apply transliteration action.
+
+Plupload integration 7.x-1.3
+=================================
+- #2063161 by mfgering | Amon_Re: Fixed Multi Upload with plupload broken when using Drupal 7.23.
+
+Plupload integration 7.x-1.2
+=================================
+- #1999264 by slashrsm: up_arrow.png and up_arrow_disabled.png are very large.
+- #1935256 by Primsi: Fixed When a form has more than one submit button plupload always submits using the first one.
+
+Plupload integration 7.x-1.1
+=================================
+- #1903818 by quicksketch, slashrsm: Fixed Double dollar signs in hook_requirements().
+- #1506642 by MrHaroldA | succinct: Fixed plupload.js issue with Internet Explorer.
+- #1814744 by slashrsm, Kevin Hankens: File URI not available to hook_file_validate() implementations.
+- #1895328 by larowlan, slashrsm: Fixed Security exploit in plupload external library examples folder.
+- #1230632 by -enzo-, slashrsm: Fixed hard-coded file size limits.
+- by slashrsm: Fix CodeSniffer errors.
+- #1827368 by Kevin Hankens: Fixed Use standard language when validating files.
+- #1565898 by slashrsm: Create docs for Plupload element usage in README.txt.
+- #1111036 by slashrsm: Blacklist script extensions if 'allow_insecure_uploads' isn't set to TRUE.
+- #1426088 by slashrsm: Anonymous User can't upload.
+
+Plupload integration 7.x-1.0
+=================================
+- #1414486 by nbucknor, slashrsm: Improvements of error handling for multiple plupload elements on a single form.
+
+Plupload integration 7.x-1.0-rc1
+==================================
+- by slashrsm: Fix 3 Coder review notices.
+- by slashrsm: Removed unnecessary popup caused by previous commit.
+- #1414486 by nbucknor, annblack: Allow for Multiple Plupload elements in a form.
+- #1461884 by atlea: File uploads larger than php post_max_size broken
+- #1445172 by Moloc: Use drupal_unlink() instead unlink()
+
+Plupload integration 7.x-1.0-beta4
+==================================
+- #1230632 by ksenzee: Hard-coded file size limits.
+- #1219992 by slashrsm, axe312, Dave Reid: Add support for Drupal native translations.
+- #1111054 by George Petsagourakis: Convert plupload_fix_temporary_filename() a private function
+- #1316438 by jcfiala, slashrsm: Plupload in AJAX call causes form.submit handler to be added multiple times
+- #1300620 by jamiecuthill, ksenzee: Update to 1.5.1.1 because uploading is broken in Firefox 7
+- #1121070 by Moloc: Warning: unlink(...) [function.unlink]: Permission denied in plupload_handle_uploads()
+- #1348892 by slashrsm, Moloc: Show library version in status report
+- #1267190 by Moloc: Plupload transliteration support for d7
+- #1240654 by Dave Reid: Use a proper namespace for file_uri_to_object().
diff --git a/sites/all/modules/plupload/LICENSE.txt b/sites/all/modules/plupload/LICENSE.txt
new file mode 100644
index 000000000..d159169d1
--- /dev/null
+++ b/sites/all/modules/plupload/LICENSE.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/sites/all/modules/plupload/README.txt b/sites/all/modules/plupload/README.txt
new file mode 100644
index 000000000..4e83d0843
--- /dev/null
+++ b/sites/all/modules/plupload/README.txt
@@ -0,0 +1,89 @@
+This module integrates the Plupload library (available from http://plupload.com)
+with Drupal forms. To install the Plupload library:
+
+1. Download it (version 1.5.1.1 or later) from
+ https://github.com/moxiecode/plupload/releases Version 2.0.0
+ is currently unsupported. Latest 1.x.x version is 1.5.8, which can be
+ downloaded from https://github.com/moxiecode/plupload/archive/v1.5.8.zip.
+2. Unzip it into sites/all/libraries, so that there's a
+ sites/all/libraries/plupload/js/plupload.full.js file, in addition to the
+ other files included in the library.
+3. Remove "examples" folder from libraries folder as it could constitute a
+ security risk to your site. See http://drupal.org/node/1895328 and
+ http://drupal.org/node/1189632 for more info.
+
+If you would like to use an alternate library location, you can install the
+http://drupal.org/project/libraries module and/or add
+
+ $conf['plupload_library_path'] = PATH/TO/PLUPLOAD;
+
+to your settings.php file.
+
+At this time, this module only provides a 'plupload' form element type that
+other modules can use for providing multiple file upload capability to their
+forms. It does not provide any end-user functionality on its own. This may
+change, however, as this module evolves. See http://drupal.org/node/880300.
+
+---=== For developers ===---
+
+Plupload from element can be used like this:
+
+$form['my_element'] = array(
+ '#type' => 'plupload',
+ '#title' => t('Upload files'),
+ '#description' => t('This multi-upload widget uses Plupload library.'),
+ '#autoupload' => TRUE,
+ '#autosubmit' => TRUE,
+ '#submit_element' => '#id-of-your-submit-element',
+ '#upload_validators' => array(
+ 'file_validate_extensions' => array('jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'),
+ 'my_custom_file_validator' => array('some validation criteria'),
+ );
+ '#plupload_settings' => array(
+ 'runtimes' => 'html5',
+ 'chunk_size' => '1mb',
+ ),
+ '#event_callbacks' => array(
+ 'FilesAdded' => 'Drupal.mymodule.filesAddedCallback',
+ 'UploadComplete' => 'Drupal.mymodule.uploadCompleteCallback',
+ ),
+);
+
+There are few optional properties of this array that have special meaning:
+
+- #autoupload: set this to TRUE if you want Plupload to start uploading
+ immediately after files are added.
+ Defaults to FALSE.
+
+- #autosubmit: set this to TRUE if you want Plupload to autosubmit
+ your form after automatic upload has finished.
+ Defaults to FALSE.
+ Has to be used in combination with #autoupload.
+
+- #submit_element: specify which submit element Plupload shall use to submit
+ the form. Can also be used in combination with #autoupload and #autosubmit.
+ See: http://drupal.org/node/1935256
+
+- #upload_validators - an array of validation function/validation criteria pairs,
+ that will be passed to file_validate().
+ Defaults to:
+ '#upload_validators' => array(
+ 'file_validate_extensions' => array('jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'),
+ );
+
+- #plupload_settings - array of settings, that will be passed to Plupload library.
+ See: http://www.plupload.com/documentation.php
+ Defaults to:
+ '#plupload_settings' => array(
+ 'runtimes' => 'html5,flash,html4',
+ 'url' => url('plupload-handle-uploads', array('query' => array('plupload_token' => drupal_get_token('plupload-handle-uploads')))),
+ 'max_file_size' => file_upload_max_size() . 'b',
+ 'chunk_size' => '1mb',
+ 'unique_names' => TRUE,
+ 'flash_swf_url' => file_create_url($library_path . '/js/plupload.flash.swf'),
+ 'silverlight_xap_url' => file_create_url($library_path . '/js/plupload.silverlight.xap'),
+ ),
+
+- #event_callbacks - array of callbacks that will be passed to js.
+ See full documentation about events in Plupload library:
+ http://www.plupload.com/example_events.php
diff --git a/sites/all/modules/plupload/images/add.png b/sites/all/modules/plupload/images/add.png
new file mode 100644
index 000000000..1a2faf656
--- /dev/null
+++ b/sites/all/modules/plupload/images/add.png
Binary files differ
diff --git a/sites/all/modules/plupload/images/backgrounds.gif b/sites/all/modules/plupload/images/backgrounds.gif
new file mode 100644
index 000000000..39e33ebc0
--- /dev/null
+++ b/sites/all/modules/plupload/images/backgrounds.gif
Binary files differ
diff --git a/sites/all/modules/plupload/images/buttons-disabled.png b/sites/all/modules/plupload/images/buttons-disabled.png
new file mode 100644
index 000000000..afa11af9b
--- /dev/null
+++ b/sites/all/modules/plupload/images/buttons-disabled.png
Binary files differ
diff --git a/sites/all/modules/plupload/images/buttons.png b/sites/all/modules/plupload/images/buttons.png
new file mode 100644
index 000000000..153e73885
--- /dev/null
+++ b/sites/all/modules/plupload/images/buttons.png
Binary files differ
diff --git a/sites/all/modules/plupload/images/delete.gif b/sites/all/modules/plupload/images/delete.gif
new file mode 100644
index 000000000..78ca8b3b4
--- /dev/null
+++ b/sites/all/modules/plupload/images/delete.gif
Binary files differ
diff --git a/sites/all/modules/plupload/images/done.gif b/sites/all/modules/plupload/images/done.gif
new file mode 100644
index 000000000..29f3ed7c9
--- /dev/null
+++ b/sites/all/modules/plupload/images/done.gif
Binary files differ
diff --git a/sites/all/modules/plupload/images/error.gif b/sites/all/modules/plupload/images/error.gif
new file mode 100644
index 000000000..4682b6300
--- /dev/null
+++ b/sites/all/modules/plupload/images/error.gif
Binary files differ
diff --git a/sites/all/modules/plupload/images/icon-feed.png b/sites/all/modules/plupload/images/icon-feed.png
new file mode 100755
index 000000000..9523eaba6
--- /dev/null
+++ b/sites/all/modules/plupload/images/icon-feed.png
Binary files differ
diff --git a/sites/all/modules/plupload/images/throbber.gif b/sites/all/modules/plupload/images/throbber.gif
new file mode 100644
index 000000000..4ae8b16a5
--- /dev/null
+++ b/sites/all/modules/plupload/images/throbber.gif
Binary files differ
diff --git a/sites/all/modules/plupload/images/transp50.png b/sites/all/modules/plupload/images/transp50.png
new file mode 100644
index 000000000..eb0efe104
--- /dev/null
+++ b/sites/all/modules/plupload/images/transp50.png
Binary files differ
diff --git a/sites/all/modules/plupload/images/up_arrow.png b/sites/all/modules/plupload/images/up_arrow.png
new file mode 100644
index 000000000..36e00c249
--- /dev/null
+++ b/sites/all/modules/plupload/images/up_arrow.png
Binary files differ
diff --git a/sites/all/modules/plupload/images/up_arrow_disabled.png b/sites/all/modules/plupload/images/up_arrow_disabled.png
new file mode 100644
index 000000000..5233594a8
--- /dev/null
+++ b/sites/all/modules/plupload/images/up_arrow_disabled.png
Binary files differ
diff --git a/sites/all/modules/plupload/images/video-indicator.png b/sites/all/modules/plupload/images/video-indicator.png
new file mode 100644
index 000000000..d9eb1361c
--- /dev/null
+++ b/sites/all/modules/plupload/images/video-indicator.png
Binary files differ
diff --git a/sites/all/modules/plupload/js/i18n.js b/sites/all/modules/plupload/js/i18n.js
new file mode 100644
index 000000000..01f858401
--- /dev/null
+++ b/sites/all/modules/plupload/js/i18n.js
@@ -0,0 +1,41 @@
+/**
+ * @file
+ * Localization file for Plupload's strings.
+ */
+
+// Add translations.
+plupload.addI18n({
+ "Select files" : Drupal.t("Select files"),
+ "Add files to the upload queue and click the start button." : Drupal.t("Add files to the upload queue and click the start button."),
+ "Filename" : Drupal.t("Filename"),
+ "Status" : Drupal.t("Status"),
+ "Size" : Drupal.t("Size"),
+ "Add files" : Drupal.t("Add files"),
+ "Stop current upload" : Drupal.t("Stop current upload"),
+ "Start uploading queue" : Drupal.t("Start uploading queue"),
+ "Uploaded %d/%d files": Drupal.t("Uploaded %d/%d files"),
+ "N/A" : Drupal.t("N/A"),
+ "Drag files here." : Drupal.t("Drag files here."),
+ "File extension error.": Drupal.t("File extension error."),
+ "File size error.": Drupal.t("File size error."),
+ "Init error.": Drupal.t("Init error."),
+ "HTTP Error.": Drupal.t("HTTP Error."),
+ "Security error.": Drupal.t("Security error."),
+ "Generic error.": Drupal.t("Generic error."),
+ "IO error.": Drupal.t("IO error."),
+ "Start upload" : Drupal.t("Start upload"),
+ "Stop upload" : Drupal.t("Stop upload"),
+ "%d files queued" : Drupal.t("%d files queued"),
+ "Drag files here." : Drupal.t("Drag files here."),
+ "Start upload" : Drupal.t("Start upload"),
+ "%d files queued" : Drupal.t("%d files queued"),
+ "File: %s" : Drupal.t("File: %s"),
+ "Close" : Drupal.t("Close"),
+ "Using runtime: " : Drupal.t("Using runtime: "),
+ "File: %f, size: %s, max file size: %m" : Drupal.t("File: %f, size: %s, max file size: %m"),
+ "Upload element accepts only %d file(s) at a time. Extra files were stripped." : Drupal.t("Upload element accepts only %d file(s) at a time. Extra files were stripped."),
+ "Upload URL might be wrong or doesn\"t exist" : Drupal.t("Upload URL might be wrong or doesn\"t exist"),
+ "Error: File too large: " : Drupal.t("Error: File too large: "),
+ "Error: Invalid file extension: " : Drupal.t("Error: Invalid file extension: "),
+ "File count error." : Drupal.t("File count error.")
+});
diff --git a/sites/all/modules/plupload/plupload.css b/sites/all/modules/plupload/plupload.css
new file mode 100644
index 000000000..a8aae7a6f
--- /dev/null
+++ b/sites/all/modules/plupload/plupload.css
@@ -0,0 +1,204 @@
+
+.plupload_button {
+ display:inline-block;
+ font:normal 12px sans-serif;
+ text-decoration:none;
+ color:#42454a;
+ margin-right:4px;
+ outline:0;
+ -moz-border-radius:3px;
+ -khtml-border-radius:3px;
+ -webkit-border-radius:3px;
+ border-radius:3px;
+ font-family:"Lucida Grande", Verdana, sans-serif;
+ border:none;
+ background:none;
+ padding:2px 8px 3px 15px;
+}
+
+.plupload_button:hover {
+ color:#000;
+ text-decoration:none;
+}
+
+.plupload_disabled,a.plupload_disabled:hover {
+ cursor:default;
+ color:#737373;
+ background:transparent url(images/up_arrow_disabled.png) no-repeat 0 center;
+ border-color:#c5c5c5;
+}
+
+.plupload_add {
+ background-position:-181px center;
+ background:transparent url(images/add.png) no-repeat 0 center;
+}
+
+.plupload_wrapper {
+ font:normal 11px Verdana,sans-serif;
+ width:100%;
+ font-family:"Lucida Grande", Verdana, sans-serif;
+}
+
+.plupload_container {
+ background:url('images/transp50.png');
+}
+
+.plupload_container input {
+ border:1px solid #DDD;
+ font:normal 11px Verdana,sans-serif;
+ width:98%;
+ font-family:"Lucida Grande", Verdana, sans-serif;
+}
+
+.plupload_scroll .plupload_filelist {
+ height:135px;
+ overflow-y:scroll;
+ background:none;
+ list-style:none;
+ margin:0;
+ padding:0;
+}
+
+.plupload_filelist li {
+ background:#F5F5F5 url('images/backgrounds.gif') repeat-x 0 -156px;
+ border-bottom:1px solid #DDD;
+ padding:10px 8px;
+}
+
+.plupload_filelist_header,.plupload_filelist_footer {
+ background:#DFDFDF;
+ color:#42454A;
+ padding:6px 8px;
+}
+
+.plupload_filelist_header {
+ border-top:1px solid #EEE;
+ border-bottom:1px solid #CDCDCD;
+}
+
+.plupload_filelist_footer {
+ border-top:1px solid #FFF;
+ height:22px;
+ line-height:20px;
+ vertical-align:middle;
+}
+
+.plupload_file_name {
+ float:left;
+ overflow:hidden;
+}
+
+.plupload_file_status {
+ color:#777;
+}
+
+.plupload_file_status span {
+ color:#42454A;
+}
+
+.plupload_file_size,.plupload_file_status,.plupload_progress {
+ float:right;
+ width:80px;
+}
+
+.plupload_file_size,.plupload_file_status,.plupload_file_action {
+ text-align:right;
+}
+
+.plupload_filelist .plupload_file_name {
+ width:205px;
+}
+
+.plupload_file_action {
+ float:right;
+ width:16px;
+ height:16px;
+ margin-left:15px;
+}
+
+.plupload_file_action * {
+ display:none;
+ width:16px;
+ height:16px;
+}
+
+ li.plupload_uploading {
+ background:#ECF3DC url('images/backgrounds.gif') repeat-x 0 -238px;
+}
+
+ li.plupload_done {
+ color:#AAA;
+}
+
+ li.plupload_delete a {
+ background:url('images/delete.gif');
+}
+
+ li.plupload_failed a {
+ background:url('images/error.gif');
+ cursor:default;
+}
+
+ li.plupload_done a {
+ background:url('images/done.gif');
+ cursor:default;
+}
+
+.plupload_progress,.plupload_upload_status {
+ display:none;
+}
+
+.plupload_progress_container {
+ margin-top:3px;
+ border:1px solid #CCC;
+ background:#FFF;
+ padding:1px;
+}
+
+.plupload_progress_bar {
+ width:0;
+ height:7px;
+ background:#CDEB8B;
+}
+
+.plupload_scroll .plupload_filelist_header .plupload_file_action,.plupload_scroll .plupload_filelist_footer .plupload_file_action {
+ margin-right:17px;
+}
+
+.plupload_clear,.plupload_clearer {
+ clear:both;
+}
+
+.plupload_clearer,.plupload_progress_bar {
+ display:block;
+ font-size:0;
+ line-height:0;
+}
+
+li.plupload_droptext {
+ background:transparent;
+ text-align:center;
+ vertical-align:middle;
+ border:0;
+ line-height:115px;
+ list-style-type:none;
+}
+
+.plupload {
+ border:solid 1px #ccc;
+}
+
+.plupload_header {
+ display:none;
+}
+
+.plupload_button,.plupload_button:hover {
+ color:#0074bd;
+ padding-bottom:0;
+ margin-bottom:0;
+}
+
+.plupload_start,a.plupload_start:hover {
+ background:transparent url(images/up_arrow.png) no-repeat 0 center;
+ z-index:100000;
+} \ No newline at end of file
diff --git a/sites/all/modules/plupload/plupload.info b/sites/all/modules/plupload/plupload.info
new file mode 100644
index 000000000..3aae9daa6
--- /dev/null
+++ b/sites/all/modules/plupload/plupload.info
@@ -0,0 +1,12 @@
+name = Plupload integration module
+description = Provides a plupload element.
+files[] = plupload.module
+core = 7.x
+package = Media
+
+; Information added by Drupal.org packaging script on 2014-11-07
+version = "7.x-1.7"
+core = "7.x"
+project = "plupload"
+datestamp = "1415390716"
+
diff --git a/sites/all/modules/plupload/plupload.install b/sites/all/modules/plupload/plupload.install
new file mode 100644
index 000000000..85cddda6a
--- /dev/null
+++ b/sites/all/modules/plupload/plupload.install
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the Plupload module.
+ */
+
+/**
+ * Implements hook_requirements().
+ */
+function plupload_requirements($phase) {
+ $requirements = array();
+ $t = get_t();
+
+ if ($phase == 'runtime') {
+ $requirements['plupload'] = array(
+ 'title' => $t('Plupload library'),
+ 'value' => $t('Unknown'),
+ );
+ $requirements['plupload']['severity'] = REQUIREMENT_OK;
+ $libraries = plupload_library();
+ $library = $libraries['plupload'];
+
+ // Check if Plupload library exists. Try to determine it's version
+ // if it does.
+ if (!_plupload_requirements_installed()) {
+ $message = 'The <a href="@url">@title</a> library (version @version or higher) is not installed.';
+ $args = array(
+ '@title' => $library['title'],
+ '@url' => url($library['website']),
+ '@version' => $library['version'],
+ );
+
+ $requirements['plupload']['description'] = $t($message, $args);
+ $requirements['plupload']['severity'] = REQUIREMENT_ERROR;
+ }
+ elseif (($installed_version = _plupload_requirements_version()) === NULL) {
+ $requirements['plupload']['description'] = $t('Plupload version could not be determined.');
+ $requirements['plupload']['severity'] = REQUIREMENT_INFO;
+ }
+ elseif (!version_compare($library['version'], $installed_version, '<=')) {
+ $requirements['plupload']['description'] = $t('Plupload @version or higher is required.', array('@version' => $library['version']));
+ $requirements['plupload']['severity'] = REQUIREMENT_INFO;
+ }
+
+ $requirements['plupload']['value'] = empty($installed_version) ? $t('Not found') : $installed_version;
+
+ if (file_exists(_plupload_library_path() . '/examples/upload.php')) {
+ $requirements['plupload_examples'] = array(
+ 'title' => $t('Plupload example folder'),
+ 'value' => $t('Example folder found'),
+ 'description' => $t('Plupload library contains example files, these could constitute a security risk to your site as per <a href="!url">PSA-2011-02</a>. Please remove the !path folder immediately.', array(
+ '!url' => 'http://drupal.org/node/1189632',
+ '!path' => _plupload_library_path() . '/examples'
+ )),
+ 'severity' => REQUIREMENT_ERROR
+ );
+ }
+ }
+
+ return $requirements;
+}
+
+/**
+ * Checks wether Plupload library exists or not.
+ *
+ * @return boolean
+ * TRUE if plupload library installed, FALSE otherwise.
+ */
+function _plupload_requirements_installed() {
+ $libraries = plupload_library();
+ $library = $libraries['plupload'];
+
+ // We grab the first file and check if it exists.
+ $testfile = key($library['js']);
+ if (!file_exists($testfile)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Returns the version of the installed plupload library.
+ *
+ * @return string
+ * The version of installed Plupload or NULL if unable to detect version.
+ */
+function _plupload_requirements_version() {
+ $library_path = _plupload_library_path();
+ $jspath = $library_path . '/js/plupload.js';
+
+ // Read contents of Plupload's javascript file.
+ $configcontents = @file_get_contents($jspath);
+ if (!$configcontents) {
+ return NULL;
+ }
+
+ // Search for version string using a regular expression.
+ $matches = array();
+ if (preg_match('#VERSION:\"(\d+[\.\d+]*)\"#', $configcontents, $matches)) {
+ return $matches[1];
+ }
+
+ // After 1.5.8 Plupload stopped adding version string to .js file. Let's check
+ // first line of changelog.txt.
+ $library_path = _plupload_library_path();
+ $clpath = $library_path . '/changelog.txt';
+
+ $configcontents = @file_get_contents($clpath);
+ if (!$configcontents) {
+ return NULL;
+ }
+
+ $lines = explode("\n", $configcontents);
+
+ if (preg_match('#^Version (\d+[\.\d+]*)#', $lines[0], $matches)) {
+ return $matches[1];
+ }
+
+ return NULL;
+}
diff --git a/sites/all/modules/plupload/plupload.js b/sites/all/modules/plupload/plupload.js
new file mode 100644
index 000000000..91a5c6b21
--- /dev/null
+++ b/sites/all/modules/plupload/plupload.js
@@ -0,0 +1,178 @@
+(function($) {
+
+Drupal.plupload = Drupal.plupload || {};
+// Add Plupload events for autoupload and autosubmit.
+Drupal.plupload.filesAddedCallback = function (up, files) {
+ setTimeout(function(){up.start()}, 100);
+};
+Drupal.plupload.uploadCompleteCallback = function(up, files) {
+ var $this = $("#"+up.settings.container);
+ // If there is submit_element trigger it.
+ var submit_element = window.Drupal.settings.plupload[$this.attr('id')].submit_element;
+ if (submit_element) {
+ $(submit_element).click();
+ }
+ // Otherwise submit default form.
+ else {
+ var $form = $this.parents('form');
+ $($form[0]).submit();
+ }
+};
+/**
+ * Attaches the Plupload behavior to each Plupload form element.
+ */
+Drupal.behaviors.plupload = {
+ attach: function (context, settings) {
+ $(".plupload-element", context).once('plupload-init', function () {
+ var $this = $(this);
+
+ // Merge the default settings and the element settings to get a full
+ // settings object to pass to the Plupload library for this element.
+ var id = $this.attr('id');
+ var defaultSettings = settings.plupload['_default'] ? settings.plupload['_default'] : {};
+ var elementSettings = (id && settings.plupload[id]) ? settings.plupload[id] : {};
+ var pluploadSettings = $.extend({}, defaultSettings, elementSettings);
+
+ // Process Plupload events.
+ if (elementSettings['init'] || false) {
+ if (!pluploadSettings.init) {
+ pluploadSettings.init = {};
+ }
+ for (var key in elementSettings['init']) {
+ var callback = elementSettings['init'][key].split('.');
+ var fn = window;
+ for (var j = 0; j < callback.length; j++) {
+ fn = fn[callback[j]];
+ }
+ if (typeof fn === 'function') {
+ pluploadSettings.init[key] = fn;
+ }
+ }
+ }
+ // Initialize Plupload for this element.
+ $this.pluploadQueue(pluploadSettings);
+
+ });
+ }
+};
+
+ /**
+ * Attaches the Plupload behavior to each Plupload form element.
+ */
+Drupal.behaviors.pluploadform = {
+ attach: function(context, settings) {
+ $('form', context).once('plupload-form', function() {
+ if (0 < $(this).find('.plupload-element').length) {
+ var $form = $(this);
+ var originalFormAttributes = {
+ 'method': $form.attr('method'),
+ 'enctype': $form.attr('enctype'),
+ 'action': $form.attr('action'),
+ 'target': $form.attr('target')
+ };
+
+ $(this).submit(function(e) {
+ var completedPluploaders = 0;
+ var totalPluploaders = $(this).find('.plupload-element').length;
+ var errors = '';
+
+ $(this).find('.plupload-element').each( function(index){
+ var uploader = $(this).pluploadQueue();
+
+ var id = $(this).attr('id');
+ var defaultSettings = settings.plupload['_default'] ? settings.plupload['_default'] : {};
+ var elementSettings = (id && settings.plupload[id]) ? settings.plupload[id] : {};
+ var pluploadSettings = $.extend({}, defaultSettings, elementSettings);
+
+ //Only allow the submit to proceed if there are files and they've all
+ //completed uploading.
+ //TODO: Implement a setting for whether the field is required, rather
+ //than assuming that all are.
+ if (uploader.state == plupload.STARTED) {
+ errors += Drupal.t("Please wait while your files are being uploaded.");
+ }
+ else if (uploader.files.length == 0 && !pluploadSettings.required) {
+ completedPluploaders++;
+ }
+
+ else if (uploader.files.length == 0) {
+ errors += Drupal.t("@index: You must upload at least one file.\n",{'@index': (index + 1)});
+ }
+
+ else if (uploader.files.length > 0 && uploader.total.uploaded == uploader.files.length) {
+ completedPluploaders++;
+ }
+
+ else {
+ var stateChangedHandler = function() {
+ if (uploader.total.uploaded == uploader.files.length) {
+ uploader.unbind('StateChanged', stateChangedHandler);
+ completedPluploaders++;
+ if (completedPluploaders == totalPluploaders ) {
+ //Plupload's html4 runtime has a bug where it changes the
+ //attributes of the form to handle the file upload, but then
+ //fails to change them back after the upload is finished.
+ for (var attr in originalFormAttributes) {
+ $form.attr(attr, originalFormAttributes[attr]);
+ }
+ // Click a specific element if one is specified.
+ if (settings.plupload[id].submit_element) {
+ $(settings.plupload[id].submit_element).click();
+ }
+ else {
+ $form.submit();
+ }
+ return true;
+ }
+ }
+ };
+ uploader.bind('StateChanged', stateChangedHandler);
+ uploader.start();
+ }
+
+ });
+ if (completedPluploaders == totalPluploaders) {
+ //Plupload's html4 runtime has a bug where it changes the
+ //attributes of the form to handle the file upload, but then
+ //fails to change them back after the upload is finished.
+ for (var attr in originalFormAttributes) {
+ $form.attr(attr, originalFormAttributes[attr]);
+ }
+ return true;
+ }
+ else if (0 < errors.length){
+ alert(errors);
+ }
+
+ return false;
+ });
+ }
+ });
+ }
+};
+
+
+/**
+ * Helper function to compare version strings.
+ *
+ * Returns one of:
+ * - A negative integer if a < b.
+ * - A positive integer if a > b.
+ * - 0 if a == b.
+ */
+Drupal.plupload.compareVersions = function (a, b) {
+ a = a.split('.');
+ b = b.split('.');
+ // Return the most significant difference, if there is one.
+ for (var i=0; i < Math.min(a.length, b.length); i++) {
+ var compare = parseInt(a[i]) - parseInt(b[i]);
+ if (compare != 0) {
+ return compare;
+ }
+ }
+ // If the common parts of the two version strings are equal, the greater
+ // version number is the one with the most sections.
+ return a.length - b.length;
+}
+
+})(jQuery);
diff --git a/sites/all/modules/plupload/plupload.make b/sites/all/modules/plupload/plupload.make
new file mode 100644
index 000000000..1c6463103
--- /dev/null
+++ b/sites/all/modules/plupload/plupload.make
@@ -0,0 +1,9 @@
+api = 2
+core = 7.x
+
+; Libraries
+libraries[plupload][directory_name] = plupload
+libraries[plupload][download][type] = file
+libraries[plupload][download][url] = https://github.com/moxiecode/plupload/archive/v1.5.8.zip
+libraries[plupload][patch][1903850] = https://drupal.org/files/issues/plupload-1_5_8-rm_examples-1903850-16.patch
+libraries[plupload][type] = library
diff --git a/sites/all/modules/plupload/plupload.module b/sites/all/modules/plupload/plupload.module
new file mode 100644
index 000000000..e187f7a57
--- /dev/null
+++ b/sites/all/modules/plupload/plupload.module
@@ -0,0 +1,523 @@
+<?php
+
+/**
+ * @file
+ * Implementation of plupload.module.
+ */
+
+/**
+ * Implements hook_menu().
+ */
+function plupload_menu() {
+ $items['plupload-handle-uploads'] = array(
+ 'title' => 'Handles uploads',
+ 'page callback' => 'plupload_handle_uploads',
+ 'type' => MENU_CALLBACK,
+ 'access callback' => 'plupload_upload_access',
+ 'access arguments' => array('access content'),
+ );
+ $items['plupload-test'] = array(
+ 'title' => 'Test Plupload',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('plupload_test'),
+ // @todo: change this to something appropriate, not sure what.
+ 'access arguments' => array('Administer site configuration'),
+ 'type' => MENU_CALLBACK,
+ );
+ return $items;
+}
+
+/**
+ * Verifies the token for this request.
+ */
+function plupload_upload_access() {
+ foreach (func_get_args() as $permission) {
+ if (!user_access($permission)) {
+ return FALSE;
+ }
+ }
+ return !empty($_REQUEST['plupload_token']) && drupal_valid_token($_REQUEST['plupload_token'], 'plupload-handle-uploads');
+}
+
+/**
+ * Form callback function for test page visible at URL "plupload-test".
+ */
+function plupload_test($form, &$form_state) {
+ $form['pud'] = array(
+ '#type' => 'plupload',
+ '#title' => 'Plupload',
+ // '#validators' => array(...);
+ );
+
+ $form['submit'] = array(
+ '#type' => 'submit',
+ '#value' => 'Submit',
+ );
+
+ return $form;
+}
+
+/**
+ * Submit callback for plupload_test form.
+ */
+function plupload_test_submit($form, &$form_state) {
+ $saved_files = array();
+ $scheme = variable_get('file_default_scheme', 'public') . '://';
+ // We can't use file_save_upload() because of
+ // http://www.jacobsingh.name/content/tight-coupling-no-not
+ // file_uri_to_object();
+ foreach ($form_state['values']['pud'] as $uploaded_file) {
+ if ($uploaded_file['status'] == 'done') {
+ $source = $uploaded_file['tmppath'];
+ $destination = file_stream_wrapper_uri_normalize($scheme . $uploaded_file['name']);
+ // Rename it to its original name, and put it in its final home.
+ // Note - not using file_move here because if we call file_get_mime
+ // (in file_uri_to_object) while it has a .tmp extension, it horks.
+ $destination = file_unmanaged_move($source, $destination, FILE_EXISTS_RENAME);
+ $file = plupload_file_uri_to_object($destination);
+ file_save($file);
+ $saved_files[] = $file;
+ }
+ else {
+ // @todo: move this to element validate or something and clean up t().
+ form_set_error('pud', "Upload of {$uploaded_file['name']} failed");
+ }
+ }
+}
+
+/**
+ * Implements hook_element_info().
+ */
+function plupload_element_info() {
+ $types = array();
+ $module_path = drupal_get_path('module', 'plupload');
+ $types['plupload'] = array(
+ '#input' => TRUE,
+ '#attributes' => array('class' => array('plupload-element')),
+ // @todo
+ // '#element_validate' => array('file_managed_file_validate'),
+ '#theme_wrappers' => array('form_element'),
+ '#theme' => 'container',
+ '#value_callback' => 'plupload_element_value',
+ '#attached' => array(
+ 'library' => array(array('plupload', 'plupload')),
+ 'js' => array($module_path . '/plupload.js'),
+ 'css' => array($module_path . '/plupload.css'),
+ ),
+ '#process' => array('plupload_element_process'),
+ '#element_validate' => array('plupload_element_validate'),
+ '#pre_render' => array('plupload_element_pre_render'),
+ );
+ return $types;
+}
+
+/**
+ * Validate callback for plupload form element.
+ */
+function plupload_element_value(&$element, $input = FALSE, $form_state = NULL) {
+ $id = $element['#id'];
+ // If a unique identifier added with '--', we need to exclude it
+ if(preg_match('/(.*)(--[0-9]+)$/', $id, $reg)) {
+ $id = $reg[1];
+ }
+ $files = array();
+ foreach ($form_state['input'] as $key => $value) {
+ if (preg_match('/' . $id . '_([0-9]+)_(.*)/', $key, $reg)) {
+ $i = $reg[1];
+ $key = $reg[2];
+
+ // Only add the keys we expect.
+ if (!in_array($key, array('tmpname', 'name', 'status'))) {
+ continue;
+ }
+
+ // Munge the submitted file names for security.
+ //
+ // Similar munging is normally done by file_save_upload(), but submit
+ // handlers for forms containing plupload elements can't use
+ // file_save_upload(), for reasons discussed in plupload_test_submit().
+ // So we have to do this for them.
+ //
+ // Note that we do the munging here in the value callback function
+ // (rather than during form validation or elsewhere) because we want to
+ // actually modify the submitted values rather than reject them outright;
+ // file names that require munging can be innocent and do not necessarily
+ // indicate an attempted exploit. Actual validation of the file names is
+ // performed later, in plupload_element_validate().
+ if (in_array($key, array('tmpname', 'name'))) {
+ // Find the whitelist of extensions to use when munging. If there are
+ // none, we'll be adding default ones in plupload_element_process(), so
+ // use those here.
+ if (isset($element['#upload_validators']['file_validate_extensions'][0])) {
+ $extensions = $element['#upload_validators']['file_validate_extensions'][0];
+ }
+ else {
+ $validators = _plupload_default_upload_validators();
+ $extensions = $validators['file_validate_extensions'][0];
+ }
+ $value = file_munge_filename($value, $extensions, FALSE);
+ // To prevent directory traversal issues, make sure the file name does
+ // not contain any directory components in it. (This more properly
+ // belongs in the form validation step, but it's simpler to do here so
+ // that we don't have to deal with the temporary file names during form
+ // validation and can just focus on the final file name.)
+ //
+ // This step is necessary since this module allows a large amount of
+ // flexibility in where its files are placed (for example, they could
+ // be intended for public://subdirectory rather than public://, and we
+ // don't want an attacker to be able to get them back into the top
+ // level of public:// in that case).
+ $value = rtrim(drupal_basename($value), '.');
+
+
+ // Based on the same feture from file_save_upload().
+ if (!variable_get('allow_insecure_uploads', 0) && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $value) && (substr($value, -4) != '.txt')) {
+ $value .= '.txt';
+
+ // The .txt extension may not be in the allowed list of extensions.
+ // We have to add it here or else the file upload will fail.
+ if (!empty($extensions)) {
+ $element['#upload_validators']['file_validate_extensions'][0] .= ' txt';
+ drupal_set_message(t('For security reasons, your upload has been renamed to %filename.', array('%filename' => $value)));
+ }
+ }
+ }
+
+ // The temporary file name has to be processed further so it matches what
+ // was used when the file was written; see plupload_handle_uploads().
+ if ($key == 'tmpname') {
+ $value = _plupload_fix_temporary_filename($value);
+ // We also define an extra key 'tmppath' which is useful so that submit
+ // handlers do not need to know which directory plupload stored the
+ // temporary files in before trying to copy them.
+ $files[$i]['tmppath'] = variable_get('plupload_temporary_uri', 'temporary://') . $value;
+ }
+ elseif ($key == 'name') {
+ if (module_exists('transliteration') && variable_get('transliteration_file_uploads', TRUE)) {
+ $value = transliteration_clean_filename($value);
+ }
+ }
+
+ // Store the final value in the array we will return.
+ $files[$i][$key] = $value;
+ }
+ }
+ return $files;
+}
+
+/**
+ * Process callback (#process) for plupload form element.
+ */
+function plupload_element_process($element) {
+ // Start session if not there yet. We need session if we want security
+ // tokens to work properly.
+ if (!drupal_session_started()) {
+ drupal_session_start();
+ }
+
+ if (!isset($element['#upload_validators'])) {
+ $element['#upload_validators'] = array();
+ }
+ $element['#upload_validators'] += _plupload_default_upload_validators();
+ return $element;
+}
+
+/**
+ * Element validation handler for a Plupload element.
+ */
+function plupload_element_validate($element, &$form_state) {
+ foreach ($element['#value'] as $file_info) {
+ // Here we create a $file object for a file that doesn't exist yet,
+ // because saving the file to its destination is done in a submit handler.
+ // Using tmp path will give validators access to the actual file on disk and
+ // filesize information. We manually modify filename and mime to allow
+ // extension checks.
+ $file = plupload_file_uri_to_object($file_info['tmppath']);
+
+ $destination = variable_get('file_default_scheme', 'public') . '://' . $file_info['name'];
+ $destination = file_stream_wrapper_uri_normalize($destination);
+ $file->filename = drupal_basename($destination);
+ $file->filemime = file_get_mimetype($destination);
+
+ foreach (file_validate($file, $element['#upload_validators']) as $error_message) {
+ $message = t('The specified file %name could not be uploaded.', array('%name' => $file->filename));
+ form_error($element, $message . ' ' . $error_message);
+ }
+ }
+}
+
+/**
+ * Pre render (#pre_render) callback to attach JS settings for the element.
+ */
+function plupload_element_pre_render($element) {
+ $settings = isset($element['#plupload_settings']) ? $element['#plupload_settings'] : array();
+
+ // The Plupload library supports client-side validation of file extension, so
+ // pass along the information for it to do that. However, as with all client-
+ // side validation, this is a UI enhancement only, and not a replacement for
+ // server-side validation.
+ if (empty($settings['filters']) && isset($element['#upload_validators']['file_validate_extensions'][0])) {
+ $settings['filters'][] = array(
+ // @todo Some runtimes (e.g., flash) require a non-empty title for each
+ // filter, but I don't know what this title is used for. Seems a shame
+ // to hard-code it, but what's a good way to avoid that?
+ 'title' => t('Allowed files'),
+ 'extensions' => str_replace(' ', ',', $element['#upload_validators']['file_validate_extensions'][0]),
+ );
+ }
+ // Check for autoupload and autosubmit settings and add appropriate callback.
+ if (!empty($element['#autoupload'])) {
+ $settings['init']['FilesAdded'] = 'Drupal.plupload.filesAddedCallback';
+ if (!empty($element['#autosubmit'])) {
+ $settings['init']['UploadComplete'] = 'Drupal.plupload.uploadCompleteCallback';
+ }
+ }
+ // Add a specific submit element that we want to click if one is specified.
+ if (!empty($element['#submit_element'])) {
+ $settings['submit_element'] = $element['#submit_element'];
+ }
+ // Check if there are event callbacks and append them to current ones, if any.
+ if (!empty($element['#event_callbacks'])) {
+ // array_merge() only accepts parameters of type array.
+ if (!isset($settings['init'])) {
+ $settings['init'] = array();
+ }
+ $settings['init'] = array_merge($settings['init'], $element['#event_callbacks']);
+ }
+
+ if (empty($element['#description'])) {
+ $element['#description'] = '';
+ }
+ $element['#description'] = theme('file_upload_help', array('description' => $element['#description'], 'upload_validators' => $element['#upload_validators']));
+
+ $element['#attached']['js'][] = array(
+ 'type' => 'setting',
+ 'data' => array('plupload' => array($element['#id'] => $settings)),
+ );
+
+ return $element;
+}
+
+/**
+ * Returns the path to the plupload library.
+ */
+function _plupload_library_path() {
+ return variable_get('plupload_library_path', module_exists('libraries') ? libraries_get_path('plupload') : 'sites/all/libraries/plupload');
+}
+
+/**
+ * Implements hook_library().
+ */
+function plupload_library() {
+ $library_path = _plupload_library_path();
+ $libraries['plupload'] = array(
+ 'title' => 'Plupload',
+ 'website' => 'http://www.plupload.com',
+ 'version' => '1.5.1.1',
+ 'js' => array(
+ // @todo - only add gears JS if gears is an enabled runtime.
+ // $library_path . '/js/gears_init.js' => array(),
+ $library_path . '/js/jquery.plupload.queue/jquery.plupload.queue.js' => array(),
+ $library_path . '/js/plupload.full.js' => array(),
+ 0 => array(
+ 'type' => 'setting',
+ 'data' => array(
+ 'plupload' => array(
+ // Element-specific settings get keyed by the element id (see
+ // plupload_element_pre_render()), so put default settings in
+ // '_default' (Drupal element ids do not have underscores, because
+ // they have hyphens instead).
+ '_default' => array(
+ // @todo Provide a settings page for configuring these.
+ 'runtimes' => 'html5,flash,html4',
+ 'url' => url('plupload-handle-uploads', array('query' => array('plupload_token' => drupal_get_token('plupload-handle-uploads')))),
+ 'max_file_size' => file_upload_max_size() . 'b',
+ 'chunk_size' => parse_size(ini_get('post_max_size')) . 'b',
+ 'unique_names' => TRUE,
+ 'flash_swf_url' => file_create_url($library_path . '/js/plupload.flash.swf'),
+ 'silverlight_xap_url' => file_create_url($library_path . '/js/plupload.silverlight.xap'),
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+
+ if (module_exists('locale')) {
+ $module_path = drupal_get_path('module', 'plupload');
+ $libraries['plupload']['js'][$module_path . '/js/i18n.js'] = array('scope' => 'footer');
+ }
+
+ return $libraries;
+}
+
+/**
+ * Callback that handles and saves uploaded files.
+ *
+ * This will respond to the URL on which plupoad library will upload files.
+ */
+function plupload_handle_uploads() {
+ // @todo: Implement file_validate_size();
+ // Added a variable for this because in HA environments, temporary may need
+ // to be a shared location for this to work.
+ $temp_directory = variable_get('plupload_temporary_uri', 'temporary://');
+ $writable = file_prepare_directory($temp_directory, FILE_CREATE_DIRECTORY);
+ if (!$writable) {
+ die('{"jsonrpc" : "2.0", "error" : {"code": 104, "message": "Failed to open temporary directory."}, "id" : "id"}');
+ }
+ // Try to make sure this is private via htaccess.
+ file_create_htaccess($temp_directory, TRUE);
+
+ // Chunk it?
+ $chunk = isset($_REQUEST["chunk"]) ? $_REQUEST["chunk"] : 0;
+
+ // Get and clean the filename.
+ $file_name = isset($_REQUEST["name"]) ? $_REQUEST["name"] : '';
+ $file_name = _plupload_fix_temporary_filename($file_name);
+
+ // Check the file name for security reasons; it must contain letters, numbers
+ // and underscores followed by a (single) ".tmp" extension. Since this check
+ // is more stringent than the one performed in plupload_element_value(), we
+ // do not need to run the checks performed in that function here. This is
+ // fortunate, because it would be difficult for us to get the correct list of
+ // allowed extensions to pass in to file_munge_filename() from this point in
+ // the code (outside the form API).
+ if (empty($file_name) || !preg_match('/^\w+\.tmp$/', $file_name)) {
+ die('{"jsonrpc" : "2.0", "error" : {"code": 105, "message": "Invalid temporary file name."}, "id" : "id"}');
+ }
+
+ // Look for the content type header.
+ if (isset($_SERVER["HTTP_CONTENT_TYPE"])) {
+ $content_type = $_SERVER["HTTP_CONTENT_TYPE"];
+ }
+ if (isset($_SERVER["CONTENT_TYPE"])) {
+ $content_type = $_SERVER["CONTENT_TYPE"];
+ }
+
+ // Is this a multipart upload?.
+ if (strpos($content_type, "multipart") !== FALSE) {
+ if (isset($_FILES['file']['tmp_name']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
+ // Open temp file.
+ $out = fopen($temp_directory . $file_name, $chunk == 0 ? "wb" : "ab");
+ if ($out) {
+ // Read binary input stream and append it to temp file.
+ $in = fopen($_FILES['file']['tmp_name'], "rb");
+
+ if ($in) {
+ while ($buff = fread($in, 4096)) {
+ fwrite($out, $buff);
+ }
+ fclose($in);
+ }
+ else {
+ die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
+ }
+
+ fclose($out);
+ drupal_unlink($_FILES['file']['tmp_name']);
+ }
+ else {
+ die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
+ }
+ }
+ else {
+ die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
+ }
+ }
+ else {
+ // Open temp file.
+ $out = fopen($temp_directory . $file_name, $chunk == 0 ? "wb" : "ab");
+ if ($out) {
+ // Read binary input stream and append it to temp file.
+ $in = fopen("php://input", "rb");
+
+ if ($in) {
+ while ($buff = fread($in, 4096)) {
+ fwrite($out, $buff);
+ }
+ fclose($in);
+ }
+ else {
+ die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
+ }
+
+ fclose($out);
+ }
+ else {
+ die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
+ }
+ }
+
+ // Return JSON-RPC response.
+ die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}');
+}
+
+/**
+ * Returns a file object which can be passed to file_save().
+ *
+ * @param string $uri
+ * A string containing the URI, path, or filename.
+ *
+ * @return boolean
+ * A file object, or FALSE on error.
+ *
+ * @todo Replace with calls to this function with file_uri_to_object() when
+ * http://drupal.org/node/685818 is fixed in core.
+ */
+function plupload_file_uri_to_object($uri) {
+ global $user;
+ $uri = file_stream_wrapper_uri_normalize($uri);
+ $wrapper = file_stream_wrapper_get_instance_by_uri($uri);
+ $file = new StdClass();
+ $file->uid = $user->uid;
+ $file->filename = drupal_basename($uri);
+ $file->uri = $uri;
+ $file->filemime = file_get_mimetype($uri);
+ // This is gagged because some uris will not support it.
+ $file->filesize = @filesize($uri);
+ $file->timestamp = REQUEST_TIME;
+ $file->status = FILE_STATUS_PERMANENT;
+ return $file;
+}
+
+/**
+ * Fix the temporary filename provided by the plupload library.
+ *
+ * Newer versions of the plupload JavaScript library upload temporary files
+ * with names that contain the intended final prefix of the uploaded file
+ * (e.g., ".jpg" or ".png"). Older versions of the plupload library always use
+ * ".tmp" as the temporary file extension.
+ *
+ * We prefer the latter behavior, since although the plupload temporary
+ * directory where these files live is always expected to be private (and we
+ * protect it via .htaccess; see plupload_handle_uploads()), in case it ever
+ * isn't we don't want people to be able to upload files with an arbitrary
+ * extension into that directory.
+ *
+ * This function therefore fixes the plupload temporary filenames so that they
+ * will always use a ".tmp" extension.
+ *
+ * @param string $filename
+ * The original temporary filename provided by the plupload library.
+ *
+ * @return string
+ * The corrected temporary filename, with a ".tmp" extension replacing the
+ * original one.
+ */
+function _plupload_fix_temporary_filename($filename) {
+ $pos = strpos($filename, '.');
+ if ($pos !== FALSE) {
+ $filename = substr_replace($filename, '.tmp', $pos);
+ }
+ return $filename;
+}
+
+/**
+ * Helper function to add defaults to $element['#upload_validators'].
+ */
+function _plupload_default_upload_validators() {
+ return array(
+ // See file_save_upload() for details.
+ 'file_validate_extensions' => array('jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'),
+ );
+}