tdiary 5.5.1 → 5.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ChangeLog +2 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +39 -40
- data/doc/HOWTO-make-theme.md +3 -3
- data/doc/UPGRADE.md +1 -1
- data/js/draft.js +152 -52
- data/js/image.js +127 -28
- data/lib/tdiary/admin.rb +11 -13
- data/lib/tdiary/application.rb +2 -7
- data/lib/tdiary/author_only_base.rb +78 -9
- data/lib/tdiary/base.rb +2 -2
- data/lib/tdiary/cgi_adapter.rb +7 -5
- data/lib/tdiary/cgi_compat.rb +27 -97
- data/lib/tdiary/configuration.rb +4 -0
- data/lib/tdiary/core_ext.rb +146 -1
- data/lib/tdiary/dispatcher/index_main.rb +5 -23
- data/lib/tdiary/dispatcher/update_main.rb +2 -17
- data/lib/tdiary/dispatcher.rb +29 -15
- data/lib/tdiary/filter/default.rb +2 -2
- data/lib/tdiary/filter/spam.rb +2 -2
- data/lib/tdiary/filter.rb +1 -1
- data/lib/tdiary/plugin/00default.rb +18 -3
- data/lib/tdiary/plugin/en/00default.rb +15 -0
- data/lib/tdiary/plugin/ja/00default.rb +15 -0
- data/lib/tdiary/plugin.rb +1 -1
- data/lib/tdiary/rack/error_handler.rb +36 -0
- data/lib/tdiary/rack.rb +1 -0
- data/lib/tdiary/request.rb +3 -2
- data/lib/tdiary/server.rb +25 -3
- data/lib/tdiary/version.rb +1 -1
- data/lib/tdiary/view.rb +33 -28
- data/lib/tdiary/view_helper.rb +10 -2
- data/lib/tdiary.rb +6 -1
- data/misc/plugin/amazon.rb +37 -11
- data/misc/plugin/amazon_rakuten.rb +75 -0
- data/misc/plugin/draft.rb +75 -0
- data/misc/plugin/en/image.rb +5 -0
- data/misc/plugin/en/makerss.rb +4 -0
- data/misc/plugin/image.rb +15 -4
- data/misc/plugin/ja/makerss.rb +3 -0
- data/misc/plugin/makerss.rb +6 -5
- data/tdiary.conf.sample +8 -0
- data/tdiary.conf.sample-en +8 -0
- data/theme/default/default.css +33 -8
- data/vendor/bundle/ruby/3.4.0/cache/net-imap-0.6.6.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/net-protocol-0.3.0.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/rack-3.2.7.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/cgi-0.5.2/cgi/escape.so +0 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/cgi-0.5.2/gem_make.out +6 -6
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/date_core.so +0 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/gem_make.out +6 -6
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/mkmf.log +4 -4
- data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/ext/cgi/escape/Makefile +3 -3
- data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/escape.so +0 -0
- data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/Makefile +3 -3
- data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/lib/date_core.so +0 -0
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/Gemfile +3 -4
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/README.md +1 -1
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.6.6/Rakefile +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/command_data.rb +62 -92
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config/attr_accessors.rb +8 -9
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config/attr_inheritance.rb +64 -1
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config/attr_version_defaults.rb +1 -4
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config.rb +209 -35
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/connection_state.rb +1 -1
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/data_encoding.rb +127 -27
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.6.6/lib/net/imap/errors.rb +372 -0
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/esearch_result.rb +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/response_data.rb +90 -11
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/response_parser/parser_utils.rb +14 -23
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/response_parser.rb +41 -26
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/response_reader.rb +16 -21
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/scram_authenticator.rb +3 -3
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/search_result.rb +11 -1
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sequence_set.rb +620 -312
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/uidplus_data.rb +2 -63
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap.rb +279 -162
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/net-imap.gemspec +1 -1
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/rdoc.rake +1 -18
- data/vendor/bundle/ruby/3.4.0/gems/{net-protocol-0.2.2/LICENSE.txt → net-protocol-0.3.0/BSDL} +3 -3
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.3.0/COPYING +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/{net-protocol-0.2.2 → net-protocol-0.3.0}/lib/net/protocol.rb +58 -4
- data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/CHANGELOG.md +54 -1
- data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/utils.rb +3 -3
- data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/version.rb +1 -1
- data/vendor/bundle/ruby/3.4.0/specifications/{net-imap-0.5.15.gemspec → net-imap-0.6.6.gemspec} +4 -4
- data/vendor/bundle/ruby/3.4.0/specifications/{net-protocol-0.2.2.gemspec → net-protocol-0.3.0.gemspec} +5 -5
- data/vendor/bundle/ruby/3.4.0/specifications/{rack-3.2.6.gemspec → rack-3.2.7.gemspec} +3 -3
- data/views/tdiary.rconf +2 -0
- metadata +128 -133
- data/misc/plugin/amp.rb +0 -118
- data/vendor/bundle/ruby/3.4.0/cache/net-imap-0.5.15.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/net-protocol-0.2.2.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/rack-3.2.6.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/Rakefile +0 -13
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/data_lite.rb +0 -226
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/errors.rb +0 -118
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/Gemfile +0 -7
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/Rakefile +0 -10
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/bin/console +0 -14
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/bin/setup +0 -8
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/net-protocol.gemspec +0 -33
- data/views/amp.rhtml +0 -34
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/BSDL +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/COPYING +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/LICENSE.txt +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/docs/styles.css +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/authenticators.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config/attr_type_coercion.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/deprecated_client_options.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/fetch_data.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/flags.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/anonymous_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/authentication_exchange.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/authenticators.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/client_adapter.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/cram_md5_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/digest_md5_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/external_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/gs2_header.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/login_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/oauthbearer_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/plain_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/protocol_adapters.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/scram_algorithm.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/stringprep.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/xoauth2_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl_adapter.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/nameprep.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/saslprep.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/saslprep_tables.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/tables.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/trace.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/vanished_data.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/benchmarks.rake +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/rfcs.rake +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/saslprep.rake +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/string_prep_tables_generator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/sample/net-imap.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-protocol-0.2.2 → net-protocol-0.3.0}/README.md +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/CONTRIBUTING.md +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/MIT-LICENSE +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/README.md +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/SPEC.rdoc +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/auth/abstract/handler.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/auth/abstract/request.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/auth/basic.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/bad_request.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/body_proxy.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/builder.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/cascade.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/common_logger.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/conditional_get.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/config.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/constants.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/content_length.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/content_type.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/deflater.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/directory.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/etag.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/events.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/files.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/head.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/headers.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/lint.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/lock.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/media_type.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/method_override.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/mime.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/mock.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/mock_request.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/mock_response.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/multipart/generator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/multipart/parser.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/multipart/uploaded_file.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/multipart.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/null_logger.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/query_parser.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/recursive.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/reloader.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/request.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/response.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/rewindable_input.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/runtime.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/sendfile.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/show_exceptions.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/show_status.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/static.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/tempfile_reaper.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/urlmap.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack.rb +0 -0
data/js/image.js
CHANGED
|
@@ -18,20 +18,57 @@ $(function(){
|
|
|
18
18
|
$(this).css('cursor', 'default');
|
|
19
19
|
})
|
|
20
20
|
.on('click', '.image-img', function(){
|
|
21
|
-
|
|
22
|
-
var w = $('#image-info-' + idx + ' .image-width').text();
|
|
23
|
-
var h = $('#image-info-' + idx + ' .image-height').text();
|
|
24
|
-
$('#body').insertAtCaret($.makePluginTag('image', function(){
|
|
25
|
-
return [idx, "'" + $tDiary.plugin.image.alt + "'", 'nil', '[' + w + ',' + h + ']']
|
|
26
|
-
}));
|
|
21
|
+
$('#body').insertAtCaret(imageTag(this));
|
|
27
22
|
});
|
|
28
|
-
|
|
23
|
+
|
|
24
|
+
var imageTag = function(img, context){
|
|
25
|
+
var idx = img.id.replace('image-index-', '');
|
|
26
|
+
var w = $('#image-info-' + idx + ' .image-width', context).text();
|
|
27
|
+
var h = $('#image-info-' + idx + ' .image-height', context).text();
|
|
28
|
+
return $.makePluginTag('image', function(){
|
|
29
|
+
return [idx, "'" + $tDiary.plugin.image.alt + "'", 'nil', '[' + w + ',' + h + ']']
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
var imageFiles = function(files){
|
|
34
|
+
return $.grep(files, function(file){
|
|
35
|
+
return /^image\//.test(file.type);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
var shrink = function(file){
|
|
40
|
+
if(!window.createImageBitmap || file.type == 'image/gif'){
|
|
41
|
+
return Promise.resolve(file);
|
|
42
|
+
}
|
|
43
|
+
return createImageBitmap(file, {imageOrientation: 'from-image'}).then(function(bitmap){
|
|
44
|
+
var scale = Math.min(1, $tDiary.plugin.image.resize / Math.max(bitmap.width, bitmap.height));
|
|
45
|
+
var type = file.type == 'image/png' && scale == 1 ? 'image/png' : 'image/jpeg';
|
|
46
|
+
var canvas = document.createElement('canvas');
|
|
47
|
+
canvas.width = Math.max(1, Math.round(bitmap.width * scale));
|
|
48
|
+
canvas.height = Math.max(1, Math.round(bitmap.height * scale));
|
|
49
|
+
var context = canvas.getContext('2d');
|
|
50
|
+
if(type == 'image/jpeg'){
|
|
51
|
+
context.fillStyle = '#fff';
|
|
52
|
+
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
53
|
+
}
|
|
54
|
+
context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
|
|
55
|
+
bitmap.close();
|
|
56
|
+
return new Promise(function(resolve){
|
|
57
|
+
canvas.toBlob(function(blob){
|
|
58
|
+
resolve(blob || file);
|
|
59
|
+
}, type, 0.85);
|
|
60
|
+
});
|
|
61
|
+
}).catch(function(){
|
|
62
|
+
return file;
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
29
66
|
var ImagePlugin = function(url){
|
|
30
67
|
this.url =url;
|
|
31
68
|
};
|
|
32
69
|
ImagePlugin.prototype = {
|
|
33
|
-
upload: function(formData
|
|
34
|
-
$.ajax({
|
|
70
|
+
upload: function(formData){
|
|
71
|
+
return $.ajax({
|
|
35
72
|
url: this.url,
|
|
36
73
|
type: 'post',
|
|
37
74
|
data: formData,
|
|
@@ -41,9 +78,6 @@ $(function(){
|
|
|
41
78
|
$('#plugin-image-addimage input[type="submit"]').attr('disabled', 'disabled');
|
|
42
79
|
$('#plugin-image-uploading').show();
|
|
43
80
|
},
|
|
44
|
-
success: function(data){
|
|
45
|
-
callback(data);
|
|
46
|
-
},
|
|
47
81
|
complete: function(){
|
|
48
82
|
$('#plugin-image-addimage input[type="submit"]').removeAttr('disabled');
|
|
49
83
|
$('#plugin-image-uploading').hide();
|
|
@@ -74,40 +108,96 @@ $(function(){
|
|
|
74
108
|
}
|
|
75
109
|
e.preventDefault();
|
|
76
110
|
|
|
77
|
-
uploadFiles(this.plugin_image_file.files);
|
|
111
|
+
uploadFiles($.makeArray(this.plugin_image_file.files));
|
|
78
112
|
this.reset();
|
|
79
113
|
return false;
|
|
80
114
|
});
|
|
81
115
|
|
|
116
|
+
var replaceMarker = function(marker, text){
|
|
117
|
+
var body = $('#body').get(0);
|
|
118
|
+
var start = body.value.indexOf(marker);
|
|
119
|
+
if(start < 0){
|
|
120
|
+
if(text){
|
|
121
|
+
$('#body').insertAtCaret(text);
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
var end = start + marker.length;
|
|
126
|
+
body.setRangeText(text, start, end, body.selectionStart == end ? 'end' : 'preserve');
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
var uploads = 0;
|
|
130
|
+
var uploading = Promise.resolve();
|
|
82
131
|
var uploadFiles = function(files) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
132
|
+
if(!files.length){
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
var marker = '[Uploading image ' + (++uploads) + '...]';
|
|
136
|
+
$('#body').insertAtCaret(marker);
|
|
137
|
+
uploading = uploading.then(function(){
|
|
138
|
+
return files.reduce(function(shrunk, file){
|
|
139
|
+
return shrunk.then(function(images){
|
|
140
|
+
return shrink(file).then(function(image){
|
|
141
|
+
return images.concat([image]);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}, Promise.resolve([]));
|
|
145
|
+
}).then(function(images){
|
|
146
|
+
var formData = new FormData();
|
|
147
|
+
formData.append('plugin', 'image');
|
|
148
|
+
formData.append('plugin_image_addimage', 'true');
|
|
149
|
+
formData.append('date', $tDiary.plugin.image.date);
|
|
150
|
+
$('form.update [name=csrf_protection_key]').first().each(function(){
|
|
151
|
+
formData.append(this.name, this.value);
|
|
152
|
+
});
|
|
153
|
+
$.each(images, function(i, image){
|
|
154
|
+
formData.append('plugin_image_file', image, image.name || (image.type == 'image/png' ? 'image.png' : 'image.jpg'));
|
|
155
|
+
});
|
|
91
156
|
|
|
92
|
-
|
|
93
|
-
|
|
157
|
+
var imagePlugin = new ImagePlugin($('form.update').attr('action'));
|
|
158
|
+
return imagePlugin.upload(formData);
|
|
159
|
+
}).then(function(result){
|
|
160
|
+
var list = $('#plugin-image-delimage', result).parents('div.form');
|
|
161
|
+
var tags = $.map(list.find('.image-img[data-added]'), function(img){
|
|
162
|
+
return imageTag(img, list);
|
|
163
|
+
});
|
|
164
|
+
if(!tags.length){
|
|
165
|
+
throw new Error('no image was saved');
|
|
166
|
+
}
|
|
94
167
|
$('#plugin-image-delimage').parents('div.form').remove();
|
|
95
168
|
$('<div>')
|
|
96
169
|
.attr({
|
|
97
170
|
'class': 'form'
|
|
98
171
|
})
|
|
99
|
-
.append(
|
|
172
|
+
.append(list.html())
|
|
100
173
|
.insertBefore('#plugin-image-addimage');
|
|
101
174
|
var timestamp = new Date().getTime();
|
|
102
175
|
$.each($('#plugin-image-delimage img'), function(){
|
|
103
176
|
$(this).attr('src', $(this).attr('src') + '?' + timestamp);
|
|
104
177
|
});
|
|
178
|
+
replaceMarker(marker, tags.join("\n"));
|
|
179
|
+
}).catch(function(error){
|
|
180
|
+
replaceMarker(marker, '');
|
|
181
|
+
console.error(error);
|
|
182
|
+
alert($tDiary.plugin.image.failed);
|
|
105
183
|
});
|
|
106
184
|
return false;
|
|
107
185
|
};
|
|
108
186
|
|
|
109
|
-
$('#
|
|
110
|
-
|
|
187
|
+
$('#body').on('paste', function(e){
|
|
188
|
+
var clipboard = e.originalEvent.clipboardData;
|
|
189
|
+
if(!clipboard || $.inArray('text/plain', clipboard.types) >= 0){
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
var files = imageFiles(clipboard.files);
|
|
193
|
+
if(files.length){
|
|
194
|
+
e.preventDefault();
|
|
195
|
+
this.setRangeText('', this.selectionStart, this.selectionEnd, 'end');
|
|
196
|
+
uploadFiles(files);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
$(document).on('submit', '#plugin-image-delimage', function(e){
|
|
111
201
|
e.preventDefault();
|
|
112
202
|
|
|
113
203
|
var ids = $.map($('#image-table input[name="plugin_image_id"]:checked'), function(i){
|
|
@@ -147,14 +237,23 @@ $(function(){
|
|
|
147
237
|
$('#plugin_image_dnd').hide();
|
|
148
238
|
$(this).css('border', 'dashed 3px #CCC');
|
|
149
239
|
$('#plugin-image-addimage form').show();
|
|
150
|
-
|
|
151
|
-
uploadFiles(files);
|
|
240
|
+
uploadFiles($.makeArray(e.originalEvent.dataTransfer.files));
|
|
152
241
|
return false;
|
|
153
242
|
})
|
|
154
243
|
.text($tDiary.plugin.image.drop_here)
|
|
155
244
|
.hide()
|
|
156
245
|
.appendTo('#plugin-image-addimage');
|
|
157
246
|
|
|
247
|
+
$('#body').on('drop', function(e){
|
|
248
|
+
var files = imageFiles(e.originalEvent.dataTransfer.files);
|
|
249
|
+
if(files.length){
|
|
250
|
+
e.preventDefault();
|
|
251
|
+
$('#plugin_image_dnd').hide();
|
|
252
|
+
$('#plugin-image-addimage form').show();
|
|
253
|
+
uploadFiles(files);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
158
257
|
var dnd_timer = false;
|
|
159
258
|
$('body')
|
|
160
259
|
.on('dragenter', function() {
|
data/lib/tdiary/admin.rb
CHANGED
|
@@ -8,7 +8,7 @@ module TDiary
|
|
|
8
8
|
super
|
|
9
9
|
|
|
10
10
|
begin
|
|
11
|
-
@date = Time::local( @
|
|
11
|
+
@date = Time::local( @request.param('year').to_i, @request.param('month').to_i, @request.param('day').to_i )
|
|
12
12
|
rescue ArgumentError, NameError
|
|
13
13
|
raise TDiaryError, 'bad date'
|
|
14
14
|
end
|
|
@@ -71,12 +71,12 @@ module TDiary
|
|
|
71
71
|
def initialize( cgi, rhtm, conf )
|
|
72
72
|
super
|
|
73
73
|
|
|
74
|
-
@title = @
|
|
75
|
-
@body = @
|
|
74
|
+
@title = @request.param('title')
|
|
75
|
+
@body = @request.param('body')
|
|
76
76
|
@title = @conf.to_native( @title )
|
|
77
77
|
@body = @conf.to_native( @body )
|
|
78
|
-
@old_date = @
|
|
79
|
-
@hide = @
|
|
78
|
+
@old_date = @request.param('old')
|
|
79
|
+
@hide = @request.param('hide') == 'true' ? true : false
|
|
80
80
|
|
|
81
81
|
@io.transaction( @date ) do |diaries|
|
|
82
82
|
@diaries = diaries
|
|
@@ -107,13 +107,11 @@ module TDiary
|
|
|
107
107
|
#
|
|
108
108
|
class TDiaryUpdate < TDiaryAdmin
|
|
109
109
|
def initialize( request, rhtml, conf )
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
@title = params['title'][0]
|
|
113
|
-
@body = params['body'][0]
|
|
110
|
+
@title = request.param('title')
|
|
111
|
+
@body = request.param('body')
|
|
114
112
|
@title = conf.to_native( @title )
|
|
115
113
|
@body = conf.to_native( @body )
|
|
116
|
-
@hide =
|
|
114
|
+
@hide = request.param('hide') == 'true' ? true : false
|
|
117
115
|
super
|
|
118
116
|
end
|
|
119
117
|
|
|
@@ -140,7 +138,7 @@ module TDiary
|
|
|
140
138
|
@date = newdate
|
|
141
139
|
end
|
|
142
140
|
|
|
143
|
-
@author = @conf.multi_user ? @
|
|
141
|
+
@author = @conf.multi_user ? @request.remote_user : nil
|
|
144
142
|
|
|
145
143
|
@io.transaction( @date ) do |diaries|
|
|
146
144
|
@diaries = diaries
|
|
@@ -166,7 +164,7 @@ module TDiary
|
|
|
166
164
|
class TDiaryReplace < TDiaryUpdate
|
|
167
165
|
def initialize( cgi, rhtm, conf )
|
|
168
166
|
super
|
|
169
|
-
old_date = @
|
|
167
|
+
old_date = @request.param('old')
|
|
170
168
|
|
|
171
169
|
@io.transaction( @date ) do |diaries|
|
|
172
170
|
@diaries = diaries
|
|
@@ -203,7 +201,7 @@ module TDiary
|
|
|
203
201
|
if @diary then
|
|
204
202
|
idx = 0
|
|
205
203
|
@diary.each_comment do |com|
|
|
206
|
-
com.show = @
|
|
204
|
+
com.show = @request.param((idx += 1).to_s) == 'true' ? true : false;
|
|
207
205
|
end
|
|
208
206
|
self << @diary
|
|
209
207
|
@io.clear_cache( /(latest|#{@date.strftime( '%Y%m' )})/ )
|
data/lib/tdiary/application.rb
CHANGED
|
@@ -15,6 +15,7 @@ module TDiary
|
|
|
15
15
|
base_dir ||= self.base_dir
|
|
16
16
|
|
|
17
17
|
@app = ::Rack::Builder.app do
|
|
18
|
+
use TDiary::Rack::ErrorHandler
|
|
18
19
|
map base_dir do
|
|
19
20
|
map '/' do
|
|
20
21
|
use TDiary::Rack::HtmlAnchor
|
|
@@ -39,13 +40,7 @@ module TDiary
|
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def call( env )
|
|
42
|
-
|
|
43
|
-
@app.call( env )
|
|
44
|
-
rescue Exception => e
|
|
45
|
-
body = ["#{e.class}: #{e}\n"]
|
|
46
|
-
body << e.backtrace.join("\n")
|
|
47
|
-
[500, {'content-type' => 'text/plain'}, body]
|
|
48
|
-
end
|
|
43
|
+
@app.call( env )
|
|
49
44
|
end
|
|
50
45
|
|
|
51
46
|
def assets_paths
|
|
@@ -6,6 +6,68 @@ module TDiary
|
|
|
6
6
|
class TDiaryAuthorOnlyBase < TDiaryBase
|
|
7
7
|
def csrf_protection_get_is_okay; false; end
|
|
8
8
|
|
|
9
|
+
# pure decision helpers for csrf_check, class methods so unit specs
|
|
10
|
+
# can exercise them without building a full TDiaryBase
|
|
11
|
+
|
|
12
|
+
# referer must be non-empty with its query string stripped; it is
|
|
13
|
+
# allowed when it names the update page itself or matches the
|
|
14
|
+
# admin-configured regexp
|
|
15
|
+
def self.csrf_referer_allowed?( referer, config_uri, allowed_referer_regexp )
|
|
16
|
+
return true if config_uri == URI.parse( referer )
|
|
17
|
+
allowed_referer_regexp != '' && Regexp.new( allowed_referer_regexp ).match?( referer )
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# normalize an absolute http(s) URL to its origin serialization
|
|
21
|
+
# (lowercase scheme://host, default port omitted); nil when the
|
|
22
|
+
# input has no usable origin
|
|
23
|
+
def self.csrf_origin_of( url )
|
|
24
|
+
uri = URI.parse( url.to_s )
|
|
25
|
+
return nil unless uri.kind_of?( URI::HTTP ) and uri.host
|
|
26
|
+
port = uri.port == uri.default_port ? '' : ":#{uri.port}"
|
|
27
|
+
"#{uri.scheme.downcase}://#{uri.host.downcase}#{port}"
|
|
28
|
+
rescue URI::InvalidURIError
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# classify the request provenance from browser fetch metadata:
|
|
33
|
+
# :same_origin / :cross_site / :unknown (no usable signal, e.g.
|
|
34
|
+
# non-browser clients or a user-initiated navigation)
|
|
35
|
+
def self.csrf_fetch_verdict( origin, sec_fetch_site, allowed_origins )
|
|
36
|
+
if origin and !origin.empty?
|
|
37
|
+
# 'null' (sandboxed or opaque initiators) never matches
|
|
38
|
+
return allowed_origins.include?( origin.downcase ) ? :same_origin : :cross_site
|
|
39
|
+
end
|
|
40
|
+
case sec_fetch_site
|
|
41
|
+
when 'same-origin'
|
|
42
|
+
:same_origin
|
|
43
|
+
when 'same-site', 'cross-site'
|
|
44
|
+
:cross_site
|
|
45
|
+
else
|
|
46
|
+
:unknown
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# main csrf decision: Origin / Sec-Fetch-Site first, the legacy
|
|
51
|
+
# Referer check only as a fallback when neither header gives a
|
|
52
|
+
# usable signal. A cross-site verdict can still be allowed by an
|
|
53
|
+
# explicit Referer allowance (the update page itself or the
|
|
54
|
+
# admin-configured regexp), but not by the empty-referer tolerance
|
|
55
|
+
# of check_referer=false.
|
|
56
|
+
def self.csrf_provenance_ok?( origin, sec_fetch_site, referer, allowed_origins, config_uri, allowed_referer_regexp, check_referer )
|
|
57
|
+
case csrf_fetch_verdict( origin, sec_fetch_site, allowed_origins )
|
|
58
|
+
when :same_origin
|
|
59
|
+
true
|
|
60
|
+
when :cross_site
|
|
61
|
+
referer != '' && csrf_referer_allowed?( referer, config_uri, allowed_referer_regexp )
|
|
62
|
+
else
|
|
63
|
+
if referer == ''
|
|
64
|
+
!check_referer
|
|
65
|
+
else
|
|
66
|
+
csrf_referer_allowed?( referer, config_uri, allowed_referer_regexp )
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
9
71
|
def initialize( cgi, rhtml, conf )
|
|
10
72
|
super
|
|
11
73
|
csrf_check( @request, conf )
|
|
@@ -43,8 +105,7 @@ module TDiary
|
|
|
43
105
|
|
|
44
106
|
referer_is_empty = referer == ''
|
|
45
107
|
referer_uri = URI.parse(referer) if !referer_is_empty
|
|
46
|
-
referer_is_config = !referer_is_empty && config_uri
|
|
47
|
-
referer_is_config ||= Regexp.new(updaterb_regexp) =~ referer if !referer_is_empty && updaterb_regexp != ''
|
|
108
|
+
referer_is_config = !referer_is_empty && self.class.csrf_referer_allowed?(referer, config_uri, updaterb_regexp)
|
|
48
109
|
is_post = request.post?
|
|
49
110
|
|
|
50
111
|
given_key = request.params['csrf_protection_key']
|
|
@@ -53,12 +114,18 @@ module TDiary
|
|
|
53
114
|
is_key_ok = masterkey != '' && given_key == masterkey
|
|
54
115
|
|
|
55
116
|
keycheck_ok = !check_key || is_key_ok
|
|
56
|
-
|
|
117
|
+
|
|
118
|
+
origin = request.env['HTTP_ORIGIN']
|
|
119
|
+
sec_fetch_site = request.env['HTTP_SEC_FETCH_SITE']
|
|
120
|
+
allowed_origins = [base_uri, config_uri, request.base_url].map {|url|
|
|
121
|
+
self.class.csrf_origin_of( url )
|
|
122
|
+
}.compact.uniq
|
|
123
|
+
provenance_ok = self.class.csrf_provenance_ok?( origin, sec_fetch_site, referer, allowed_origins, config_uri, updaterb_regexp, check_referer )
|
|
57
124
|
|
|
58
125
|
if csrf_protection_get_is_okay then
|
|
59
126
|
return if is_post || given_key == nil
|
|
60
127
|
else
|
|
61
|
-
return if keycheck_ok &&
|
|
128
|
+
return if keycheck_ok && provenance_ok
|
|
62
129
|
end
|
|
63
130
|
|
|
64
131
|
raise Exception.new(<<"EOS")
|
|
@@ -69,6 +136,8 @@ Security Error: Possible Cross-site Request Forgery (CSRF)
|
|
|
69
136
|
- Mode is #{ self.mode || 'unknown' }
|
|
70
137
|
- GET is #{ csrf_protection_get_is_okay ? '' : 'not '}allowed
|
|
71
138
|
- Request Method is #{ is_post ? 'POST' : 'not POST' }
|
|
139
|
+
- Origin is #{ origin ? h(origin) : 'nothing' }
|
|
140
|
+
- Sec-Fetch-Site is #{ sec_fetch_site ? h(sec_fetch_site) : 'nothing' }
|
|
72
141
|
- Referer is #{ referer_is_empty ? 'empty' : referer_is_config ? 'config' : 'another page' }
|
|
73
142
|
- Given referer: #{h referer_uri.to_s}
|
|
74
143
|
- Expected base URI: #{h base_uri.to_s}
|
|
@@ -91,11 +160,11 @@ EOS
|
|
|
91
160
|
def initialize( cgi, rhtm, conf )
|
|
92
161
|
super
|
|
93
162
|
|
|
94
|
-
if @
|
|
95
|
-
if @
|
|
96
|
-
date = @
|
|
163
|
+
if @request.valid?( 'date' ) then
|
|
164
|
+
if @request.param('date').kind_of?( String ) then
|
|
165
|
+
date = @request.param('date')
|
|
97
166
|
else
|
|
98
|
-
date = @
|
|
167
|
+
date = @request.param('date').read
|
|
99
168
|
end
|
|
100
169
|
@date = Time::local( *date.scan( /(\d{4})(\d\d)(\d\d)/ )[0] )
|
|
101
170
|
else
|
|
@@ -125,7 +194,7 @@ EOS
|
|
|
125
194
|
|
|
126
195
|
def initialize( cgi, rhtml, conf )
|
|
127
196
|
super
|
|
128
|
-
@key = @
|
|
197
|
+
@key = @request.param('conf') || ''
|
|
129
198
|
end
|
|
130
199
|
end
|
|
131
200
|
|
data/lib/tdiary/base.rb
CHANGED
|
@@ -203,7 +203,7 @@ module TDiary
|
|
|
203
203
|
def initialize(cgi, rhtml, conf)
|
|
204
204
|
super
|
|
205
205
|
|
|
206
|
-
tdiary = tdiary_class(@
|
|
206
|
+
tdiary = tdiary_class(@request.param('date') || '').new(@request, '', conf)
|
|
207
207
|
@date = tdiary.date
|
|
208
208
|
@diaries = tdiary.diaries
|
|
209
209
|
@last_modified = Time.now
|
|
@@ -221,7 +221,7 @@ module TDiary
|
|
|
221
221
|
|
|
222
222
|
def plugin_name
|
|
223
223
|
# plugin name MUST contain only words ([a-zA-Z0-9_])
|
|
224
|
-
@plugin_name ||= (@
|
|
224
|
+
@plugin_name ||= (@request.param('plugin') || '').match(/^(\w+)$/).to_a[1]
|
|
225
225
|
raise TDiary::PermissionError.new('invalid plugin name') unless @plugin_name
|
|
226
226
|
@plugin_name
|
|
227
227
|
end
|
data/lib/tdiary/cgi_adapter.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'stringio'
|
|
2
|
+
require 'tdiary/rack/error_handler'
|
|
2
3
|
|
|
3
4
|
module TDiary
|
|
4
5
|
#
|
|
@@ -23,9 +24,10 @@ module TDiary
|
|
|
23
24
|
|
|
24
25
|
def run( request, dispatcher )
|
|
25
26
|
env = build_env( request.env.to_hash, request.in, request.err )
|
|
26
|
-
|
|
27
|
+
app = TDiary::Rack::ErrorHandler.new( dispatcher )
|
|
28
|
+
write_response( request.out, *app.call( env ) )
|
|
27
29
|
rescue Exception => e
|
|
28
|
-
write_error( request
|
|
30
|
+
write_error( request, e )
|
|
29
31
|
ensure
|
|
30
32
|
request.finish
|
|
31
33
|
end
|
|
@@ -69,9 +71,9 @@ module TDiary
|
|
|
69
71
|
end
|
|
70
72
|
end
|
|
71
73
|
|
|
72
|
-
def write_error(
|
|
73
|
-
|
|
74
|
-
write_response( out, 500, { 'content-type' => 'text/
|
|
74
|
+
def write_error( request, e )
|
|
75
|
+
TDiary::Rack::ErrorHandler.report( request.err, e )
|
|
76
|
+
write_response( request.out, 500, { 'content-type' => 'text/plain' }, ["500 Internal Server Error\n"] )
|
|
75
77
|
end
|
|
76
78
|
end
|
|
77
79
|
end
|
data/lib/tdiary/cgi_compat.rb
CHANGED
|
@@ -16,37 +16,51 @@ module TDiary
|
|
|
16
16
|
# built eagerly so that a clone (Object#clone copies instance
|
|
17
17
|
# variables by reference) shares the same params Hash, like a
|
|
18
18
|
# cloned CGI instance does. Plugins may still rely on this.
|
|
19
|
-
@params =
|
|
19
|
+
@params = request.cgi_params
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
attr_reader :params
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
# the env of the wrapped request, for the stateless RequestExtension
|
|
25
|
+
# readers (remote_addr, https?, tdiary_base_url, ...)
|
|
26
|
+
def env
|
|
27
|
+
@request.env
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# the stateful RequestExtension readers delegate to the wrapped
|
|
31
|
+
# request, so core code reading the request directly sees the same
|
|
32
|
+
# params Hash and the same hidden-referer state as plugins do
|
|
33
|
+
# through this facade
|
|
34
|
+
def cgi_params
|
|
35
|
+
@request.cgi_params
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def cgi_cookies
|
|
39
|
+
@request.cgi_cookies
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def hide_referer!
|
|
43
|
+
@request.hide_referer!
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def referer
|
|
47
|
+
@request.referer
|
|
26
48
|
end
|
|
27
49
|
|
|
28
50
|
def cookies
|
|
29
51
|
# CGI::Cookie keeps the multi-value cookie behaviour (00default.rb
|
|
30
52
|
# reads name and mail from the two values of the tdiary cookie)
|
|
31
|
-
|
|
53
|
+
cgi_cookies
|
|
32
54
|
end
|
|
33
55
|
|
|
34
56
|
def env_table
|
|
35
57
|
@request.env
|
|
36
58
|
end
|
|
37
59
|
|
|
38
|
-
def referer
|
|
39
|
-
env_table['HTTP_REFERER']
|
|
40
|
-
end
|
|
41
|
-
|
|
42
60
|
def user_agent
|
|
43
61
|
env_table['HTTP_USER_AGENT']
|
|
44
62
|
end
|
|
45
63
|
|
|
46
|
-
def remote_addr
|
|
47
|
-
env_table['REMOTE_ADDR']
|
|
48
|
-
end
|
|
49
|
-
|
|
50
64
|
def request_method
|
|
51
65
|
env_table['REQUEST_METHOD']
|
|
52
66
|
end
|
|
@@ -55,10 +69,6 @@ module TDiary
|
|
|
55
69
|
env_table['SCRIPT_NAME']
|
|
56
70
|
end
|
|
57
71
|
|
|
58
|
-
def remote_user
|
|
59
|
-
env_table['REMOTE_USER']
|
|
60
|
-
end
|
|
61
|
-
|
|
62
72
|
def auth_type
|
|
63
73
|
env_table['AUTH_TYPE']
|
|
64
74
|
end
|
|
@@ -77,12 +87,6 @@ module TDiary
|
|
|
77
87
|
|
|
78
88
|
# the URL helpers below come from the CGI patches that used to live
|
|
79
89
|
# in core_ext.rb
|
|
80
|
-
def https?
|
|
81
|
-
return true if env_table['HTTP_X_FORWARDED_PROTO'] == 'https'
|
|
82
|
-
return false if env_table['HTTPS'].nil? or /off/i =~ env_table['HTTPS'] or env_table['HTTPS'] == ''
|
|
83
|
-
true
|
|
84
|
-
end
|
|
85
|
-
|
|
86
90
|
def request_uri
|
|
87
91
|
_request_uri = env_table['REQUEST_URI']
|
|
88
92
|
_script_name = env_table['SCRIPT_NAME']
|
|
@@ -103,81 +107,7 @@ module TDiary
|
|
|
103
107
|
end
|
|
104
108
|
|
|
105
109
|
def base_url
|
|
106
|
-
|
|
107
|
-
begin
|
|
108
|
-
script_dirname = script_name.empty? ? '' : File::dirname(script_name)
|
|
109
|
-
if https?
|
|
110
|
-
port = (server_port == 443) ? '' : ':' + server_port.to_s
|
|
111
|
-
"https://#{server_name}#{port}#{script_dirname}/"
|
|
112
|
-
else
|
|
113
|
-
port = (server_port == 80) ? '' : ':' + server_port.to_s
|
|
114
|
-
"http://#{server_name}#{port}#{script_dirname}/"
|
|
115
|
-
end.sub(%r|/+$|, '/')
|
|
116
|
-
rescue SecurityError
|
|
117
|
-
''
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
private
|
|
122
|
-
|
|
123
|
-
def build_params
|
|
124
|
-
source =
|
|
125
|
-
if request_method == 'POST'
|
|
126
|
-
if %r|\Amultipart/form-data|.match?( env_table['CONTENT_TYPE'].to_s )
|
|
127
|
-
@request.POST
|
|
128
|
-
else
|
|
129
|
-
# Rack's nested query parser behind request.POST keeps only
|
|
130
|
-
# the last of duplicated keys; CGI collects all of them.
|
|
131
|
-
# CGI also splits on ';' as well as '&', and tDiary's own edit
|
|
132
|
-
# links (00default.rb, edit_today.rb) still use ';'
|
|
133
|
-
::Rack::Utils.parse_query( read_raw_body, '&;' )
|
|
134
|
-
end
|
|
135
|
-
else
|
|
136
|
-
::Rack::Utils.parse_query( env_table['QUERY_STRING'].to_s, '&;' )
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
params = {}
|
|
140
|
-
source.each do |key, value|
|
|
141
|
-
values = value.kind_of?( Array ) ? value : [value]
|
|
142
|
-
params[key] = values.map {|v| normalize_value( v ) }
|
|
143
|
-
end
|
|
144
|
-
params.default = []
|
|
145
|
-
params
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def read_raw_body
|
|
149
|
-
input = env_table['rack.input']
|
|
150
|
-
return '' unless input
|
|
151
|
-
# Rack::Request#POST leaves rack.input at EOF, so rewind first in
|
|
152
|
-
# case the request params were already parsed
|
|
153
|
-
input.rewind if input.respond_to?( :rewind )
|
|
154
|
-
body = input.read
|
|
155
|
-
input.rewind if input.respond_to?( :rewind )
|
|
156
|
-
body || ''
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
def normalize_value( value )
|
|
160
|
-
if value.kind_of?( Hash ) and value[:tempfile]
|
|
161
|
-
# Rack multipart file upload: expose an object responding to
|
|
162
|
-
# read, which is all the consumers use
|
|
163
|
-
value[:tempfile]
|
|
164
|
-
else
|
|
165
|
-
repair_encoding( value.to_s )
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
# CGI/FCGI hosting retries broken UTF-8 input as Shift_JIS (index.rb,
|
|
170
|
-
# misc/lib/fcgi_patch.rb). The facade implements the same fallback on
|
|
171
|
-
# each value: invalid UTF-8 is converted from Shift_JIS when possible,
|
|
172
|
-
# otherwise scrubbed.
|
|
173
|
-
def repair_encoding( str )
|
|
174
|
-
str = str.dup.force_encoding( Encoding::UTF_8 ) unless str.encoding == Encoding::UTF_8
|
|
175
|
-
return str if str.valid_encoding?
|
|
176
|
-
begin
|
|
177
|
-
str.dup.force_encoding( Encoding::Shift_JIS ).encode( Encoding::UTF_8 )
|
|
178
|
-
rescue EncodingError
|
|
179
|
-
str.scrub
|
|
180
|
-
end
|
|
110
|
+
tdiary_base_url
|
|
181
111
|
end
|
|
182
112
|
end
|
|
183
113
|
end
|
data/lib/tdiary/configuration.rb
CHANGED
|
@@ -87,6 +87,7 @@ module TDiary
|
|
|
87
87
|
:tdiary_version,
|
|
88
88
|
:html_title, :author_name, :author_mail, :index_page, :hour_offset,
|
|
89
89
|
:description, :icon, :banner, :x_frame_options,
|
|
90
|
+
:referrer_policy, :hsts,
|
|
90
91
|
:header, :footer,
|
|
91
92
|
:section_anchor, :comment_anchor, :date_format, :latest_limit, :show_nyear,
|
|
92
93
|
:theme, :css,
|
|
@@ -155,6 +156,9 @@ module TDiary
|
|
|
155
156
|
|
|
156
157
|
@html_title = '' unless @html_title
|
|
157
158
|
@x_frame_options = nil unless @x_frame_options
|
|
159
|
+
@referrer_policy = 'strict-origin-when-cross-origin' unless @referrer_policy
|
|
160
|
+
@hsts = nil unless @hsts
|
|
161
|
+
@hsts = 'max-age=31536000' if @hsts == true
|
|
158
162
|
@header = '' unless @header
|
|
159
163
|
@footer = '' unless @footer
|
|
160
164
|
|