Build.PL100644000765000024 45515124606754 15663 0ustar00askastaff000000000000WebService-Dropbox-2.10# ========================================================================= # THIS FILE IS AUTOMATICALLY GENERATED BY MINILLA. # DO NOT EDIT DIRECTLY. # ========================================================================= use 5.008_001; use strict; use Module::Build::Tiny 0.035; Build_PL(); Changes100644000765000024 516715124606754 15707 0ustar00askastaff000000000000WebService-Dropbox-2.10Revision history for Perl extension WebService::Dropbox 2.10 2025-12-29T23:25:29Z - Add support for delete_batch and delete_batch_check 2.09 2021-06-15T07:56:02Z - Add shared for README.md 2.08 2021-06-15T16:27:00Z - Add WebService::Dropbox::Sharing (softwrx) 2.07 2017-05-31T11:23:05Z - Fix verbose for with Furl 2.06 2017-05-31T09:51:08Z - Update cpanfile 2.05 2016-07-11T14:57:28Z - Check Furl::VERSION 2.04 2016-07-04T09:49:40Z - Add migration guide 2.03 2016-07-04T09:30:07Z - Support perl 5.8 2.02 2016-07-03T05:07:22Z - Fix CPAN Testers 2.01 2016-07-02T19:06:18Z - Fix document format 2.00 2016-07-02T17:14:48Z - migrate API v2 1.22 2014-10-07T09:12:06Z - support WebService::Dropbox#files's error 1.21 2013-10-01T04:06:00Z - added HTTP::Message for the cpanfile 1.20 2013-09-30T10:00:21Z - minil migrate 1.19 Mon Sep 30 15:33:45 JST 2013 - remove MYMETA and .gitignore (charsbar) 1.18 Thu Jul 25 16:09:16 JST 2013 - wrong return precedence (Reini Urban) 1.17 Thu Feb 7 17:35:27 JST 2013 - add range header (rosti) 1.16 Tue Jan 15 22:35:58 JST 2013 - add binmode (venomo9) 1.15 Mon Jan 7 20:22:12 JST 2013 - fix utf8 filename bug - support furl's env_proxy 1.14 Sun Jan 6 07:19:10 JST 2013 - No warnings, more security (gfx) 1.13 Thu Oct 18 17:23:40 JST 2012 - remove require String::Random 1.12 Tue Oct 16 18:04:23 JST 2012 - add require IO::Socket::SSL 1.11 Fri Oct 12 17:42:46 JST 2012 - add require URI.pm 1.60 ( include URI::Escape ) 1.10 Tue Oct 9 10:26:08 JST 2012 - signature_method HMAC-SHA1 to PLAINTEXT ( delete %20.txt bug :/ ) 1.09 Mon Aug 27 22:33:01 JST 2012 - add files_put_chunked method - add chunked_upload method - add commit_chunked_upload method 1.07 Fri Jun 29 03:58:56 JST 2012 - add delta method - add $ua->env_proxy 1.06 Fri Mar 30 13:36:58 JST 2012 - do not do decode_json at the time of an error 1.05 Wed Jan 18 12:44:01 JST 2012 - default timeout 10sec => 1day 1.04 Fri Jan 6 17:56:59 JST 2012 - add root document. 0.06 Thu Dec 1 15:41:20 JST 2011 - fix typo, thanks (wata) 0.05 Thu Dec 1 15:41:20 JST 2011 - add require Furl or LWP 0.04 Tue Nov 29 11:23:39 JST 2011 - add require JSON 0.03 Thu Nov 24 14:58:50 JST 2011 - support lwp 0.02 Thu Nov 24 10:43:52 JST 2011 - fix pod 0.01 Wed Nov 23 21:10:39 JST 2011 - original version HOW_TO_DEVELOPMENT.md100644000765000024 377115124606754 17636 0ustar00askastaff000000000000WebService-Dropbox-2.10 ## 開発環境を作る ```sh export MACOSX_DEPLOYMENT_TARGET=$(sw_vers -productVersion | cut -d. -f-2) xbuild/perl-install 5.26.0 ~/local/perl-5.26 export PATH=/Users/aska/local/perl-5.26/bin:$PATH carton install > Installing modules using /Users/aska/Documents/Perl/p5-WebService-Dropbox/cpanfile > Successfully installed Module-Build-0.4218 > Successfully installed ExtUtils-Config-0.008 > Successfully installed ExtUtils-InstallPaths-0.011 > Successfully installed ExtUtils-Helpers-0.026 > Successfully installed Module-Build-Tiny-0.039 > Successfully installed Test-Simple-1.302085 (upgraded from 1.302073) > Successfully installed Net-SSLeay-1.74 > Successfully installed Mozilla-CA-20160104 > Successfully installed IO-Socket-SSL-2.029 > Successfully installed URI-1.71 > Successfully installed Net-HTTP-6.09 > Successfully installed HTML-Tagset-3.20 > Successfully installed HTML-Parser-3.72 > Successfully installed LWP-MediaTypes-6.02 > Successfully installed Encode-Locale-1.05 > Successfully installed HTTP-Date-6.02 > Successfully installed IO-HTML-1.001 > Successfully installed HTTP-Message-6.11 > Successfully installed HTTP-Daemon-6.01 > Successfully installed HTTP-Cookies-6.01 > Successfully installed Try-Tiny-0.28 > Successfully installed File-Listing-6.04 > Successfully installed HTTP-Negotiate-6.01 > Successfully installed WWW-RobotRules-6.02 > Successfully installed libwww-perl-6.26 > Successfully installed LWP-Protocol-https-6.07 > Successfully installed JSON-2.94 > 27 distributions installed > Complete! Modules were installed into /Users/aska/Documents/Perl/p5-WebService-Dropbox/local ``` ## バージョン番号の更新 lib/WebService/Dropbox.pm ```perl our $VERSION = '2.06'; ``` ## Test ```sh carton exec -- prove -I lib t ``` ## Test for with Furl ```sh cpanm -L local-furl --with-recommends ./ PERL_CARTON_PATH=local-furl carton exec -- prove -I lib t ``` ## README.md の更新 ```sh cpanm Minilla minil dist --no-test ``` ## Release ```sh $EDITOR ~/.pause minil release --no-test ``` LICENSE100644000765000024 4376315124606754 15445 0ustar00askastaff000000000000WebService-Dropbox-2.10This software is copyright (c) 2016 by Shinichiro Aska . This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2013 by Shinichiro Aska . This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our 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. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, 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 a 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 tell them 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. 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 Agreement 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 work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 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 General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual 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 General Public License. d) 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. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 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 Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying 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. 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. 7. 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 the 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 the license, you may choose any version ever published by the Free Software Foundation. 8. 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 9. 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. 10. 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 Appendix: 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 humanity, 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. Copyright (C) 19yy 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 1, 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) 19xx 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 a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2013 by Shinichiro Aska . This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End META.json100644000765000024 672615124606754 16037 0ustar00askastaff000000000000WebService-Dropbox-2.10{ "abstract" : "Perl interface to Dropbox API", "author" : [ "Shinichiro Aska" ], "dynamic_config" : 0, "generated_by" : "Minilla/v3.1.29", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "WebService-Dropbox", "no_index" : { "directory" : [ "t", "xt", "inc", "share", "eg", "examples", "author", "builder" ] }, "prereqs" : { "configure" : { "requires" : { "Module::Build" : "0", "Module::Build::Tiny" : "0.035" } }, "develop" : { "requires" : { "Test::CPAN::Meta" : "0", "Test::MinimumVersion::Fast" : "0.04", "Test::PAUSE::Permissions" : "0.07", "Test::Pod" : "1.41", "Test::Spellunker" : "v0.2.7" } }, "runtime" : { "recommends" : { "Furl" : "3.11", "IO::Socket::SSL" : "2.048", "JSON::XS" : "3.03", "Software::License" : "0" }, "requires" : { "HTTP::Message" : "6.11", "JSON" : "2.94", "LWP::Protocol::https" : "6.07", "LWP::UserAgent" : "6.26", "URI" : "1.71", "perl" : "5.008001" } }, "test" : { "requires" : { "Test::More" : "1.302085" } } }, "provides" : { "WebService::Dropbox" : { "file" : "lib/WebService/Dropbox.pm", "version" : "2.10" }, "WebService::Dropbox::Auth" : { "file" : "lib/WebService/Dropbox/Auth.pm" }, "WebService::Dropbox::Files" : { "file" : "lib/WebService/Dropbox/Files.pm" }, "WebService::Dropbox::Files::CopyReference" : { "file" : "lib/WebService/Dropbox/Files/CopyReference.pm" }, "WebService::Dropbox::Files::ListFolder" : { "file" : "lib/WebService/Dropbox/Files/ListFolder.pm" }, "WebService::Dropbox::Files::UploadSession" : { "file" : "lib/WebService/Dropbox/Files/UploadSession.pm" }, "WebService::Dropbox::Sharing" : { "file" : "lib/WebService/Dropbox/Sharing.pm" }, "WebService::Dropbox::TokenFromOAuth1" : { "file" : "lib/WebService/Dropbox/TokenFromOAuth1.pm" }, "WebService::Dropbox::Users" : { "file" : "lib/WebService/Dropbox/Users.pm" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/s-aska/p5-WebService-Dropbox/issues" }, "homepage" : "https://github.com/s-aska/p5-WebService-Dropbox", "repository" : { "type" : "git", "url" : "https://github.com/s-aska/p5-WebService-Dropbox.git", "web" : "https://github.com/s-aska/p5-WebService-Dropbox" } }, "version" : "2.10", "x_authority" : "cpan:ASKADNA", "x_contributors" : [ "Dondi Michael Stroma ", "Fuji, Goro ", "Greg Youngblood <47649208+softwrx@users.noreply.github.com>", "Nick Tonkin ", "Rostislav Georgiev ", "Shinichiro Aska ", "aska ", "aska " ], "x_serialization_backend" : "JSON::PP version 4.06", "x_static_install" : 1 } README.md100644000765000024 6744215124606754 15717 0ustar00askastaff000000000000WebService-Dropbox-2.10[![Build Status](https://travis-ci.org/s-aska/p5-WebService-Dropbox.svg?branch=master)](https://travis-ci.org/s-aska/p5-WebService-Dropbox) # NAME WebService::Dropbox - Perl interface to Dropbox API # SYNOPSIS ```perl use WebService::Dropbox; my $dropbox = WebService::Dropbox->new({ key => '...', # App Key secret => '...' # App Secret }); # Authorization if ($access_token) { $dropbox->access_token($access_token); } else { my $url = $dropbox->authorize; print "Please Access URL and press Enter: $url\n"; print "Please Input Code: "; chomp( my $code = ); unless ($dropbox->token($code)) { die $dropbox->error; } print "Successfully authorized.\nYour AccessToken: ", $dropbox->access_token, "\n"; } my $info = $dropbox->get_current_account or die $dropbox->error; # download # https://www.dropbox.com/developers/documentation/http/documentation#files-download my $fh_download = IO::File->new('some file', '>'); $dropbox->download('/make_test_folder/test.txt', $fh_download) or die $dropbox->error; $fh_get->close; # upload # https://www.dropbox.com/developers/documentation/http/documentation#files-upload my $fh_upload = IO::File->new('some file'); $dropbox->upload('/make_test_folder/test.txt', $fh_upload) or die $dropbox->error; $fh_upload->close; # get_metadata # https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata my $data = $dropbox->get_metadata('/folder_a'); ``` # DESCRIPTION WebService::Dropbox is Perl interface to Dropbox API \- Support Dropbox v2 REST API \- Support Furl (Fast!!!) \- Streaming IO (Low Memory) # API v1 => v2 Migration guide ## Migration API files => download, files\_put => upload ...etc [https://www.dropbox.com/developers/reference/migration-guide](https://www.dropbox.com/developers/reference/migration-guide) ## Migration OAuth1 Token => OAuth2 Token ```perl use WebService::Dropbox::TokenFromOAuth1; my $oauth2_access_token = WebService::Dropbox::TokenFromOAuth1->token_from_oauth1({ consumer_key => $dropbox->key, consumer_secret => $dropbox->secret, access_token => $access_token, # OAuth1 access_token access_secret => $access_secret, # OAuth1 access_secret }); warn $oauth2_access_token; ``` # Use API v1 **Dropbox will be turning off API v1 on 6/28/2017.** [https://blogs.dropbox.com/developers/2016/06/api-v1-deprecated/](https://blogs.dropbox.com/developers/2016/06/api-v1-deprecated/) ## cpanfile ``` requires 'WebService::Dropbox', '== 1.22'; ``` ## cpanm ``` cpanm -L local ASKADNA/WebService-Dropbox-1.22.tar.gz ``` ## curl ```perl mkdir lib/WebService curl -o lib/WebService/Dropbox.pm https://raw.githubusercontent.com/s-aska/p5-WebService-Dropbox/1.22/lib/WebService/Dropbox.pm ``` # API ## Auth [https://www.dropbox.com/developers/documentation/http/documentation#oauth2-authorize](https://www.dropbox.com/developers/documentation/http/documentation#oauth2-authorize) ### for CLI Sample ```perl my $url = $dropbox->authorize; print "Please Access URL: $url\n"; print "Please Input Code: "; chomp( my $code = ); unless ($dropbox->token($code)) { die $dropbox->error; } print "Successfully authorized.\nYour AccessToken: ", $dropbox->access_token, "\n"; ``` ### for Web Sample ```perl use Amon2::Lite; use WebService::Dropbox; __PACKAGE__->load_plugins('Web::JSON'); my $key = $ENV{DROPBOX_APP_KEY}; my $secret = $ENV{DROPBOX_APP_SECRET}; my $dropbox = WebService::Dropbox->new({ key => $key, secret => $secret }); my $redirect_uri = 'http://localhost:5000/callback'; get '/' => sub { my ($c) = @_; my $url = $dropbox->authorize({ redirect_uri => $redirect_uri }); return $c->redirect($url); }; get '/callback' => sub { my ($c) = @_; my $code = $c->req->param('code'); my $token = $dropbox->token($code, $redirect_uri); my $account = $dropbox->get_current_account || { error => $dropbox->error }; return $c->render_json({ token => $token, account => $account }); }; __PACKAGE__->to_app(); ``` ### authorize(\\%optional\_params) ```perl # for Simple CLI my $url = $dropbox->authorize(); # for Other my $url = $dropbox->authorize({ response_type => 'code', # code or token redirect_uri => '', state => '', require_role => '', force_reapprove => JSON::false, disable_signup => JSON::false, }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#oauth2-authorize](https://www.dropbox.com/developers/documentation/http/documentation#oauth2-authorize) ### token($code \[, $redirect\_uri\]) This endpoint only applies to apps using the authorization code flow. An app calls this endpoint to acquire a bearer token once the user has authorized the app. Calls to /oauth2/token need to be authenticated using the apps's key and secret. These can either be passed as POST parameters (see parameters below) or via HTTP basic authentication. If basic authentication is used, the app key should be provided as the username, and the app secret should be provided as the password. ```perl # for CLI my $token = $dropbox->token($code); # for Web my $token = $dropbox->token($code, $redirect_uri); ``` [https://www.dropbox.com/developers/documentation/http/documentation#oauth2-token](https://www.dropbox.com/developers/documentation/http/documentation#oauth2-token) ### revoke Disables the access token used to authenticate the call. ```perl my $result = $dropbox->revoke; ``` [https://www.dropbox.com/developers/documentation/http/documentation#auth-token-revoke](https://www.dropbox.com/developers/documentation/http/documentation#auth-token-revoke) ## Files ### copy($from\_path, $to\_path) Copy a file or folder to a different location in the user's Dropbox. If the source path is a folder all its contents will be copied. ```perl my $result = $dropbox->copy($from_path, $to_path); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-copy](https://www.dropbox.com/developers/documentation/http/documentation#files-copy) ### copy\_reference\_get($path) Get a copy reference to a file or folder. This reference string can be used to save that file or folder to another user's Dropbox by passing it to copy\_reference/save. ```perl my $result = $dropbox->copy_reference_get($path); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-copy\_reference-get](https://www.dropbox.com/developers/documentation/http/documentation#files-copy_reference-get) ### copy\_reference\_save($copy\_reference, $path) Save a copy reference returned by copy\_reference/get to the user's Dropbox. ```perl my $result = $dropbox->copy_reference_save($copy_reference, $path); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-copy\_reference-save](https://www.dropbox.com/developers/documentation/http/documentation#files-copy_reference-save) ### create\_folder($path) Create a folder at a given path. ```perl my $result = $dropbox->create_folder($path); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-create\_folder](https://www.dropbox.com/developers/documentation/http/documentation#files-create_folder) ### delete($path) Delete the file or folder at a given path. If the path is a folder, all its contents will be deleted too. A successful response indicates that the file or folder was deleted. The returned metadata will be the corresponding FileMetadata or FolderMetadata for the item at time of deletion, and not a DeletedMetadata object. ```perl my $result = $dropbox->delete($path); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-delete](https://www.dropbox.com/developers/documentation/http/documentation#files-delete) ### delete\_batch($paths) Delete the files or folders at a list of given paths. The list is provided as the first arg in an arrayref. A successful response indicates that the files or folders were queued for async deletion. The returned object will include the async\_job\_id. ```perl my $result = $dropbox->delete_batch($paths); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-delete\_batch](https://www.dropbox.com/developers/documentation/http/documentation#files-delete_batch) ### delete\_batch\_check($async\_job\_id) Fetch the status of a asynchronous job for a delete\_batch call. Returns a status tag .tag with possible values 'in\_progress', 'complete' and 'failed'. If success, also returns list of result for each entry. ```perl my $result = $dropbox->delete_batch_check($async_job_id); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-delete\_batch-check](https://www.dropbox.com/developers/documentation/http/documentation#files-delete_batch-check) ### download($path, $output \[, \\%opts\]) Download a file from a user's Dropbox. ```perl # File handle my $fh = IO::File->new('some file', '>'); $dropbox->download($path, $fh); # Code reference my $write_code = sub { # compatible with LWP::UserAgent and Furl::HTTP my $chunk = @_ == 4 ? @_[3] : $_[0]; print $chunk; }; $dropbox->download($path, $write_code); # Range my $fh = IO::File->new('some file', '>'); $dropbox->download($path, $fh, { headers => ['Range' => 'bytes=5-6'] }); # If-None-Match / ETag my $fh = IO::File->new('some file', '>'); $dropbox->download($path, $fh); # $dropbox->res->code => 200 my $etag = $dropbox->res->header('ETag'); $dropbox->download($path, $fh, { headers => ['If-None-Match', $etag] }); # $dropbox->res->code => 304 ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-download](https://www.dropbox.com/developers/documentation/http/documentation#files-download) ### get\_metadata($path \[, \\%optional\_params\]) Returns the metadata for a file or folder. Note: Metadata for the root folder is unsupported. ```perl my $result = $dropbox->get_metadata($path); my $result = $dropbox->get_metadata($path, { include_media_info => JSON::true, include_deleted => JSON::true, include_has_explicit_shared_members => JSON::false, }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-get\_metadata](https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata) ### get\_preview($path, $outout \[, \\%opts\]) Get a preview for a file. Currently previews are only generated for the files with the following extensions: .doc, .docx, .docm, .ppt, .pps, .ppsx, .ppsm, .pptx, .pptm, .xls, .xlsx, .xlsm, .rtf ```perl # File handle my $fh = IO::File->new('some file', '>'); $dropbox->get_preview($path, $fh); # Code reference my $write_code = sub { # compatible with LWP::UserAgent and Furl::HTTP my $chunk = @_ == 4 ? @_[3] : $_[0]; print $chunk; }; $dropbox->get_preview($path, $write_code); # Range my $fh = IO::File->new('some file', '>'); $dropbox->get_preview($path, $fh, { headers => ['Range' => 'bytes=5-6'] }); # If-None-Match / ETag my $fh = IO::File->new('some file', '>'); $dropbox->get_preview($path, $fh); # $dropbox->res->code => 200 my $etag = $dropbox->res->header('ETag'); $dropbox->get_preview($path, $fh, { headers => ['If-None-Match', $etag] }); # $dropbox->res->code => 304 ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-get\_preview](https://www.dropbox.com/developers/documentation/http/documentation#files-get_preview) ### get\_temporary\_link($path) Get a temporary link to stream content of a file. This link will expire in four hours and afterwards you will get 410 Gone. Content-Type of the link is determined automatically by the file's mime type. ```perl my $result = $dropbox->get_temporary_link($path); my $content_type = $dropbox->res->header('Content-Type'); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-get\_temporary\_link](https://www.dropbox.com/developers/documentation/http/documentation#files-get_temporary_link) ### get\_thumbnail($path, $output \[, \\%optional\_params, $opts\]) Get a thumbnail for an image. This method currently supports files with the following file extensions: jpg, jpeg, png, tiff, tif, gif and bmp. Photos that are larger than 20MB in size won't be converted to a thumbnail. ```perl # File handle my $fh = IO::File->new('some file', '>'); $dropbox->get_thumbnail($path, $fh); my $optional_params = { format => 'jpeg', size => 'w64h64' }; $dropbox->get_thumbnail($path, $fh, $optional_params); # Code reference my $write_code = sub { # compatible with LWP::UserAgent and Furl::HTTP my $chunk = @_ == 4 ? @_[3] : $_[0]; print $chunk; }; $dropbox->get_thumbnail($path, $write_code); # Range my $fh = IO::File->new('some file', '>'); $dropbox->get_thumbnail($path, $fh, $optional_params, { headers => ['Range' => 'bytes=5-6'] }); # If-None-Match / ETag my $fh = IO::File->new('some file', '>'); $dropbox->get_thumbnail($path, $fh); # $dropbox->res->code => 200 my $etag = $dropbox->res->header('ETag'); $dropbox->get_thumbnail($path, $fh, $optional_params, { headers => ['If-None-Match', $etag] }); # $dropbox->res->code => 304 ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-get\_thumbnail](https://www.dropbox.com/developers/documentation/http/documentation#files-get_thumbnail) ### list\_folder($path \[, \\%optional\_params\]) Returns the contents of a folder. ```perl my $result = $dropbox->list_folder($path); my $result = $dropbox->list_folder($path, { recursive => JSON::false, include_media_info => JSON::false, include_deleted => JSON::false, include_has_explicit_shared_members => JSON::false }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-list\_folder](https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder) ### list\_folder\_continue($cursor) Once a cursor has been retrieved from list\_folder, use this to paginate through all files and retrieve updates to the folder. ```perl my $result = $dropbox->list_folder_continue($cursor); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-list\_folder-continue](https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-continue) ### list\_folder\_get\_latest\_cursor($path \[, \\%optional\_params\]) A way to quickly get a cursor for the folder's state. Unlike list\_folder, list\_folder/get\_latest\_cursor doesn't return any entries. This endpoint is for app which only needs to know about new files and modifications and doesn't need to know about files that already exist in Dropbox. ```perl my $result = $dropbox->list_folder_get_latest_cursor($path); my $result = $dropbox->list_folder_get_latest_cursor($path, { recursive => JSON::false, include_media_info => JSON::false, include_deleted => JSON::false, include_has_explicit_shared_members => JSON::false }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-list\_folder-get\_latest\_cursor](https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-get_latest_cursor) ### list\_folder\_longpoll($cursor \[, \\%optional\_params\]) A longpoll endpoint to wait for changes on an account. In conjunction with list\_folder/continue, this call gives you a low-latency way to monitor an account for file changes. The connection will block until there are changes available or a timeout occurs. This endpoint is useful mostly for client-side apps. If you're looking for server-side notifications, check out our webhooks documentation. ```perl my $result = $dropbox->list_folder_longpoll($cursor); my $result = $dropbox->list_folder_longpoll($cursor, { timeout => 30 }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-list\_folder-longpoll](https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-longpoll) ### list\_revisions($path \[, \\%optional\_params\]) Return revisions of a file. ```perl my $result = $dropbox->list_revisions($path); my $result = $dropbox->list_revisions($path, { limit => 10 }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-list\_revisions](https://www.dropbox.com/developers/documentation/http/documentation#files-list_revisions) ### move($from\_path, $to\_path) Return revisions of a file. ```perl my $result = $dropbox->move($from_path, $to_path); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-move](https://www.dropbox.com/developers/documentation/http/documentation#files-move) ### permanently\_delete($path) Permanently delete the file or folder at a given path (see https://www.dropbox.com/en/help/40). Note: This endpoint is only available for Dropbox Business apps. ```perl my $result = $dropbox->permanently_delete($path); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-permanently\_delete](https://www.dropbox.com/developers/documentation/http/documentation#files-permanently_delete) ### restore($path, $rev) Restore a file to a specific revision. ```perl my $result = $dropbox->restore($path, $rev); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-restore](https://www.dropbox.com/developers/documentation/http/documentation#files-restore) ### save\_url($path, $url) Save a specified URL into a file in user's Dropbox. If the given path already exists, the file will be renamed to avoid the conflict (e.g. myfile (1).txt). ```perl my $result = $dropbox->save_url($path, $url); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-save\_url](https://www.dropbox.com/developers/documentation/http/documentation#files-save_url) ### save\_url\_check\_job\_status($async\_job\_id) Check the status of a save\_url job. ```perl my $result = $dropbox->save_url_check_job_status($async_job_id); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-save\_url-check\_job\_status](https://www.dropbox.com/developers/documentation/http/documentation#files-save_url-check_job_status) ### search($path, $query, \[, \\%optional\_params\]) Searches for files and folders. Note: Recent changes may not immediately be reflected in search results due to a short delay in indexing. ```perl my $result = $dropbox->search($path); my $result = $dropbox->search($path, 'prime numbers', { start => 0, max_results => 100, mode => 'filename' }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-search](https://www.dropbox.com/developers/documentation/http/documentation#files-search) ### upload($path, $content \[, \\%optional\_params\]) Create a new file with the contents provided in the request. Do not use this to upload a file larger than 150 MB. Instead, create an upload session with upload\_session/start. ```perl # File Handle my $content = IO::File->new('./my.cnf', '<'); my $result = $dropbox->upload($path, $content); my $result = $dropbox->upload($path, $content, { mode => 'add', autorename => JSON::true, mute => JSON::false }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-upload](https://www.dropbox.com/developers/documentation/http/documentation#files-upload) ### upload\_session($path, $content \[, \\%optional\_params, $limit\]) Uploads large files by upload\_session API ```perl # File Handle my $content = IO::File->new('./mysql.dump', '<'); my $result = $dropbox->upload_session($path, $content); my $result = $dropbox->upload_session($path, $content, { mode => 'add', autorename => JSON::true, mute => JSON::false }); ``` - [https://www.dropbox.com/developers/documentation/http/documentation#files-upload\_session-start](https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start) - [https://www.dropbox.com/developers/documentation/http/documentation#files-upload\_session-append\_v2](https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-append_v2) - [https://www.dropbox.com/developers/documentation/http/documentation#files-upload\_session-finish](https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-finish) ### upload\_session\_start($content \[, \\%optional\_params\]) Upload sessions allow you to upload a single file using multiple requests. This call starts a new upload session with the given data. You can then use upload\_session/append\_v2 to add more data and upload\_session/finish to save all the data to a file in Dropbox. A single request should not upload more than 150 MB of file contents. ```perl # File Handle my $content = IO::File->new('./access.log', '<'); $dropbox->upload_session_start($content); $dropbox->upload_session_start($content, { close => JSON::true }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-upload\_session-start](https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start) ### upload\_session\_append\_v2($content, $params) Append more data to an upload session. When the parameter close is set, this call will close the session. A single request should not upload more than 150 MB of file contents. ```perl # File Handle my $content = IO::File->new('./access.log.1', '<'); my $result = $dropbox->upload_session_append_v2($content, { cursor => { session_id => $session_id, offset => $offset }, close => JSON::true }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-upload\_session-append\_v2](https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-append_v2) ### upload\_session\_finish($content, $params) Finish an upload session and save the uploaded data to the given file path. A single request should not upload more than 150 MB of file contents. ```perl # File Handle my $content = IO::File->new('./access.log.last', '<'); my $result = $dropbox->upload_session_finish($content, { cursor => { session_id => $session_id, offset => $offset }, commit => { path => '/Homework/math/Matrices.txt', mode => 'add', autorename => JSON::true, mute => JSON::false } }); ``` [https://www.dropbox.com/developers/documentation/http/documentation#files-upload\_session-finish](https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-finish) ## Users ### get\_account($account\_id) Get information about a user's account. ```perl my $result = $dropbox->get_account($account_id); ``` [https://www.dropbox.com/developers/documentation/http/documentation#users-get\_account](https://www.dropbox.com/developers/documentation/http/documentation#users-get_account) ### get\_account\_batch(\\@account\_ids) Get information about multiple user accounts. At most 300 accounts may be queried per request. ```perl my $result = $dropbox->get_account_batch($account_ids); ``` [https://www.dropbox.com/developers/documentation/http/documentation#users-get\_account\_batch](https://www.dropbox.com/developers/documentation/http/documentation#users-get_account_batch) ### get\_current\_account() Get information about the current user's account. ```perl my $result = $dropbox->get_current_account; ``` [https://www.dropbox.com/developers/documentation/http/documentation#users-get\_current\_account](https://www.dropbox.com/developers/documentation/http/documentation#users-get_current_account) ### get\_space\_usage() Get the space usage information for the current user's account. ```perl my $result = $dropbox->get_space_usage; ``` [https://www.dropbox.com/developers/documentation/http/documentation#users-get\_space\_usage](https://www.dropbox.com/developers/documentation/http/documentation#users-get_space_usage) ## Sharing ### create\_shared\_link\_with\_settings($path, $settings) Create a shared link with custom settings. If no settings are given then the default visibility is RequestedVisibility.public (The resolved visibility, though, may depend on other aspects such as team and shared folder settings). ```perl my $result = $dropbox->create_shared_link_with_settings($path, $settings); ``` [https://www.dropbox.com/developers/documentation/http/documentation#sharing-create\_shared\_link\_with\_settings](https://www.dropbox.com/developers/documentation/http/documentation#sharing-create_shared_link_with_settings) ### list\_shared\_links($path) List shared links of this user. If no path is given, returns a list of all shared links for the current user. For members of business teams using team space and member folders, returns all shared links in the team member's home folder unless the team space ID is specified in the request header. For more information, refer to the Namespace Guide. If a non-empty path is given, returns a list of all shared links that allow access to the given path - direct links to the given path and links to parent folders of the given path. Links to parent folders can be suppressed by setting direct\_only to true. ```perl my $result = $dropbox->list_shared_links($path); ``` [https://www.dropbox.com/developers/documentation/http/documentation#sharing-list\_shared\_links](https://www.dropbox.com/developers/documentation/http/documentation#sharing-list_shared_links) ### modify\_shared\_link\_settings($path, $settings, $remove\_expiration) Modify the shared link's settings. If the requested visibility conflict with the shared links policy of the team or the shared folder (in case the linked file is part of a shared folder) then the LinkPermissions.resolved\_visibility of the returned SharedLinkMetadata will reflect the actual visibility of the shared link and the LinkPermissions.requested\_visibility will reflect the requested visibility. ```perl my $result = $dropbox->modify_shared_link_settings($path, $settings, $remove_expiration); ``` [https://www.dropbox.com/developers/documentation/http/documentation#sharing-modify\_shared\_link\_settings](https://www.dropbox.com/developers/documentation/http/documentation#sharing-modify_shared_link_settings) ### revoke\_shared\_link($url) Revoke a shared link. Note that even after revoking a shared link to a file, the file may be accessible if there are shared links leading to any of the file parent folders. To list all shared links that enable access to a specific file, you can use the list\_shared\_links with the file as the ListSharedLinksArg.path argument. ```perl my $result = $dropbox->revoke_shared_link($url); ``` [https://www.dropbox.com/developers/documentation/http/documentation#sharing-revoke\_shared\_link](https://www.dropbox.com/developers/documentation/http/documentation#sharing-revoke_shared_link) ## Error Handling and Debug ### error : str ```perl my $result = $dropbox->$some_api; unless ($result) { die $dropbox->error; } ``` ### req : HTTP::Request or Furl::Request ```perl my $result = $dropbox->$some_api; warn $dropbox->req->as_string; ``` ### res : HTTP::Response or Furl::Response ```perl my $result = $dropbox->$some_api; warn $dropbox->res->code; warn $dropbox->res->header('ETag'); warn $dropbox->res->header('Content-Type'); warn $dropbox->res->header('Content-Length'); warn $dropbox->res->header('X-Dropbox-Request-Id'); warn $dropbox->res->as_string; ``` ### env\_proxy enable HTTP\_PROXY, NO\_PROXY ```perl my $dropbox = WebService::Dropbox->new(); $dropbox->env_proxy; ``` ### debug enable or disable debug mode ```perl my $dropbox = WebService::Dropbox->new(); $dropbox->debug; # disabled $dropbox->debug(0); # disabled $dropbox->debug(1); # enabled ``` ### verbose more warnings. ```perl my $dropbox = WebService::Dropbox->new(); $dropbox->verbose; # disabled $dropbox->verbose(0); # disabled $dropbox->verbose(1); # enabled ``` # AUTHOR Shinichiro Aska # SEE ALSO - [https://www.dropbox.com/developers/documentation/http/documentation](https://www.dropbox.com/developers/documentation/http/documentation) - [https://www.dropbox.com/developers/reference/migration-guide](https://www.dropbox.com/developers/reference/migration-guide) # LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. cpanfile100644000765000024 100615124606754 16104 0ustar00askastaff000000000000WebService-Dropbox-2.10requires 'perl', '5.008001'; requires 'JSON', '2.94'; requires 'URI', '1.71'; requires 'HTTP::Message', '6.11'; requires 'LWP::UserAgent', '6.26'; requires 'LWP::Protocol::https', '6.07'; # Modern http client. recommends 'Furl', '3.11'; recommends 'IO::Socket::SSL', '2.048'; recommends 'JSON::XS', '3.03'; # Module required for license otherwise Perl_5 license. recommends 'Software::License'; on 'test' => sub { requires 'Test::More', '1.302085'; }; on 'configure' => sub { requires 'Module::Build'; }; README.md100644000765000024 17515124606754 20047 0ustar00askastaff000000000000WebService-Dropbox-2.10/example/cli ```sh $ carton install $ export DROPBOX_APP_KEY="****" $ export DROPBOX_APP_SECRET="****" $ carton exec -- perl app.pl ``` app.pl100644000765000024 300415124606754 17717 0ustar00askastaff000000000000WebService-Dropbox-2.10/example/cliuse strict; use warnings; use WebService::Dropbox; my $key = $ENV{DROPBOX_APP_KEY}; my $secret = $ENV{DROPBOX_APP_SECRET}; my $access_token = $ENV{DROPBOX_ACCESS_TOKEN}; my $box = WebService::Dropbox->new({ key => $key, secret => $secret, }); $box->debug; $box->verbose; if ($access_token) { $box->access_token($access_token); } else { my $url = $box->authorize; print "Please Access URL and press Enter: $url\n"; print "Please Input Code: "; chomp( my $code = ); unless ($box->token($code)) { die $box->error; } print "Successfully authorized.\nYour AccessToken: ", $box->access_token, "\n"; } my $res = $box->search('/Photos', '39.jpg'); # use Data::Dumper; # warn Dumper($res); # { # my $res = $box->get_current_account; # my $account_id = $res->{account_id}; # $box->get_account($account_id); # $box->get_account_batch([ $account_id ]); # $box->get_space_usage; # } # # use Data::Dumper; # # warn Dumper($res); # { # my $res = $box->download('/aerith.json', './aerith.json'); # # warn Dumper($res); # } # { # open(my $fh, '<', './aerith.json'); # # $box->debug; # my $res = $box->upload_session('/aerith-test.json', $fh, { mode => 'overwrite' }, 20000); # # warn Dumper($res); # } # { # open(my $fh, '>', './hoge.pdf'); # # $box->debug; # my $res = $box->get_preview('/work/recruit/職務経歴書.doc', $fh); # my $ct = $box->res->header('Content-Type'); # warn $ct; # # warn Dumper($res); # } cpanfile100644000765000024 23615124606754 20272 0ustar00askastaff000000000000WebService-Dropbox-2.10/example/clirequires 'JSON', '2.90'; requires 'URI', '1.71'; requires 'HTTP::Message', '6.11'; requires 'LWP::UserAgent', '6.15'; requires 'LWP::Protocol::https', '6.06';cpanfile.snapshot100644000765000024 2047315124606754 22175 0ustar00askastaff000000000000WebService-Dropbox-2.10/example/cli# carton snapshot format: version 1.0 DISTRIBUTIONS Encode-Locale-1.05 pathname: G/GA/GAAS/Encode-Locale-1.05.tar.gz provides: Encode::Locale 1.05 requirements: Encode 2 Encode::Alias 0 ExtUtils::MakeMaker 0 perl 5.008 File-Listing-6.04 pathname: G/GA/GAAS/File-Listing-6.04.tar.gz provides: File::Listing 6.04 File::Listing::apache 6.04 File::Listing::dosftp 6.04 File::Listing::netware 6.04 File::Listing::unix 6.04 File::Listing::vms 6.04 requirements: ExtUtils::MakeMaker 0 HTTP::Date 6 perl 5.006002 HTML-Parser-3.72 pathname: G/GA/GAAS/HTML-Parser-3.72.tar.gz provides: HTML::Entities 3.69 HTML::Filter 3.72 HTML::HeadParser 3.71 HTML::LinkExtor 3.69 HTML::Parser 3.72 HTML::PullParser 3.57 HTML::TokeParser 3.69 requirements: ExtUtils::MakeMaker 0 HTML::Tagset 3 XSLoader 0 perl 5.008 HTML-Tagset-3.20 pathname: P/PE/PETDANCE/HTML-Tagset-3.20.tar.gz provides: HTML::Tagset 3.20 requirements: ExtUtils::MakeMaker 0 HTTP-Cookies-6.01 pathname: G/GA/GAAS/HTTP-Cookies-6.01.tar.gz provides: HTTP::Cookies 6.01 HTTP::Cookies::Microsoft 6.00 HTTP::Cookies::Netscape 6.00 requirements: ExtUtils::MakeMaker 0 HTTP::Date 6 HTTP::Headers::Util 6 Time::Local 0 perl 5.008001 HTTP-Daemon-6.01 pathname: G/GA/GAAS/HTTP-Daemon-6.01.tar.gz provides: HTTP::Daemon 6.01 HTTP::Daemon::ClientConn 6.01 requirements: ExtUtils::MakeMaker 0 HTTP::Date 6 HTTP::Request 6 HTTP::Response 6 HTTP::Status 6 IO::Socket 0 LWP::MediaTypes 6 Sys::Hostname 0 perl 5.008001 HTTP-Date-6.02 pathname: G/GA/GAAS/HTTP-Date-6.02.tar.gz provides: HTTP::Date 6.02 requirements: ExtUtils::MakeMaker 0 Time::Local 0 perl 5.006002 HTTP-Message-6.11 pathname: E/ET/ETHER/HTTP-Message-6.11.tar.gz provides: HTTP::Config 6.11 HTTP::Headers 6.11 HTTP::Headers::Auth 6.11 HTTP::Headers::ETag 6.11 HTTP::Headers::Util 6.11 HTTP::Message 6.11 HTTP::Request 6.11 HTTP::Request::Common 6.11 HTTP::Response 6.11 HTTP::Status 6.11 requirements: Compress::Raw::Zlib 0 Encode 2.21 Encode::Locale 1 Exporter 5.57 ExtUtils::MakeMaker 0 HTTP::Date 6 IO::Compress::Bzip2 2.021 IO::Compress::Deflate 0 IO::Compress::Gzip 0 IO::HTML 0 IO::Uncompress::Bunzip2 2.021 IO::Uncompress::Gunzip 0 IO::Uncompress::Inflate 0 IO::Uncompress::RawInflate 0 LWP::MediaTypes 6 MIME::Base64 2.1 MIME::QuotedPrint 0 URI 1.10 perl 5.008001 HTTP-Negotiate-6.01 pathname: G/GA/GAAS/HTTP-Negotiate-6.01.tar.gz provides: HTTP::Negotiate 6.01 requirements: ExtUtils::MakeMaker 0 HTTP::Headers 6 perl 5.008001 IO-HTML-1.001 pathname: C/CJ/CJM/IO-HTML-1.001.tar.gz provides: IO::HTML 1.001 requirements: Carp 0 Encode 2.10 Exporter 5.57 ExtUtils::MakeMaker 6.30 IO-Socket-SSL-2.029 pathname: S/SU/SULLR/IO-Socket-SSL-2.029.tar.gz provides: IO::Socket::SSL 2.029 IO::Socket::SSL::Intercept 2.014 IO::Socket::SSL::OCSP_Cache 2.029 IO::Socket::SSL::OCSP_Resolver 2.029 IO::Socket::SSL::PublicSuffix undef IO::Socket::SSL::SSL_Context 2.029 IO::Socket::SSL::SSL_HANDLE 2.029 IO::Socket::SSL::Session_Cache 2.029 IO::Socket::SSL::Utils 2.014 requirements: ExtUtils::MakeMaker 0 Net::SSLeay 1.46 Scalar::Util 0 JSON-2.90 pathname: M/MA/MAKAMAKA/JSON-2.90.tar.gz provides: JSON 2.90 JSON::Backend::PP 2.90 JSON::Boolean 2.90 requirements: ExtUtils::MakeMaker 0 Test::More 0 LWP-MediaTypes-6.02 pathname: G/GA/GAAS/LWP-MediaTypes-6.02.tar.gz provides: LWP::MediaTypes 6.02 requirements: ExtUtils::MakeMaker 0 perl 5.006002 LWP-Protocol-https-6.06 pathname: M/MS/MSCHILLI/LWP-Protocol-https-6.06.tar.gz provides: LWP::Protocol::https 6.06 LWP::Protocol::https::Socket 6.06 requirements: ExtUtils::MakeMaker 0 IO::Socket::SSL 1.54 LWP::UserAgent 6.06 Mozilla::CA 20110101 Net::HTTPS 6 perl 5.008001 Mozilla-CA-20160104 pathname: A/AB/ABH/Mozilla-CA-20160104.tar.gz provides: Mozilla::CA 20160104 requirements: ExtUtils::MakeMaker 0 Test 0 perl 5.006 Net-HTTP-6.09 pathname: E/ET/ETHER/Net-HTTP-6.09.tar.gz provides: Net::HTTP 6.09 Net::HTTP::Methods 6.09 Net::HTTP::NB 6.09 Net::HTTPS 6.09 requirements: Compress::Raw::Zlib 0 ExtUtils::MakeMaker 0 IO::Select 0 IO::Socket::INET 0 IO::Uncompress::Gunzip 0 URI 0 perl 5.006002 Net-SSLeay-1.74 pathname: M/MI/MIKEM/Net-SSLeay-1.74.tar.gz provides: Net::SSLeay 1.74 Net::SSLeay::Handle 0.61 requirements: ExtUtils::MakeMaker 6.36 MIME::Base64 0 Test::More 0.60_01 perl 5.005 URI-1.71 pathname: E/ET/ETHER/URI-1.71.tar.gz provides: URI 1.71 URI::Escape 3.31 URI::Heuristic 4.20 URI::IRI 1.71 URI::QueryParam 1.71 URI::Split 1.71 URI::URL 5.04 URI::WithBase 2.20 URI::_foreign 1.71 URI::_generic 1.71 URI::_idna 1.71 URI::_ldap 1.71 URI::_login 1.71 URI::_punycode 1.71 URI::_query 1.71 URI::_segment 1.71 URI::_server 1.71 URI::_userpass 1.71 URI::data 1.71 URI::file 4.21 URI::file::Base 1.71 URI::file::FAT 1.71 URI::file::Mac 1.71 URI::file::OS2 1.71 URI::file::QNX 1.71 URI::file::Unix 1.71 URI::file::Win32 1.71 URI::ftp 1.71 URI::gopher 1.71 URI::http 1.71 URI::https 1.71 URI::ldap 1.71 URI::ldapi 1.71 URI::ldaps 1.71 URI::mailto 1.71 URI::mms 1.71 URI::news 1.71 URI::nntp 1.71 URI::pop 1.71 URI::rlogin 1.71 URI::rsync 1.71 URI::rtsp 1.71 URI::rtspu 1.71 URI::sftp 1.71 URI::sip 1.71 URI::sips 1.71 URI::snews 1.71 URI::ssh 1.71 URI::telnet 1.71 URI::tn3270 1.71 URI::urn 1.71 URI::urn::isbn undef URI::urn::oid 1.71 requirements: Exporter 5.57 ExtUtils::MakeMaker 0 MIME::Base64 2 Scalar::Util 0 parent 0 perl 5.008001 utf8 0 WWW-RobotRules-6.02 pathname: G/GA/GAAS/WWW-RobotRules-6.02.tar.gz provides: WWW::RobotRules 6.02 WWW::RobotRules::AnyDBM_File 6.00 WWW::RobotRules::InCore 6.02 requirements: AnyDBM_File 0 ExtUtils::MakeMaker 0 Fcntl 0 URI 1.10 perl 5.008001 libwww-perl-6.15 pathname: E/ET/ETHER/libwww-perl-6.15.tar.gz provides: LWP 6.15 LWP::Authen::Basic undef LWP::Authen::Digest undef LWP::Authen::Ntlm 6.15 LWP::ConnCache 6.15 LWP::Debug undef LWP::DebugFile undef LWP::MemberMixin undef LWP::Protocol 6.15 LWP::Protocol::GHTTP undef LWP::Protocol::MyFTP undef LWP::Protocol::cpan undef LWP::Protocol::data undef LWP::Protocol::file undef LWP::Protocol::ftp undef LWP::Protocol::gopher undef LWP::Protocol::http undef LWP::Protocol::http::Socket undef LWP::Protocol::http::SocketMethods undef LWP::Protocol::loopback undef LWP::Protocol::mailto undef LWP::Protocol::nntp undef LWP::Protocol::nogo undef LWP::RobotUA 6.15 LWP::Simple 6.15 LWP::UserAgent 6.15 requirements: Digest::MD5 0 Encode 2.12 Encode::Locale 0 ExtUtils::MakeMaker 0 File::Copy 0 File::Listing 6 Getopt::Long 0 HTML::Entities 0 HTML::HeadParser 0 HTTP::Cookies 6 HTTP::Daemon 6 HTTP::Date 6 HTTP::Negotiate 6 HTTP::Request 6 HTTP::Request::Common 6 HTTP::Response 6 HTTP::Status 6 IO::Select 0 IO::Socket 0 LWP::MediaTypes 6 MIME::Base64 2.1 Net::FTP 2.58 Net::HTTP 6.07 URI 1.10 URI::Escape 0 WWW::RobotRules 6 perl 5.008001 mig.pl100644000765000024 67315124606754 17711 0ustar00askastaff000000000000WebService-Dropbox-2.10/example/miguse strict; use warnings; use WebService::Dropbox::TokenFromOAuth1; my $key = shift; my $secret = shift; my $oauth1_access_token = shift; my $oauth1_access_secret = shift; my $oauth2_access_token = WebService::Dropbox::TokenFromOAuth1->token_from_oauth1({ consumer_key => $key, consumer_secret => $secret, access_token => $oauth1_access_token, access_secret => $oauth1_access_secret, }); warn $oauth2_access_token; README.md100644000765000024 22715124606754 20053 0ustar00askastaff000000000000WebService-Dropbox-2.10/example/web ```sh $ carton install $ export DROPBOX_APP_KEY="****" $ export DROPBOX_APP_SECRET="****" $ carton exec -- plackup $ open http://localhost:5000/ ``` app.psgi100644000765000024 157415124606754 20266 0ustar00askastaff000000000000WebService-Dropbox-2.10/example/webuse strict; use warnings; use Amon2::Lite; use WebService::Dropbox; __PACKAGE__->load_plugins('Web::JSON'); my $key = $ENV{DROPBOX_APP_KEY}; my $secret = $ENV{DROPBOX_APP_SECRET}; my $dropbox = WebService::Dropbox->new({ key => $key, secret => $secret }); my $redirect_uri = 'http://localhost:5000/callback'; get '/' => sub { my ($c) = @_; my $url = $dropbox->authorize({ redirect_uri => $redirect_uri }); return $c->redirect($url); }; get '/callback' => sub { my ($c) = @_; my $code = $c->req->param('code'); my $token = $dropbox->token($code, $redirect_uri); my $account = $dropbox->get_current_account || { error => $dropbox->error }; return $c->render_json({ token => $token, account => $account }); }; __PACKAGE__->to_app(); __DATA__ @@ index.tt

Hello

[% res %] cpanfile100644000765000024 20315124606754 20272 0ustar00askastaff000000000000WebService-Dropbox-2.10/example/webrequires 'Amon2::Lite' => '0.13'; requires 'Furl' => '2.19'; requires 'IO::Socket::SSL' => '1.954'; requires 'JSON::XS' => '3.02'; Dropbox.pm100644000765000024 10231715124606754 21226 0ustar00askastaff000000000000WebService-Dropbox-2.10/lib/WebServicepackage WebService::Dropbox; use strict; use warnings; use Carp (); use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK SEEK_SET SEEK_END); use JSON; use URI; use File::Temp; use WebService::Dropbox::Auth; use WebService::Dropbox::Files; use WebService::Dropbox::Files::CopyReference; use WebService::Dropbox::Files::ListFolder; use WebService::Dropbox::Files::UploadSession; use WebService::Dropbox::Sharing; use WebService::Dropbox::Users; our $VERSION = '2.10'; __PACKAGE__->mk_accessors(qw/ timeout key secret access_token error req res /); $WebService::Dropbox::USE_LWP = 0; $WebService::Dropbox::DEBUG = 0; $WebService::Dropbox::VERBOSE = 0; my $JSON = JSON->new->ascii; my $JSON_PRETTY = JSON->new->pretty->utf8->canonical; sub import { eval { require Furl; require IO::Socket::SSL; };if ($@ || ($Furl::VERSION < 3.08)) { __PACKAGE__->use_lwp; } } sub use_lwp { require LWP::UserAgent; require HTTP::Request; require HTTP::Request::Common; $WebService::Dropbox::USE_LWP++; } sub debug { $WebService::Dropbox::DEBUG = defined $_[0] ? $_[0] : 1; } sub verbose { $WebService::Dropbox::VERBOSE = defined $_[0] ? $_[0] : 1; } sub new { my ($class, $args) = @_; bless { timeout => $args->{timeout} || 86400, key => $args->{key} || '', secret => $args->{secret} || '', access_token => $args->{access_token} || '', env_proxy => $args->{env_proxy} || 0, }, $class; } sub api { my ($self, $args) = @_; # Content-download endpoints if (my $output = delete $args->{output}) { if (ref $output eq 'CODE') { $args->{write_code} = $output; # code ref } elsif (ref $output) { $args->{write_file} = $output; # file handle binmode $args->{write_file}; } else { open $args->{write_file}, '>', $output; # file path Carp::croak("invalid output, output must be code ref or filehandle or filepath.") unless $args->{write_file}; binmode $args->{write_file}; } } # Always HTTP POST. https://www.dropbox.com/developers/documentation/http/documentation#formats $args->{method} = 'POST'; $args->{headers} ||= []; if ($self->access_token && $args->{url} ne 'https://notify.dropboxapi.com/2/files/list_folder/longpoll') { push @{ $args->{headers} }, 'Authorization', 'Bearer ' . $self->access_token; } # Set PARAMETERS my $params = delete $args->{params}; # Token # * PARAMETERS in to Request Body (application/x-www-form-urlencoded) # * RETURNS in to Response Body (application/json) if ($args->{url} eq 'https://api.dropboxapi.com/oauth2/token') { $args->{content} = $params; } # RPC endpoints # * PARAMETERS in to Request Body (application/json) # * RETURNS in to Response Body (application/json) elsif ($args->{url} =~ qr{ \A https://(?:api|notify).dropboxapi.com }xms) { if ($params) { push @{ $args->{headers} }, 'Content-Type', 'application/json'; $args->{content} = $JSON->encode($params); } } # Content-upload endpoints or Content-download endpoints # * PARAMETERS in to Dropbox-API-Arg (JSON Format) # * RETURNS in to Dropbox-API-Result (JSON Format) elsif ($args->{url} =~ qr{ \A https://content.dropboxapi.com }xms) { if ($params) { push @{ $args->{headers} }, 'Dropbox-API-Arg', $JSON->encode($params); } if ($args->{content}) { push @{ $args->{headers} }, 'Content-Type', 'application/octet-stream'; } } my ($req, $res); if ($WebService::Dropbox::USE_LWP) { ($req, $res) = $self->api_lwp($args); } else { ($req, $res) = $self->api_furl($args); } $self->req($req); $self->res($res); my $is_success = $self->res->code =~ qr{ \A [23] }xms ? 1 : 0; my $decoded_content = $res->decoded_content; my $res_data; my $res_json = $res->header('Dropbox-Api-Result'); if (!$res_json && $res->header('Content-Type') =~ qr{ \A (?:application/json|text/javascript) }xms) { $res_json = $decoded_content; } if ($res_json && $res_json ne 'null') { $res_data = $JSON->decode($res_json); } if ($WebService::Dropbox::DEBUG || !$is_success) { my $level = $is_success ? 'DEBUG': 'ERROR'; my $color = $is_success ? "\e[32m" : "\e[31m"; my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); my $time = sprintf("%04d-%02d-%02dT%02d:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec); if ($WebService::Dropbox::VERBOSE) { warn sprintf(qq|%s [WebService::Dropbox] [%s] %s \e[90m%s %s %s %s %s\e[0m ${color}%s %s\e[0m \e[90m%s %s\e[0m |, $time, $level, $req->uri, $req->method, $req->uri, $req->protocol || '', $req->headers->as_string, ( ref $args->{content} ? '' : $args->{content} && $params ? $JSON_PRETTY->encode($params) : '' ), $res->protocol, $res->status_line, $res->headers->as_string, ( $res_data ? $JSON_PRETTY->encode($res_data) : $decoded_content . "\n" ), ); } else { warn sprintf("%s [WebService::Dropbox] [%s] %s %s -> [%s] %s", $time, $level, $req->uri, ( $params ? $JSON->encode($params) : '-' ), $res->code, ( $res_json || $decoded_content ), ); } } unless ($is_success) { unless ($self->error) { $self->error($decoded_content); } return; } $self->error(undef); return $res_data || +{}; } sub api_lwp { my ($self, $args) = @_; my @headers = @{ $args->{headers} || +[] }; if ($args->{write_file}) { $args->{write_code} = sub { my $buf = shift; $args->{write_file}->print($buf); }; } if ($args->{content} && UNIVERSAL::can($args->{content}, 'read')) { my $buf; my $content = delete $args->{content}; $args->{content} = sub { read($content, $buf, 1024); return $buf; }; my $assert = sub { $_[0] or Carp::croak( "Failed to $_[1] for Content-Length: $!", ); }; $assert->(defined(my $cur_pos = tell($content)), 'tell'); $assert->(seek($content, 0, SEEK_END), 'seek'); $assert->(defined(my $end_pos = tell($content)), 'tell'); $assert->(seek($content, $cur_pos, SEEK_SET), 'seek'); my $content_length = $end_pos - $cur_pos; push @headers, 'Content-Length' => $content_length; } my $req; if ($args->{content} && ref $args->{content} eq 'HASH') { # application/x-www-form-urlencoded $req = HTTP::Request::Common::request_type_with_data( $args->{method}, $args->{url}, @headers, Content => $args->{content} ); } else { # application/json or application/octet-stream # $args->{content} is encodeed json or file handle $req = HTTP::Request->new( $args->{method}, $args->{url}, \@headers, $args->{content}, ); } $req->protocol('HTTP/1.1'); my $res = $self->ua->request($req, $args->{write_code}); ($req, $res); } sub api_furl { my ($self, $args) = @_; if (my $write_file = delete $args->{write_file}) { $args->{write_code} = sub { $write_file->print($_[3]); }; } if (my $write_code = delete $args->{write_code}) { $args->{write_code} = sub { if ($_[0] =~ qr{ \A 2 }xms) { $write_code->(@_); } else { $self->error($_[3]); } }; } my $res = $self->furl->request(%$args); ($res->request, $res); } sub ua { my $self = shift; my $ua = LWP::UserAgent->new; $ua->timeout($self->timeout); if ($self->{env_proxy}) { $ua->env_proxy; } $ua; } sub furl { my $self = shift; unless ($self->{furl}) { $self->{furl} = Furl->new( timeout => $self->timeout, ssl_opts => { SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_PEER(), }, ); $self->{furl}->env_proxy if $self->{env_proxy}; } $self->{furl}; } sub mk_accessors { my $package = shift; no strict 'refs'; foreach my $field ( @_ ) { *{ $package . '::' . $field } = sub { return $_[0]->{ $field } if scalar( @_ ) == 1; return $_[0]->{ $field } = scalar( @_ ) == 2 ? $_[1] : [ @_[1..$#_] ]; }; } } sub env_proxy { $_[0]->{env_proxy} = defined $_[1] ? $_[1] : 1 } 1; __END__ =head1 NAME WebService::Dropbox - Perl interface to Dropbox API =head1 SYNOPSIS use WebService::Dropbox; my $dropbox = WebService::Dropbox->new({ key => '...', # App Key secret => '...' # App Secret }); # Authorization if ($access_token) { $dropbox->access_token($access_token); } else { my $url = $dropbox->authorize; print "Please Access URL and press Enter: $url\n"; print "Please Input Code: "; chomp( my $code = ); unless ($dropbox->token($code)) { die $dropbox->error; } print "Successfully authorized.\nYour AccessToken: ", $dropbox->access_token, "\n"; } my $info = $dropbox->get_current_account or die $dropbox->error; # download # https://www.dropbox.com/developers/documentation/http/documentation#files-download my $fh_download = IO::File->new('some file', '>'); $dropbox->download('/make_test_folder/test.txt', $fh_download) or die $dropbox->error; $fh_get->close; # upload # https://www.dropbox.com/developers/documentation/http/documentation#files-upload my $fh_upload = IO::File->new('some file'); $dropbox->upload('/make_test_folder/test.txt', $fh_upload) or die $dropbox->error; $fh_upload->close; # get_metadata # https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata my $data = $dropbox->get_metadata('/folder_a'); =head1 DESCRIPTION WebService::Dropbox is Perl interface to Dropbox API - Support Dropbox v2 REST API - Support Furl (Fast!!!) - Streaming IO (Low Memory) =head1 API v1 => v2 Migration guide =head2 Migration API files => download, files_put => upload ...etc L =head2 Migration OAuth1 Token => OAuth2 Token use WebService::Dropbox::TokenFromOAuth1; my $oauth2_access_token = WebService::Dropbox::TokenFromOAuth1->token_from_oauth1({ consumer_key => $dropbox->key, consumer_secret => $dropbox->secret, access_token => $access_token, # OAuth1 access_token access_secret => $access_secret, # OAuth1 access_secret }); warn $oauth2_access_token; =head1 Use API v1 B L =head2 cpanfile requires 'WebService::Dropbox', '== 1.22'; =head2 cpanm cpanm -L local ASKADNA/WebService-Dropbox-1.22.tar.gz =head2 curl mkdir lib/WebService curl -o lib/WebService/Dropbox.pm https://raw.githubusercontent.com/s-aska/p5-WebService-Dropbox/1.22/lib/WebService/Dropbox.pm =head1 API =head2 Auth L =head3 for CLI Sample my $url = $dropbox->authorize; print "Please Access URL: $url\n"; print "Please Input Code: "; chomp( my $code = ); unless ($dropbox->token($code)) { die $dropbox->error; } print "Successfully authorized.\nYour AccessToken: ", $dropbox->access_token, "\n"; =head3 for Web Sample use Amon2::Lite; use WebService::Dropbox; __PACKAGE__->load_plugins('Web::JSON'); my $key = $ENV{DROPBOX_APP_KEY}; my $secret = $ENV{DROPBOX_APP_SECRET}; my $dropbox = WebService::Dropbox->new({ key => $key, secret => $secret }); my $redirect_uri = 'http://localhost:5000/callback'; get '/' => sub { my ($c) = @_; my $url = $dropbox->authorize({ redirect_uri => $redirect_uri }); return $c->redirect($url); }; get '/callback' => sub { my ($c) = @_; my $code = $c->req->param('code'); my $token = $dropbox->token($code, $redirect_uri); my $account = $dropbox->get_current_account || { error => $dropbox->error }; return $c->render_json({ token => $token, account => $account }); }; __PACKAGE__->to_app(); =head3 authorize(\%optional_params) # for Simple CLI my $url = $dropbox->authorize(); # for Other my $url = $dropbox->authorize({ response_type => 'code', # code or token redirect_uri => '', state => '', require_role => '', force_reapprove => JSON::false, disable_signup => JSON::false, }); L =head3 token($code [, $redirect_uri]) This endpoint only applies to apps using the authorization code flow. An app calls this endpoint to acquire a bearer token once the user has authorized the app. Calls to /oauth2/token need to be authenticated using the apps's key and secret. These can either be passed as POST parameters (see parameters below) or via HTTP basic authentication. If basic authentication is used, the app key should be provided as the username, and the app secret should be provided as the password. # for CLI my $token = $dropbox->token($code); # for Web my $token = $dropbox->token($code, $redirect_uri); L =head3 revoke Disables the access token used to authenticate the call. my $result = $dropbox->revoke; L =head2 Files =head3 copy($from_path, $to_path) Copy a file or folder to a different location in the user's Dropbox. If the source path is a folder all its contents will be copied. my $result = $dropbox->copy($from_path, $to_path); L =head3 copy_reference_get($path) Get a copy reference to a file or folder. This reference string can be used to save that file or folder to another user's Dropbox by passing it to copy_reference/save. my $result = $dropbox->copy_reference_get($path); L =head3 copy_reference_save($copy_reference, $path) Save a copy reference returned by copy_reference/get to the user's Dropbox. my $result = $dropbox->copy_reference_save($copy_reference, $path); L =head3 create_folder($path) Create a folder at a given path. my $result = $dropbox->create_folder($path); L =head3 delete($path) Delete the file or folder at a given path. If the path is a folder, all its contents will be deleted too. A successful response indicates that the file or folder was deleted. The returned metadata will be the corresponding FileMetadata or FolderMetadata for the item at time of deletion, and not a DeletedMetadata object. my $result = $dropbox->delete($path); L =head3 delete_batch($paths) Delete the files or folders at a list of given paths. The list is provided as the first arg in an arrayref. A successful response indicates that the files or folders were queued for async deletion. The returned object will include the async_job_id. my $result = $dropbox->delete_batch($paths); L =head3 delete_batch_check($async_job_id) Fetch the status of a asynchronous job for a delete_batch call. Returns a status tag .tag with possible values 'in_progress', 'complete' and 'failed'. If success, also returns list of result for each entry. my $result = $dropbox->delete_batch_check($async_job_id); L =head3 download($path, $output [, \%opts]) Download a file from a user's Dropbox. # File handle my $fh = IO::File->new('some file', '>'); $dropbox->download($path, $fh); # Code reference my $write_code = sub { # compatible with LWP::UserAgent and Furl::HTTP my $chunk = @_ == 4 ? @_[3] : $_[0]; print $chunk; }; $dropbox->download($path, $write_code); # Range my $fh = IO::File->new('some file', '>'); $dropbox->download($path, $fh, { headers => ['Range' => 'bytes=5-6'] }); # If-None-Match / ETag my $fh = IO::File->new('some file', '>'); $dropbox->download($path, $fh); # $dropbox->res->code => 200 my $etag = $dropbox->res->header('ETag'); $dropbox->download($path, $fh, { headers => ['If-None-Match', $etag] }); # $dropbox->res->code => 304 L =head3 get_metadata($path [, \%optional_params]) Returns the metadata for a file or folder. Note: Metadata for the root folder is unsupported. my $result = $dropbox->get_metadata($path); my $result = $dropbox->get_metadata($path, { include_media_info => JSON::true, include_deleted => JSON::true, include_has_explicit_shared_members => JSON::false, }); L =head3 get_preview($path, $outout [, \%opts]) Get a preview for a file. Currently previews are only generated for the files with the following extensions: .doc, .docx, .docm, .ppt, .pps, .ppsx, .ppsm, .pptx, .pptm, .xls, .xlsx, .xlsm, .rtf # File handle my $fh = IO::File->new('some file', '>'); $dropbox->get_preview($path, $fh); # Code reference my $write_code = sub { # compatible with LWP::UserAgent and Furl::HTTP my $chunk = @_ == 4 ? @_[3] : $_[0]; print $chunk; }; $dropbox->get_preview($path, $write_code); # Range my $fh = IO::File->new('some file', '>'); $dropbox->get_preview($path, $fh, { headers => ['Range' => 'bytes=5-6'] }); # If-None-Match / ETag my $fh = IO::File->new('some file', '>'); $dropbox->get_preview($path, $fh); # $dropbox->res->code => 200 my $etag = $dropbox->res->header('ETag'); $dropbox->get_preview($path, $fh, { headers => ['If-None-Match', $etag] }); # $dropbox->res->code => 304 L =head3 get_temporary_link($path) Get a temporary link to stream content of a file. This link will expire in four hours and afterwards you will get 410 Gone. Content-Type of the link is determined automatically by the file's mime type. my $result = $dropbox->get_temporary_link($path); my $content_type = $dropbox->res->header('Content-Type'); L =head3 get_thumbnail($path, $output [, \%optional_params, $opts]) Get a thumbnail for an image. This method currently supports files with the following file extensions: jpg, jpeg, png, tiff, tif, gif and bmp. Photos that are larger than 20MB in size won't be converted to a thumbnail. # File handle my $fh = IO::File->new('some file', '>'); $dropbox->get_thumbnail($path, $fh); my $optional_params = { format => 'jpeg', size => 'w64h64' }; $dropbox->get_thumbnail($path, $fh, $optional_params); # Code reference my $write_code = sub { # compatible with LWP::UserAgent and Furl::HTTP my $chunk = @_ == 4 ? @_[3] : $_[0]; print $chunk; }; $dropbox->get_thumbnail($path, $write_code); # Range my $fh = IO::File->new('some file', '>'); $dropbox->get_thumbnail($path, $fh, $optional_params, { headers => ['Range' => 'bytes=5-6'] }); # If-None-Match / ETag my $fh = IO::File->new('some file', '>'); $dropbox->get_thumbnail($path, $fh); # $dropbox->res->code => 200 my $etag = $dropbox->res->header('ETag'); $dropbox->get_thumbnail($path, $fh, $optional_params, { headers => ['If-None-Match', $etag] }); # $dropbox->res->code => 304 L =head3 list_folder($path [, \%optional_params]) Returns the contents of a folder. my $result = $dropbox->list_folder($path); my $result = $dropbox->list_folder($path, { recursive => JSON::false, include_media_info => JSON::false, include_deleted => JSON::false, include_has_explicit_shared_members => JSON::false }); L =head3 list_folder_continue($cursor) Once a cursor has been retrieved from list_folder, use this to paginate through all files and retrieve updates to the folder. my $result = $dropbox->list_folder_continue($cursor); L =head3 list_folder_get_latest_cursor($path [, \%optional_params]) A way to quickly get a cursor for the folder's state. Unlike list_folder, list_folder/get_latest_cursor doesn't return any entries. This endpoint is for app which only needs to know about new files and modifications and doesn't need to know about files that already exist in Dropbox. my $result = $dropbox->list_folder_get_latest_cursor($path); my $result = $dropbox->list_folder_get_latest_cursor($path, { recursive => JSON::false, include_media_info => JSON::false, include_deleted => JSON::false, include_has_explicit_shared_members => JSON::false }); L =head3 list_folder_longpoll($cursor [, \%optional_params]) A longpoll endpoint to wait for changes on an account. In conjunction with list_folder/continue, this call gives you a low-latency way to monitor an account for file changes. The connection will block until there are changes available or a timeout occurs. This endpoint is useful mostly for client-side apps. If you're looking for server-side notifications, check out our webhooks documentation. my $result = $dropbox->list_folder_longpoll($cursor); my $result = $dropbox->list_folder_longpoll($cursor, { timeout => 30 }); L =head3 list_revisions($path [, \%optional_params]) Return revisions of a file. my $result = $dropbox->list_revisions($path); my $result = $dropbox->list_revisions($path, { limit => 10 }); L =head3 move($from_path, $to_path) Return revisions of a file. my $result = $dropbox->move($from_path, $to_path); L =head3 permanently_delete($path) Permanently delete the file or folder at a given path (see https://www.dropbox.com/en/help/40). Note: This endpoint is only available for Dropbox Business apps. my $result = $dropbox->permanently_delete($path); L =head3 restore($path, $rev) Restore a file to a specific revision. my $result = $dropbox->restore($path, $rev); L =head3 save_url($path, $url) Save a specified URL into a file in user's Dropbox. If the given path already exists, the file will be renamed to avoid the conflict (e.g. myfile (1).txt). my $result = $dropbox->save_url($path, $url); L =head3 save_url_check_job_status($async_job_id) Check the status of a save_url job. my $result = $dropbox->save_url_check_job_status($async_job_id); L =head3 search($path, $query, [, \%optional_params]) Searches for files and folders. Note: Recent changes may not immediately be reflected in search results due to a short delay in indexing. my $result = $dropbox->search($path); my $result = $dropbox->search($path, 'prime numbers', { start => 0, max_results => 100, mode => 'filename' }); L =head3 upload($path, $content [, \%optional_params]) Create a new file with the contents provided in the request. Do not use this to upload a file larger than 150 MB. Instead, create an upload session with upload_session/start. # File Handle my $content = IO::File->new('./my.cnf', '<'); my $result = $dropbox->upload($path, $content); my $result = $dropbox->upload($path, $content, { mode => 'add', autorename => JSON::true, mute => JSON::false }); L =head3 upload_session($path, $content [, \%optional_params, $limit]) Uploads large files by upload_session API # File Handle my $content = IO::File->new('./mysql.dump', '<'); my $result = $dropbox->upload_session($path, $content); my $result = $dropbox->upload_session($path, $content, { mode => 'add', autorename => JSON::true, mute => JSON::false }); =over 4 =item L =item L =item L =back =head3 upload_session_start($content [, \%optional_params]) Upload sessions allow you to upload a single file using multiple requests. This call starts a new upload session with the given data. You can then use upload_session/append_v2 to add more data and upload_session/finish to save all the data to a file in Dropbox. A single request should not upload more than 150 MB of file contents. # File Handle my $content = IO::File->new('./access.log', '<'); $dropbox->upload_session_start($content); $dropbox->upload_session_start($content, { close => JSON::true }); L =head3 upload_session_append_v2($content, $params) Append more data to an upload session. When the parameter close is set, this call will close the session. A single request should not upload more than 150 MB of file contents. # File Handle my $content = IO::File->new('./access.log.1', '<'); my $result = $dropbox->upload_session_append_v2($content, { cursor => { session_id => $session_id, offset => $offset }, close => JSON::true }); L =head3 upload_session_finish($content, $params) Finish an upload session and save the uploaded data to the given file path. A single request should not upload more than 150 MB of file contents. # File Handle my $content = IO::File->new('./access.log.last', '<'); my $result = $dropbox->upload_session_finish($content, { cursor => { session_id => $session_id, offset => $offset }, commit => { path => '/Homework/math/Matrices.txt', mode => 'add', autorename => JSON::true, mute => JSON::false } }); L =head2 Users =head3 get_account($account_id) Get information about a user's account. my $result = $dropbox->get_account($account_id); L =head3 get_account_batch(\@account_ids) Get information about multiple user accounts. At most 300 accounts may be queried per request. my $result = $dropbox->get_account_batch($account_ids); L =head3 get_current_account() Get information about the current user's account. my $result = $dropbox->get_current_account; L =head3 get_space_usage() Get the space usage information for the current user's account. my $result = $dropbox->get_space_usage; L =head2 Sharing =head3 create_shared_link_with_settings($path, $settings) Create a shared link with custom settings. If no settings are given then the default visibility is RequestedVisibility.public (The resolved visibility, though, may depend on other aspects such as team and shared folder settings). my $result = $dropbox->create_shared_link_with_settings($path, $settings); L =head3 list_shared_links($path) List shared links of this user. If no path is given, returns a list of all shared links for the current user. For members of business teams using team space and member folders, returns all shared links in the team member's home folder unless the team space ID is specified in the request header. For more information, refer to the Namespace Guide. If a non-empty path is given, returns a list of all shared links that allow access to the given path - direct links to the given path and links to parent folders of the given path. Links to parent folders can be suppressed by setting direct_only to true. my $result = $dropbox->list_shared_links($path); L =head3 modify_shared_link_settings($path, $settings, $remove_expiration) Modify the shared link's settings. If the requested visibility conflict with the shared links policy of the team or the shared folder (in case the linked file is part of a shared folder) then the LinkPermissions.resolved_visibility of the returned SharedLinkMetadata will reflect the actual visibility of the shared link and the LinkPermissions.requested_visibility will reflect the requested visibility. my $result = $dropbox->modify_shared_link_settings($path, $settings, $remove_expiration); L =head3 revoke_shared_link($url) Revoke a shared link. Note that even after revoking a shared link to a file, the file may be accessible if there are shared links leading to any of the file parent folders. To list all shared links that enable access to a specific file, you can use the list_shared_links with the file as the ListSharedLinksArg.path argument. my $result = $dropbox->revoke_shared_link($url); L =head2 Error Handling and Debug =head3 error : str my $result = $dropbox->$some_api; unless ($result) { die $dropbox->error; } =head3 req : HTTP::Request or Furl::Request my $result = $dropbox->$some_api; warn $dropbox->req->as_string; =head3 res : HTTP::Response or Furl::Response my $result = $dropbox->$some_api; warn $dropbox->res->code; warn $dropbox->res->header('ETag'); warn $dropbox->res->header('Content-Type'); warn $dropbox->res->header('Content-Length'); warn $dropbox->res->header('X-Dropbox-Request-Id'); warn $dropbox->res->as_string; =head3 env_proxy enable HTTP_PROXY, NO_PROXY my $dropbox = WebService::Dropbox->new(); $dropbox->env_proxy; =head3 debug enable or disable debug mode my $dropbox = WebService::Dropbox->new(); $dropbox->debug; # disabled $dropbox->debug(0); # disabled $dropbox->debug(1); # enabled =head3 verbose more warnings. my $dropbox = WebService::Dropbox->new(); $dropbox->verbose; # disabled $dropbox->verbose(0); # disabled $dropbox->verbose(1); # enabled =head1 AUTHOR Shinichiro Aska =head1 SEE ALSO =over 4 =item L =item L =back =head1 LICENSE This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Auth.pm100644000765000024 426615124606754 22073 0ustar00askastaff000000000000WebService-Dropbox-2.10/lib/WebService/Dropboxpackage WebService::Dropbox::Auth; use strict; use warnings; use parent qw(Exporter); our @EXPORT = do { no strict 'refs'; grep { $_ !~ qr{ \A [A-Z]+ \z }xms } keys %{ __PACKAGE__ . '::' }; }; # https://www.dropbox.com/developers/documentation/http/documentation#oauth2-authorize sub authorize { my ($self, $params) = @_; $params ||= {}; $params->{response_type} ||= 'code'; my $url = URI->new('https://www.dropbox.com/oauth2/authorize'); $url->query_form( client_id => $self->key, %$params, ); $url->as_string; } # https://www.dropbox.com/developers/documentation/http/documentation#oauth2-token sub token { my ($self, $code, $redirect_uri) = @_; my $data = $self->api({ url => 'https://api.dropboxapi.com/oauth2/token', params => { client_id => $self->key, client_secret => $self->secret, grant_type => 'authorization_code', code => $code, ( $redirect_uri ? ( redirect_uri => $redirect_uri ) : () ), }, }); if ($data && $data->{access_token}) { $self->access_token($data->{access_token}); } $data; } # https://www.dropbox.com/developers/documentation/http/documentation#oauth2-token # This uses the token method with a refresh token to get an updated access token. sub refresh_access_token { my ($self, $refresh_token) = @_; my $data = $self->api({ url => 'https://api.dropboxapi.com/oauth2/token', params => { client_id => $self->key, client_secret => $self->secret, grant_type => 'refresh_token', refresh_token => $refresh_token, }, }); # at this point the access token should be in $data # so set it like WebService::Dropbox::Auth::token does if ($data && $data->{access_token}) { $self->access_token($data->{access_token}); } $data; } # https://www.dropbox.com/developers/documentation/http/documentation#auth-token-revoke sub revoke { my ($self) = @_; my $res = $self->api({ url => 'https://api.dropboxapi.com/2/auth/token/revoke', }); $self->access_token(undef); $res; } 1; Files.pm100644000765000024 1450315124606754 22247 0ustar00askastaff000000000000WebService-Dropbox-2.10/lib/WebService/Dropboxpackage WebService::Dropbox::Files; use strict; use warnings; use parent qw(Exporter); our @EXPORT = do { no strict 'refs'; grep { $_ =~ qr{ \A [a-z] }xms } keys %{ __PACKAGE__ . '::' }; }; # https://www.dropbox.com/developers/documentation/http/documentation#files-copy sub copy { my ($self, $from_path, $to_path) = @_; my $params = { from_path => $from_path, to_path => $to_path, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/copy', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-create_folder sub create_folder { my ($self, $path) = @_; my $params = { path => $path, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/create_folder', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-delete sub delete { my ($self, $path) = @_; my $params = { path => $path, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/delete', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-delete_batch sub delete_batch { my ($self, $paths) = @_; my $params = { entries => [map {+{path => $_}} @$paths], }; $self->api({ url => 'https://api.dropboxapi.com/2/files/delete_batch', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-delete_batch-check sub delete_batch_check { my ($self, $job_id) = @_; my $params = { async_job_id => $job_id, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/delete_batch/check', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-download sub download { my ($self, $path, $output, $opts) = @_; $self->api({ url => 'https://content.dropboxapi.com/2/files/download', params => { path => $path }, output => $output, %{ $opts || +{} }, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata sub get_metadata { my ($self, $path, $optional_params) = @_; my $params = { path => $path, %{ $optional_params || {} }, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/get_metadata', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-get_preview sub get_preview { my ($self, $path, $output, $opts) = @_; my $params = { path => $path, }; $self->api({ url => 'https://content.dropboxapi.com/2/files/get_preview', params => $params, output => $output, %{ $opts || +{} }, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-get_temporary_link sub get_temporary_link { my ($self, $path) = @_; my $params = { path => $path, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/get_temporary_link', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-get_thumbnail sub get_thumbnail { my ($self, $path, $output, $optional_params, $opts) = @_; my $params = { path => $path, %{ $optional_params || {} }, }; $self->api({ url => 'https://content.dropboxapi.com/2/files/get_thumbnail', params => $params, output => $output, %{ $opts || +{} }, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-list_revisions sub list_revisions { my ($self, $path, $optional_params) = @_; my $params = { path => $path, %{ $optional_params || {} }, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/list_revisions', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-move sub move { my ($self, $from_path, $to_path) = @_; my $params = { from_path => $from_path, to_path => $to_path, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/move', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-permanently_delete sub permanently_delete { my ($self, $path) = @_; my $params = { path => $path, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/permanently_delete', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-restore sub restore { my ($self, $path, $rev) = @_; my $params = { path => $path, rev => $rev, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/restore', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-save_url sub save_url { my ($self, $path, $url) = @_; my $params = { path => $path, url => $url, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/save_url', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-save_url-check_job_status sub save_url_check_job_status { my ($self, $async_job_id) = @_; my $params = { async_job_id => $async_job_id, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/save_url/check_job_status', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-search sub search { my ($self, $path, $query, $optional_params) = @_; my $params = { path => $path, query => $query, %{ $optional_params || {} }, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/search', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-upload sub upload { my ($self, $path, $content, $optional_params) = @_; my $params = { path => $path, %{ $optional_params || {} }, }; $self->api({ url => 'https://content.dropboxapi.com/2/files/upload', params => $params, content => $content, }); } 1; CopyReference.pm100644000765000024 165115124606754 24760 0ustar00askastaff000000000000WebService-Dropbox-2.10/lib/WebService/Dropbox/Filespackage WebService::Dropbox::Files::CopyReference; use strict; use warnings; use parent qw(Exporter); our @EXPORT = do { no strict 'refs'; grep { $_ !~ qr{ \A [A-Z]+ \z }xms } keys %{ __PACKAGE__ . '::' }; }; # https://www.dropbox.com/developers/documentation/http/documentation#files-copy_reference-get sub copy_reference_get { my ($self, $path) = @_; my $params = { path => $path, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/copy_reference/get', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-copy_reference-save sub copy_reference_save { my ($self, $copy_reference, $path) = @_; my $params = { copy_reference => $copy_reference, path => $path, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/copy_reference/save', params => $params, }); } 1; ListFolder.pm100644000765000024 330015124606754 24267 0ustar00askastaff000000000000WebService-Dropbox-2.10/lib/WebService/Dropbox/Filespackage WebService::Dropbox::Files::ListFolder; use strict; use warnings; use parent qw(Exporter); our @EXPORT = do { no strict 'refs'; grep { $_ !~ qr{ \A [A-Z]+ \z }xms } keys %{ __PACKAGE__ . '::' }; }; # https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder sub list_folder { my ($self, $path, $optional_params) = @_; my $params = { path => $path, %{ $optional_params || {} }, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/list_folder', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-continue sub list_folder_continue { my ($self, $cursor) = @_; my $params = { cursor => $cursor, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/list_folder/continue', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-get_latest_cursor sub list_folder_get_latest_cursor { my ($self, $path, $optional_params) = @_; my $params = { path => $path, %{ $optional_params || {} }, }; $self->api({ url => 'https://api.dropboxapi.com/2/files/list_folder/get_latest_cursor', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-longpoll sub list_folder_longpoll { my ($self, $cursor, $optional_params) = @_; my $params = { cursor => $cursor, %{ $optional_params || {} }, }; $self->api({ url => 'https://notify.dropboxapi.com/2/files/list_folder/longpoll', params => $params, }); } 1; UploadSession.pm100644000765000024 637715124606754 25031 0ustar00askastaff000000000000WebService-Dropbox-2.10/lib/WebService/Dropbox/Filespackage WebService::Dropbox::Files::UploadSession; use strict; use warnings; use parent qw(Exporter); our @EXPORT = do { no strict 'refs'; grep { $_ !~ qr{ \A [A-Z]+ \z }xms } keys %{ __PACKAGE__ . '::' }; }; sub upload_session { my ($self, $path, $content, $optional_params, $limit) = @_; $limit ||= 4 * 1024 * 1024; # A typical chunk is 4 MB my $session_id; my $offset = 0; my $commit_params = { path => $path, %{ $optional_params || {} }, }; my $upload; $upload = sub { my $buf; my $total = 0; my $chunk = 1024; my $tmp = File::Temp->new; my $is_last; while (my $read = read($content, $buf, $chunk)) { $tmp->print($buf); $total += $read; my $remaining = $limit - $total; if ($chunk > $remaining) { $chunk = $remaining; } unless ($chunk) { last; } } $tmp->flush; $tmp->seek(0, 0); # finish or small file if ($total < $limit) { if ($session_id) { my $params = { cursor => { session_id => $session_id, offset => $offset, }, commit => $commit_params, }; return $self->upload_session_finish($tmp, $params); } else { return $self->upload($path, $tmp, $commit_params); } } # append elsif ($session_id) { my $params = { cursor => { session_id => $session_id, offset => $offset, }, }; unless ($self->upload_session_append_v2($tmp, $params)) { # some error return; } $offset += $total; } # start else { my $res = $self->upload_session_start($tmp); if ($res && $res->{session_id}) { $session_id = $res->{session_id}; $offset = $total; } else { # some error return; } } $upload->(); }; $upload->(); } # https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start sub upload_session_start { my ($self, $content, $params) = @_; $self->api({ url => 'https://content.dropboxapi.com/2/files/upload_session/start', params => $params, content => $content, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-append_v2 sub upload_session_append_v2 { my ($self, $content, $params) = @_; $self->api({ url => 'https://content.dropboxapi.com/2/files/upload_session/append_v2', params => $params, content => $content, }); } # https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-finish sub upload_session_finish { my ($self, $content, $params) = @_; $self->api({ url => 'https://content.dropboxapi.com/2/files/upload_session/finish', params => $params, content => $content, }); } 1; Sharing.pm100644000765000024 377415124606754 22570 0ustar00askastaff000000000000WebService-Dropbox-2.10/lib/WebService/Dropboxpackage WebService::Dropbox::Sharing; use strict; use warnings; use parent qw(Exporter); ## preliminary version with support for creating and managing links ## to shared files. more to follow... our @EXPORT = do { no strict 'refs'; grep { $_ =~ qr{ \A [a-z] }xms } keys %{ __PACKAGE__ . '::' }; }; # https://www.dropbox.com/developers/documentation/http/documentation#sharing-create_shared_link_with_settings sub create_shared_link_with_settings { my ($self, $path, $settings) = @_; my $params = { path => $path, settings => $settings, }; $self->api({ url => 'https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#sharing-list_shared_links sub list_shared_links { my ($self, $path) = @_; my $params = { path => $path, }; $self->api({ url => 'https://api.dropboxapi.com/2/sharing/list_shared_links', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#sharing-modify_shared_link_settings sub modify_shared_link_settings { my ($self, $path, $settings, $remove_expiration) = @_; # this assumes the api converts 1 and 0 to JSON::true and JSON::false accordingly if ($remove_expiration) { $remove_expiration = 1; } else { $remove_expiration = 0; } my $params = { path => $path, settings => $settings, remove_expiration => $remove_expiration, }; $self->api({ url => 'https://api.dropboxapi.com/2/sharing/modify_shared_link_settings', params => $params, }); } # https://www.dropbox.com/developers/documentation/http/documentation#sharing-revoke_shared_link sub revoke_shared_link { my ($self, $url) = @_; my $params = { url => $url, }; $self->api({ url => 'https://api.dropboxapi.com/2/sharing/revoke_shared_link', params => $params, }); } 1; TokenFromOAuth1.pm100644000765000024 216415124606754 24113 0ustar00askastaff000000000000WebService-Dropbox-2.10/lib/WebService/Dropboxpackage WebService::Dropbox::TokenFromOAuth1; use strict; use warnings; use JSON; use Net::OAuth; use LWP::UserAgent; sub token_from_oauth1 { my ($class, $args) = @_; my $request = Net::OAuth->request('protected resource')->new( consumer_key => $args->{consumer_key}, consumer_secret => $args->{consumer_secret}, request_url => 'https://api.dropboxapi.com/1/oauth2/token_from_oauth1', request_method => 'POST', signature_method => 'PLAINTEXT', # HMAC-SHA1 can't delete %20.txt bug... timestamp => time, nonce => &nonce, token => $args->{access_token}, token_secret => $args->{access_secret}, ); $request->sign; my $ua = LWP::UserAgent->new; my $res = $ua->post($request->to_url); if ($res->is_success) { my $data = decode_json($res->decoded_content); return $data->{access_token}; } warn $res->decoded_content; return; } sub nonce { my $length = 16; my @chars = ( 'A'..'Z', 'a'..'z', '0'..'9' ); my $ret; for (1..$length) { $ret .= $chars[int rand @chars]; } return $ret; } 1; Users.pm100644000765000024 244215124606754 22265 0ustar00askastaff000000000000WebService-Dropbox-2.10/lib/WebService/Dropboxpackage WebService::Dropbox::Users; use strict; use warnings; use parent qw(Exporter); our @EXPORT = do { no strict 'refs'; grep { $_ !~ qr{ \A [A-Z]+ \z }xms } keys %{ __PACKAGE__ . '::' }; }; # https://www.dropbox.com/developers/documentation/http/documentation#users-get_account sub get_account { my ($self, $account_id) = @_; $self->api({ url => 'https://api.dropboxapi.com/2/users/get_account', params => { account_id => $account_id, }, }); } # https://www.dropbox.com/developers/documentation/http/documentation#users-get_account_batch sub get_account_batch { my ($self, $account_ids) = @_; $self->api({ url => 'https://api.dropboxapi.com/2/users/get_account_batch', params => { account_ids => $account_ids, }, }); } # https://www.dropbox.com/developers/documentation/http/documentation#users-get_current_account sub get_current_account { my ($self) = @_; $self->api({ url => 'https://api.dropboxapi.com/2/users/get_current_account', }); } # https://www.dropbox.com/developers/documentation/http/documentation#users-get_space_usage sub get_space_usage { my ($self) = @_; $self->api({ url => 'https://api.dropboxapi.com/2/users/get_space_usage', }); } 1; minil.toml100644000765000024 16315124606754 16370 0ustar00askastaff000000000000WebService-Dropbox-2.10name = "WebService-Dropbox" authority = "cpan:ASKADNA" badges = ['travis'] markdown_maker = "Pod::Markdown::Github"00_compile.t100644000765000024 13215124606754 16736 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Test::More; use_ok $_ for qw( WebService::Dropbox ); done_testing; 05_accessor.t100644000765000024 52315124606754 17121 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Test::More; use WebService::Dropbox; my $dropbox = WebService::Dropbox->new(); is $dropbox->{env_proxy}, 0; $dropbox->env_proxy; is $dropbox->{env_proxy}, 1; $dropbox->env_proxy(0); is $dropbox->{env_proxy}, 0; $dropbox = WebService::Dropbox->new({ env_proxy => 1 }); is $dropbox->{env_proxy}, 1; done_testing(); 10_api.t100644000765000024 1375215124606754 16134 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Data::Dumper; use Encode; use Test::More; use File::Temp; use IO::File; use File::Basename qw(dirname); use File::Spec; use WebService::Dropbox; if (!$ENV{'DROPBOX_APP_KEY'} or !$ENV{'DROPBOX_APP_SECRET'}) { plan skip_all => 'missing App Key or App Secret'; } my $dropbox = WebService::Dropbox->new({ key => $ENV{'DROPBOX_APP_KEY'}, secret => $ENV{'DROPBOX_APP_SECRET'}, env_proxy => 1, }); $dropbox->use_lwp if $ENV{'DROPBOX_USE_LWP'}; $dropbox->debug; $dropbox->verbose; if ($ENV{'DROPBOX_ACCESS_TOKEN'}) { $dropbox->access_token($ENV{'DROPBOX_ACCESS_TOKEN'}); } else { my $url = $dropbox->authorize or die $dropbox->error; warn "Please Access URL $url\n"; warn "Enter Code: "; chomp( my $code = ); $dropbox->token($code) or die $dropbox->error; warn "access_token: ", $dropbox->access_token, "\n"; } $dropbox->get_current_account or die $dropbox->error; my $exists = $dropbox->get_metadata('/make_test_folder'); if ($exists) { $dropbox->delete('/make_test_folder') or die $dropbox->error; is $dropbox->res->code, 200, "delete make_test_folder"; } $dropbox->download("/x", File::Temp->new); like $dropbox->error, qr|not_found|, 'File not found'; $dropbox->create_folder('/make_test_folder') or die $dropbox->error; is $dropbox->res->code, 200, "create_folder success"; $dropbox->create_folder('/make_test_folder'); is $dropbox->res->code, 409, "create_folder error already exists."; # my $file_mark = decode_utf8('\'!"#$%&(=~|@`{}[]+*;,<>_?-^ 日本語.txt'); # # files_put # my $fh_put = File::Temp->new; # $fh_put->print('test.test.test.'); # $fh_put->flush; # $fh_put->seek(0, 0); # $dropbox->files_put('make_test_folder/' . $file_mark, $fh_put); # $fh_put->close; # # files_put_chunked # if (-f '/tmp/1GB.dat') { # my $fh = IO::File->new('/tmp/1GB.dat'); # my $data = $dropbox->files_put_chunked('make_test_folder/large-' . $file_mark, $fh); # $fh->close; # } # # metadata # $exists = $dropbox->metadata('make_test_folder/' . $file_mark) # or die $dropbox->error; # if ($exists and !$exists->{is_deleted}) { # pass "put."; # } # # copy # my $copy = $dropbox->copy('make_test_folder/' . $file_mark, 'make_test_folder/test.txt') # or die $dropbox->error; # # copy_ref # my $copy_ref = $dropbox->copy_ref('make_test_folder/' . $file_mark) # or die $dropbox->error; # $copy = $dropbox->copy($copy_ref, 'make_test_folder/test2.txt') # or die $dropbox->error; # # move # my $move = $dropbox->move('make_test_folder/' . $file_mark, 'make_test_folder/test2b.txt') # or die $dropbox->error; # # files_put # $fh_put = File::Temp->new; # $fh_put->print('test.'); # $fh_put->flush; # $fh_put->seek(0, 0); # $dropbox->files_put('make_test_folder/' . $file_mark, $fh_put) # or die $dropbox->error; # $fh_put->close; # # files # my $fh_get = File::Temp->new; # $dropbox->files('make_test_folder/' . $file_mark, $fh_get) or die $dropbox->error; # $fh_get->flush; # $fh_get->seek(0, 0); # is $fh_get->getline, 'test.', 'download success.'; # $fh_get->close; # # files_put overwrite # $fh_put = File::Temp->new; # $fh_put->print('test2.'); # $fh_put->flush; # $fh_put->seek(0, 0); # $dropbox->files_put('make_test_folder/' . $file_mark, $fh_put) or die $dropbox->error; # $fh_put->close; # $fh_get = File::Temp->new; # $dropbox->files('make_test_folder/' . $file_mark, $fh_get) or die $dropbox->error; # $fh_get->flush; # $fh_get->seek(0, 0); # is $fh_get->getline, 'test2.', 'overwrite success.'; # $fh_get->close; # # files_put no overwrite # $fh_put = File::Temp->new; # $fh_put->print('test3.'); # $fh_put->flush; # $fh_put->seek(0, 0); # $dropbox->files_put('make_test_folder/test.txt', $fh_put, { overwrite => 0 }) # or die $dropbox->error; # $fh_put->close; # $exists = $dropbox->metadata('make_test_folder/test (1).txt'); # if ($exists and !$exists->{is_deleted}) { # pass "no overwrite success."; # } # # delta # my $delta = $dropbox->delta() # or die $dropbox->error; # # revisions # my $revisions = $dropbox->revisions('make_test_folder/' . $file_mark) # or die $dropbox->error; # # restore # my $restore = $dropbox->restore('make_test_folder/' . $file_mark, { rev => $revisions->[1]->{rev} }) # or die $dropbox->error; # $fh_get = File::Temp->new; # $dropbox->files('make_test_folder/' . $file_mark, $fh_get) or die $dropbox->error; # $fh_get->flush; # $fh_get->seek(0, 0); # is $fh_get->getline, 'test.', 'restore success.'; # $fh_get->close; # # search # my $search = $dropbox->search('make_test_folder/', { query => 'test' }) # or die $dropbox->error; # is scalar(@$search), 4, 'search'; # # shares # my $shares = $dropbox->shares('make_test_folder/' . $file_mark) # or die $dropbox->error; # ok $shares->{url}, "shares"; # # media # my $media = $dropbox->media('make_test_folder/' . $file_mark) # or die $dropbox->error; # ok $shares->{url}, "media"; # # delete # $dropbox->delete('make_test_folder/' . $file_mark) or die $dropbox->error; # # thumbnails # $fh_put = IO::File->new(File::Spec->catfile(dirname(__FILE__), 'sample.png')); # $dropbox->files_put('make_test_folder/sample.png', $fh_put) or die $dropbox->error; # $fh_put->close; # $fh_get = File::Temp->new; # $dropbox->thumbnails('make_test_folder/sample.png', $fh_get) or die $dropbox->error; # $fh_get->flush; # $fh_get->seek(0, 0); # ok -s $fh_get, 'thumbnails.'; # $fh_get->close; # # japanese # my $file_utf8 = decode_utf8('日本語.txt'); # my $file_move_utf8 = decode_utf8('日本語_移動.txt'); # $fh_put = File::Temp->new; # $fh_put->print('test5.'); # $fh_put->flush; # $fh_put->seek(0, 0); # $dropbox->files_put('make_test_folder/' . $file_utf8, $fh_put) # or die $dropbox->error; # $fh_put->close; # $exists = $dropbox->metadata('make_test_folder/' . $file_utf8); # if ($exists and !$exists->{is_deleted}) { # pass "utf8."; # } # $dropbox->move('make_test_folder/' . $file_utf8, 'make_test_folder/' . $file_move_utf8) or die $dropbox->error; # $dropbox->delete('make_test_folder/' . $file_move_utf8) or die $dropbox->error; done_testing(); 11_range.t100644000765000024 357715124606754 16444 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Data::Dumper; use Encode; use Test::More; use File::Temp; use IO::File; use File::Basename qw(dirname); use File::Spec; use WebService::Dropbox; if (!$ENV{'DROPBOX_APP_KEY'} or !$ENV{'DROPBOX_APP_SECRET'} or !$ENV{'DROPBOX_ACCESS_TOKEN'}) { plan skip_all => 'missing App Key or App Secret'; } my $dropbox = WebService::Dropbox->new({ key => $ENV{'DROPBOX_APP_KEY'}, secret => $ENV{'DROPBOX_APP_SECRET'}, access_token => $ENV{'DROPBOX_ACCESS_TOKEN'}, env_proxy => 1, }); $dropbox->debug; $dropbox->verbose; $dropbox->get_current_account or die $dropbox->error; my $exists = $dropbox->get_metadata('/make_test_folder'); unless ($exists) { $dropbox->create_folder('/make_test_folder') or die $dropbox->error; is $dropbox->res->code, 200, "delete make_test_folder"; } my $file_mark = decode_utf8('\'!"#$%&(=~|@`{}[]+*;,<>_?-^ 日本語.txt'); # upload my $fh_put = File::Temp->new; $fh_put->print('test.test.test.'); $fh_put->flush; $fh_put->seek(0, 0); $dropbox->upload('/make_test_folder/' . $file_mark, $fh_put) or die $dropbox->error; $fh_put->close; # download my $fh_get = File::Temp->new; $dropbox->download('/make_test_folder/' . $file_mark, $fh_get) or die $dropbox->error; $fh_get->flush; $fh_get->seek(0, 0); is $fh_get->getline, 'test.test.test.', 'download success.'; $fh_get->close; $fh_get = File::Temp->new; $dropbox->download('/make_test_folder/' . $file_mark, $fh_get, { headers => ['Range' => 'bytes=10-14'] }) or die $dropbox->error; $fh_get->flush; $fh_get->seek(0, 0); is $fh_get->getline, 'test.', 'download range success.'; $fh_get->close; $dropbox->use_lwp; $fh_get = File::Temp->new; $dropbox->download('/make_test_folder/' . $file_mark, $fh_get, { headers => ['Range' => 'bytes=10-14'] }) or die $dropbox->error; $fh_get->flush; $fh_get->seek(0, 0); is $fh_get->getline, 'test.', 'download range success.'; $fh_get->close; done_testing(); 12_304.t100644000765000024 207715124606754 15651 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Data::Dumper; use Encode; use Test::More; use File::Temp; use IO::File; use File::Basename qw(dirname); use File::Spec; use WebService::Dropbox; if (!$ENV{'DROPBOX_APP_KEY'} or !$ENV{'DROPBOX_APP_SECRET'} or !$ENV{'DROPBOX_ACCESS_TOKEN'}) { plan skip_all => 'missing App Key or App Secret'; } my $dropbox = WebService::Dropbox->new({ key => $ENV{'DROPBOX_APP_KEY'}, secret => $ENV{'DROPBOX_APP_SECRET'}, access_token => $ENV{'DROPBOX_ACCESS_TOKEN'}, env_proxy => 1, }); $dropbox->debug; $dropbox->verbose; $dropbox->get_current_account or die $dropbox->error; my $fh_put = File::Temp->new; $fh_put->print('test.test.test.'); $fh_put->flush; $fh_put->seek(0, 0); $dropbox->upload('/304.dat', $fh_put) or die $dropbox->error; $fh_put->close; my $fh_get = File::Temp->new; $dropbox->download('/304.dat', $fh_get); is $dropbox->res->code, 200; my $etag = $dropbox->res->header('ETag'); $dropbox->download('/304.dat', $fh_get, { headers => ['If-None-Match', $etag] }); is $dropbox->res->code, 304; $dropbox->delete('/304.dat'); done_testing(); 15_auth.t100644000765000024 261415124606754 16304 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Test::More; use WebService::Dropbox; if (!$ENV{'DROPBOX_APP_KEY'} or !$ENV{'DROPBOX_APP_SECRET'} or !$ENV{'DROPBOX_REFRESH_TOKEN'}) { plan skip_all => 'missing App Key, App Secret, and/or Refresh Token'; } my $dropbox = WebService::Dropbox->new({ key => $ENV{'DROPBOX_APP_KEY'}, secret => $ENV{'DROPBOX_APP_SECRET'}, env_proxy => 1, }); $dropbox->debug; $dropbox->verbose; ### initial authorization to get a refresh token #my $url = $dropbox->authorize({ token_access_type => 'offline' }); #print "Go To $url\n"; #print "Enter code : "; #chomp( my $code = ); #my $result = $dropbox->token($code) or die $dropbox->error; #printf("Refresh Token: %s\nAccess Token: %s\n", $result->{'refresh_token'}, $result->{'access_token'}); #$VAR1 = { # 'account_id' => '...', # 'uid' => '...', # 'refresh_token' => '...', # 'scope' => 'account_info.read files.content.read files.metadata.read sharing.read ...', # 'expires_in' => 14399, # 'token_type' => 'bearer', # 'access_token' => '...', # }; ## Test getting an access token when you only have the refresh token my $result = $dropbox->refresh_access_token($ENV{'DROPBOX_REFRESH_TOKEN'}) or die $dropbox->error; is $dropbox->res->code, 200; is $result->{'token_type'}, 'bearer'; my $token = $result->{'access_token'}; like $token, qr/\S+/; done_testing(); 20_copy.t100644000765000024 367715124606754 16323 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Data::Dumper; use Encode; use Test::More; use File::Temp; use IO::File; use File::Basename qw(dirname); use File::Spec; use WebService::Dropbox; if (!$ENV{'DROPBOX_APP_KEY'} or !$ENV{'DROPBOX_APP_SECRET'} or !$ENV{'DROPBOX_ACCESS_TOKEN'}) { plan skip_all => 'missing App Key or App Secret'; } my $dropbox = WebService::Dropbox->new({ key => $ENV{'DROPBOX_APP_KEY'}, secret => $ENV{'DROPBOX_APP_SECRET'}, access_token => $ENV{'DROPBOX_ACCESS_TOKEN'}, env_proxy => 1, }); $dropbox->debug; $dropbox->verbose; my $fh_put = File::Temp->new; $fh_put->print('test.test.test.'); $fh_put->flush; $fh_put->seek(0, 0); $dropbox->upload('/make_test_folder/copy.txt', $fh_put) or die $dropbox->error; $fh_put->close; is $dropbox->res->code, 200; $dropbox->copy('/make_test_folder/copy.txt', '/make_test_folder/copy.2.txt'); $dropbox->move('/make_test_folder/copy.txt', '/make_test_folder/copy.4.txt'); is $dropbox->res->code, 200; my $reference = $dropbox->copy_reference_get('/make_test_folder/copy.2.txt'); is $dropbox->res->code, 200; $dropbox->copy_reference_save($reference->{copy_reference}, '/make_test_folder/copy.3.txt'); is $dropbox->res->code, 200; $dropbox->get_metadata('/make_test_folder/copy.3.txt', { include_media_info => JSON::true, include_deleted => JSON::true, include_has_explicit_shared_members => JSON::false, }); is $dropbox->res->code, 200; my $write_code_data = ''; my $write_code = sub { # compatible with LWP::UserAgent and Furl::HTTP my $chunk = @_ == 4 ? $_[3] : $_[0]; $write_code_data .= $chunk; }; $dropbox->download('/make_test_folder/copy.3.txt', $write_code); is $write_code_data, 'test.test.test.'; is $dropbox->res->code, 200; $dropbox->get_temporary_link('/make_test_folder/copy.3.txt'); is $dropbox->res->code, 200; my $fh = IO::File->new('./thumbnail.jpeg', '>'); $dropbox->get_thumbnail('/Photos/1ONWv.png', $fh); $fh->close; is $dropbox->res->code, 200; done_testing(); 30_list.t100644000765000024 171415124606754 16313 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Data::Dumper; use Encode; use Test::More; use File::Temp; use IO::File; use File::Basename qw(dirname); use File::Spec; use WebService::Dropbox; if (!$ENV{'DROPBOX_APP_KEY'} or !$ENV{'DROPBOX_APP_SECRET'} or !$ENV{'DROPBOX_ACCESS_TOKEN'}) { plan skip_all => 'missing App Key or App Secret'; } my $dropbox = WebService::Dropbox->new({ key => $ENV{'DROPBOX_APP_KEY'}, secret => $ENV{'DROPBOX_APP_SECRET'}, access_token => $ENV{'DROPBOX_ACCESS_TOKEN'}, env_proxy => 1, }); $dropbox->debug; $dropbox->verbose; $dropbox->list_folder('/work', { recursive => JSON::true, }); my $get_latest_cursor = $dropbox->list_folder_get_latest_cursor('/work', { recursive => JSON::true, }); is $dropbox->res->code, 200; # $dropbox->list_folder_continue($get_latest_cursor->{cursor}); # is $dropbox->res->code, 200; $dropbox->list_folder_longpoll($get_latest_cursor->{cursor}, { timeout => 30 }); is $dropbox->res->code, 200; done_testing(); 40_save_url.t100644000765000024 140615124606754 17157 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Data::Dumper; use Encode; use Test::More; use File::Temp; use IO::File; use File::Basename qw(dirname); use File::Spec; use WebService::Dropbox; if (!$ENV{'DROPBOX_APP_KEY'} or !$ENV{'DROPBOX_APP_SECRET'} or !$ENV{'DROPBOX_ACCESS_TOKEN'}) { plan skip_all => 'missing App Key or App Secret'; } my $dropbox = WebService::Dropbox->new({ key => $ENV{'DROPBOX_APP_KEY'}, secret => $ENV{'DROPBOX_APP_SECRET'}, access_token => $ENV{'DROPBOX_ACCESS_TOKEN'}, env_proxy => 1, }); $dropbox->debug; $dropbox->verbose; my $save_url = $dropbox->save_url('/make_test_folder/copy.5.html', 'https://aska.pw'); is $dropbox->res->code, 200; $dropbox->save_url_check_job_status($save_url->{async_job_id}); is $dropbox->res->code, 200; done_testing();50_sharing.t100644000765000024 265215124606754 16777 0ustar00askastaff000000000000WebService-Dropbox-2.10/tuse strict; use Test::More; use IO::File; use File::Basename qw(dirname); use File::Spec; use WebService::Dropbox; if (!$ENV{'DROPBOX_APP_KEY'} or !$ENV{'DROPBOX_APP_SECRET'} or !$ENV{'DROPBOX_ACCESS_TOKEN'}) { plan skip_all => 'missing App Key, App Secret, and/or Access Token'; } my $testfile = File::Spec->catfile(dirname(__FILE__), 'sample.png'); my $path = '/work/sharing-test-sample.png'; if (! -r $testfile) { plan skip_all => 'missing sample.png'; } my $dropbox = WebService::Dropbox->new({ key => $ENV{'DROPBOX_APP_KEY'}, secret => $ENV{'DROPBOX_APP_SECRET'}, access_token => $ENV{'DROPBOX_ACCESS_TOKEN'}, env_proxy => 1, }); $dropbox->debug; $dropbox->verbose; my $fh = IO::File->new($testfile, 'r'); $dropbox->upload($path, $fh) or die $dropbox->error; $fh->close; ## create a shared link to the test file my $settings = { requested_visibility => 'public', audience => 'public', access => 'viewer' }; my $result = $dropbox->create_shared_link_with_settings($path, $settings) or die $dropbox->error; is $dropbox->res->code, 200; ## list the shared links with test file $result = $dropbox->list_shared_links($path) or die $dropbox->error; is $dropbox->res->code, 200; ## revoke shared links with test file my $revoke = $dropbox->revoke_shared_link($result->{'links'}->[0]->{'url'}) or die $dropbox->error; is $dropbox->res->code, 200; $dropbox->delete($path) or die $dropbox->error; done_testing(); sample.png100644000765000024 17435215124606754 16711 0ustar00askastaff000000000000WebService-Dropbox-2.10/tPNG  IHDRJu'RiCCPICC ProfilexYgXKͻ,a9sQr%/9G"(* Q b"b@Ex>߽;ϳTUWLUWw@u47pM PjThC{{^ 8 {+Fѱ#h87^~0K x:*56BHFMR"h0#X?g9"#,oz S~R lBl" -]dݶoؐ\A~|@\.NmDŚ9" GmcAA3RCLKL9J=B`%:"(]j2_Mp L[nł\(,zd,X Xp@,FY`߭,T@xG' W`(ل=24?t*26oۺ8Zο#5 ~ -VBкh=&@,Z6D룵&0lq)(<*E5n?.p%M?,ᅎ?Sbi! PRPTfsoc8EBPGhtD)_4H8[r$@ Hr> $E );3 Ab0$ p$ \}0I0fGupb8!~H H2l G򅂡H( ": 5B. =Aoyh`:`yX6agcT8.nx bC dQ(c'*@@jPQݨ;1jƢhY$N-.ht :}]n@c7E&Hc0wL0& )c00O03oX, +UZ`=4Al5ۋ}Ʈp8N4NGpf (nOfxO|$>_oGu#AEA ݄:(N%:Cry- $D$9h,R9iFG3K+;KK L#=Br#&;=3%}}&}};(g(!.TR  bƌT *.Ƨ+LLL;"251e(bSJ%RKIfF1 333ac<Âegd e)`iafYd&V^gbCYf6ݐ==<(*7G V'?88M98rvpBsIq9p%qŵ­}sGǑ'ggל7&_(_ _ޡὣn;NN>NMNߜ;OH$2z6M˻ytz<]==Wvq{$Q ELEEŶ%%J9vTd,lܦBHʐ'UFUy_=apIޓ'8m~F[Xε3\g#N586 47664>K87,_ -/,.m-W++E|[_={Úڝn?fד~~oHntoZo؊ڊRPH |!ߒ}a-3b,YRvҭr֕TNQ_ӤҖ5ѳ41L43.5i06gbrmhc'C^s.wW_G^jT0s.d9M;Ȭ<U}(&%g9/,)**E8e#iZܺ]G79wnoO^:lzZkttD\BbrJjqjf'Oe3<]y6!hSչ3ͭ-]o^tIrvɎWgmPu+Uu7E = qy>7F[{<מx7Wᯍ8ߌnxW5sٔy( ?\Wbݲ+z+xs}nkk;N p#DG {Hzan8^FEc189|?N s';ѻ31&0PGX{ss>& :%'JK>*(+!"$̧¨ ~UAVA.FJ4PvFFr&"\fXuE ! v5;sNz.Үn%wc+Ce~{P?(,6DD$=<"%=J-=s#8. ^50x&)!4%e:RZntݙBsLګOzh>A!o,]+ƕp(U/3)Y\{mF}F ,3簰4>cK`gao9< x_ |:,#,J}'/^'/'+ c*#.dlS5R-O^榶NyeM\1qLI mj {b{;~:98p~LJ^{|D}6tӃB43a6Q?cOVHIK#]+#;s8[('e^}42(}JIq1BilD^eq|uԉSkYg 4۶L&_$]:yE^oJkuV`dq鸇x1|6 p(B"ѱU l^# f-eńe͕Ǒʩ;ǒucDEK=bG%"W2eSd]ңI]@MHkTU[IިɄ`a򶵍̈́8T98u-tXy;Gwٯ*@:%X*>T,1B>+󤤤?Oܾ%%%k֬3jԨN:eff_ꫯ,X'vEKg=ާSUr?^?ĠNڊ|}Bҽ0d||V_##:xr4"@"Ν;|HH;XerE9}p+:!opa_p!$񩜯֎3Q t s/L=V?[=1LWjLixȅ =jV"PW `iVi@~Hnp+-0_א`M{GF>:'xDQX##nBq4 pKE_*]21ܚ 9#+M'NDą7Hv82rGu-EhРAʧ~'ȚDȑ#yu"&q>4VU9]5W7; > ˝4E2}WNM7c`Bئ7d[;ްZ<7-3amW_^{JeUYK|EpJү+;{"whs~ڟ=nr)-}w47hhkTy ꁽߙ3]22n[K 4jڽ>*`'/P.+Kׇ[qRޠӫoyEiR,C.Ӯon}\|ۚCFߛ$$D<ئ?1"`1%\ ,|Dt<$'^Ё&]5 ##;#7xQeEM(XvȪȠM8p`ѢEw<R[Yr!X ֋\3\1mʦd}&+bM pbPK.H+y9ρ pf<4Mhh(ӌ}F-,aey}$yTPڬ즦cr \ra]fƌT>XwP=I!?lY8Ů3k'? qYY,C;w_Y8Dn]- 6m8av|-TYɑft1hاk%h;05ɺZU`tA*ܼQʘ+e6X ЫSb6 ~iKk#&ع͊bIƿV~r xsq%;w12ָ׈Y?T G -nL_v_[u]t+&N_p`c ~!n۲*2]I-g+d,xٷo8oMT7豱F7DB/j[Z{ڴi\RTT_ tp q MI4xqV.(wїׄc6􊍯XLm\<ױ^Y~h,%[{1bf͚8}0:[pzEP1p8Ȯ XO aAS 0}ۊ)_|bA _LG%}b&TzXweLe8p ˕Pd^ɆlBGxAb)+><25S(GЬYVא! b}~c8w9KuSX=Ǻ>V5)0 ߴUCe.ĕʷ/ـ@LgcbͿ(Ϟ9TGϙuGSnݴh)4ӊNIZ}۵OD0X^ c;+֭K?v,zZI20ݙkɮŧouwd̠vࣳz~d D~90ׁ]cƌ59sfϞ=+@qy(10|ɦYH0iXa1bnyYi)u ӧK N+C}E yn9'% ,]%k`4< I2koq<;w_ \ҖŨ>ɧÅR sZ[ I)Xu۷o')xx|[G9xYL"/1ղsN9AѴj Wpk 㼩]q7oҥre` ةE(%3rkG!!!Q,ZX*8CQemݞbKFp .|br*{$ԮJXg'<јhv dR!d .f㬈3h!`3?3@9z),Q"l)Wvn']"tbDDIN#򁣹˷o1uTW#FFP\E O&Lp<]]񫬄[x #M9ő)*bзKM<-\'Zv` Qeky\`_exo矇dӦM 8\6*#, :R/Ih)p,.J:xի7+믞6s-Sɺ5cA;s{yP\XtJ;%pcHʞ󗅫v^_tlՌ>Ƕm;E#A#25ۆ-rHgͮ/LEkVtݨ}䔰 /oXٕ0` >;l906!K.Ȃ$RQV{%q[RXS1)6vȆ/w36W{ b2H{;7# ݒ+0#%͕"dC CڲWRSH 5/}ǾJeg Ռl.D:M 71"Vb5Hp*N31q8r9wX `4GP,%΍"lA\$Wԇ {$;צF`YQ IK_ #n/uzr p%"@H>0hv0i]c\r<7@.ΈJ`,F?~ C) 2%+pDӒ5"DӑgmiɤŲPv*ڳ(pD0}EQ{F{ v?ũ> G,թzab{1v!ק51XWP۩.˙oԌb9Xs!o՘gre2wk-x \I[TT6oMe Tl89\Il*P5ϮURIN^=ٴ© Cص8Ӗ2_c$"@{ag8OVy9m2FG+,cI b8F\é[ MGG:u ;#y(V>x#1Hz|jh<$?ru'pS^x-[` IJbű(D+f&{b"i hb3;X])PKD*ո\Q)WxC| 9W^uN*#a Ye56&%ep%olJH7?vxD^vy#r Px}/Q..k6ݛyMPKTIzN `X3f` "e ǾHDqPsE}+pQ)B/p M_y8B4T4'h"rGD;n1d8v8kպ UDS|qL`)ӂ/v7b jF_ß1N9ry~ym!x`IGaw5 FL/uk8U@Ep.=qٕ !iEvdŮ)*tMv0⪬(gWGD[Vp̈vuG"@CL#0㦫 XM%5xKv ,eR; "qdD}Q~+VÍ~/uD9Wv W\; "ϛ-_퀚<#+S"@ITB@a ScB8/4l~-\ ψ] #R6eV!tUN_n0*80 dKd;!D"h nK`!sMT$r/;}ю4ʏ (.wu+MG\Dp1)nuܑRW,7t6`-S"@xD .r5ʏ>d#5.zCokjsUc vE'P"@x`qy4wP~nPRE^t 1܂ݵv@E jWt%+e QǕqQ.rqwEю(w.QG,[Ѿ+ʊr1/[Ѿ+ʊr1/[Ѿ+ʊr1/[Ѿ+ʊr1/[Ѿ+ʊr1/[Ѿ+ʊr1/[Ѿ+ʊr1/[Ѿ+ʊr1/M<hԔXXUU8Y;"W3++r{NYW:)yY|HD" oE*ʺWaզ.We]﹑UM]ʺ;68JhQ"EG$!D"P>v#UYWr3UYWr6[6U\u%Go{U IDAT+&k50ł+M}QD)S/=Uhly W,Fy"@ D<`RWI"@ Ç eVsDPT:ø W> xD"@'WumڴKpZ</¯űoj D"H;o{xޏ?'<i"@ w;0GZWx!L ~ErI@C"@ 4H pgܑG:O Dvcݻ7oބ/-oT*|d $w} d"@#M0?޻w…;w`]:tի^'Mp呦E'D"@o}vjj*v4mCtD޸q#77Æ #w>'D"@c| ֈF1;5J4pJ4 F~i"@ D~< b$>>>/+bHRRiR w74KVIn0g  %U#8L#A\B#<ӯ_?`e EGj˚zD`250$%D+do׮]`Hyy9?H+c*G!zfj2 [E㱃GcX DGp+Hu oZN;lp޳$ȘϲIQohkTql_gs k&7-_cØn#CGfASYpwDZE9/ Bm3p7>YG$`U$g/ٱoէ0@u_*=P+/e`-1_ >?"arGx@BD'|vQ,^EK]:%}4aiFHO ʿ+Q"DQ"WCv;xFG/Փ1eA?jb/Oۺr=o:Xnša Am#`PqW& wb ]<?ӟP|%4z@n?L; tKi\9kW'Tܜ? ԞKr >L4;^zRf.IIU\jxՔԹL2("H;G58S #u8lcIjzyGL5sH 2lJ5DMVqʿ\"+B_b&x$ ^8YcGkn赥:IRz;McN_Z3>ʅv:tKM`޽cƌG85M4#xNHݟ1cEG$U9: S3rƮM[" ojcD7N !5"@@}& ;| <}"wDAy"@ D|pD\jT=Ycis{^>9"@ D^ྈaW~ҬQKOiE+D"@pܑjq>YsrΧ$_D;˺Q:'勺wFB D+wq/8Y_ھcyCƵڧO"@ DTOF#5|Ʈ3wĠ%My{ڷǂ}Jy}yjS%[d#\Sލ *B+=Jnzq%l +F~yyj:5 Lu67.OD"@@= rƮ&kP6 v?՛ ۲#Q)h"ʀU!1zݒFn(xtA:_~ʼnWʬn| >#94"Fu ;g_|%qȟ~ٮtK D:VWg5eѨڷZAP`oʹ3AzExqک /|sPs?]xV%m1yEqLz=M['\] kiϿ] E%%k>_>~xdŊ(O DArDxͬk> ŸBf?{ٸ~)}%_ɻիSCyDHbDŽ)[4d*Ei)V=b$O_,`9vFs2P}O"@_I 16k6?5ve"@ݛ?f8"XZPPФIFy{{[>c 'KYI]L?]Em"D"@\#"U;Q5RzB DԌ;8;$f6 D"@\ё!w%>z@ DԞ;;_nܑs& D"@K"oM%D"@H&ueKR.#҂x \N_eo3 i0\"o ݛ6%D"@jK@\ܑx})ab! )F[XI)ս9kf%{N[ҧToFQD"@@ wH};s+\"(#ko U+\6P\͒'ZpL""@ DVeV>5~LYhlhS'214llfrk%>‡`b"%V 5iҙLzCc@wD"@@舝ag#ZC؀acLq(M}1kRc752V`,Sc݇*l3oxgmF#%D"@ܑzyHk8bM>u! 0:鋵](.!]'r2t'|FJ yIbvqFe DZpۡVy_ؚyV'gڲ•Wp)* Ƿn1YPlHnN^LnR?lA "@0~m5#<#w@b435SzZV:~zG̛a'CYj/oYD~a+ $D"p_țk]5u)_ScժΥo`,j@B_juw!.Ɍۖɚ'CdJD"@}% oq c)+{1<*1B1h`^$<_"-GNn 0|9%\jZP봏K"@ D*{M)oMYCf'AБ&XGva̕G4qJK[|MԀn]yYB596g)+*"@ VrhsG𰉵}"@ D3ݛ?vXoTFyfƌ6T~V~Zm” D 4"Ey[Cy©< DG@BfֽSYHD"@@='ᝰp!#"@dD5; tK Dxog:vDIc[}_wV.yJ=WTHYAY"@ |ԣsG*:yiVQKOiLKXU;u~xϣSt1&L|lӻg(v~s^VL9AںsJzlO<7ۑ :c¬Ǧn/v8>q_X D%"]֍ 9yOmKY!hht|-.I$]T$#&+Y)QFvKlB;dG.`'Ɵ/IPl̟WT!6ǒP' DE.֩oXx@?s;'F} ukz@ԎI6]<l cWwG(?DD1xPty߯.;qhUfr)"@xXT{Hhwo[/Mm zϺT[Ldv@,6~JFk0YSsNHHW#jT>m )*E_hbx掽[]^VSkl-DD"@9c׳4Yxͬk> WɸB S^͖l5CLTS7 :ҔM>3W~(e%<ͣ}c5!suDzĭZHZ> D<u<ԥI'Y배)a,$i:z_ђMwq(}g## [3C9o_[V⩗BGEG wYƖ9e5Et*̯c [o* H D^ZPRxT ċpom?xgX|ZTu+i1lɓ<),Nү{pZuжgXJ_ Pj)  D""#Kmqp~]lUOVoFɧll y%Pd?wv)_RuQSk\u"@@#}yidU=gǤGvt[UIln35NJh̚duZxuidS|&}eiY6k@l*ĂrFM\e D<T{HrGc)IuZ֘+:oNIS6n1z37~M}|w^,?9:L8r W4kl[㎲hD"@;ҠCz՜hR(YWޗF#ST5Fd"@#w1c#FI&^^^JQ#˶3fXV`'{Og?ݦ>"@#C/Aw];BwCD"@>'ԡq D" qt"@ 94R?y8S/ DiQ.iFAy"@ Dw"/RV3 ݵ"YII }]9H&"n`ݘu'C0^3AS6O5L?GHdw-I-K8Y]Q^rvYe}G:Ud|eGi޾gpo_Ƨ 1+}B'ѭ<'RJܷog079ep}B+}w\.h6+0esݮӕRLFO9/GXP*'Sփ)flQlKGVMWO}Fv ^>e=dxCSxdz}'D"&#8_npfT+/bijJzdfxuZ*6YZC؀aȚSŔMSK7VN]υsBf1Yc4mT/IY"7T.1w?(y4q &""}6$vNV= b D"PS"NCo;ؽ pF}Zybg} j>܏iYk}uU)Oߕ0( e+8}0mˆYH%CZ3}Ēc BpI=%D"P~RΆ*G>~lRj25y[BZr1ܽgDW$nΛ:9׎kV}=+= 'm:'Y{ <2jGF^ U\#쩔eXOaUMrƘvV>rAjDIf)HW0[T4( H@ Dm "g֡#@LK9n7fwa`֭U|d]Gؙڶ<5Y; >H/X|3.Q!S9oY܈C{VR3/^ O]jRg~i]j4ޘoA֟uWTZ*qPUUFψ DTI@^*@Rvi+$X*ƍnЪCYGuP}q3dʢS6pbSҜ>aWŦ1ou̺LVqmOlRuCPFr!}ټ Ho qßa}euΥK u{q(ϜDW|fŇAD"@! GD˹#la]/ι4u{/cY[>YsvN .cϤ̑܀e ԋ[딍ـwUQŒ9n͓̎4EO9]ѡ*C itǦ{bTjW"Ң%)#u=ɢ0(i橔Ʌ<' Ef T?T!˜ZSTɊ!oR22i۳,x ]'D"PpD\*KA HCr\f7CφD1 iEڵݳh[5T0cҔM$f""ec-k ҧ7Q>h)ݧ3u΍%,/= -3֪kNS+ocPCw'}"@ @D{$U;Rv֘{SqlׁWë}y"CZ4<s8Q cmu %% ӳ5:?\x!]µ˜v%uНOmp_TVH!D"p7׸:wN#xͬ4'=okqLخh#|_?ŁZKacn!XZv bq }nD֍KrP"D"H#"zaO`aaSX|iI>u%8>Cr *X+N eMY([ ǷYb-a> ilJte w!ۼQY' Dܑ:vD6o[P8>^ZPRxT9T`6e4| J:S6 ZwVTeV1OlgDTLfUyTr_)C DёCvÎÇ+wr/$`xrXqjPQѹti~/ o3֙]8$Gk7ջm(i͠U$gHi2%"@ =#8wݔw"/ס#V=DZv|TXmU%yWj0xYfjpSw%ϥ2{=:OT 8' 3WAN2/5EOͤ pZQo }&>Y^]ߟI_#Z7< 6  DzL@B!w1s$JjMZcnw&ИSl cV2WVA%td9]&sM\V&BW{׽_6]:{er:o0μ_|jwpu"@xsG\mAT=31K7F~v"պTShdJοe? Dػwo~~1cI*KT6jd1cƌ:i0k9ُPoD"#".h[80uE"@CK@v>8wyh DGڭ!w"@iW; ɉ D;RK᭼VL-EEr#kTW5h4W՗T^5.L Dg%P1ϙkCPv7؝bGO դݛ޾<_bzt_=#MnERLԨqYAӟ t~1`\qlׁWK!CZ"b-fyk/loXRpI5*1-ZN7f67հc^:[i K١^:c|MKX{d:]̨ s-0|te;'\+3Qogh.`nvYx,NAKd<ٯŌ0  Dܑ:8xf-u*Og҈֗Fv2:Bzk?<S1|m*{SYifn]YTIg"ܾ)5fU`Ycqbޔ09U]_r?j X+~JP"D@@TqHϹDQ*9͒62:Ց @S6^S}svzϺ,&8~Iz)gCmo/4ҖMG2aql{̅-P2KDA M&hȴ7w܊l=8jǷԌbKB*IY"T.1WFLz.ӡ+,̾c⿰FOPP{$;lI DGGG=kfsGxܮGOlD3m)=o3VS7'kYi.9}eOzBnRmd\P?u0k?{oU`|D[\ aQhuo.?ݍ5wE]d-kl*X`B2&* ""1ws93Asx͹s{/+=@A'1I?؃X&1 &P!l؏>(y Sy}7yI?YiKCs:5=&c<4wA:aQ+ KߋBNT;ˮ߿& IDAT|6E @@? ;B_.X~ӼFe\zT[&qUflY+'7 /$g)6nKVZ`ad\U?)[:zd+ҔʽڢG/7VU_jWrG<0M?X#dFL^p 玦eyFHW,P2;" @@B5V݌KYf,VǪ/9dBw/GV '$nU-Zm9x_ƿ~7ԧp JO]sgJcKb6hq:˪\J$o>$~2\n+uPn j]NsTscr:Ԟ@q#1l˜a dELL.^ɯ<_HLJم㟝7yZށcX!䏶Iբv9+sU@@Aոy3#j.c{_F [JIK2'8e)+˃wsۻ~v=n7B\0AurRǭ}8"1REZo.dIR\c]UY'DBOJLGX [3i[='e/Lƺ:c^eq~+~K~=FP9̂ ]=.>+pn!  p \)be`UI# {uU,:>%^WO`'c道9sBK\iH8~qʛvyE9rrqjkԦ{  pklwfrGTywt#uMqЬ~—3K %L4bݦJ_SgE7f.H,w>9]||k?}u=N zn=5c4mXvXgWL)$&ȿgُƍuC<_],垼@ܨcd@eNBD4'c9;:y/ؖC{H^`V.P*a'9Ify昵墲ꈁ(҈eeZ_=}ܼ]H9Sr'HC?qU+Bv#?I'ڮr=<'z @@`ܹf&pႛ {~W*-@#@S?e w*atMp7Lܑn;r3>Ys; @@0{G݄mN|mO=HH+$@ֱ N ܑ>&q   ra#pGc4""x$OI%2#} @@@_W8+ H%rG#$Qz H_,+"w    }Lc   SԌ+ H1ic   ' 9x   GFDDU/Hh;XVXA@@@/ ;%P)wP@@@ #}A@@zD@zFX5WYdu'3[5o!wmT14"c(ᗬ3;BAz1Zctk^:SeQ[g ̔RmNF?ymRBcBQe+ 5   p Cpn14v": ?"&"W|-`I;9'U;Ri }SXw\kGay a0^&rJ(y%`^)r67r9)rkקZΕW"BC>t4qV4iְX\U( }G u4W9jz9Νt%䈐;A #gHU|ɽwJ@[MpC߲s3]^4azmֺ/V?U Q_ՖL0v7   7-qqqɚQƒ64LD=z4 ;8o :)&ˢlV>&egmY˂֫>AIkaro`!tDaƹ)lA@@n5y\pfd$/~P<χ؝2+}:((h<?[oL!^cϾQxEݯ^+2-hr74a^yp]~&8Yw Ԕh?nl@@@&'@{w}wss3 ^Hz=-!_;EpJ\8K7 w) 3\v斛poh?&DF43|BDM+_JꜯOyףpG8y$4MFc$44BZABI8!G<rYaц|ϸwk4ptQ]P`,Hz C3Bþ,疨V}U7ɥO!^B9vԣ[R۶*1oL +~0>*IKB-b}÷⧮*$`عj^n\Qs7/ oߞ'*rx r yKuDL[ϼwc+(6@FZ̡ёZĐ%s\ aIW1+tpMoVN0 r=XjVOU\8>$,))imK6iY)j.ӗ Qu{Ϙ)w7:eI o=%K.lvdkr K"l־c%RqBVNmŬ-\ݘ&a.aKuzno 'mK(j]y|C( Il2%/@sItQMbeV8X쀎 6;=EV꣕ )i>&]vrp8d(o-=ဘdJ/^E$;8;Km╄3,s%5J8fŃ%s-fyEp_|W_UUU?~… ^7 FPvfts'zҖF}tl;~t W4gqW^w"!]q:NqMS-fIy7/Vwf(d1 [r ݳRtS5;b~EǺ%2g5{p2mGQޅۺCأ<.&in8ٜ=gwjnݮlfꀬ}c[!툮edd7E:.wF~O[DD}Ye5ygBZ8\tZ!C/.&¾OT[4jQ=%4|~:y맴8}[6 <9ZepFcaN c{HfF_yq{G=2]6wW,ba)?v[;fQ1sO>Q#-v,yJQTg?x?2 fvB;GImr混&e⹺S~]AGt wjhE J:Zw! DMC8-Θ'IovCA 'j'!FqEBEz73*LV<5q^v- ?/Ůn `7> 31Gܪe/޺ۙeѝ2}#r@h[*QY'ב7İtʲ*7.+N,]TH[$SmaJm^Kiđy"vYeP_;]׶kq]u9<oJح| C^WDZ("sSo8GNCWFˬomYEv– S6?5.C^q{8+\MܣK]}Ԭ>U[94txSR'}tKn5?n%{'Ľ'^G߳˞Z1gYl}<g̼Y~nns;t+Y0G^cypOf(c96HoWAxO%{d-^8]3Lݲ*ibHw>JٹFufkNdHqq=-PU{Lx"&2a,=Y~s}bVŊ[yǯH?"èB!:EԦ}.o"6dXrNz)'rK_eSWi͝c>Mԥ#soy SxoMy⥶^ܷ ɫТs|s:L LE,,lNJV'Y崴9!=^%l6iK"qf[RBzR=[!<(aač =ZG>dzY˜g5=:HVj?.KO XP2wJ5 GdZ {,wa۪9Y;MF^k2i9@u/fyh6M.ysG֥J"I8<ڹ#ͩ$Yy'5"jyI(o%B|ĖNj9HnD-x631sVnْk]Fy/=^J*,A@[?YsN 6Q_NQO.*^MO:^ߎ6/^62i Ě5\]2^j^6Ir8*tvvFɚ,_4~FV.ј 9^QA3D__2c 9T󝦄j}Bl y~i/BꏍO;jj* 4!|vKvkϔ+_~!Z [_=q8WG 4ѭ񖢸74PrGgL G=h1faCݐA3MKN_0Mxo*MߘM[E9)ŮpaI Tz"{oX{di>.gs^夜qfiM-)<ĒEUg=YskW_֙U=ƋhheM3J5%fI#&meyq>S01;=$w5L%(BW}Yn&4WbJ%9:rFqiYN(SiL䙼C +棭W},yXX k|if+IA!jϦ.0/Xqxh"k(}GNo/zlԡæ>֕nD+$ӉLWE'Ť|Y-e'ݦS+[@y_VJy|uGSݸ gW7Jnjӱ&r,mA @@@wFG/g_.6̏*$n>bEeq;ۺ ]+G4 E+j]n}"wT~nn+Efau4 \/ё!Ga] /{o`>Ox<`QC-[rS>vꇼq&%!^HpxQ./ѱ&(G!0ϑNߖ3\^PP&Gm=+&gfąS;{C<eO+hJ𚴶e^&ԉyx~B\H?ʡsrzDY/rA@@d cǝ)^RcDe.sr54m'pqc¯3xS ~&qIgklMhI ^.xN4T@ (Sb>Z[yNjO-au4@@BOFٍV{z0:   wɚ;    0 ~ &wdO 4#@@xpGC@@@` =   p;r  M@;ܑ;hpGz@?@;2{A@@'w?@@ܑ  w<UWWP$l2|3jc dgg=CH#‡   'w !@@@W ܑ3^;+|h    {pGz@@@zEH1@ =CH#‡   'w !@@@W ܑ3^;+|h    {pGz@@@zE``nlihhUAo?}  wqGE;ɂZBܴ/_o D$Dt09|Mۃ#Ӈw([5%H ;T><ҝ1Ñ;M(̎z~Ǻ|y=:F^U մt⥖KC@@@;b(\dcEQ1яU#:UWjl ɑA~Ik PSV37/(('nU9Gc#_.vCy* ?83B]a*2S7kE/ 4|kM+B@@@:;Oe MV!)*fY9OG&kn?wT[{hl.&'-.Y֌Z k#_V)Yei}r๨،J]r2K:8q'XveE@@@#+0$dωjNu2]%*pfmmI*Csq2go-c;a[r]UP_[1͉4TUZB 62)1W,8@\@cyG1v}YEQpЧS ԍ92M\Lۨ`JRՐXƮv([V|i.mbb$_y]gc,x{XNX C@@@舧='XB܇"G|j!.'2!ws͍Qv8 AiUi醡"n~\b[ffjasʼ̄EKY >Ę\   }K?UȔ2r̸lĸC2‹5*csBcV8r|oh4 ͮpA![y㓤vSZr[{'UHB>^?Jub_Y?.dUh8(dmms1#3YҼ܌RVi{vV#ud.W&GfpyK7n=qT@r{s }$P8mi]ʗtD,A@@n|uA@@nepGnA@@ w؍n#J M -S`_/utE5el _5}Q`wOZTΔ'7RE'O.ib.24?N=D;ňmAVyQc#kOI/au|<Hu fa.ذsdd|f]VȐ ?U:[u/Tefn$\]k @@n};roɤT66l\Z)m;$*`G}\EY;dYޏ eŅ99`h1V&:MC @@n'7;b4\k6ZvU*7weDE{OѻLV[|G38ϳ ˹ +!J[a+ey,7'RUw*y*_(#8)YEB-yBѰX՘T|a7 sHO}|7+-%EQwPso|5, |Bbr#'R   p{gwa;.]|i.mbb$_tĈ}4";O؄C1W}7"TKrKkNUcygv3rw>ggoE?FN*?B{no?ۨ (g՘iIBjtQӼ^cXu &7J619` %%%gTI:mƭ{Irq]_blZE^{Fol93!!ԢLQ   pG M kcdAH+ b' VdUhы?W䱉 1E|~4b_MK,*ycSB.5+ c4\a]yTcRQKCCrc,Y\<`ىGɼqW4M 'm'g, ג 4=:_;"Ȥu5N^:%%*}ޠWy`}KN_nh&][ڌ[{Y2hFrol R*a<٩U!k_W e˖)ڿ+RJ4h]|4V.>Τ^Bw@lѢ(TO+Rj'7IbmXؕ:H[#$7Z=o'0@@ &r7i @@zG_革h    p{;r{W @@n!pGnSA@@$Z /sLC9zQjKMV[hﳽ *F6I**eY{J67,O*:n ӷ k%"3k֔tw1wk6s{ 9Vu'[d IM502/iןȓX h6 ;GFƧaQѱvzvFm`QhPҀz6*%k_ַhhQrHncmSff>AڌĂfӗ>I{lʱ6;^{hь't9%!   ЧQ9+J * 6.-ڔ6qAn}*qee/Ͻvnj%ңȌՕf&*7щZմ>klMMcɹs-c꿏xh8(Wͼ>sRuE,y\ w0H{_ʱnɵ/گ3Cg3dW 9uGzV^SܕŊmz$U YTD[ Fzk_OBd8Ԗmz#QYFK?ӫY5(lK~|+l ^^fI>h3t+%k=¢O ]o"vYN~v۔A'2_+@-3xU5?Umʏ[koE}M~ZTZ)+]x4}}imǭWԬKdqD-gW;- ~>9+~lZLl{iGV0/:@8Oam>?-:U[η.N&Z*>ѫj 2~8"$(ʧ/Ĕm2W.7- 2ҘZ`N1{}h>r 2ڏ/Ǎr)GoaQ*}ʤAd)i2>X,c+:⎘-W J`|[~Ut{4O42}Z]:]EM³+c'Xvc@Kk/ed$fȨ Q\YSYJI*!DiuiPkEdFma y]|A3&[ڄҌEiyej}>4fw^ڎ*m7V-*VO ]͒x>(eуywd 7bRƅ9z)bdºݾ+_y}/c)mEEɹ ,FiSv@^ff|qemMiF6>|<9$_}_t(WP4  #03|ODٖovЂߜ4?P3 -*[_D?b;) n0w䈈##d̼UmQk6777$swny'=h?M&օmZ_ t6YnΝ{s灚&o5VͶjg)HzS IDATi02uZxHxQLwܑ%ca,pkQBCcKgob _xDKY`ޙRDRM:־ LCYI2}f3h˭TGxӽlHY:3P*.t@/_ͫ BYc |JUJ  }EpJݴ(jU}X`. MUHSs7tM0rREb ~m7<=cf ~^sQ42Нjº c#Vvӯ\I!?^#"RP!1Xƚ͉T@vG[B:O* P+dBkO=|n 'x~HѨ@$$h:ee s@[ WVD=g)uva+7  ?7Ș0k"Ʋc>LMt ^Ô}aSD z,c©9Q|=;H3!ɔ6,Yxn9OSL4F|uLk 5%̼ЄiԠ]Ȇ٪GNe!>3Xu(X;s3FMbiMdWQ+#[ OEc IHp~TՑ.;4 ? z&,726:ƶ:G%\/?+//?ƤEćXBʚʆSވZD ^cXu &75jsJJJ*wwŒVt|brG$-L@viaXY8{E΄,=al8@4n +jm~]E>?jcNl&x*O^%?>NeYնXꑭ|Ѿ>p qu ZE]kc+5FuȌqOM˹#+ziLȆYn{5{(1CVQ"/t_ WCsڴDP`)!jM&WpW^:/gUG--NoEe><sv;ɽBcb!,V[]i+7"Yi᤿EZrB'Wg6vi H,gå Y%"e+MJMfk9}/LX5RГ݋ɖ;B"[=R4tE'X֮W#xS.fW56(H;]T6:!2]Z S^bWD˝8F]f%`)))V4Є{Y.4hF Rr^xa6,4IS{%lʨi~!6zl峖&1sw}8z*5is !$V&#-_Vt[`%Di+ƙܑU!k_{^B%3dgg/[Lwvvvqqquu_ trrRT FeEͽ|*w_8"H5tȲa!y" ;fY)*dUȹ7g:)M(L@~=jqfyƆsE_]tP!  K7;9O@Y[{d+ Q>@QOY𧲊qk+rs]e3,+^+͌+tyȠ5gt4Uf,J+.+Vkg1,2+k*Y) Y%q^j'G)۾ ku@@@{M /vD5{=/n?khݸ""dovЂߜK%Th&&U:]alane@Ȍ*ʹDH&2Rf;{`B\xl?8bGFLVXǥ:*/ӥN󷖂4@;b,<Ʈuy?/(tʴ/ ,fGNJlCL)ںPNVٯb<=cf 5ǧHٕOUtGFZ@,5@@@#)y,!}CK.b _z]-zpQ{c0*|c%LH3V+V*9   =%ПkGT!Sf>Xzq3fƲs#- '0ԁ72b k%L:הtw7ߩcKxWIw[[߹M=4&nqdKpG>#oR{cl&_]Ru?dfֻ.'$\?F%-מ&NU h6 ;GFƧaQѱvjFo!/5^tr ia\Fd-ܛ6 -Js)1{?mMk3 /)_.&MCfT9KZ * 6.-ڔ6qAnS Qݣ}b .B0Z_ĒWk)ptH9][w'گ3CgsN ӵ;93N2Af%0PQ7qז. =5 \]%`.4z-Mq9U*7weDE{esʷ)!!^a</v+!RU Fzk_OB^mJU҆(rvc8 x8]ol$3e/ݽgGwWr(}evڑfЭ\NOjD'H6K^/`vhW` NWf{c6~|wV43NQ2A$Я0.:pgn_PPOܪ&o͞~4U12/iMP?UDZM+4m&:[F(^['k}0v{jo.}X2ɓPkl(_d6:ush^XH6h;FO]J+eIG_ZtDq˦fM\t\Z>G7I4IW- r&vRs'g*DW{,DŽA=w4ڑi1 ɠ[N =r^N3f#:U+L E gK'zU؟XOE.)>t)ͽ2\b#)!B_ifd-^,GXlBA8J/^Z}D0#k׮W& 5GFeʚbgVJBV Diui`DEieb9OKĘ/=>ӽ|Es}Lo.?#"T](-:X{CczNo{Siuޢ2~jAj,yy^Qʢ*nu*Dq!iΤ^ w^d_|]SS*C[sXPU)C1:j23+kkJ3b!C7u][ׁrūk|fUa 7#~uG{/}GKhάߜ+J-sy N\fJ}͵f3GFY~J*iCȌbK(yMjG) b,g ȝپ-|5_,eQcy+nnqi.uڤ)+P39b yѓ'EDh>SLc&]B-4wjHoO>\CC#KgZŅn>yu]A(}sOFB\IAHNJOXvZMn+ݴ(|/ , M}`J,Ta>U#iwky36aPp⷟mT tڲ‚a}daJJw /4)gkDD 177$fQb^KX9 hgb"yԜ}Ri_<@+پе{Sߣe'2C R4*t< l$ȝUR>3J~0Ru@f"ʷҊud<ц9s.)&VN14+PĆyyf^uhBzy4B>Qnko!;`٪~5;1֖`Չ'_;s3FMbi܂+["[|QhǤumlq}N8"TՑ.;4 ? z&,726:ƶ:YnuM+Nw Rl]l+G`&=fŁ3--g6oƘ^!W1t9;;>&U/ڠkC+Zײ߬6E@Pz8wyVSk^̤ZqkOܕQ[K*֤+/?+//?ƤEć_{gyeAX"4j,R@`S)ILZT7cX-%ffEY\v +b[-!h@AEDP>9sf8g@syaO5 Y?%pi՗ߐ>EQ?l ]̭[աlWHޑ@-_tܹkm׭rCДE4.UyMS#ڞ鬻L/joq+TeWGj130ZJ~B=.|%N@?Q#thrۺ|q9eo_.8kgG"t[B7lrjbN7Z^L(HZEl) p{׊(^$>Y{85nnc\{[.e5bJ&HhU'kk|Ы҆v4G=Jevxk?e.ki[)`kcY]"+|R%UWѽDm " EX$3UG&g1؉Mru\j?>.^ qdx؆>i_KT.Bb>KN/RqjDK" }G2ny0o4@q bv2km$DYxũ<*䂀#ggZZZRRU$y7W֨vy ;ʹ` =RvS]q$鷿FH^f78s;jmW,TǧuudmoX!*.OhUx-}U-XVav-hKUԇaL5_p6 hZ}U/[ 3#JߋV#eXND˷BjapwTOK-adh8pm{:qℋRFqrrć^(ݲ w&?RVw?!=St+嶖à78 z mYZe!g0 6,P/*.OhR*+[S.N#k!)U] Sh,~+-G!SXu?"M6Ǩ巟wZb `FUh|&ƭ" IDAT>a~wm{?Ν5FhԬQRlHK-߾ޢwXs?-$0,5v8Y3Q%;#|t    @@@ G|=>   v&9b A@@ G3;_t   9 @{|@@@Lr݃@3   `g?@Ngg=! Gm6a؟k Lp# @ G&5   0 @L  '9bk@@@` @@Or'92?>؟< Nrd0|?_x  `   `%zwSwj=_EIyIiVwEnzﭻXWo`d[#97``TZ8 giD}A.pPz2VކeS~~~a![ҟ] wCݐ! /rʋ C,k說~PŌ`M@@@ (/xNFqPꤨbuZ\WVwO޸ ~&/  tEψ2nx+6n/Ӹ8^~9ߙ&OGzn#sy3m JOoied%눱vSr" #rLƖ M#o_lj6 {`֋%z}2c֓S[z9j$ĘIpN`<'IAkjduŞT4HNqw_X?cNwᢍs;s mo? -_SNxȢ@\ drp5wf3WoaYx|Ir0};ˤʑHq3NH0l[Tg'|!ܑˆ7_yvkգBR?`F@@& e9",# 081% @|o S Q!c\Z!x{P'cse"ӻ. kY.2OD,Y81_o`3M Tg^NHMQ0n;T   㑀q5mm|H4~Op7^TGfRzl~73Ȅ/  BǴ㶏PfY Xj\u| UL(95o~ܟ1W1q5Ĥ.6G |RD@Ynk=FmLasRvq=9d8a? L\v#H{.͡ɹ1 O͙30̀'ήz:gWOhbh   `E@ivDiGlaKV Y;Vc7̠Zޱ1o= #{~Wmܼq5kU ribY܍G9 B|7U;/wlݞum؟jo=ܳ&D<-{"ؑI`]!"%&r{-kꗩWJh/M0y'6ytXBJZJ _^۰QԒa9-%d;&ݪnsc|)n7QK 9}}`fr(Ifs5 :%KDdz՞IJE&{>hvTSlג)x7L9ydD }$E@WvRfy0_&D@@@nӧO_r֭[z`0o)ݒK(j͔L[%},*\cM3VsV-%\9rPdG% :AP&N*#PFEUwpUO\pBpUtZ* fS-%2Mu_GrjL`c8 \M 7@R$|G$dy.o/   `g#J5E%,>iWJTI+ McpuH^iQT{my<{znA)КHdnL_͜Mi)W].zPwٿ+-s&OmN^}_9Z(<9m!~G>R'ÿnh4 I?~bE ]JZam8]9dEL&w6G::+:.j:"짉IJ)e,C@W/t )EVֲ;wwwwӁ:\Cݻ'kI1dHGX9!ih:߶opgTF)   09__|͛7I|7?HZD#1.xOQ6 (hmikکcV}eOUah<y_wcV#Nn^F_v[X%,Ĺd;a9ܴZ\kG)؛'hCVWWWW!ho#_$o|Z;" *,;x(F=Z F[o_m[J)_@47_enS )Q%@jW)УτG "BoT]:2.v*Җ7{+ C; tGo>; 6a@@*R4"",ĩ͎ qf|~ѲṊhf$ָj@@@`|(**EZ5a"R#,֐.aXbce踭-#fA@@`l A+24/"MKhC넔#cJhjDxt V(Cq##41nb`   E#֐IhvT JHs$:4Q@@@`H|ݸq@ѐ &AAA#C&    1uTھJOeɓ'Gf4/Bf6m… }|| G   C l_ɏ)S\z =!ohk=%#C&    3g_)`rd`   05$EZcB 䈜   #BnhɆtW%4}Bq^   #A@>BR/$A@qHMNv:X~ IQp#"D@@@F@]]|P[[Ihrdd:Ld$;~G\:+ #rJ  ;u˗)yڵ3gB{G$> ? tO>ǐH]͚eEM@Ǐonn`Z>,IRL&mۦX~FdǠ.@[FZ[[| Oh2h    'pyrhq, Z ȑaC C   C#924nh   0l yܹCyzzz =0M&OFȑA@@` L6m'kX3—A@@"92!0ȑ   A@@F0``@ =:e#O?O'<g@@@`H?j*:e#uCG|׭['hʄ    0HmHCG?'Hbrd8D@x\l)tRArD0C?O(:99 E+0s95J`` ;!G;ƶ65X8Ɯ;   8H|ҫEwJE !C5A 1H}_;Ʉ  㖀\s4r-""Gna/?O~}"B/(-)yap!IMԆ4@AytuuQB#Uf3SX(j1r#m #N~Ǣ6%VA^Z5A@@T Ԇ` !L;5h M9+ggl+W nvVeP_7Gf%o62}U~ʭgGqrIѨ џ7':uU[eFܸ?kgʷ8[}s]w8DtF]]]ee3gJKK/]tͦ[bhll(COnϺ^d{z.Vu$ᡙsktq>#Eּ4"8)#[$EFk+[p7*ϐ`дJG%J=T0tY_>"޽ k S׻6UΚ^VYDA@@@=UТd4gG׬ ƆYH3kMMM}gK׷:N-T [b,sqZE-_>u*4ux~`xZ@j./.f>kFDA@@vgr?,x6ǾUQ_{n<lSA 9&NR􀵌S*J}+qiq6U|rGuKo\"jkcH QV+? Xޟ-}wŀ:+.᪆΂:(.3mל+fMl*Ն٘PSkӖ;YՌuk2_eSnqa$pє#',fLJеKgȦFh|n e^pkEd1c+a">yؖBhu S,ii:U}|6]mXd zxM"XΓUD9S^    0H:tH]^:/fo/?+н[(]nkT)]nfhrۺ|<.YdK(S]Tg_]B 9!. ~uSY薜?[Yc.^@@@@uuu^^^bb$z$QOۚۘKYiqS~t}}|öt5L+tels{O 5|cm]3 "BuE8$PUUgѼiZrzq=/o?:R}mpbQwR'sy[~#~T4yIDAT}|-B{Gb}A@@F.ȵȕ+Wid4O֌   0f XiaX;2fI1)((hh^P = EH87ӏsϙF)-x_&'`Ems8o/"]"_o@IENDB`META.yml100644000765000024 424315124606754 15657 0ustar00askastaff000000000000WebService-Dropbox-2.10--- abstract: 'Perl interface to Dropbox API' author: - 'Shinichiro Aska' build_requires: Test::More: '1.302085' configure_requires: Module::Build: '0' Module::Build::Tiny: '0.035' dynamic_config: 0 generated_by: 'Minilla/v3.1.29, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: WebService-Dropbox no_index: directory: - t - xt - inc - share - eg - examples - author - builder provides: WebService::Dropbox: file: lib/WebService/Dropbox.pm version: '2.10' WebService::Dropbox::Auth: file: lib/WebService/Dropbox/Auth.pm WebService::Dropbox::Files: file: lib/WebService/Dropbox/Files.pm WebService::Dropbox::Files::CopyReference: file: lib/WebService/Dropbox/Files/CopyReference.pm WebService::Dropbox::Files::ListFolder: file: lib/WebService/Dropbox/Files/ListFolder.pm WebService::Dropbox::Files::UploadSession: file: lib/WebService/Dropbox/Files/UploadSession.pm WebService::Dropbox::Sharing: file: lib/WebService/Dropbox/Sharing.pm WebService::Dropbox::TokenFromOAuth1: file: lib/WebService/Dropbox/TokenFromOAuth1.pm WebService::Dropbox::Users: file: lib/WebService/Dropbox/Users.pm recommends: Furl: '3.11' IO::Socket::SSL: '2.048' JSON::XS: '3.03' Software::License: '0' requires: HTTP::Message: '6.11' JSON: '2.94' LWP::Protocol::https: '6.07' LWP::UserAgent: '6.26' URI: '1.71' perl: '5.008001' resources: bugtracker: https://github.com/s-aska/p5-WebService-Dropbox/issues homepage: https://github.com/s-aska/p5-WebService-Dropbox repository: https://github.com/s-aska/p5-WebService-Dropbox.git version: '2.10' x_authority: cpan:ASKADNA x_contributors: - 'Dondi Michael Stroma ' - 'Fuji, Goro ' - 'Greg Youngblood <47649208+softwrx@users.noreply.github.com>' - 'Nick Tonkin ' - 'Rostislav Georgiev ' - 'Shinichiro Aska ' - 'aska ' - 'aska ' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' x_static_install: 1 MANIFEST100644000765000024 136515124606754 15541 0ustar00askastaff000000000000WebService-Dropbox-2.10Build.PL Changes HOW_TO_DEVELOPMENT.md LICENSE META.json README.md cpanfile example/cli/README.md example/cli/app.pl example/cli/cpanfile example/cli/cpanfile.snapshot example/mig/mig.pl example/web/README.md example/web/app.psgi example/web/cpanfile lib/WebService/Dropbox.pm lib/WebService/Dropbox/Auth.pm lib/WebService/Dropbox/Files.pm lib/WebService/Dropbox/Files/CopyReference.pm lib/WebService/Dropbox/Files/ListFolder.pm lib/WebService/Dropbox/Files/UploadSession.pm lib/WebService/Dropbox/Sharing.pm lib/WebService/Dropbox/TokenFromOAuth1.pm lib/WebService/Dropbox/Users.pm minil.toml t/00_compile.t t/05_accessor.t t/10_api.t t/11_range.t t/12_304.t t/15_auth.t t/20_copy.t t/30_list.t t/40_save_url.t t/50_sharing.t t/sample.png META.yml MANIFEST