from environment variable http_proxy
#+BEGIN_SRC emacs-lisp
- (add-to-list 'load-path "~/.emacs.d/xemacs-packages/lisp/twittering-mode-3.0.0")
+ (add-to-list 'load-path "~/.emacs.d/elpa/twittering-mode-20150105.333")
(require 'twittering-mode)
(cond
((string-equal system-type "gnu/linux")
(setq twittering-use-master-password t)
+ (if (getenv "http_proxy")
+ (twittering-toggle-proxy))
+
#+END_SRC
*** [[http://www.emacswiki.org/emacs/MalyonMode][Mylon]]
(define-key bba/launcher "s" 'shell)
(define-key bba/launcher "S" 'synonyms)
(define-key bba/launcher "t" 'git-timemachine)
+ (define-key bba/launcher "T" 'twittering-mode)
(define-key global-map "\C-c\C-t" 'insert-timestamp)
(define-key global-map "\C-c\M-c" 'centered-cursor-mode)
(custom-set-variables
- ;; custom-set-variables was added by Custom.
- ;; If you edit it by hand, you could mess it up, so be careful.
- ;; Your init file should contain only one such instance.
- ;; If there is more than one, they won't work right.
+ ;; custom-set-variables was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
'(blink-cursor-mode t)
'(gnuserv-program (concat exec-directory "/gnuserv"))
'(history-length 1000)
'(magit-repo-dirs (quote ("~/git")))
'(package-archives (quote (("gnu" . "http://elpa.gnu.org/packages/") ("marmalade" . "http://marmalade-repo.org/packages/") ("melpa" . "http://melpa.milkbox.net/packages/"))))
'(package-user-dir "~/.emacs.d/elpa")
+ '(paradox-github-token t)
'(recentf-max-saved-items 42)
'(savehist-mode t nil (savehist))
'(template-default-directories (quote ("~/.emacs.d/templates/")))
'(toolbar-visible-p nil)
'(vc-handled-backends (quote (RCS CVS SVN SCCS Bzr Hg Mtn Arch))))
(custom-set-faces
- ;; custom-set-faces was added by Custom.
- ;; If you edit it by hand, you could mess it up, so be careful.
- ;; Your init file should contain only one such instance.
- ;; If there is more than one, they won't work right.
+ ;; custom-set-faces was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
'(default ((t (:size "14pt" :family "Lucidatypewriter"))))
'(cursor ((t (:foreground "red"))))
'(rainbow-delimiters-depth-1-face ((((background dark)) (:foreground "gray90"))))
--- /dev/null
+;;; twittering-mode-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+\f
+;;;### (autoloads (twit) "twittering-mode" "twittering-mode.el" (21685
+;;;;;; 21202 0 0))
+;;; Generated autoloads from twittering-mode.el
+
+(autoload 'twit "twittering-mode" "\
+Start twittering-mode.
+
+\(fn)" t nil)
+
+;;;***
+\f
+;;;### (autoloads nil nil ("twittering-mode-pkg.el") (21685 21202
+;;;;;; 231505 0))
+
+;;;***
+\f
+(provide 'twittering-mode-autoloads)
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; twittering-mode-autoloads.el ends here
--- /dev/null
+(define-package "twittering-mode" "20150105.333" "Major mode for Twitter" (quote nil))
--- /dev/null
+;;; twittering-mode.el --- Major mode for Twitter
+
+;; Copyright (C) 2007, 2009, 2010 Yuto Hayamizu.
+;; 2008 Tsuyoshi CHO
+
+;; Author: Y. Hayamizu <y.hayamizuNOSPAMgmail.com>
+;; Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
+;; Alberto Garcia <agarciaNOSPAMigalia.com>
+;; Created: Sep 4, 2007
+;; Version: 20150105.333
+;; X-Original-Version: HEAD
+;; Identity: $Id: 3900030719827789c5fe196feacaa78b4ea5a702 $
+;; Keywords: twitter web
+;; URL: http://twmode.sf.net/
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; twittering-mode.el is a major mode for Twitter.
+;; You can check friends timeline, and update your status on Emacs.
+
+;;; Feature Request:
+
+;; URL : http://twitter.com/d00dle/statuses/577876082
+;; * Status Input from Popup buffer and C-cC-c to POST.
+;; URL : http://code.nanigac.com/source/view/419
+;; * update status for region
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'xml)
+
+(eval-and-compile
+ ;; On byte-compilation, Emacs21 requires loading the libraries
+ ;; distributed with twittering-mode.el for macros defined in them.
+ (when (> 22 emacs-major-version)
+ (setq load-path
+ (append (mapcar (lambda (dir)
+ (expand-file-name
+ dir
+ (if load-file-name
+ (or (file-name-directory load-file-name)
+ ".")
+ ".")))
+ '("url-emacs21" "emacs21"))
+ load-path))))
+
+(when (> 22 emacs-major-version)
+ (and (require 'un-define nil t)
+ ;; the explicitly require 'unicode to update a workaround with
+ ;; navi2ch. see a comment of `twittering-ucs-to-char' for more
+ ;; details.
+ (require 'unicode nil t))
+ (defadvice url-scheme-register-proxy (around twittering-fix-process-env (scheme) activate)
+ (let ((process-environment
+ (apply 'append
+ (let ((env-var (concat scheme "_proxy")))
+ (mapcar
+ (lambda (str)
+ (if (string-match
+ (concat "^\\("
+ (regexp-opt (list (upcase env-var)
+ (downcase env-var)))
+ "\\)=$")
+ str)
+ nil
+ (list str)))
+ process-environment)))))
+ ad-do-it)))
+(require 'url)
+
+(defconst twittering-mode-version "HEAD")
+(defconst twittering-mode-identity "$Id: 3900030719827789c5fe196feacaa78b4ea5a702 $")
+(defvar twittering-api-host "api.twitter.com")
+(defvar twittering-api-search-host "search.twitter.com")
+(defvar twittering-web-host "twitter.com")
+(defvar twittering-oauth-request-token-url-without-scheme
+ "://api.twitter.com/oauth/request_token")
+(defvar twittering-oauth-authorization-url-base-without-scheme
+ "://api.twitter.com/oauth/authorize?oauth_token=")
+(defvar twittering-oauth-access-token-url-without-scheme
+ "://api.twitter.com/oauth/access_token")
+
+(defun twittering-mode-version ()
+ "Display a message for twittering-mode version."
+ (interactive)
+ (let ((version-string
+ (format "twittering-mode-v%s" twittering-mode-version)))
+ (if (interactive-p)
+ (message "%s" version-string)
+ version-string)))
+
+(defvar twittering-auth-method 'oauth
+ "*Authentication method for `twittering-mode'.
+The symbol `basic' means Basic Authentication. The symbol `oauth' means
+OAuth Authentication. The symbol `xauth' means xAuth Authentication.
+OAuth Authentication requires `twittering-oauth-consumer-key' and
+`twittering-oauth-consumer-secret'. Additionally, it requires an external
+command `curl' or another command included in `tls-program', which may be
+`openssl' or `gnutls-cli', for SSL.")
+
+(defvar twittering-account-authorization nil
+ "State of account authorization for `twittering-username' and
+`twittering-password'. The value is one of the following symbols:
+nil -- The account have not been authorized yet.
+queried -- The authorization has been queried, but not finished yet.
+authorized -- The account has been authorized.")
+
+(defvar twittering-oauth-use-ssl t
+ "*Whether to use SSL on authentication via OAuth. Twitter requires SSL
+on authorization via OAuth.")
+(defvar twittering-oauth-invoke-browser nil
+ "*Whether to invoke a browser on authorization of access key automatically.")
+
+(defvar twittering-oauth-consumer-key nil)
+(defvar twittering-oauth-consumer-secret nil)
+(defvar twittering-oauth-access-token-alist nil)
+
+(defconst twittering-max-number-of-tweets-on-retrieval 200
+ "The maximum number of `twittering-number-of-tweets-on-retrieval'.")
+
+(defvar twittering-number-of-tweets-on-retrieval 20
+ "*The number of tweets which will be retrieved in one request.
+The upper limit is `twittering-max-number-of-tweets-on-retrieval'.")
+
+(defvar twittering-tinyurl-service 'tinyurl
+ "*The service to shorten URI.
+This must be one of key symbols of `twittering-tinyurl-services-map'.
+To use 'bit.ly or 'j.mp, you have to configure `twittering-bitly-login' and
+`twittering-bitly-api-key'.")
+
+(defvar twittering-tinyurl-services-map
+ '((bit.ly twittering-make-http-request-for-bitly
+ (lambda (service reply)
+ (if (string-match "\n\\'" reply)
+ (substring reply 0 (match-beginning 0))
+ reply)))
+ (goo.gl
+ (lambda (service longurl)
+ (twittering-make-http-request-from-uri
+ "POST" '(("Content-Type" . "application/json"))
+ "https://www.googleapis.com/urlshortener/v1/url"
+ (concat "{\"longUrl\": \"" longurl "\"}")))
+ (lambda (service reply)
+ (when (string-match "\"id\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\""
+ reply)
+ (match-string 1 reply))))
+ (is.gd . "http://is.gd/create.php?format=simple&url=")
+ (j.mp twittering-make-http-request-for-bitly
+ (lambda (service reply)
+ (if (string-match "\n\\'" reply)
+ (substring reply 0 (match-beginning 0))
+ reply)))
+ (migre.me . "http://migre.me/api.txt?url=")
+ (tinyurl . "http://tinyurl.com/api-create.php?url=")
+ (toly
+ (lambda (service longurl)
+ (twittering-make-http-request-from-uri
+ "POST" nil
+ "http://to.ly/api.php"
+ (concat "longurl=" (twittering-percent-encode longurl))))))
+ "Alist of URL shortening services.
+The key is a symbol specifying the service.
+The value is a string or a list consisting of two elements at most.
+
+If the value is a string, `(concat THE-FIRST-ELEMENT longurl)' is used as the
+URL invoking the service.
+If the value is a list, it is interpreted as follows.
+The first element specifies how to make a HTTP request for shortening a URL.
+If the first element is a string, `(concat THE-FIRST-ELEMENT longurl)' is
+used as the URL invoking the service.
+If the first element is a function, it is called as `(funcall THE-FIRST-ELEMENT
+service-symbol longurl)' to obtain a HTTP request alist for invoking the
+service, which must be generated by `twittering-make-http-request'.
+
+The second element specifies how to post-process a HTTP reply by the HTTP
+request.
+If the second element is nil, the reply is directly used as a shortened URL.
+If the second element is a function, it is called as `(funcall
+THE-SECOND-ELEMENT service-symbol HTTP-reply-string)' and its result is used
+as a shortened URL.")
+
+(defvar twittering-bitly-login nil
+ "*The login name for URL shortening service bit.ly and j.mp.")
+(defvar twittering-bitly-api-key nil
+ "*The API key for URL shortening service bit.ly and j.mp.")
+
+(defvar twittering-mode-map (make-sparse-keymap))
+(defvar twittering-mode-menu-on-uri-map (make-sparse-keymap "Twittering Mode"))
+(defvar twittering-mode-on-uri-map (make-sparse-keymap))
+
+(defvar twittering-tweet-history nil)
+(defvar twittering-user-history nil)
+(defvar twittering-timeline-history nil)
+(defvar twittering-hashtag-history nil)
+(defvar twittering-search-history nil)
+
+(defvar twittering-current-hashtag nil
+ "A hash tag string currently set. You can set it by calling
+`twittering-set-current-hashtag'.")
+
+(defvar twittering-timer nil
+ "Timer object for timeline refreshing will be stored here.
+DO NOT SET VALUE MANUALLY.")
+
+(defvar twittering-timer-interval 90
+ "The interval of auto reloading. You should use 60 or more
+seconds for this variable because the number of API call is
+limited by the hour.")
+
+(defvar twittering-timer-for-redisplaying nil
+ "Timer object for timeline redisplay statuses will be stored here.
+DO NOT SET VALUE MANUALLY.")
+
+(defvar twittering-timer-interval-for-redisplaying 5.0
+ "The interval of auto redisplaying statuses.
+Each time Emacs remains idle for the interval, twittering-mode updates parts
+requiring to be redrawn.")
+
+(defvar twittering-username nil
+ "*An username of your Twitter account.")
+
+(defvar twittering-password nil
+ "*A password of your Twitter account. Leave it blank is the
+recommended way because writing a password in .emacs file is so
+dangerous.")
+
+(defvar twittering-initial-timeline-spec-string ":home"
+ "*An initial timeline spec string or a list of timeline spec strings.
+This specifies one or more initial timeline spec strings, which are
+automatically visited when invoking `twittering-mode' or `twit'.
+
+If it is a string, it specifies a timeline spec string.
+If it is a list of strings, it specifies multiple timeline spec strings.")
+
+(defvar twittering-timeline-spec nil
+ "The timeline spec for the current buffer.")
+(defvar twittering-timeline-spec-string ""
+ "The timeline spec string for the current buffer.")
+
+(defvar twittering-timeline-spec-alias nil
+ "*Alist for aliases of timeline spec.
+Each element is (NAME . SPEC-STRING), where NAME is a string and
+SPEC-STRING is a string or a function that returns a timeline spec string.
+
+The alias can be referred as \"$NAME\" or \"$NAME(ARG)\" in timeline spec
+string. If SPEC-STRING is a string, ARG is simply ignored.
+If SPEC-STRING is a function, it is called with a string argument.
+For the style \"$NAME\", the function is called with nil.
+For the style \"$NAME(ARG)\", the function is called with a string ARG.
+
+For example, if you specify
+ `((\"FRIENDS\" . \"my-account/friends-list\")
+ (\"related-to\" .
+ ,(lambda (username)
+ (if username
+ (format \":search/to:%s OR from:%s OR @%s/\"
+ username username username)
+ \":home\")))),
+then you can use \"$FRIENDS\" and \"$related-to(USER)\" as
+\"my-account/friends-list\" and \":search/to:USER OR from:USER OR @USER/\",
+respectively.")
+
+(defvar twittering-current-timeline-spec-string nil
+ "The current timeline spec string. This variable should not be referred
+directly. Use `twittering-current-timeline-spec-string' or
+`twittering-current-timeline-spec'.")
+(defvar twittering-list-index-retrieved nil)
+
+(defvar twittering-process-info-alist nil
+ "Alist of active process and timeline spec retrieved by the process.")
+
+(defvar twittering-server-info-alist nil
+ "Alist of server information.")
+
+(defvar twittering-api-limit-info-alist '()
+ "Alist of an API identifier and an alist representing rate limit for the API.")
+
+(defvar twittering-timeline-spec-to-api-table '()
+ "Alist of a timeline spec and an API identifier for retrieving the timeline.")
+
+
+(defvar twittering-mode-init-hook nil
+ "*Hook run after initializing global variables for `twittering-mode'.")
+(defvar twittering-mode-hook nil
+ "*Hook run every time a buffer is initialized as a twittering-mode buffer.")
+
+(defvar twittering-cookie-alist nil
+ "Alist for stroing cookies for each account.
+This variable stores an alist.
+A key of the alist is a string that is a screen name of an account.
+A value of the alist is a cookie alist which corresponds to a list of
+a pair of a cookie name and value.")
+
+(defvar twittering-new-tweets-count 0
+ "Number of new tweets when `twittering-new-tweets-hook' is run.")
+(defvar twittering-new-tweets-spec nil
+ "Timeline spec, which new tweets belong to, when
+`twittering-new-tweets-hook' is run.")
+(defvar twittering-new-tweets-statuses nil
+ "New tweet status messages, when
+`twittering-new-tweets-hook' is run.")
+
+(defvar twittering-new-tweets-hook nil
+ "*Hook run when new tweets are received.
+
+You can read `twittering-new-tweets-count' or `twittering-new-tweets-spec'
+to get the number of new tweets received when this hook is run.")
+
+(defvar twittering-rendered-new-tweets-spec nil
+ "A timeline spec of newly rendered tweets.
+This variable is bound when invoking hooks registered with
+`twittering-new-tweets-rendered-hook'.")
+
+(defvar twittering-rendered-new-tweets-spec-string nil
+ "A timeline spec string of newly rendered tweets.
+This variable is bound when invoking hooks registered with
+`twittering-new-tweets-rendered-hook'.")
+
+(defvar twittering-rendered-new-tweets nil
+ "A list of newly rendered tweets.
+Hooks registered with `twittering-new-tweets-rendered-hook' can use this
+variable as a list of rendered tweets. Each tweet is represented as an alist.
+You can refer to a property of a tweet alist as
+ (cdr (assq PROPERTY-SYMBOL TWEET-ALIST)).
+Valid symbols are following; id, text, user-name, user-screen-name, user-id,
+ source, source-uri.
+In the list, tweets are placed in order of time. The car of the list is the
+latest one, and the last is the oldest one.")
+
+(defvar twittering-new-tweets-rendered-hook nil
+ "*Hook run when new tweets are rendered.
+When the registered functions are called, the current buffer is the buffer
+that the new tweets are just rendered on.
+The functions can refer to the timeline spec and timeline spec string as
+`twittering-rendered-new-tweets-spec' and
+`twittering-rendered-new-tweets-spec-string', repectively.
+Hooks can also use the local variable `twittering-rendered-new-tweets' as a
+list of rendered tweets.
+For the detail of the representation of tweets, see the variable
+`twittering-rendered-new-tweets'.")
+
+(defvar twittering-active-mode nil
+ "Non-nil if new statuses should be retrieved periodically.
+Do not modify this variable directly. Use `twittering-activate-buffer',
+`twittering-deactivate-buffer', `twittering-toggle-activate-buffer' or
+`twittering-set-active-flag-for-buffer'.")
+
+(defvar twittering-jojo-mode nil)
+(defvar twittering-reverse-mode nil
+ "*Non-nil means tweets are aligned in reverse order of `http://twitter.com/'.")
+(defvar twittering-display-remaining nil
+ "*If non-nil, display remaining of rate limit on the mode-line.")
+(defvar twittering-display-connection-method t
+ "*If non-nil, display the current connection method on the mode-line.")
+(defvar twittering-status-format "%i %s, %@:\n%FILL[ ]{%T // from %f%L%r%R}\n "
+ "Format string for rendering statuses.
+Ex. \"%i %s, %@:\\n%FILL{ %T // from %f%L%r%R}\n \"
+
+Items:
+ %s - screen_name
+ %S - name
+ %i - profile_image
+ %d - description
+ %l - location
+ %L - \" [location]\"
+ %r - \" sent to user\" (use on direct_messages{,_sent})
+ %r - \" in reply to user\" (use on other standard timeline)
+ %R - \" (retweeted by user)\"
+ %RT{...} - strings rendered only when the tweet is a retweet.
+ The braced strings are rendered with the information of the
+ retweet itself instead of that of the retweeted original tweet.
+ For example, %s for a retweet means who posted the original
+ tweet, but %RT{%s} means who retweeted it.
+ %u - url
+ %j - user.id
+ %p - protected?
+ %c - created_at (raw UTC string)
+ %C{time-format-str} - created_at (formatted with time-format-str)
+ %@ - X seconds ago
+ %T - raw text
+ %t - text filled as one paragraph
+ %' - truncated
+ %FACE[face-name]{...} - strings decorated with the specified face.
+ %FIELD[format-str]{field-name}
+ - a value of the given field of a tweet formatted with format-str.
+ The format-str is optional. As a field-name, you can use
+ \"retweet_count\", \"favorite_count\" and so on.
+ %FIELD-IF-NONZERO[format-str]{field-name}
+ - similar to %FIELD[...]{...} except that this makes an empty string
+ if the field value is zero.
+ %FILL[prefix]{...} - strings filled as a paragraph. The prefix is optional.
+ You can use any other specifiers in braces.
+ %FOLD[prefix]{...} - strings folded within the frame width.
+ The prefix is optional. This keeps newlines and does not
+ squeeze a series of white spaces.
+ You can use any other specifiers in braces.
+ %f - source
+ %# - id
+")
+
+(defvar twittering-retweet-format '(nil _ " RT: %t (via @%s)")
+ "*A format string or a skeleton for retweet.
+If the value is a string, it means a format string for generating an initial
+string of a retweet. The format string is converted with the below replacement
+table. And then, the cursor is placed on the next of the initial string.
+It is equivalent to the skeleton '(nil STRING _).
+Note that this string is inserted before the edit skeleton specified by
+`twittering-edit-skeleton' is performed.
+
+If the value is a list, it is treated as a skeleton used with
+`skeleton-insert'. The strings included in the list are converted with the
+following replacement table. And then, the list with converted strings is
+inserted by `skeleton-insert'.
+Note that this skeleton is performed before the edit skeleton specified by
+`twittering-edit-skeleton' is performed.
+
+Replacement table:
+ %s - The screen-name of the cited tweet.
+ %t - The text of the cited tweet.
+ %u - The URL of the cited tweet.
+ %# - The ID of the cited tweet.
+ %% - % itself.")
+
+(defvar twittering-fill-column nil
+ "*The fill-column used for \"%FILL{...}\" in `twittering-status-format'.
+If nil, the fill-column is automatically calculated.")
+
+(defvar twittering-show-replied-tweets t
+ "*The number of replied tweets which will be showed in one tweet.
+
+If the value is not a number and is non-nil, show all replied tweets
+which is already fetched.
+If the value is nil, doesn't show replied tweets.")
+
+(defvar twittering-default-show-replied-tweets nil
+ "*The number of default replied tweets which will be showed in one tweet.
+This value will be used only when showing new tweets.
+
+See `twittering-show-replied-tweets' for more details.")
+
+(defvar twittering-disable-overlay-on-too-long-string nil
+ "*If non-nil, disable overlay on too long string on edit buffer.
+
+If nil, `twittering-edit-mode' puts an overlay `twittering-warning-overlay' on
+characters following the 140th character.
+
+On some environments, some input methods seem to interfere the update of the
+overlay. In such case, you may avoid the problems by setting this variable to
+non-nil.")
+
+(defvar twittering-use-show-minibuffer-length t
+ "*Show current length of minibuffer if this variable is non-nil.
+
+We suggest that you should set to nil to disable the showing function
+when it conflict with your input method (such as AquaSKK, etc.)")
+
+(defvar twittering-notify-successful-http-get t)
+
+(defvar twittering-use-ssl t
+ "Use SSL connection if this variable is non-nil.
+
+SSL connections use 'curl' command as a backend.")
+(defvar twittering-allow-insecure-server-cert nil
+ "*If non-nil, twittering-mode allows insecure server certificates.")
+
+(defvar twittering-curl-program nil
+ "Cache a result of `twittering-find-curl-program'.
+DO NOT SET VALUE MANUALLY.")
+(defvar twittering-curl-program-https-capability nil
+ "Cache a result of `twittering-start-http-session-curl-https-p'.
+DO NOT SET VALUE MANUALLY.")
+
+(defvar twittering-wget-program nil
+ "Cache a result of `twittering-find-wget-program'.
+DO NOT SET VALUE MANUALLY.")
+
+(defvar twittering-tls-program nil
+ "*List of strings containing commands to start TLS stream to a host.
+Each entry in the list is tried until a connection is successful.
+%h is replaced with server hostname, %p with port to connect to.
+Also see `tls-program'.
+If nil, this is initialized with a list of valied entries extracted from
+`tls-program'.")
+
+(defvar twittering-connection-type-order
+ '(curl wget urllib-http native urllib-https))
+ "*A list of connection methods in the preferred order."
+
+(defvar twittering-connection-type-table
+ '((native (check . t)
+ (https . twittering-start-http-session-native-tls-p)
+ (send-http-request . twittering-send-http-request-native)
+ (pre-process-buffer . twittering-pre-process-buffer-native))
+ (curl (check . twittering-start-http-session-curl-p)
+ (https . twittering-start-http-session-curl-https-p)
+ (send-http-request . twittering-send-http-request-curl)
+ (pre-process-buffer . twittering-pre-process-buffer-curl))
+ (wget (check . twittering-start-http-session-wget-p)
+ (https . t)
+ (send-http-request . twittering-send-http-request-wget)
+ (pre-process-buffer . twittering-pre-process-buffer-wget))
+ (urllib-http
+ (display-name . "urllib")
+ (check . twittering-start-http-session-urllib-p)
+ (https . nil)
+ (send-http-request . twittering-send-http-request-urllib)
+ (pre-process-buffer . twittering-pre-process-buffer-urllib))
+ (urllib-https
+ (display-name . "urllib")
+ (check . twittering-start-http-session-urllib-p)
+ (https . twittering-start-http-session-urllib-https-p)
+ (send-http-request . twittering-send-http-request-urllib)
+ (pre-process-buffer . twittering-pre-process-buffer-urllib)))
+ "A list of alist of connection methods.")
+
+(defvar twittering-format-status-function-source ""
+ "The status format string that has generated the current
+`twittering-format-status-function'.")
+(defvar twittering-format-status-function nil
+ "The formating function generated from `twittering-format-status-function-source'.")
+(defvar twittering-format-status-function-without-compile nil
+ "The formating function generated from `twittering-format-status-function-source',
+which is a lambda expression without being compiled.")
+
+(defvar twittering-timeline-data-table (make-hash-table :test 'equal))
+
+(defvar twittering-username-face 'twittering-username-face)
+(defvar twittering-uri-face 'twittering-uri-face)
+
+(defvar twittering-use-native-retweet nil
+ "Post retweets using native retweets if this variable is non-nil.")
+
+(defvar twittering-update-status-function
+ 'twittering-update-status-from-pop-up-buffer
+ "The function used to posting a tweet. It takes 5 arguments,
+INIT-STR, REPLY-TO-ID, USERNAME, TWEET-TYPE, CURRENT-SPEC.
+The first argument INIT-STR is nil or an initial text to be edited.
+REPLY-TO-ID and USERNAME are an ID and a user-screen-name of a tweet to
+which you are going to reply. If the tweet is not a reply, they are nil.
+TWEET-TYPE is a symbol specifying a type of a tweet being edited. It must
+be one of 'direct-message, 'normal, 'organic-retweet and 'reply.
+CURRENT-SPEC means on which timeline the function is called.
+
+Twittering-mode provides two functions for updating status:
+* `twittering-update-status-from-minibuffer': edit tweets in minibuffer
+* `twittering-update-status-from-pop-up-buffer': edit tweets in pop-up buffer")
+
+(defvar twittering-request-confirmation-on-posting nil
+ "*If *non-nil*, confirmation will be requested on posting a tweet edited in
+pop-up buffer.")
+
+(defvar twittering-use-master-password nil
+ "*Wheter to store private information encrypted with a master password.")
+(defvar twittering-private-info-file
+ (expand-file-name "~/.twittering-mode.gpg")
+ "*File for storing encrypted private information when
+`twittering-use-master-password' is non-nil.")
+(defvar twittering-private-info-file-loaded nil
+ "Whether the private info file has been loaded or not.")
+(defvar twittering-variables-stored-with-encryption
+ '(twittering-oauth-access-token-alist))
+
+(defvar twittering-api-prefix "1/")
+(defvar twittering-search-api-method "search")
+(defvar twittering-web-path-prefix "")
+
+(defvar twittering-service-method 'twitter-api-v1.1
+ "*Service method for `twittering-mode'.
+The symbol `twitter' means Twitter Service. The symbol `statusnet' means
+StatusNet Service.")
+
+(defvar twittering-service-method-table
+ '((twitter (status-url . twittering-get-status-url-twitter)
+ (search-url . twittering-get-search-url-twitter))
+ (twitter-api-v1.1
+ (status-url . twittering-get-status-url-twitter)
+ (search-url . twittering-get-search-url-twitter))
+ (statusnet (status-url . twittering-get-status-url-statusnet)
+ (search-url . twittering-get-search-url-statusnet)))
+ "A list of alist of service methods.")
+
+(defvar twittering-timeline-header-face 'twittering-timeline-header-face
+ "*Face for the header on `twittering-mode'.
+The face is used for rendering `twittering-timeline-header'.")
+(defvar twittering-timeline-footer-face 'twittering-timeline-footer-face
+ "*Face for the footer on `twittering-mode'.
+The face is used for rendering `twittering-timeline-footer'.")
+(defvar twittering-timeline-header "-- Press Enter here to update --\n"
+ "*Timeline header string on `twittering-mode'.
+The string is rendered on the beginning of a `twittering-mode' buffer.
+Its face is specified by `twittering-timeline-header-face'.")
+(defvar twittering-timeline-footer "-- Press Enter here to update --"
+ "*Timeline footer string on `twittering-mode'.
+The string is rendered on the end of a `twittering-mode' buffer.
+Its face is specified by `twittering-timeline-footer-face'.")
+
+(defvar twittering-pop-to-buffer-function
+ 'twittering-pop-to-buffer-in-bottom-largest-window
+ "*Function being invoked by `twittering-pop-to-buffer'.
+It will receive an argument, the buffer being selected.
+For example, the following functions can be used; `pop-to-buffer',
+`twittering-pop-to-buffer-simple',
+`twittering-pop-to-buffer-in-current-window',
+`twittering-pop-to-buffer-in-largest-window', and
+`twittering-pop-to-buffer-in-bottom-largest-window'.")
+
+(defvar twittering-relative-retrieval-interval-alist
+ '(("\\`:direct.*\\'" 4)
+ (":home" ":mentions" 1)
+ (t 1))
+ "*An alist of relative intervals of retrieving timelines.
+Each element looks like (TIMELINE-SPEC-REGEXP RELATIVE-INTERVAL).
+
+TIMELINE-SPEC-REGEXP must be t or a regexp string specifying primary
+timeline specs.
+If TIMELINE-SPEC-REGEXP is t, it matches all timelines.
+RELATIVE-INTERVAL must be zero or a positive integer specifying relative
+interval of retrieving timelines that match TIMELINE-SPEC-REGEXP.
+
+An interval for a timeline is determined as follows;
+1. Find the first element where TIMELINE-SPEC-REGEXP matches the
+ timeline or TIMELINE-SPEC-REGEXP is t.
+ If no elements are found, the interval is `twittering-timer-interval'.
+2. Check the RELATIVE-INTERVAL of the element.
+ If RELATIVE-INTERVAL is a positive integer, the interval is
+ RELATIVE-INTERVAL times as long as `twittering-timer-interval'.
+
+ If RELATIVE-INTERVAL is zero, the interval is infinity.
+ The timeline is not retrieved automatically.")
+
+(defvar twittering-relative-retrieval-count-alist '()
+ "An alist for counting retrieval of primary timelines.")
+
+(defvar twittering-filter-alist '()
+ "*An alist of hidden tweet patterns for each primary timeline.
+Each element looks like:
+ (TIMELINE-SPECIFIER (SYM1 . REGEXP1) (SYM2 . REGEXP2) ...).
+
+TIMELINE-SPECIFIER must be a string or a list of strings.
+Each string is a regexp for specifying primary timelines.
+Note that you cannot specify composite timelines such as \":merge\",
+\":exclude-if\" or \":exclude-re\".
+Following regexps (REGEXP1, REGEXP2, ...) specify which tweet should
+be hidden in a certain timeline.
+
+In a timeline that matches TIMELINE-SPECIFIER, a tweet is hidden if
+its elements specified by SYM1, SYM2, ... match corresponding REGEXP1, REGEXP2,
+... respectively.
+
+If a timeline matches multiple specifiers, all regexps of matched elements
+are effective.
+
+For example, if you specify
+ '(((\":home\" \":mentions\") (text . \"http://\"))
+ (\"^[^:]\" (text . \"sample\") (user-screen-name . \"\\`FOO\\'\"))
+ (\"twitter/.*\" (text . \"^aa\"))),
+the following tweets are hidden.
+
+- tweets including \"http://\" in the home timeline and the mentions timeline,
+- tweets that are posted by the user FOO and include \"sample\"
+ in user timelines and list timelines,
+- tweets including \"aa\" at a beginning of a line in list timelines of
+ twitter, such as \"twitter/media\" or \"twitter/support\".")
+
+
+;;;;
+;;;; Macro and small utility function
+;;;;
+
+(defun assocref (item alist)
+ (cdr (assoc item alist)))
+
+(defmacro list-push (value listvar)
+ `(setq ,listvar (cons ,value ,listvar)))
+
+(defmacro case-string (str &rest clauses)
+ `(cond
+ ,@(mapcar
+ (lambda (clause)
+ (let ((keylist (car clause))
+ (body (cdr clause)))
+ `(,(if (listp keylist)
+ `(or ,@(mapcar (lambda (key) `(string-equal ,str ,key))
+ keylist))
+ 't)
+ ,@body)))
+ clauses)))
+
+(defmacro twittering-wait-while (timeout interval condition &optional form &rest timeout-forms)
+ "Wait while CONDITION returns non-nil until TIMEOUT seconds passes.
+
+The form CONDITION is repeatedly evaluated for every INTERVAL seconds
+until CONDITION returns nil or TIMEOUT seconds passes unless TIMEOUT is nil.
+If TIMEOUT is nil, there is no time limit.
+
+If CONDITION returns nil, evaluate the form FORM and return its value.
+If TIMEOUT seconds passes, evaluate the forms TIMEOUT-FORMS and return
+the value of the last form in TIMEOUT-FORMS."
+ `(lexical-let (,@(when timeout `((timeout ,timeout)))
+ (interval ,interval)
+ (current 0.0))
+ (while (and ,@(when timeout '((< current timeout)))
+ ,condition)
+ (sleep-for interval)
+ (setq current (+ current interval)))
+ ,(when (or form timeout-forms)
+ (if (null timeout)
+ form
+ `(if (< current timeout)
+ ,form
+ ,@timeout-forms)))))
+
+
+(defun twittering-extract-matched-substring-all (regexp str)
+ (let ((pos 0)
+ (result nil))
+ (while (string-match regexp str pos)
+ (setq result (cons (match-string 1 str) result))
+ (setq pos (match-end 0)))
+ (reverse result)))
+
+(defun twittering-process-alive-p (proc)
+ "Return non-nil if PROC is alive."
+ (not (memq (process-status proc) '(nil closed exit failed signal))))
+
+(defun twittering-start-process-with-sentinel (name buffer program args sentinel)
+ "Start a program in a subprocess with a sentinel.
+
+This function is the same as `start-process' except that SENTINEL must
+be invoked when the process is successfully started."
+ (let ((proc (apply 'start-process name buffer program args)))
+ (when (and proc (functionp sentinel))
+ (if (twittering-process-alive-p proc)
+ (set-process-sentinel proc sentinel)
+ ;; Ensure that the sentinel is invoked if a subprocess is
+ ;; successfully started.
+ (funcall sentinel proc "finished")))
+ proc))
+
+(defun twittering-parse-time-string (str &optional round-up)
+ "Parse the time-string STR into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).
+This function is the same as `parse-time-string' except to complement the
+lacked parameters with the current time.
+If ROUND-UP is nil, complement the lacked parameters with the oldest ones.
+If ROUND-UP is non-nil, complement the lacked parameters with the latest ones.
+For example, (twittering-parse-time-string \"2012-04-20\")
+returns (0 0 0 20 4 2012 nil nil 32400).
+And (twittering-parse-time-string \"2012-04-20\" t)
+returns (59 59 23 20 4 2012 nil nil 32400).
+The values are identical to those of `decode-time', but any values that are
+unknown are returned as nil."
+ (let* ((parsed (parse-time-string str))
+ (current (decode-time (current-time)))
+ (replacement-alist
+ `((SEC . ,(if round-up
+ 59
+ 0))
+ (MIN . ,(if round-up
+ 59
+ 0))
+ (HOUR . ,(if round-up
+ 23
+ 0))
+ (DAY . nil)
+ (MON . nil)
+ (YEAR . nil)
+ (DOW . nil)
+ (DST . nil)
+ (TZ . nil)))
+ (sym-list (mapcar 'car replacement-alist))
+ (result nil))
+ (while (and parsed current sym-list)
+ (let* ((sym (car sym-list))
+ (v (or (car parsed)
+ (cdr (assq sym replacement-alist))
+ ;; If `sym' is not 'DOW and it is bound to nil
+ ;; in `replacement-alist', use `current'.
+ (unless (eq sym 'DOW)
+ (car current)))))
+ (setq result (cons v result)))
+ (setq parsed (cdr parsed))
+ (setq current (cdr current))
+ (setq sym-list (cdr sym-list)))
+ (reverse result)))
+
+(defun twittering-normalize-string (str)
+ (if (require 'ucs-normalize nil t)
+ (ucs-normalize-NFC-string str)
+ str))
+
+;;;;
+;;;; Utility for portability
+;;;;
+
+(defun twittering-remove-duplicates (list)
+ "Return a copy of LIST with all duplicate elements removed.
+This is non-destructive version of `delete-dups' which is not
+defined in Emacs21."
+ (if (fboundp 'delete-dups)
+ (delete-dups (copy-sequence list))
+ (let ((rest list)
+ (result nil))
+ (while rest
+ (unless (member (car rest) result)
+ (setq result (cons (car rest) result)))
+ (setq rest (cdr rest)))
+ (nreverse result))))
+
+(defun twittering-completing-read (prompt collection &optional predicate require-match initial-input hist def inherit-input-method)
+ "Read a string in the minibuffer, with completion.
+This is a modified version of `completing-read' and accepts candidates
+as a list of a string on Emacs21."
+ ;; completing-read() of Emacs21 does not accepts candidates as
+ ;; a list. Candidates must be given as an alist.
+ (let* ((collection (twittering-remove-duplicates collection))
+ (collection
+ (if (and (> 22 emacs-major-version)
+ (listp collection)
+ (stringp (car collection)))
+ (mapcar (lambda (x) (cons x nil)) collection)
+ collection)))
+ (completing-read prompt collection predicate require-match
+ initial-input hist def inherit-input-method)))
+
+(defun twittering-add-to-history (history-var elt &optional maxelt keep-all)
+ (if (functionp 'add-to-history)
+ (add-to-history history-var elt maxelt keep-all)
+ (let* ((added (cons elt
+ (if (and (not keep-all)
+ (boundp 'history-delete-duplicates)
+ history-delete-duplicates)
+ (delete elt (symbol-value history-var))
+ (symbol-value history-var))))
+ (maxelt (or maxelt history-length))
+ (len (length added)))
+ (set history-var
+ (if (<= len maxelt)
+ added
+ (butlast added (- len maxelt)))))))
+
+(if (fboundp 'assoc-string)
+ (defalias 'twittering-assoc-string 'assoc-string)
+ (defun twittering-assoc-string (key list &optional case-fold)
+ "Like `assoc' but specifically for strings (and symbols).
+This returns the first element of LIST whose car matches the string or
+symbol KEY, or nil if no match exists. When performing the
+comparison, symbols are first converted to strings, and unibyte
+strings to multibyte. If the optional arg CASE-FOLD is non-nil, case
+is ignored.
+
+Unlike `assoc', KEY can also match an entry in LIST consisting of a
+single string, rather than a cons cell whose car is a string.
+
+This is reimplemented version of `assoc-string' which is not
+defined in Emacs21."
+ (let* ((key (if (stringp key)
+ key
+ (symbol-name key)))
+ (regexp (concat "\\`" key "\\'"))
+ (rest list)
+ (result nil)
+ (case-fold-search case-fold))
+ (while (not (null rest))
+ (let* ((current (car rest))
+ (current-key
+ (if (listp current)
+ (car current)
+ current))
+ (current-key
+ (if (stringp current-key)
+ current-key
+ (symbol-name current-key))))
+ (if (string-match key current-key)
+ (setq result current
+ rest nil)
+ (setq rest (cdr rest)))))
+ result)))
+
+;;;;
+;;;; Debug mode
+;;;;
+
+(defvar twittering-debug-mode nil)
+(defvar twittering-debug-buffer "*debug*")
+
+(defun twittering-get-or-generate-buffer (buffer)
+ (if (bufferp buffer)
+ (if (buffer-live-p buffer)
+ buffer
+ (generate-new-buffer (buffer-name buffer)))
+ (if (stringp buffer)
+ (or (get-buffer buffer)
+ (generate-new-buffer buffer)))))
+
+(defun twittering-debug-buffer ()
+ (twittering-get-or-generate-buffer twittering-debug-buffer))
+
+(defmacro debug-print (obj)
+ (let ((obsym (gensym)))
+ `(let ((,obsym ,obj))
+ (if twittering-debug-mode
+ (with-current-buffer (twittering-debug-buffer)
+ (insert "[debug] " (prin1-to-string ,obsym))
+ (newline)
+ ,obsym)
+ ,obsym))))
+
+(defun debug-printf (fmt &rest args)
+ (when twittering-debug-mode
+ (with-current-buffer (twittering-debug-buffer)
+ (insert "[debug] " (apply 'format fmt args))
+ (newline))))
+
+(defun twittering-debug-mode ()
+ (interactive)
+ (setq twittering-debug-mode
+ (not twittering-debug-mode))
+ (message (if twittering-debug-mode "debug mode:on" "debug mode:off")))
+
+;;;;
+;;;; Proxy setting / functions
+;;;;
+
+(defvar twittering-proxy-use nil)
+(defvar twittering-proxy-server nil
+ "*Proxy server for `twittering-mode'.
+If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.
+
+To use individual proxies for HTTP and HTTPS, both `twittering-proxy-server'
+and `twittering-proxy-port' must be nil.")
+(defvar twittering-proxy-port nil
+ "*Port number for `twittering-mode'.
+If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.
+
+To use individual proxies for HTTP and HTTPS, both `twittering-proxy-server'
+and `twittering-proxy-port' must be nil.")
+(defvar twittering-proxy-keep-alive nil)
+(defvar twittering-proxy-user nil
+ "*Username for `twittering-proxy-server'.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+(defvar twittering-proxy-password nil
+ "*Password for `twittering-proxy-server'.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+
+(defvar twittering-http-proxy-server nil
+ "*HTTP proxy server for `twittering-mode'.
+If nil, it is initialized on entering `twittering-mode'.
+The port number is specified by `twittering-http-proxy-port'.
+For HTTPS connection, the proxy specified by `twittering-https-proxy-server'
+and `twittering-https-proxy-port' is used.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+(defvar twittering-http-proxy-port nil
+ "*Port number of a HTTP proxy server for `twittering-mode'.
+If nil, it is initialized on entering `twittering-mode'.
+The server is specified by `twittering-http-proxy-server'.
+For HTTPS connection, the proxy specified by `twittering-https-proxy-server'
+and `twittering-https-proxy-port' is used.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+(defvar twittering-http-proxy-keep-alive nil
+ "*If non-nil, the Keep-alive is enabled. This is experimental.")
+(defvar twittering-http-proxy-user nil
+ "*Username for `twittering-http-proxy-server'.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+(defvar twittering-http-proxy-password nil
+ "*Password for `twittering-http-proxy-server'.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+
+(defvar twittering-https-proxy-server nil
+ "*HTTPS proxy server for `twittering-mode'.
+If nil, it is initialized on entering `twittering-mode'.
+The port number is specified by `twittering-https-proxy-port'.
+For HTTP connection, the proxy specified by `twittering-http-proxy-server'
+and `twittering-http-proxy-port' is used.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+(defvar twittering-https-proxy-port nil
+ "*Port number of a HTTPS proxy server for `twittering-mode'.
+If nil, it is initialized on entering `twittering-mode'.
+The server is specified by `twittering-https-proxy-server'.
+For HTTP connection, the proxy specified by `twittering-http-proxy-server'
+and `twittering-http-proxy-port' is used.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+(defvar twittering-https-proxy-keep-alive nil
+ "*If non-nil, the Keep-alive is enabled. This is experimental.")
+(defvar twittering-https-proxy-user nil
+ "*Username for `twittering-https-proxy-server'.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+(defvar twittering-https-proxy-password nil
+ "*Password for `twittering-https-proxy-server'.
+
+NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
+non-nil, the variables `twittering-proxy-*' have priority over other
+variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
+regardless of HTTP or HTTPS.")
+
+(defun twittering-normalize-proxy-vars ()
+ "Normalize the type of `twittering-http-proxy-port' and
+`twittering-https-proxy-port'."
+ (mapc (lambda (sym)
+ (let ((value (symbol-value sym)))
+ (cond
+ ((null value)
+ nil)
+ ((integerp value)
+ nil)
+ ((stringp value)
+ (set sym (string-to-number value)))
+ (t
+ (set sym nil)))))
+ '(twittering-proxy-port
+ twittering-http-proxy-port
+ twittering-https-proxy-port)))
+
+(defun twittering-proxy-info (scheme &optional item)
+ "Return an alist for proxy configuration registered for SCHEME.
+SCHEME must be a string \"http\", \"https\" or a symbol 'http or 'https.
+The server name is a string and the port number is an integer."
+ (twittering-normalize-proxy-vars)
+ (let ((scheme (if (symbolp scheme)
+ (symbol-name scheme)
+ scheme))
+ (info-list
+ `((("http" "https")
+ . ((server . ,twittering-proxy-server)
+ (port . ,twittering-proxy-port)
+ (keep-alive . ,twittering-proxy-keep-alive)
+ (user . ,twittering-proxy-user)
+ (password . ,twittering-proxy-password)))
+ (("http")
+ . ((server . ,twittering-http-proxy-server)
+ (port . ,twittering-http-proxy-port)
+ (keep-alive . ,twittering-http-proxy-keep-alive)
+ (user . ,twittering-http-proxy-user)
+ (password . ,twittering-http-proxy-password)))
+ (("https")
+ . ((server . ,twittering-https-proxy-server)
+ (port . ,twittering-https-proxy-port)
+ (keep-alive . ,twittering-https-proxy-keep-alive)
+ (user . ,twittering-https-proxy-user)
+ (password . ,twittering-https-proxy-password))))))
+ (let ((info
+ (car (remove nil
+ (mapcar
+ (lambda (entry)
+ (when (member scheme (car entry))
+ (let ((info (cdr entry)))
+ (when (and (cdr (assq 'server info))
+ (cdr (assq 'port info)))
+ info))))
+ info-list)))))
+ (if item
+ (cdr (assq item info))
+ info))))
+
+(defun twittering-url-proxy-services ()
+ "Return the current proxy configuration for `twittering-mode' in the format
+of `url-proxy-services'."
+ (remove nil (mapcar
+ (lambda (scheme)
+ (let ((server (twittering-proxy-info scheme 'server))
+ (port (twittering-proxy-info scheme 'port)))
+ (when (and server port)
+ `(,scheme . ,(format "%s:%s" server port)))))
+ '("http" "https"))))
+
+(defun twittering-find-proxy (scheme)
+ "Find proxy server and its port from the environmental variables and return
+a cons pair of them.
+SCHEME must be \"http\" or \"https\"."
+ (cond
+ ((require 'url-methods nil t)
+ (url-scheme-register-proxy scheme)
+ (let* ((proxy-service (assoc scheme url-proxy-services))
+ (proxy (if proxy-service (cdr proxy-service) nil)))
+ (if (and proxy
+ (string-match "^\\([^:]+\\):\\([0-9]+\\)$" proxy))
+ (let ((host (match-string 1 proxy))
+ (port (string-to-number (match-string 2 proxy))))
+ (cons host port))
+ nil)))
+ (t
+ (let* ((env-var (concat scheme "_proxy"))
+ (env-proxy (or (getenv (upcase env-var))
+ (getenv (downcase env-var))))
+ (default-port (if (string= "https" scheme) "443" "80")))
+ (if (and env-proxy
+ (string-match
+ "^\\(https?://\\)?\\([^:/]+\\)\\(:\\([0-9]+\\)\\)?/?$"
+ env-proxy))
+ (let* ((host (match-string 2 env-proxy))
+ (port-str (or (match-string 4 env-proxy) default-port))
+ (port (string-to-number port-str)))
+ (cons host port))
+ nil)))))
+
+(defun twittering-setup-proxy ()
+ (when (require 'url-methods nil t)
+ ;; If `url-scheme-registry' is not initialized,
+ ;; `url-proxy-services' will be reset by calling
+ ;; `url-insert-file-contents' or `url-retrieve-synchronously', etc.
+ ;; To avoid it, initialize `url-scheme-registry' by calling
+ ;; `url-scheme-get-property' before calling such functions.
+ (url-scheme-get-property "http" 'name)
+ (url-scheme-get-property "https" 'name))
+ (unless (and twittering-http-proxy-server
+ twittering-http-proxy-port)
+ (let ((info (twittering-find-proxy "http")))
+ (setq twittering-http-proxy-server (car-safe info))
+ (setq twittering-http-proxy-port (cdr-safe info))))
+ (unless (and twittering-https-proxy-server
+ twittering-https-proxy-port)
+ (let ((info (twittering-find-proxy "https")))
+ (setq twittering-https-proxy-server (car-safe info))
+ (setq twittering-https-proxy-port (cdr-safe info))))
+ (if (and twittering-proxy-use
+ (null (twittering-proxy-info "http"))
+ (null (twittering-proxy-info "https")))
+ (progn
+ (message "Disabling proxy due to lack of configuration.")
+ (setq twittering-proxy-use nil))
+ t))
+
+(defun twittering-toggle-proxy ()
+ (interactive)
+ (setq twittering-proxy-use
+ (not twittering-proxy-use))
+ (if (twittering-setup-proxy)
+ (message (if twittering-proxy-use "Use Proxy:on" "Use Proxy:off")))
+ (twittering-update-mode-line))
+
+;;;;
+;;;; Functions for URL library
+;;;;
+
+(defvar twittering-url-show-status nil
+ "*Whether to show a running total of bytes transferred.")
+
+;;;;
+;;;; CA certificate
+;;;;
+
+(defvar twittering-cert-file nil
+ "The full-path of the file including the certificates authorizing
+servers on SSL.")
+
+(defconst twittering-ca-cert-list
+ '(
+;; #BEGIN-CERTIFICATE
+;; Equifax Secure CA
+;; issuer= /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
+;; subject= /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
+;; serial=35DEF4CF
+;; SHA1 Fingerprint=D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A
+;; notBefore=Aug 22 16:41:51 1998 GMT
+;; notAfter=Aug 22 16:41:51 2018 GMT
+"-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
+UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
+dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
+MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
+dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
+AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
+BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
+cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
+AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
+MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
+aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
+ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
+IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
+MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
+A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
+7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
+1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
+-----END CERTIFICATE-----
+"
+;; Verisign Class 3 Public Primary Certification Authority - G2
+;; issuer= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority - G2/OU=(c) 1998 VeriSign, Inc. - For authorized use only/OU=VeriSign Trust Network
+;; subject= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority - G2/OU=(c) 1998 VeriSign, Inc. - For authorized use only/OU=VeriSign Trust Network
+;; serial=7DD9FE07CFA81EB7107967FBA78934C6
+;; SHA1 Fingerprint=85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F
+;; notBefore=May 18 00:00:00 1998 GMT
+;; notAfter=Aug 1 23:59:59 2028 GMT
+"-----BEGIN CERTIFICATE-----
+MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
+BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
+c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
+MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
+emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
+DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
+FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
+UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
+YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
+MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
+pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
+13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
+AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
+U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
+F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
+oJ2daZH9
+-----END CERTIFICATE-----
+"
+;; Verisign Class 3 Public Primary Certification Authority - G3
+;; issuer= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G3
+;; subject= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G3
+;; serial=9B7E0649A33E62B9D5EE90487129EF57
+;; SHA1 Fingerprint=13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6
+;; notBefore=Oct 1 00:00:00 1999 GMT
+;; notAfter=Jul 16 23:59:59 2036 GMT
+"-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
+N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
+KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
+kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
+CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
+Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
+imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
+2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
+DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
+F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
+TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+"
+;; Verisign Class 4 Public Primary Certification Authority - G3
+;; issuer= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 4 Public Primary Certification Authority - G3
+;; subject= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 1999 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 4 Public Primary Certification Authority - G3
+;; serial=ECA0A78B6E756A01CFC47CCC2F945ED7
+;; SHA1 Fingerprint=C8:EC:8C:87:92:69:CB:4B:AB:39:E9:8D:7E:57:67:F3:14:95:73:9D
+;; notBefore=Oct 1 00:00:00 1999 GMT
+;; notAfter=Jul 16 23:59:59 2036 GMT
+"-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1
+GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ
++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd
+U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm
+NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY
+ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/
+ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1
+CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq
+g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
+fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c
+2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/
+bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
+-----END CERTIFICATE-----
+"
+;; Equifax Secure Global eBusiness CA
+;; issuer= /C=US/O=Equifax Secure Inc./CN=Equifax Secure Global eBusiness CA-1
+;; subject= /C=US/O=Equifax Secure Inc./CN=Equifax Secure Global eBusiness CA-1
+;; serial=01
+;; SHA1 Fingerprint=7E:78:4A:10:1C:82:65:CC:2D:E1:F1:6D:47:B4:40:CA:D9:0A:19:45
+;; notBefore=Jun 21 04:00:00 1999 GMT
+;; notAfter=Jun 21 04:00:00 2020 GMT
+"-----BEGIN CERTIFICATE-----
+MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT
+ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw
+MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj
+dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l
+c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC
+UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc
+58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/
+o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH
+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr
+aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA
+A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA
+Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv
+8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
+-----END CERTIFICATE-----
+"
+;; Equifax Secure eBusiness CA 1
+;; issuer= /C=US/O=Equifax Secure Inc./CN=Equifax Secure eBusiness CA-1
+;; subject= /C=US/O=Equifax Secure Inc./CN=Equifax Secure eBusiness CA-1
+;; serial=04
+;; SHA1 Fingerprint=DA:40:18:8B:91:89:A3:ED:EE:AE:DA:97:FE:2F:9D:F5:B7:D1:8A:41
+;; notBefore=Jun 21 04:00:00 1999 GMT
+;; notAfter=Jun 21 04:00:00 2020 GMT
+"-----BEGIN CERTIFICATE-----
+MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc
+MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT
+ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw
+MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j
+LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo
+RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu
+WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw
+Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD
+AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK
+eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM
+zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+
+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN
+/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ==
+-----END CERTIFICATE-----
+"
+;; VeriSign Class 3 Public Primary Certification Authority - G5
+;; issuer= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
+;; subject= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5
+;; serial=18DAD19E267DE8BB4A2158CDCC6B3B4A
+;; SHA1 Fingerprint=4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5
+;; notBefore=Nov 8 00:00:00 2006 GMT
+;; notAfter=Jul 16 23:59:59 2036 GMT
+"-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
+nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
+t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
+SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
+BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
+NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
+BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
+BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
+MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
+p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
+5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
+WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
+4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
+hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+"
+;; VeriSign Universal Root Certification Authority
+;; issuer= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2008 VeriSign, Inc. - For authorized use only/CN=VeriSign Universal Root Certification Authority
+;; subject= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2008 VeriSign, Inc. - For authorized use only/CN=VeriSign Universal Root Certification Authority
+;; serial=401AC46421B31321030EBBE4121AC51D
+;; SHA1 Fingerprint=36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54
+;; notBefore=Apr 2 00:00:00 2008 GMT
+;; notAfter=Dec 1 23:59:59 2037 GMT
+"-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB
+vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
+ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX
+MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0
+IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y
+IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh
+bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF
+9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH
+H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H
+LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN
+/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT
+rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw
+WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs
+exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
+DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4
+sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+
+seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz
+4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+
+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR
+lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3
+7M2CYfE45k+XmCpajQ==
+-----END CERTIFICATE-----
+"
+;; VeriSign Class 3 Public Primary Certification Authority - G4
+;; issuer= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2007 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G4
+;; subject= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2007 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G4
+;; serial=2F80FE238C0E220F486712289187ACB3
+;; SHA1 Fingerprint=22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A
+;; notBefore=Nov 5 00:00:00 2007 GMT
+;; notAfter=Jan 18 23:59:59 2038 GMT
+"-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
+U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
+SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
+biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
+GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
+fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
+aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
+aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
+kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
+4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
+FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+"
+;; #END-CERTIFICATE
+))
+
+(defun twittering-delete-ca-cert ()
+ (when (and twittering-cert-file
+ (file-exists-p twittering-cert-file))
+ (delete-file twittering-cert-file))
+ (setq twittering-cert-file nil))
+
+(defun twittering-ensure-ca-cert ()
+ "Return a full-path of the file including CA certificates.
+
+If it does not exist, create it. The directory includes root certificates
+in \"hash format\". In detail, see verify(1SSL)."
+ (unless twittering-cert-file
+ (let ((coding-system-for-write 'iso-safe)
+ (file (make-temp-file "twmode-cacert")))
+ (with-temp-file file
+ (apply 'insert twittering-ca-cert-list))
+ (setq twittering-cert-file file)
+ (add-hook 'kill-emacs-hook 'twittering-delete-ca-cert)))
+ twittering-cert-file)
+
+;;;;
+;;;; User agent
+;;;;
+
+(defvar twittering-user-agent-function 'twittering-user-agent-default-function)
+
+(defun twittering-user-agent-default-function ()
+ "Twittering mode default User-Agent function."
+ (format "Emacs/%d.%d Twittering-mode/%s"
+ emacs-major-version emacs-minor-version
+ twittering-mode-version))
+
+(defun twittering-user-agent ()
+ "Return User-Agent header string."
+ (funcall twittering-user-agent-function))
+
+;;;;
+;;;; Basic HTTP functions (general)
+;;;;
+
+(defun twittering-percent-encode (str &optional coding-system)
+ "Encode STR according to Percent-Encoding defined in RFC 3986."
+ (twittering-oauth-url-encode str coding-system))
+
+(defun twittering-lookup-connection-type (use-ssl &optional order table)
+ "Return available entry extracted fron connection type table.
+TABLE is connection type table, which is an alist of type symbol and its
+item alist, such as
+ '((native (check . t)
+ (https . twittering-start-http-session-native-tls-p)
+ (start . twittering-start-http-session-native))
+ (curl (check . twittering-start-http-session-curl-p)
+ (https . twittering-start-http-session-curl-https-p)
+ (start . twittering-start-http-session-curl))) .
+ORDER means the priority order of type symbols.
+If USE-SSL is nil, the item `https' is ignored.
+When the type `curl' has priority and is available for the above table,
+the function returns
+ '((check . twittering-start-http-session-curl-p)
+ (https . twittering-start-http-session-curl-https-p)
+ (start . twittering-start-http-session-curl)) ."
+ (let ((rest (or order twittering-connection-type-order))
+ (table (or table twittering-connection-type-table))
+ (result nil))
+ (while (and rest (null result))
+ (let* ((candidate (car rest))
+ (entry (cons `(symbol . ,candidate)
+ (cdr (assq candidate table))))
+ (entry (if (assq 'display-name entry)
+ entry
+ (cons `(display-name . ,(symbol-name candidate))
+ entry)))
+ (validate (lambda (item)
+ (let ((v (cdr (assq item entry))))
+ (or (null v) (eq t v) (functionp v)))))
+ (confirm (lambda (item)
+ (let ((v (cdr (assq item entry))))
+ (cond
+ ((null v) nil)
+ ((eq t v) t)
+ ((functionp v) (funcall v)))))))
+ (if (and (funcall validate 'check)
+ (or (not use-ssl) (funcall validate 'https)))
+ (cond
+ ((and (funcall confirm 'check)
+ (or (not use-ssl) (funcall confirm 'https)))
+ (setq rest nil)
+ (setq result entry))
+ (t
+ (setq rest (cdr rest))))
+ (message "The configuration for conncetion type `%s' is invalid."
+ candidate)
+ (setq rest nil))))
+ result))
+
+(defun twittering-get-connection-method-name (use-ssl)
+ "Return a name of the preferred connection method.
+If USE-SSL is non-nil, return a connection method for HTTPS.
+If USE-SSL is nil, return a connection method for HTTP."
+ (cdr (assq 'display-name (twittering-lookup-connection-type use-ssl))))
+
+(defun twittering-lookup-http-start-function (&optional order table)
+ "Decide a connection method from currently available methods."
+ (let ((entry
+ (twittering-lookup-connection-type twittering-use-ssl order table)))
+ (cdr (assq 'send-http-request entry))))
+
+(defun twittering-ensure-connection-method (&optional order table)
+ "Ensure a connection method with a compromise.
+Return nil if no connection methods are available with a compromise."
+ (let* ((use-ssl (or twittering-use-ssl twittering-oauth-use-ssl))
+ (entry (twittering-lookup-connection-type use-ssl order table)))
+ (cond
+ (entry
+ t)
+ ((and (null entry) use-ssl
+ (yes-or-no-p "HTTPS(SSL) is unavailable. Use HTTP instead? "))
+ ;; Fall back on connection without SSL.
+ (setq twittering-use-ssl nil)
+ (setq twittering-oauth-use-ssl nil)
+ (twittering-update-mode-line)
+ (twittering-ensure-connection-method order table))
+ (t
+ (message "No connection methods are available.")
+ nil))))
+
+(defun twittering-make-http-request (method header-list host port path query-parameters post-body use-ssl)
+ "Returns an alist specifying a HTTP request.
+METHOD specifies HTTP method. It must be \"GET\" or \"POST\".
+HEADER-LIST is a list of (field-name . field-value) specifying HTTP header
+fields. The fields \"Host\", \"User-Agent\" and \"Content-Length\" are
+automatically filled if necessary.
+HOST specifies the host.
+PORT specifies the port. This must be an integer.
+PATH specifies the absolute path in URI (without query string).
+QUERY-PARAMTERS is a string or an alist.
+If QUERY-PARAMTERS is a string, it is treated as an encoded query string.
+If QUERY-PARAMTERS is an alist, it represents a list of cons pairs of
+string, (query-key . query-value).
+POST-BODY specifies the post body sent when METHOD equals to \"POST\".
+If POST-BODY is nil, no body is posted.
+If USE-SSL is non-nil, the request is performed with SSL.
+
+The result alist includes the following keys, where a key is a symbol.
+ method: HTTP method such as \"GET\" or \"POST\".
+ scheme: the scheme name. \"http\" or \"https\".
+ host: the host to which the request is sent.
+ port: the port to which the request is sent (integer).
+ path: the absolute path string. Note that it does not include query string.
+ query-string: the query string.
+ encoded-query-alist: the alist consisting of pairs of encoded query-name and
+ encoded query-value.
+ uri: the URI. It includes the query string.
+ uri-without-query: the URI without the query string.
+ header-list: an alist specifying pairs of a parameter and its value in HTTP
+ header field.
+ post-body: the entity that will be posted."
+ (let* ((scheme (if use-ssl "https" "http"))
+ (default-port (if use-ssl 443 80))
+ (port (if port port default-port))
+ (query-string
+ (cond
+ ((stringp query-parameters)
+ query-parameters)
+ ((consp query-parameters)
+ (mapconcat (lambda (pair)
+ (cond
+ ((stringp pair)
+ (twittering-percent-encode pair))
+ ((consp pair)
+ (format
+ "%s=%s"
+ (twittering-percent-encode (car pair))
+ (twittering-percent-encode (cdr pair))))
+ (t
+ nil)))
+ query-parameters
+ "&"))
+ (t
+ nil)))
+ (encoded-query-alist
+ (cond
+ ((stringp query-parameters)
+ ;; Query name and its value must be already encoded.
+ (mapcar (lambda (str)
+ (if (string-match "=" str)
+ (let ((key (substring str 0 (match-beginning 0)))
+ (value (substring str (match-end 0))))
+ `(,key . ,value))
+ `(,str . nil)))
+ (split-string query-parameters "&")))
+ ((consp query-parameters)
+ (mapcar (lambda (pair)
+ (cond
+ ((stringp pair)
+ (cons (twittering-percent-encode pair) nil))
+ ((consp pair)
+ (cons (twittering-percent-encode (car pair))
+ (twittering-percent-encode (cdr pair))))
+ (t
+ nil)))
+ query-parameters))
+ (t
+ nil)))
+ (uri-without-query
+ (concat scheme "://"
+ host
+ (when (and port (not (= port default-port)))
+ (format ":%d" port))
+ path))
+ (uri
+ (if query-string
+ (concat uri-without-query "?" query-string)
+ uri-without-query))
+ (header-list
+ `(,@(when (and (string= method "POST")
+ (not (assoc "Content-Length" header-list)))
+ `(("Content-Length" . ,(format "%d" (length post-body)))))
+ ,@(unless (assoc "Host" header-list)
+ `(("Host" . ,host)))
+ ,@(unless (assoc "User-Agent" header-list)
+ `(("User-Agent" . ,(twittering-user-agent))))
+ ,@header-list)))
+ (cond
+ ((not (member method '("POST" "GET")))
+ (error "Unknown HTTP method: %s" method)
+ nil)
+ ((not (string-match "^/" path))
+ (error "Invalid HTTP path: %s" path)
+ nil)
+ (t
+ `((method . ,method)
+ (scheme . ,scheme)
+ (host . ,host)
+ (port . ,port)
+ (path . ,path)
+ (query-string . ,query-string)
+ (encoded-query-alist . ,encoded-query-alist)
+ (uri . ,uri)
+ (uri-without-query . ,uri-without-query)
+ (header-list . ,header-list)
+ (post-body . ,post-body))))))
+
+(defun twittering-make-http-request-from-uri (method header-list uri &optional post-body)
+ "Returns an alist specifying a HTTP request.
+The result alist has the same form as an alist generated by
+`twittering-make-http-request'.
+
+METHOD specifies HTTP method. It must be \"GET\" or \"POST\".
+HEADER-LIST is a list of (field-name . field-value) specifying HTTP header
+fields. The fields \"Host\" and \"User-Agent\" are automatically filled
+if necessary.
+URI specifies the URI including query string.
+POST-BODY specifies the post body sent when METHOD equals to \"POST\".
+If POST-BODY is nil, no body is posted."
+ (let* ((parts-alist
+ (let ((parsed-url (url-generic-parse-url uri)))
+ ;; This is required for the difference of url library
+ ;; distributed with Emacs 22 and 23.
+ (cond
+ ((and (fboundp 'url-p) (url-p parsed-url))
+ ;; Emacs 23 and later.
+ `((scheme . ,(url-type parsed-url))
+ (host . ,(url-host parsed-url))
+ (port . ,(url-portspec parsed-url))
+ (path . ,(url-filename parsed-url))))
+ ((vectorp parsed-url)
+ ;; Emacs 22.
+ `((scheme . ,(aref parsed-url 0))
+ (host . ,(aref parsed-url 3))
+ (port . ,(aref parsed-url 4))
+ (path . ,(aref parsed-url 5))))
+ (t
+ nil))))
+ (path (let ((path (cdr (assq 'path parts-alist))))
+ (if (string-match "\\`\\(.*\\)\\?" path)
+ (match-string 1 path)
+ path)))
+ (query-string (let ((path (cdr (assq 'path parts-alist))))
+ (if (string-match "\\?\\(.*\\)\\'" path)
+ (match-string 1 path)
+ nil))))
+ (twittering-make-http-request method header-list
+ (cdr (assq 'host parts-alist))
+ (cdr (assq 'port parts-alist))
+ path
+ query-string
+ post-body
+ (string= "https"
+ (cdr (assq 'scheme parts-alist))))))
+
+(defun twittering-make-connection-info (request &optional additional order table)
+ "Make an alist specifying the information of connection for REQUEST.
+REQUEST must be an alist that has the same keys as that generated by
+`twittering-make-http-request'.
+
+ADDITIONAL is appended to the tail of the result alist.
+Following ADDITIONAL, an entry in TABLE is also appended to the result alist,
+where `twittering-lookup-connection-type' determines the entry according to
+the priority order ORDER.
+If ORDER is nil, `twittering-connection-type-order' is used in place of ORDER.
+If TABLE is nil, `twittering-connection-type-table' is used in place of TABLE.
+
+The parameter symbols are following:
+ use-ssl: whether SSL is enabled or not.
+ allow-insecure-server-cert: non-nil if an insecure server certificate is
+ allowed on SSL.
+ cacert-file-fullpath: the full-path of a file including the certificates
+ authorizing a server certificate on SSL. The file must be in PEM format.
+ use-proxy: non-nil if using a proxy.
+ proxy-server: a proxy server or nil.
+ proxy-port: a port for connecting the proxy (integer) or nil.
+ proxy-user: a username for connecting the proxy or nil.
+ proxy-password: a password for connecting the proxy or nil.
+ request: an alist specifying a HTTP request."
+ (let* ((order (or order twittering-connection-type-order))
+ (table (or table twittering-connection-type-table))
+ (scheme (cdr (assq 'scheme request)))
+ (use-ssl (string= "https" scheme))
+ (entry (twittering-lookup-connection-type use-ssl order table)))
+ `((use-ssl . ,use-ssl)
+ (allow-insecure-server-cert
+ . ,twittering-allow-insecure-server-cert)
+ (cacert-file-fullpath
+ . ,(when use-ssl (twittering-ensure-ca-cert)))
+ (use-proxy . ,twittering-proxy-use)
+ ,@(when twittering-proxy-use
+ `((proxy-server . ,(twittering-proxy-info scheme 'server))
+ (proxy-port . ,(twittering-proxy-info scheme 'port))
+ (proxy-user . ,(twittering-proxy-info scheme 'user))
+ (proxy-password . ,(twittering-proxy-info scheme 'password))))
+ (request . ,request)
+ ,@additional
+ ,@entry)))
+
+(defun twittering-get-response-header (buffer)
+ "Extract HTTP response header from HTTP response.
+BUFFER may be a buffer or the name of an existing buffer which contains the HTTP response."
+ (with-current-buffer buffer
+ (save-excursion
+ (goto-char (point-min))
+ (if (search-forward-regexp "\r?\n\r?\n" nil t)
+ (prog1
+ (buffer-substring (point-min) (match-end 0))
+ (when twittering-debug-mode
+ (debug-printf "connection-info=%s\n" connection-info)
+ (debug-print "HTTP response header:\n--BEGIN\n")
+ (debug-print (buffer-substring (point-min) (match-end 0)))
+ (debug-print "--END\n")))
+ nil))))
+
+(defun twittering-make-header-info-alist (header-str)
+ "Make HTTP header alist from HEADER-STR.
+The alist consists of pairs of field-name and field-value, such as
+'((\"Content-Type\" . \"application/xml\; charset=utf-8\")
+ (\"Content-Length\" . \"2075\"))."
+ (let* ((lines (split-string header-str "\r?\n"))
+ (status-line (car lines))
+ (header-lines (cdr lines)))
+ (when (string-match
+ "^\\(HTTP/1\.[01]\\) \\([0-9][0-9][0-9]\\) \\(.*\\)$"
+ status-line)
+ (append `((status-line . ,status-line)
+ (http-version . ,(match-string 1 status-line))
+ (status-code . ,(match-string 2 status-line))
+ (reason-phrase . ,(match-string 3 status-line)))
+ (remove nil
+ (mapcar
+ (lambda (line)
+ (when (string-match "^\\([^: ]*\\): *\\(.*\\)$" line)
+ (cons (match-string 1 line) (match-string 2 line))))
+ header-lines))))))
+
+(defun twittering-get-content-subtype-symbol-from-header-info (header-info)
+ "Return a symbol corresponding to the subtype of content-type."
+ (let* ((content-type
+ ;; According to RFC2616, field name of a HTTP header is
+ ;; case-insensitive.
+ (car
+ (remove
+ nil
+ (mapcar (lambda (entry)
+ (when (and (stringp (car entry))
+ (let ((case-fold-search t))
+ (string-match "\\`content-type\\'"
+ (car entry))))
+ (cdr entry)))
+ header-info))))
+ (subtype (when (and (stringp content-type)
+ (string-match "\\` *[^/]*/\\([^ ;]*\\)"
+ content-type))
+ (downcase (match-string 1 content-type))))
+ (symbol-alist
+ '(("json" . json)
+ ("atom+xml" . atom)
+ ("xml" . xml))))
+ (cdr (assoc subtype symbol-alist))))
+
+(defun twittering-decode-response-body (header-info)
+ "Decode the current buffer according to the content-type in HEADER-INFO."
+ (let* ((content-type
+ ;; According to RFC2616, field name of a HTTP header is
+ ;; case-insensitive.
+ (car
+ (remove
+ nil
+ (mapcar (lambda (entry)
+ (when (and (stringp (car entry))
+ (let ((case-fold-search t))
+ (string-match "\\`content-type\\'"
+ (car entry))))
+ (cdr entry)))
+ header-info))))
+ (parameters (when (stringp content-type)
+ (cdr (split-string content-type ";"))))
+ (regexp "^[[:space:]]*charset=utf-8[[:space:]]*$")
+ (encoded-with-utf-8
+ (let ((case-fold-search t))
+ (remove nil
+ (mapcar (lambda (entry)
+ (string-match regexp entry))
+ parameters)))))
+ (when encoded-with-utf-8
+ (decode-coding-region (point-min) (point-max) 'utf-8))))
+
+(defun twittering-send-http-request-internal (request additional-info sentinel &optional order table)
+ "Open a connection and return a subprocess object for the connection.
+REQUEST must be an alist that has the same keys as that generated by
+`twittering-make-http-request'.
+SENTINEL is called as a function when the process changes state.
+It gets three arguments: the process, a string describing the change, and
+the connection-info, which is generated by `twittering-make-connection-info'
+and also includes an alist ADDITIONAL-INFO.
+
+How to perform the request is selected from TABLE according to the priority
+order ORDER. ORDER and TABLE are directly sent to
+`twittering-make-connection-info'.
+If ORDER is nil, `twittering-connection-type-order' is used in place of ORDER.
+If TABLE is nil, `twittering-connection-type-table' is used in place of TABLE.
+"
+ (let* ((order (or order twittering-connection-type-order))
+ (table (or table twittering-connection-type-table))
+ (connection-info
+ (twittering-make-connection-info request additional-info
+ order table))
+ (func (cdr (assq 'send-http-request connection-info)))
+ (temp-buffer (generate-new-buffer "*twmode-http-buffer*"))
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (cond
+ ((and func (functionp func))
+ (funcall func "*twmode-generic*" temp-buffer
+ connection-info
+ (when (and sentinel (functionp sentinel))
+ (lexical-let ((sentinel sentinel)
+ (connection-info connection-info))
+ (lambda (proc status)
+ (apply sentinel proc status connection-info nil))))))
+ (t
+ (error "No valid connection method is found")
+ nil))))
+
+(defun twittering-send-http-request (request additional-info func &optional clean-up-func)
+ "Send a HTTP request and return a subprocess object for the connection.
+REQUEST must be an alist that has the same keys as that generated by
+`twittering-make-http-request'.
+
+FUNC is called when a HTTP response has been received without errors.
+It is called with the current buffer containing the HTTP response (without
+HTTP headers). FUNC is called with four arguments: the process, a symbol
+describing the status of the process, a connection-info generated by
+`twittering-make-connection-info', and a header-info generated by
+`twittering-get-response-header' and `twittering-make-header-info-alist'.
+The connection-info also includes an alist ADDITIONAL-INFO.
+If FUNC returns non-nil and `twittering-buffer-related-p' is non-nil, the
+returned value is displayed as a message.
+And also, if FUNC returns a string and it matches the regular expression
+\"^\\\\(Failuare\\\\|Response\\\\): \", the returned value is displayed
+as a message.
+
+CLEAN-UP-FUNC is called whenever the sentinel of the subprocess for the
+connection is called (as `set-process-sentinel').
+It is called with three arguments: the process, a symbol describing the status
+of the proess, and a connection-info generated by
+`twittering-make-connection-info'.
+They are the same as arguments for FUNC.
+When a HTTP response has been received, FUNC is called in advance of
+CLEAN-UP-FUNC. CLEAN-UP-FUNC can overwrite the message displayed by FUNC.
+
+If the subprocess has exited, the buffer bound to it is automatically killed
+after calling CLEAN-UP-FUNC.
+
+The method to perform the request is determined from
+`twittering-connection-type-table' according to the priority order
+`twittering-connection-type-order'."
+ (lexical-let ((func func)
+ (clean-up-func clean-up-func))
+ (twittering-send-http-request-internal
+ request additional-info
+ (lambda (proc status-str connection-info)
+ (let ((status (cond
+ ((string= status-str "urllib-finished") 'exit)
+ ((processp proc) (process-status proc))
+ (t nil)))
+ (buffer (process-buffer proc))
+ (exit-status (cond
+ ((string= status-str "urllib-finished") 0)
+ ((processp proc) (process-exit-status proc))
+ (t 1)))
+ (command (process-command proc))
+ (pre-process-func
+ (cdr (assq 'pre-process-buffer connection-info)))
+ (mes nil))
+ (unwind-protect
+ (setq mes
+ (cond
+ ((null status)
+ (format "Failure: process %s does not exist" proc))
+ ((or (memq status '(run stop open listen connect))
+ (not (memq status '(exit signal closed failed))))
+ ;; If the process is running, FUNC is not called.
+ nil)
+ ((and command
+ (not (= 0 exit-status)))
+ ;; If the process abnormally exited,
+ (format "Failure: %s exited abnormally (exit-status=%s)"
+ (car command) exit-status))
+ ((not (buffer-live-p buffer))
+ (format "Failure: the buffer for %s is already killed"
+ proc))
+ (t
+ (when (functionp pre-process-func)
+ ;; Pre-process buffer.
+ (funcall pre-process-func proc buffer connection-info))
+ (let* ((header (twittering-get-response-header buffer))
+ (header-info
+ (and header
+ (twittering-make-header-info-alist header))))
+ (with-current-buffer buffer
+ (goto-char (point-min))
+ (when (search-forward-regexp "\r?\n\r?\n" nil t)
+ ;; delete HTTP headers.
+ (delete-region (point-min) (match-end 0)))
+ ;; It may be necessary to decode the contents of
+ ;; the buffer by UTF-8 because
+ ;; `twittering-http-application-headers' specifies
+ ;; utf-8 as one of acceptable charset.
+ ;; For the present, only UTF-8 is taken into account.
+ (twittering-decode-response-body header-info)
+ (apply func proc status connection-info
+ header-info nil))))))
+ ;; unwind-forms
+ (setq mes
+ (cond
+ ((null mes)
+ nil)
+ ((string-match "^\\(Failure\\|Response\\): " mes)
+ (let* ((request (cdr (assq 'request connection-info)))
+ (method (cdr (assq 'method request)))
+ (uri (cdr (assq 'uri request))))
+ (concat mes " for " method " " uri)))
+ ((twittering-buffer-related-p)
+ mes)))
+ (when mes
+ ;; CLEAN-UP-FUNC can overwrite a message from the return value
+ ;; of FUNC.
+ (message "%s" mes))
+ (when (functionp clean-up-func)
+ (funcall clean-up-func proc status connection-info))
+ (when (and (memq status '(exit signal closed failed))
+ (buffer-live-p buffer)
+ (not twittering-debug-mode))
+ (kill-buffer buffer))))))))
+
+;;;;
+;;;; Basic HTTP functions with tls and Emacs builtins.
+;;;;
+
+(eval-when-compile (require 'tls nil t))
+(defun twittering-start-http-session-native-tls-p ()
+ (when (and (not twittering-proxy-use)
+ (require 'tls nil t))
+ (unless twittering-tls-program
+ (let ((programs
+ (remove nil
+ (mapcar (lambda (cmd)
+ (when (string-match "\\`\\([^ ]+\\) " cmd)
+ (when (executable-find (match-string 1 cmd))
+ cmd)))
+ tls-program))))
+ (setq twittering-tls-program
+ (if twittering-allow-insecure-server-cert
+ (mapcar
+ (lambda (str)
+ (cond
+ ((string-match "^\\([^ ]*/\\)?openssl s_client " str)
+ (concat (match-string 0 str) "-verify 0 "
+ (substring str (match-end 0))))
+ ((string-match "^\\([^ ]*/\\)?gnutls-cli " str)
+ (concat (match-string 0 str) "--insecure "
+ (substring str (match-end 0))))
+ (t
+ str)))
+ programs)
+ programs))))
+ (not (null twittering-tls-program))))
+
+;; TODO: proxy
+(defun twittering-send-http-request-native (name buffer connection-info sentinel)
+ (let* ((request (cdr (assq 'request connection-info)))
+ (uri (cdr (assq 'uri connection-info)))
+ (method (cdr (assq 'method request)))
+ (scheme (cdr (assq 'scheme request)))
+ (host (cdr (assq 'host request)))
+ (port (cdr (assq 'port request)))
+ (path (cdr (assq 'path request)))
+ (query-string (cdr (assq 'query-string request)))
+ (post-body (cdr (assq 'post-body request)))
+ (use-proxy (cdr (assq 'use-proxy connection-info)))
+ (proxy-server (cdr (assq 'proxy-server connection-info)))
+ (proxy-port (cdr (assq 'proxy-port connection-info)))
+ (proxy-user (cdr (assq 'proxy-user connection-info)))
+ (proxy-password (cdr (assq 'proxy-password connection-info)))
+ (proxy-credentials
+ (when (and proxy-user proxy-password)
+ (concat "Basic "
+ (base64-encode-string
+ (concat proxy-user ":" proxy-password)))))
+ (header-list
+ (let ((original-header-list (cdr (assq 'header-list request))))
+ (if proxy-credentials
+ (cons
+ `("Proxy-Authorization" ,proxy-credentials)
+ original-header-list)
+ original-header-list)))
+ (use-ssl (cdr (assq 'use-ssl connection-info)))
+ (allow-insecure-server-cert
+ (cdr (assq 'allow-insecure-server-cert connection-info)))
+ (connect-host (or proxy-server host))
+ (connect-port (or proxy-port port))
+ (request-str
+ (format "%s %s HTTP/1.1\r\n%s\r\n\r\n%s\r\n"
+ method
+ (if use-proxy
+ ;; As described in 5.1.2 of RFC2616, the
+ ;; absolute URI is required here if the connection
+ ;; uses a proxy.
+ uri
+ (concat path
+ (when query-string
+ (concat "?" query-string))))
+ (mapconcat (lambda (pair)
+ (format "%s: %s" (car pair) (cdr pair)))
+ header-list "\r\n")
+ (or post-body "")))
+ (coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ (tls-program twittering-tls-program)
+ (proc
+ (funcall (if use-ssl
+ 'open-tls-stream
+ 'open-network-stream)
+ "network-connection-process"
+ nil connect-host connect-port)))
+ (when proc
+ (set-process-buffer proc buffer)
+ (when (functionp sentinel)
+ (if (twittering-process-alive-p proc)
+ (set-process-sentinel proc sentinel)
+ (funcall sentinel proc "finished")))
+ (process-send-string proc request-str)
+ proc)))
+
+(defun twittering-pre-process-buffer-native (proc buffer connection-info)
+ (let ((use-ssl (cdr (assq 'use-ssl connection-info)))
+ (args (process-command proc)))
+ (cond
+ ((and use-ssl args
+ (car
+ (remove nil
+ (mapcar (lambda (cmd)
+ (string-match "^\\(.*/\\)?gnutls-cli\\b" cmd))
+ args))))
+ (with-current-buffer buffer
+ (save-excursion
+ (goto-char (point-max))
+ (when (search-backward-regexp
+ "- Peer has closed the GNUTLS connection\r?\n\\'")
+ (let ((beg (match-beginning 0))
+ (end (match-end 0)))
+ (delete-region beg end))))))
+ ((and use-ssl args
+ (car
+ (remove nil
+ (mapcar
+ (lambda (cmd)
+ (string-match "^\\(.*/\\)?openssl s_client\\b" cmd))
+ args))))
+ (with-current-buffer buffer
+ (save-excursion
+ (goto-char (point-max))
+ (when (search-backward-regexp "closed\r?\n\\'")
+ (let ((beg (match-beginning 0))
+ (end (match-end 0)))
+ (delete-region beg end))))))
+ (t
+ nil))))
+
+;;;;
+;;;; Basic HTTP functions with curl
+;;;;
+
+(defun twittering-find-curl-program ()
+ "Returns an appropriate `curl' program pathname or nil if not found."
+ (or (executable-find "curl")
+ (let ((windows-p (memq system-type '(windows-nt cygwin)))
+ (curl.exe
+ (expand-file-name
+ "curl.exe"
+ (expand-file-name
+ "win-curl"
+ (file-name-directory (symbol-file 'twit))))))
+ (and windows-p
+ (file-exists-p curl.exe) curl.exe))))
+
+(defun twittering-start-http-session-curl-p ()
+ "Return t if curl was installed, otherwise nil."
+ (unless twittering-curl-program
+ (setq twittering-curl-program (twittering-find-curl-program)))
+ (not (null twittering-curl-program)))
+
+(defun twittering-start-http-session-curl-https-p ()
+ "Return t if curl was installed and the curl support HTTPS, otherwise nil."
+ (when (twittering-start-http-session-curl-p)
+ (unless twittering-curl-program-https-capability
+ (with-temp-buffer
+ (let ((coding-system-for-read 'iso-safe)
+ (coding-system-for-write 'iso-safe)
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (call-process twittering-curl-program
+ nil (current-buffer) nil
+ "--version")
+ (goto-char (point-min))
+ (setq twittering-curl-program-https-capability
+ (if (search-forward-regexp "^Protocols: .*https" nil t)
+ 'capable
+ 'incapable)))))
+ (eq twittering-curl-program-https-capability 'capable)))
+
+(defun twittering-send-http-request-curl (name buffer connection-info sentinel)
+ (let* ((request (cdr (assq 'request connection-info)))
+ (method (cdr (assq 'method request)))
+ (uri (cdr (assq 'uri request)))
+ (header-list (cdr (assq 'header-list request)))
+ (post-body (cdr (assq 'post-body request)))
+ (use-proxy (cdr (assq 'use-proxy connection-info)))
+ (proxy-server (cdr (assq 'proxy-server connection-info)))
+ (proxy-port (cdr (assq 'proxy-port connection-info)))
+ (proxy-user (cdr (assq 'proxy-user connection-info)))
+ (proxy-password (cdr (assq 'proxy-password connection-info)))
+ (use-ssl (cdr (assq 'use-ssl connection-info)))
+ (allow-insecure-server-cert
+ (cdr (assq 'allow-insecure-server-cert connection-info)))
+ (cacert-file-fullpath
+ (cdr (assq 'cacert-file-fullpath connection-info)))
+ (cacert-file-base-directory
+ (when cacert-file-fullpath
+ (file-name-directory cacert-file-fullpath)))
+ (cacert-file-body
+ (when cacert-file-fullpath
+ (file-name-nondirectory cacert-file-fullpath)))
+ (header-list
+ `(,@header-list
+ ;; Make `curl' remove the HTTP header field "Expect" for
+ ;; avoiding '417 Expectation Failed' HTTP response error.
+ ;; The header field is automatically added for a HTTP request
+ ;; exceeding 1024 byte. See
+ ;; http://d.hatena.ne.jp/imait/20091228/1262004813 and
+ ;; http://www.escafrace.co.jp/blog/09/10/16/1008
+ ("Expect" . "")))
+ (curl-args
+ `("--include" "--silent" "--compressed"
+ ,@(apply 'append
+ (mapcar
+ (lambda (pair)
+ ;; Do not overwrite internal headers `curl' would use.
+ ;; Thanks to William Xu.
+ ;; "cURL - How To Use"
+ ;; http://curl.haxx.se/docs/manpage.html
+ (unless (string= (car pair) "Host")
+ `("-H" ,(format "%s: %s" (car pair) (cdr pair)))))
+ header-list))
+ ,@(when use-ssl `("--cacert" ,cacert-file-body))
+ ,@(when (and use-ssl allow-insecure-server-cert)
+ `("--insecure"))
+ ,@(when (and use-proxy proxy-server proxy-port)
+ (append
+ `("-x" ,(format "%s:%s" proxy-server proxy-port))
+ (when (and proxy-user proxy-password)
+ `("-U" ,(format "%s:%s" proxy-user proxy-password)))))
+ ,@(when (string= "POST" method)
+ `("-d" ,(or post-body "")))
+ ,uri))
+ (coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ (default-directory
+ ;; If `use-ssl' is non-nil, the `curl' process
+ ;; is executed at the same directory as the temporary cert file.
+ ;; Without changing directory, `curl' misses the cert file if
+ ;; you use Emacs on Cygwin because the path on Emacs differs
+ ;; from Windows.
+ ;; With changing directory, `curl' on Windows can find the cert
+ ;; file if you use Emacs on Cygwin.
+ (if use-ssl
+ cacert-file-base-directory
+ default-directory)))
+ (twittering-start-process-with-sentinel name buffer
+ twittering-curl-program
+ curl-args sentinel)))
+
+(defun twittering-pre-process-buffer-curl (proc buffer connection-info)
+ (let ((use-ssl (cdr (assq 'use-ssl connection-info)))
+ (use-proxy (cdr (assq 'use-proxy connection-info))))
+ (when (and use-ssl use-proxy)
+ ;; When using SSL via a proxy with CONNECT method,
+ ;; omit a successful HTTP response and headers if they seem to be
+ ;; sent from the proxy.
+ (with-current-buffer buffer
+ (save-excursion
+ (goto-char (point-min))
+ (let ((first-regexp
+ ;; successful HTTP response
+ "\\`HTTP/1\.[01] 2[0-9][0-9] .*?\r?\n")
+ (next-regexp
+ ;; following HTTP response
+ "^\\(\r?\n\\)HTTP/1\.[01] [0-9][0-9][0-9] .*?\r?\n"))
+ (when (and (search-forward-regexp first-regexp nil t)
+ (search-forward-regexp next-regexp nil t))
+ (let ((beg (point-min))
+ (end (match-end 1)))
+ (delete-region beg end)))))))))
+
+;;;;
+;;;; Basic HTTP functions with wget
+;;;;
+
+(defun twittering-find-wget-program ()
+ "Returns an appropriate `wget' program pathname or nil if not found."
+ (executable-find "wget"))
+
+(defun twittering-start-http-session-wget-p ()
+ "Return t if `wget' was installed, otherwise nil."
+ (unless twittering-wget-program
+ (setq twittering-wget-program (twittering-find-wget-program)))
+ (not (null twittering-wget-program)))
+
+(defun twittering-send-http-request-wget (name buffer connection-info sentinel)
+ (let* ((request (cdr (assq 'request connection-info)))
+ (method (cdr (assq 'method request)))
+ (scheme (cdr (assq 'scheme request)))
+ (uri (cdr (assq 'uri request)))
+ (header-list (cdr (assq 'header-list request)))
+ (post-body (cdr (assq 'post-body request)))
+ (use-proxy (cdr (assq 'use-proxy connection-info)))
+ (proxy-server (cdr (assq 'proxy-server connection-info)))
+ (proxy-port (cdr (assq 'proxy-port connection-info)))
+ (proxy-user (cdr (assq 'proxy-user connection-info)))
+ (proxy-password (cdr (assq 'proxy-password connection-info)))
+ (use-ssl (cdr (assq 'use-ssl connection-info)))
+ (allow-insecure-server-cert
+ (cdr (assq 'allow-insecure-server-cert connection-info)))
+ (cacert-file-fullpath
+ (cdr (assq 'cacert-file-fullpath connection-info)))
+ (cacert-file-base-directory
+ (when cacert-file-fullpath
+ (file-name-directory cacert-file-fullpath)))
+ (cacert-file-body
+ (when cacert-file-fullpath
+ (file-name-nondirectory cacert-file-fullpath)))
+ (args
+ `("--save-headers"
+ "--quiet"
+ "--output-document=-"
+ ,@(remove nil
+ (mapcar
+ (lambda (pair)
+ (unless (string= (car pair) "Host")
+ (format "--header=%s: %s" (car pair) (cdr pair))))
+ header-list))
+ ,@(when use-ssl
+ `(,(format "--ca-certificate=%s" cacert-file-body)))
+ ,@(when (and use-ssl allow-insecure-server-cert)
+ `("--no-check-certificate"))
+ ,@(cond
+ ((not use-proxy)
+ '("--no-proxy"))
+ ((and use-proxy proxy-server proxy-port
+ proxy-user proxy-password)
+ `(,(format "--proxy-user=%s" proxy-user)
+ ,(format "--proxy-password=%s" proxy-password)))
+ (t
+ nil))
+ ,@(when (string= "POST" method)
+ `(,(concat "--post-data=" (or post-body ""))))
+ ,uri))
+ (coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ (default-directory
+ ;; If `use-ssl' is non-nil, the `wget' process
+ ;; is executed at the same directory as the temporary cert file.
+ ;; Without changing directory, `wget' misses the cert file if
+ ;; you use Emacs on Cygwin because the path on Emacs differs
+ ;; from Windows.
+ ;; With changing directory, `wget' on Windows can find the cert
+ ;; file if you use Emacs on Cygwin.
+ (if use-ssl
+ cacert-file-base-directory
+ default-directory))
+ (process-environment
+ `(,@(when (and use-proxy proxy-server proxy-port)
+ `(,(format "%s_proxy=%s://%s:%s/" scheme
+ scheme proxy-server proxy-port)))
+ ,@process-environment)))
+ (twittering-start-process-with-sentinel name buffer
+ twittering-wget-program args
+ sentinel)))
+
+(defun twittering-pre-process-buffer-wget (proc buffer connection-info)
+ (with-current-buffer buffer
+ (save-excursion
+ (goto-char (point-min))
+ (when (search-forward-regexp "\\`[^\n]*?\r\r\n" (point-max) t)
+ ;; When `wget.exe' writes HTTP response in text mode,
+ ;; CRLF may be converted into CRCRLF.
+ (goto-char (point-min))
+ (while (search-forward "\r\n" nil t)
+ (replace-match "\n" nil t)))
+ (goto-char (point-max))
+ (when (search-backward-regexp "\nProcess [^\n]* finished\n\\'"
+ (point-min) t)
+ (replace-match "" nil t))
+ )))
+
+;;;;
+;;;; Basic HTTP functions with url library
+;;;;
+
+(defun twittering-start-http-session-urllib-p ()
+ "Return t if url library is available, otherwise nil."
+ (require 'url nil t))
+
+(defun twittering-start-http-session-urllib-https-p ()
+ "Return t if url library can be used for HTTPS, otherwise nil."
+ (and (not twittering-proxy-use)
+ (require 'url nil t)
+ (cond
+ ((<= 22 emacs-major-version)
+ ;; On Emacs22 and later, `url' requires `tls'.
+ (twittering-start-http-session-native-tls-p))
+ ((require 'ssl nil t)
+ ;; On Emacs21, `url' requires `ssl'.
+ t)
+ ((or (and (fboundp 'open-ssl-stream)
+ ;; Since `url-gw' (required by `url') defines autoload of
+ ;; `open-ssl-stream' from "ssl",
+ ;; (fboundp 'open-ssl-stream) will be non-nil even if
+ ;; "ssl" cannot be loaded and `open-ssl-stream' is
+ ;; unavailable.
+ ;; Here, the availability is confirmed by `documentation'.
+ (documentation 'open-ssl-stream))
+ ;; On Emacs21, `url' requires `ssl' in order to use
+ ;; `open-ssl-stream', which is included in `ssl.el'.
+ ;; Even if `ssl' cannot be loaded, `open-tls-stream' can be
+ ;; used as an alternative of the function.
+ (and (twittering-start-http-session-native-tls-p)
+ (defalias 'open-ssl-stream 'open-tls-stream)))
+ (provide 'ssl)
+ t)
+ (t
+ nil))))
+
+(defun twittering-send-http-request-urllib (name buffer connection-info sentinel)
+ (let* ((request (cdr (assq 'request connection-info)))
+ (method (cdr (assq 'method request)))
+ (scheme (cdr (assq 'scheme request)))
+ (uri (cdr (assq 'uri request)))
+ (header-list (cdr (assq 'header-list request)))
+ (post-body (cdr (assq 'post-body request)))
+ (use-proxy (cdr (assq 'use-proxy connection-info)))
+ (proxy-server (cdr (assq 'proxy-server connection-info)))
+ (proxy-port (cdr (assq 'proxy-port connection-info)))
+ (proxy-user (cdr (assq 'proxy-user connection-info)))
+ (proxy-password (cdr (assq 'proxy-password connection-info)))
+ (proxy-credentials
+ (when (and proxy-user proxy-password)
+ (concat "Basic "
+ (base64-encode-string
+ (concat proxy-user ":" proxy-password)))))
+ (coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ (url-proxy-services
+ (when use-proxy
+ `((,scheme . ,(format "%s:%s" proxy-server proxy-port)))))
+ (url-request-method method)
+ (url-request-extra-headers
+ ;; Remove some headers that should be configured by url library.
+ ;; They may break redirections by url library because
+ ;; `url-request-extra-headers' overwrites the new headers
+ ;; that are adapted to redirected connection.
+ (apply 'append
+ (mapcar (lambda (pair)
+ (if (member (car pair)
+ '("Host" "Content-Length"))
+ nil
+ `(,pair)))
+ (if proxy-credentials
+ (cons
+ `("Proxy-Authorization" ,proxy-credentials)
+ header-list)
+ header-list))))
+ (url-request-data post-body)
+ (url-show-status twittering-url-show-status)
+ (url-http-attempt-keepalives nil)
+ (tls-program twittering-tls-program)
+ (coding-system-for-read 'binary)
+ (coding-system-for-write 'binary))
+ (lexical-let ((sentinel sentinel)
+ (buffer buffer))
+ (let ((result-buffer
+ (url-retrieve
+ uri
+ (lambda (&rest args)
+ (let ((proc url-http-process)
+ (url-buffer (current-buffer))
+ (status-str
+ (if (and (< emacs-major-version 22)
+ (boundp 'url-http-end-of-headers)
+ url-http-end-of-headers)
+ "urllib-finished"
+ "finished")))
+ ;; Callback may be called multiple times.
+ ;; (as filter and sentinel?)
+ (unless (local-variable-if-set-p 'twittering-retrieved)
+ (set (make-local-variable 'twittering-retrieved)
+ 'not-completed)
+ (with-current-buffer buffer
+ (set-buffer-multibyte nil)
+ (insert-buffer-substring url-buffer))
+ (set-process-buffer proc buffer)
+ (unwind-protect
+ (apply sentinel proc status-str nil)
+ (set-process-buffer proc url-buffer)
+ (if (eq twittering-retrieved 'exited)
+ (url-mark-buffer-as-dead url-buffer)
+ (setq twittering-retrieved 'completed))))
+ (when (memq (process-status proc)
+ '(nil closed exit failed signal))
+ ;; Mark `url-buffer' as dead when the process exited
+ ;; and `sentinel' is completed.
+ ;; If this `lambda' is evaluated via a filter, the
+ ;; process may exit before it is finished to evaluate
+ ;; `(apply sentinel ...)'. In the case, `buffer' should
+ ;; not be killed. It should be killed after the
+ ;; evaluation of `sentinel'.
+ (if (eq twittering-retrieved 'completed)
+ (url-mark-buffer-as-dead url-buffer)
+ (setq twittering-retrieved 'exited))))))))
+ (when (buffer-live-p result-buffer)
+ (with-current-buffer result-buffer
+ (set (make-local-variable 'url-show-status)
+ twittering-url-show-status)
+ ;; Make `url-http-attempt-keepalives' buffer-local
+ ;; in order to send the current value of the variable
+ ;; to the sentinel invoked for HTTP redirection,
+ (make-local-variable 'url-http-attempt-keepalives))
+ (get-buffer-process result-buffer))))))
+
+(defun twittering-pre-process-buffer-urllib (proc buffer connection-info)
+ (with-current-buffer buffer
+ (save-excursion
+ (goto-char (point-max))
+ (cond
+ ((search-backward-regexp
+ "- Peer has closed the GNUTLS connection\r?\n\\'"
+ nil t)
+ (let ((beg (match-beginning 0))
+ (end (match-end 0)))
+ (delete-region beg end)))
+ ((search-backward-regexp "closed\r?\n\\'" nil t)
+ (let ((beg (match-beginning 0))
+ (end (match-end 0)))
+ (delete-region beg end)))
+ (t nil)))))
+
+;;;;
+;;;; HTTP functions for twitter-like serivce
+;;;;
+
+(defun twittering-http-application-headers (&optional method headers)
+ "Return an assoc list of HTTP headers for twittering-mode."
+ (unless method
+ (setq method "GET"))
+
+ (let ((headers headers))
+ (push (cons "User-Agent" (twittering-user-agent)) headers)
+ (when (string= "GET" method)
+ (push (cons "Accept"
+ (concat
+ "text/xml"
+ ",application/xml"
+ ",application/xhtml+xml"
+ ",application/html;q=0.9"
+ ",text/plain;q=0.8"
+ ",image/png,*/*;q=0.5"))
+ headers)
+ (push (cons "Accept-Charset" "utf-8;q=0.7,*;q=0.7")
+ headers))
+ (when (string= "POST" method)
+ (push (cons "Content-Type" "text/plain") headers))
+ headers
+ ))
+
+(defun twittering-add-application-header-to-http-request (request account-info)
+ "Make a new HTTP request based on REQUEST with the authorization header.
+The authorization header is generated from ACCOUNT-INFO.
+ACCOUNT-INFO must be an alist that includes the following keys;
+ \"screen_name\" and \"password\" if `twittering-auth-method' is 'basic,
+ \"screen_name\", \"oauth_token\" and \"oauth_token_secret\" if
+ `twittering-auth-method' is 'oauth or 'xauth."
+ (let* ((method (cdr (assq 'method request)))
+ (auth-str
+ (cond
+ ((eq twittering-auth-method 'basic)
+ (twittering-make-basic-authentication-string account-info))
+ ((memq twittering-auth-method '(oauth xauth))
+ (twittering-make-oauth-authentication-string account-info request))
+ (t
+ nil)))
+ (cookie-str (twittering-make-cookie-string request account-info))
+ (application-headers
+ `(,@(twittering-http-application-headers method)
+ ("Authorization" . ,auth-str)
+ ,@(when cookie-str
+ `(("Cookie" . ,cookie-str))))))
+ (mapcar (lambda (entry)
+ (if (eq (car entry) 'header-list)
+ `(header-list
+ . ,(append (cdr entry) application-headers))
+ entry))
+ request)))
+
+(defun twittering-get-error-message (header-info connection-info &optional buffer)
+ "Return an error message generated from the arguments.
+HEADER-INFO must be an alist generated by `twittering-get-response-header'.
+CONNECTION-INFO must be an alist generated by
+`twittering-make-connection-info'. It may include some additional information
+which is added by `twittering-send-http-request'.
+BUFFER must be nil or a HTTP response body, which includes error messages from
+the server when the HTTP status code equals to 400 or 403.
+If BUFFER is nil, the current buffer is used instead."
+ (let ((buffer (or buffer (current-buffer)))
+ (status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info)))
+ (format
+ (twittering-get-content-subtype-symbol-from-header-info header-info)))
+ (cond
+ ((and (buffer-live-p buffer)
+ (member status-code '("400" "401" "403" "404")))
+ ;; Twitter returns an error message as a HTTP response body if
+ ;; HTTP status is "400 Bad Request" or "403 Forbidden".
+ ;; See "HTTP Response Codes and Errors | dev.twitter.com"
+ ;; http://dev.twitter.com/pages/responses_errors .
+ ;;
+ ;; However, Twitter seems to return an error message even when
+ ;; the HTTP status is "401 Unauthorized" or "404 Not Found".
+ (let* ((error-mes
+ (cond
+ ((eq format 'xml)
+ (let ((xmltree
+ (with-current-buffer buffer
+ (twittering-xml-parse-region (point-min)
+ (point-max)))))
+ (car (cddr (assq 'error (or (assq 'errors xmltree)
+ (assq 'hash xmltree)))))))
+ ((eq format 'json)
+ (let ((json-object (with-current-buffer buffer
+ (twittering-json-read))))
+ (cdr (assq 'error json-object))))
+ (t
+ ;; ATOM is not supported.
+ nil))))
+ (if error-mes
+ (format "%s (%s)" status-line error-mes)
+ status-line)))
+ (t
+ status-line))))
+
+(defun twittering-http-get (account-info-alist host method &optional parameters format additional-info sentinel clean-up-sentinel)
+ "Send a HTTP GET request with application headers.
+ACCOUNT-INFO-ALIST is an alist used by
+`twittering-add-application-header-to-http-request'.
+The alist made by `((account-info . ,ACCOUNT-INFO-ALIST) ,@ADDITIONAL-INFO)'
+is used as the argument `additional-info' of `twittering-send-http-request'.
+HOST is hostname of remote side, api.twitter.com (or search.twitter.com).
+METHOD must be one of Twitter API method classes
+ (statuses, users or direct_messages).
+PARAMETERS is alist of URI parameters.
+ ex) ((\"mode\" . \"view\") (\"page\" . \"6\")) => <URI>?mode=view&page=6
+FORMAT is a response data format (\"xml\", \"atom\", \"json\")"
+ (let* ((format (or format "xml"))
+ (sentinel
+ (lexical-let ((sentinel (or sentinel
+ 'twittering-http-get-default-sentinel)))
+ (lambda (proc status connection-info header-info)
+ (twittering-update-server-info connection-info header-info)
+ (apply sentinel proc status connection-info header-info nil))))
+ (path (concat "/" method "." format))
+ (headers nil)
+ (port nil)
+ (post-body "")
+ (request
+ (twittering-add-application-header-to-http-request
+ (twittering-make-http-request "GET" headers host port path
+ parameters post-body
+ twittering-use-ssl)
+ account-info-alist))
+ (additional-info
+ `((account-info . ,account-info-alist)
+ ,@additional-info)))
+ (twittering-send-http-request request additional-info
+ sentinel clean-up-sentinel)))
+
+(defun twittering-http-get-default-sentinel (proc status connection-info header-info)
+ (let ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info)))
+ (format
+ (twittering-get-content-subtype-symbol-from-header-info header-info)))
+ (case-string
+ status-code
+ (("200")
+ (debug-printf "connection-info=%s" connection-info)
+ (let* ((spec (cdr (assq 'timeline-spec connection-info)))
+ (spec-string (cdr (assq 'timeline-spec-string connection-info)))
+ (service-method (cdr (assq 'service-method connection-info)))
+ (statuses
+ (cond
+ ((eq format 'json)
+ (let ((json-array (twittering-json-read)))
+ (cond
+ ((null json-array)
+ nil)
+ ((eq (car spec) 'search)
+ (cond
+ ((memq service-method '(twitter statusnet))
+ (mapcar 'twittering-json-object-to-a-status-on-search
+ (cdr (assq 'results json-array))))
+ ((eq service-method 'twitter-api-v1.1)
+ (mapcar 'twittering-json-object-to-a-status
+ (cdr (assq 'statuses json-array))))))
+ ((twittering-timeline-spec-is-direct-messages-p spec)
+ (mapcar
+ 'twittering-json-object-to-a-status-on-direct-messages
+ json-array))
+ (t
+ (mapcar 'twittering-json-object-to-a-status
+ json-array)))))
+ ((eq format 'xml)
+ (let ((xmltree
+ (twittering-xml-parse-region (point-min) (point-max))))
+ (when xmltree
+ (twittering-xmltree-to-status xmltree))))
+ ((eq format 'atom)
+ (let ((xmltree
+ (twittering-xml-parse-region (point-min) (point-max))))
+ (when xmltree
+ (twittering-atom-xmltree-to-status xmltree))))
+ (t
+ nil)))
+ (rendered-tweets nil))
+ (let ((updated-timeline-info
+ (twittering-add-statuses-to-timeline-data statuses spec))
+ (buffer (twittering-get-buffer-from-spec spec)))
+ ;; FIXME: We should retrieve un-retrieved statuses until
+ ;; statuses is nil. twitter server returns nil as
+ ;; xmltree with HTTP status-code is "200" when we
+ ;; retrieved all un-retrieved statuses.
+ (if twittering-notify-successful-http-get
+ (if updated-timeline-info
+ (concat
+ (format "Fetching %s. Success. " spec-string)
+ (mapconcat
+ (lambda (info)
+ (let ((spec-string (nth 0 info))
+ (num (nth 1 info)))
+ (format "%s: +%d" spec-string num)))
+ updated-timeline-info
+ ", "))
+ (format "Fetching %s. Success. (No new tweets)"
+ spec-string))
+ nil))))
+ (("404")
+ ;; The requested resource does not exist.
+ (let ((spec (cdr (assq 'timeline-spec connection-info)))
+ (spec-string (cdr (assq 'timeline-spec-string connection-info))))
+ ;; Remove specs related to the invalid spec from history.
+ (mapc
+ (lambda (buffer)
+ (let ((other-spec (twittering-get-timeline-spec-for-buffer buffer))
+ (other-spec-string
+ (twittering-get-timeline-spec-string-for-buffer buffer)))
+ (when (twittering-timeline-spec-depending-on-p other-spec spec)
+ (twittering-remove-timeline-spec-string-from-history
+ other-spec-string))))
+ (twittering-get-buffer-list)))
+ (format "Response: %s"
+ (twittering-get-error-message header-info connection-info)))
+ (t
+ (format "Response: %s"
+ (twittering-get-error-message header-info connection-info))))))
+
+(defun twittering-retrieve-single-tweet-sentinel (proc status connection-info header-info)
+ (let ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info)))
+ (format
+ (twittering-get-content-subtype-symbol-from-header-info header-info)))
+ (case-string
+ status-code
+ (("200" "403" "404")
+ (debug-printf "connection-info=%s" connection-info)
+ (let* ((id (cdr (assq 'id connection-info)))
+ (user-screen-name (cdr (assq 'user-screen-name connection-info)))
+ (status
+ (cond
+ ((string= status-code "403")
+ ;; Forbidden. Maybe a protected tweet?
+ (twittering-make-alist-of-forbidden-tweet id
+ user-screen-name))
+ ((string= status-code "404")
+ ;; The requested resource does not exist.
+ (twittering-make-alist-of-non-existent-tweet id
+ user-screen-name))
+ ((eq format 'json)
+ (let ((json-object (twittering-json-read)))
+ (twittering-json-object-to-a-status json-object)))
+ ((eq format 'xml)
+ (let ((xmltree
+ (twittering-xml-parse-region (point-min) (point-max))))
+ (when xmltree
+ (car
+ (twittering-xmltree-to-status
+ `((statuses nil ,@xmltree)))))))
+ (t
+ nil))))
+ (when status
+ (twittering-add-statuses-to-timeline-data `(,status) '(:single))
+ (let ((buffer (cdr (assq 'buffer connection-info)))
+ (spec (cdr (assq 'timeline-spec connection-info)))
+ (prop
+ (cdr (assq 'property-to-be-redisplayed connection-info))))
+ (cond
+ ((null prop)
+ ;; The process has been invoked via `twittering-call-api' with
+ ;; the command `retrieve-timeline', not the command
+ ;; `retrieve-single-tweet' for rendering a replied tweet.
+ ;; No special property that specifies regions being re-rendered
+ ;; is given.
+ (let ((new-statuses `(,status))
+ (buffer (twittering-get-buffer-from-spec spec)))
+ (when (and new-statuses buffer)
+ (twittering-render-timeline buffer new-statuses t))))
+ ((and buffer prop (buffer-live-p buffer))
+ (twittering-redisplay-status-on-each-buffer buffer prop)
+ (with-current-buffer buffer
+ (save-excursion
+ (let ((buffer-read-only nil))
+ (lexical-let ((prop prop))
+ (twittering-for-each-property-region
+ prop
+ (lambda (beg end value)
+ ;; Remove the property required no longer.
+ (remove-text-properties beg end `(,prop nil))
+ (goto-char beg)
+ (twittering-render-replied-statuses)))))))))))
+ (cond
+ ((string= status-code "403")
+ (format "You are not authorized to see this tweet (ID %s)." id))
+ ((string= status-code "404")
+ (format "The tweet with ID %s does not exist." id))
+ (twittering-notify-successful-http-get
+ (format "Fetching %s. Success." id))
+ (t
+ nil))))
+ (t
+ (format "Response: %s"
+ (twittering-get-error-message header-info connection-info))))))
+
+(defmacro twittering-http-get-list-sentinel-base (what)
+ `(let ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info)))
+ (format
+ (twittering-get-content-subtype-symbol-from-header-info header-info))
+ (indexes nil)
+ (mes nil))
+ (case-string
+ status-code
+ (("200")
+ (cond
+ ((eq format 'xml)
+ (let ((xmltree (twittering-xml-parse-region (point-min) (point-max))))
+ (when xmltree
+ (setq indexes
+ (mapcar
+ (lambda (c-node)
+ (caddr (assq ,what c-node)))
+ (remove nil
+ (mapcar
+ (lambda (node)
+ (and (consp node) (eq 'list (car node))
+ node))
+ (cdr-safe
+ (assq 'lists (assq 'lists_list xmltree))))
+ ))
+ ))))
+ ((eq format 'json)
+ (let* ((json-object (twittering-json-read))
+ (json-list
+ (cond
+ ((arrayp json-object)
+ ;; GET lists/list in the Twitter REST API v1.1 returns
+ ;; an array.
+ json-object)
+ (t
+ ;; GET lists/subscriptions in the Twitter REST API v1.1
+ ;; returns an alist.
+ (cdr (assq 'lists json-object))))))
+ (when json-object
+ (setq indexes
+ (mapcar (lambda (entry)
+ (cdr (assq ,what entry)))
+ json-list)))))
+ (t
+ (error "Format \"%s\" is not supported" format)
+ nil)))
+ (t
+ (setq mes (format "Response: %s"
+ (twittering-get-error-message header-info
+ connection-info)))))
+ (setq twittering-list-index-retrieved
+ (or indexes
+ mes
+ "")) ;; set "" explicitly if user does not have a list.
+ mes))
+
+(defun twittering-http-get-list-index-sentinel (proc status connection-info header-info)
+ (twittering-http-get-list-sentinel-base 'slug))
+
+(defun twittering-http-get-list-subscriptions-sentinel (proc status connection-info header-info)
+ (let ((result (twittering-http-get-list-sentinel-base 'full_name)))
+ (when (listp twittering-list-index-retrieved)
+ (setq twittering-list-index-retrieved
+ (mapcar (lambda (str)
+ (and (string-match "\\`@\\(.*\\)\\'" str)
+ (match-string 1 str)))
+ twittering-list-index-retrieved)))
+ result))
+
+(defun twittering-http-post (account-info-alist host method &optional parameters format additional-info sentinel clean-up-sentinel)
+ "Send HTTP POST request to api.twitter.com (or search.twitter.com)
+ACCOUNT-INFO-ALIST is an alist used by
+`twittering-add-application-header-to-http-request'.
+The alist made by `((account-info . ,ACCOUNT-INFO-ALIST) ,@ADDITIONAL-INFO)'
+is used as the argument `additional-info' of `twittering-send-http-request'.
+HOST is hostname of remote side, api.twitter.com (or search.twitter.com).
+METHOD must be one of Twitter API method classes
+ (statuses, users or direct_messages).
+PARAMETERS is alist of URI parameters.
+ ex) ((\"mode\" . \"view\") (\"page\" . \"6\")) => <URI>?mode=view&page=6
+FORMAT is a response data format (\"xml\", \"atom\", \"json\")"
+ (let* ((format (or format "xml"))
+ (sentinel
+ (lexical-let ((sentinel (or sentinel
+ 'twittering-http-post-default-sentinel)))
+ (lambda (proc status connection-info header-info)
+ (twittering-update-server-info connection-info header-info)
+ (apply sentinel proc status connection-info header-info nil))))
+ (path (concat "/" method "." format))
+ (headers nil)
+ (port nil)
+ (post-body "")
+ (request
+ (twittering-add-application-header-to-http-request
+ (twittering-make-http-request "POST" headers host port path
+ parameters post-body
+ twittering-use-ssl)
+ account-info-alist))
+ (additional-info `((account-info . ,account-info-alist)
+ ,@additional-info)))
+ (twittering-send-http-request request additional-info
+ sentinel clean-up-sentinel)))
+
+(defun twittering-http-post-default-sentinel (proc status connection-info header-info)
+ (let ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info))))
+ (case-string
+ status-code
+ (("200")
+ "Success: Post.")
+ (t
+ (format "Response: %s"
+ (twittering-get-error-message header-info connection-info))))))
+
+(defun twittering-http-post-destroy-status-sentinel (proc status connection-info header-info)
+ "A sentinel for deleting a status invoked via `twittering-call-api'."
+ (let ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info)))
+ (format
+ (twittering-get-content-subtype-symbol-from-header-info header-info)))
+ (case-string
+ status-code
+ (("200")
+ (let* ((params
+ (cond
+ ((eq format 'xml)
+ (let ((xml
+ (twittering-xml-parse-region (point-min) (point-max))))
+ `((id . ,(elt (assq 'id (assq 'status xml)) 2))
+ (text . ,(elt (assq 'text (assq 'status xml)) 2)))))
+ ((eq format 'json)
+ (let ((json-object (twittering-json-read)))
+ `((id . ,(cdr (assq 'id_str json-object)))
+ (text . ,(cdr (assq 'text json-object))))))
+ (t
+ (error "Format \"%s\" is not supported" format)
+ nil)))
+ (id (cdr (assq 'id params)))
+ (text (cdr (assq 'text params))))
+ (cond
+ (id
+ (twittering-delete-status-from-data-table id)
+ (format "Deleting \"%s\". Success." text))
+ (t
+ "Failure: the response for deletion could not be parsed."))))
+ (t
+ (format "Response: %s"
+ (twittering-get-error-message header-info connection-info))))))
+
+;;;;
+;;;; OAuth
+;;;;
+
+(defun twittering-oauth-url-encode (str &optional coding-system)
+ "Encode string according to Percent-Encoding defined in RFC 3986."
+ (let ((coding-system (or (when (and coding-system
+ (coding-system-p coding-system))
+ coding-system)
+ 'utf-8)))
+ (mapconcat
+ (lambda (c)
+ (cond
+ ((or (and (<= ?A c) (<= c ?Z))
+ (and (<= ?a c) (<= c ?z))
+ (and (<= ?0 c) (<= c ?9))
+ (eq ?. c)
+ (eq ?- c)
+ (eq ?_ c)
+ (eq ?~ c))
+ (char-to-string c))
+ (t (format "%%%02X" c))))
+ (encode-coding-string str coding-system)
+ "")))
+
+(defun twittering-oauth-unhex (c)
+ (cond
+ ((and (<= ?0 c) (<= c ?9))
+ (- c ?0))
+ ((and (<= ?A c) (<= c ?F))
+ (+ 10 (- c ?A)))
+ ((and (<= ?a c) (<= c ?f))
+ (+ 10 (- c ?a)))
+ ))
+
+(defun twittering-oauth-url-decode (str &optional coding-system)
+ (let* ((coding-system (or (when (and coding-system
+ (coding-system-p coding-system))
+ coding-system)
+ 'utf-8))
+ (substr-list (split-string str "%"))
+ (head (car substr-list))
+ (tail (cdr substr-list)))
+ (decode-coding-string
+ (concat
+ head
+ (mapconcat
+ (lambda (substr)
+ (if (string-match "\\`\\([0-9a-fA-F]\\)\\([0-9a-fA-F]\\)\\(.*\\)\\'"
+ substr)
+ (let* ((c1 (string-to-char (match-string 1 substr)))
+ (c0 (string-to-char (match-string 2 substr)))
+ (tail (match-string 3 substr))
+ (ch (+ (* 16 (twittering-oauth-unhex c1))
+ (twittering-oauth-unhex c0))))
+ (concat (char-to-string ch) tail))
+ substr))
+ tail
+ ""))
+ coding-system)))
+
+(defun twittering-oauth-make-signature-base-string (method base-url parameters)
+ ;; "OAuth Core 1.0a"
+ ;; http://oauth.net/core/1.0a/#anchor13
+ (let* ((sorted-parameters (copy-sequence parameters))
+ (sorted-parameters
+ (sort sorted-parameters
+ (lambda (entry1 entry2)
+ (string< (car entry1) (car entry2))))))
+ (concat
+ method
+ "&"
+ (twittering-oauth-url-encode base-url)
+ "&"
+ (mapconcat
+ (lambda (entry)
+ (let ((key (car entry))
+ (value (cdr entry)))
+ (concat (twittering-oauth-url-encode key)
+ "%3D"
+ (twittering-oauth-url-encode value))))
+ sorted-parameters
+ "%26"))))
+
+(defun twittering-oauth-make-random-string (len)
+ (let* ((table
+ (concat
+ "0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"))
+ (n (length table))
+ (l 0)
+ (result (make-string len ?0)))
+ (while (< l len)
+ (aset result l (aref table (random n)))
+ (setq l (1+ l)))
+ result))
+
+(defun twittering-sha1 (&rest args)
+ "Return the SHA1 (Secure Hash Algorithm) of an object.
+
+This is equivalent to the function `sha1' except that
+`coding-system-for-read' and `coding-system-for-write' are bound to the
+symbol `binary'.
+
+The function `sha1' uses an external program for large object. However,
+the coding system for transferring data from/to the program is not fixed,
+at least in the implementation distributed with GNU Emacs 21.4.1, 22.2.1
+and 23.2.1.
+Therefore, the result from the function `sha1' may depend on the current
+coding system.
+
+This function avoid the dependency by binding `coding-system-for-read' and
+`coding-system-for-write' to the symbol `binary'."
+ (require 'sha1)
+ (let ((coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (apply 'sha1 args)))
+
+;;;
+;;; The below function is derived from `hmac-sha1' retrieved
+;;; from http://www.emacswiki.org/emacs/HmacShaOne.
+;;;
+(defun twittering-hmac-sha1 (key message)
+ "Return an HMAC-SHA1 authentication code for KEY and MESSAGE.
+
+KEY and MESSAGE must be unibyte strings. The result is a unibyte
+string. Use the function `encode-hex-string' or the function
+`base64-encode-string' to produce human-readable output.
+
+See URL:<http://en.wikipedia.org/wiki/HMAC> for more information
+on the HMAC-SHA1 algorithm.
+
+The Emacs multibyte representation actually uses a series of
+8-bit values under the hood, so we could have allowed multibyte
+strings as arguments. However, internal 8-bit values don't
+correspond to any external representation \(at least for major
+version 22). This makes multibyte strings useless for generating
+hashes.
+
+Instead, callers must explicitly pick and use an encoding for
+their multibyte data. Most callers will want to use UTF-8
+encoding, which we can generate as follows:
+
+ (let ((unibyte-key (encode-coding-string key 'utf-8 t))
+ (unibyte-value (encode-coding-string value 'utf-8 t)))
+ (twittering-hmac-sha1 unibyte-key unibyte-value))
+
+For keys and values that are already unibyte, the
+`encode-coding-string' calls just return the same string."
+;;; Return an HMAC-SHA1 authentication code for KEY and MESSAGE.
+;;;
+;;; KEY and MESSAGE must be unibyte strings. The result is a unibyte
+;;; string. Use the function `encode-hex-string' or the function
+;;; `base64-encode-string' to produce human-readable output.
+;;;
+;;; See URL:<http://en.wikipedia.org/wiki/HMAC> for more information
+;;; on the HMAC-SHA1 algorithm.
+;;;
+;;; The Emacs multibyte representation actually uses a series of
+;;; 8-bit values under the hood, so we could have allowed multibyte
+;;; strings as arguments. However, internal 8-bit values don't
+;;; correspond to any external representation \(at least for major
+;;; version 22). This makes multibyte strings useless for generating
+;;; hashes.
+;;;
+;;; Instead, callers must explicitly pick and use an encoding for
+;;; their multibyte data. Most callers will want to use UTF-8
+;;; encoding, which we can generate as follows:
+;;;
+;;; (let ((unibyte-key (encode-coding-string key 'utf-8 t))
+;;; (unibyte-value (encode-coding-string value 'utf-8 t)))
+;;; (hmac-sha1 unibyte-key unibyte-value))
+;;;
+;;; For keys and values that are already unibyte, the
+;;; `encode-coding-string' calls just return the same string.
+;;;
+;;; Author: Derek Upham - sand (at) blarg.net
+;;;
+;;; Copyright: This code is in the public domain.
+ (require 'sha1)
+ (when (multibyte-string-p key)
+ (error "key must be unibyte"))
+ (when (multibyte-string-p message)
+ (error "message must be unibyte"))
+
+ ;; The key block is always exactly the block size of the hash
+ ;; algorithm. If the key is too small, we pad it with zeroes (or
+ ;; instead, we initialize the key block with zeroes and copy the
+ ;; key onto the nulls). If the key is too large, we run it
+ ;; through the hash algorithm and use the hashed value (strange
+ ;; but true).
+
+ (let ((+hmac-sha1-block-size-bytes+ 64)) ; SHA-1 uses 512-bit blocks
+ (when (< +hmac-sha1-block-size-bytes+ (length key))
+ (setq key (twittering-sha1 key nil nil t)))
+
+ (let ((key-block (make-vector +hmac-sha1-block-size-bytes+ 0)))
+ (dotimes (i (length key))
+ (aset key-block i (aref key i)))
+
+ (let ((opad (make-vector +hmac-sha1-block-size-bytes+ #x5c))
+ (ipad (make-vector +hmac-sha1-block-size-bytes+ #x36)))
+
+ (dotimes (i +hmac-sha1-block-size-bytes+)
+ (aset ipad i (logxor (aref ipad i) (aref key-block i)))
+ (aset opad i (logxor (aref opad i) (aref key-block i))))
+
+ (when (fboundp 'unibyte-string)
+ ;; `concat' of Emacs23 (and later?) generates a multi-byte
+ ;; string from a vector of characters with eight bit.
+ ;; Since `opad' and `ipad' must be unibyte, we have to
+ ;; convert them by using `unibyte-string'.
+ ;; We cannot use `string-as-unibyte' here because it encodes
+ ;; bytes with the manner of UTF-8.
+ (setq opad (apply 'unibyte-string (mapcar 'identity opad)))
+ (setq ipad (apply 'unibyte-string (mapcar 'identity ipad))))
+
+ (twittering-sha1 (concat opad
+ (twittering-sha1 (concat ipad message)
+ nil nil t))
+ nil nil t)))))
+
+(defun twittering-oauth-auth-str (method base-url query-parameters oauth-parameters key)
+ "Generate the value for HTTP Authorization header on OAuth.
+QUERY-PARAMETERS is an alist for query parameters, where name and value
+must be encoded into the same as they will be sent."
+ (let* ((parameters (append query-parameters oauth-parameters))
+ (base-string
+ (twittering-oauth-make-signature-base-string method base-url parameters))
+ (key (if (multibyte-string-p key)
+ (string-make-unibyte key)
+ key))
+ (base-string (if (multibyte-string-p base-string)
+ (string-make-unibyte base-string)
+ base-string))
+ (signature
+ (base64-encode-string (twittering-hmac-sha1 key base-string))))
+ (concat
+ "OAuth "
+ (mapconcat
+ (lambda (entry)
+ (concat (car entry) "=\"" (cdr entry) "\""))
+ oauth-parameters
+ ",")
+ ",oauth_signature=\"" (twittering-oauth-url-encode signature) "\"")))
+
+(defun twittering-oauth-auth-str-request-token (url query-parameters consumer-key consumer-secret &optional oauth-parameters)
+ (let ((key (concat consumer-secret "&"))
+ (oauth-params
+ (or oauth-parameters
+ `(("oauth_nonce" . ,(twittering-oauth-make-random-string 43))
+ ("oauth_callback" . "oob")
+ ("oauth_signature_method" . "HMAC-SHA1")
+ ("oauth_timestamp" . ,(format-time-string "%s"))
+ ("oauth_consumer_key" . ,consumer-key)
+ ("oauth_version" . "1.0")))))
+ (twittering-oauth-auth-str "POST" url query-parameters oauth-params key)))
+
+(defun twittering-oauth-auth-str-exchange-token (url query-parameters consumer-key consumer-secret request-token request-token-secret verifier &optional oauth-parameters)
+ (let ((key (concat consumer-secret "&" request-token-secret))
+ (oauth-params
+ (or oauth-parameters
+ `(("oauth_consumer_key" . ,consumer-key)
+ ("oauth_nonce" . ,(twittering-oauth-make-random-string 43))
+ ("oauth_signature_method" . "HMAC-SHA1")
+ ("oauth_timestamp" . ,(format-time-string "%s"))
+ ("oauth_version" . "1.0")
+ ("oauth_token" . ,request-token)
+ ("oauth_verifier" . ,verifier)))))
+ (twittering-oauth-auth-str "POST" url query-parameters oauth-params key)))
+
+(defun twittering-oauth-auth-str-access (method url query-parameters consumer-key consumer-secret access-token access-token-secret &optional oauth-parameters)
+ "Generate a string for Authorization in HTTP header on OAuth.
+METHOD means HTTP method such as \"GET\", \"POST\", etc. URL means a simple
+URL without port number and query parameters.
+QUERY-PARAMETERS means an alist of query parameters such as
+'((\"status\" . \"test%20tweet\")
+ (\"in_reply_to_status_id\" . \"12345678\")),
+where name and value must be encoded into the same as they will be sent.
+CONSUMER-KEY and CONSUMER-SECRET specifies the consumer.
+ACCESS-TOKEN and ACCESS-TOKEN-SECRET must be authorized before calling this
+function."
+ (let ((key (concat consumer-secret "&" access-token-secret))
+ (oauth-params
+ (or oauth-parameters
+ `(("oauth_consumer_key" . ,consumer-key)
+ ("oauth_nonce" . ,(twittering-oauth-make-random-string 43))
+ ("oauth_signature_method" . "HMAC-SHA1")
+ ("oauth_timestamp" . ,(format-time-string "%s"))
+ ("oauth_version" . "1.0")
+ ("oauth_token" . ,access-token)))))
+ (twittering-oauth-auth-str method url query-parameters oauth-params key)))
+
+;; "Using xAuth | dev.twitter.com"
+;; http://dev.twitter.com/pages/xauth
+(defun twittering-xauth-auth-str-access-token (url query-parameters consumer-key consumer-secret username password &optional oauth-parameters)
+ (let ((key (concat consumer-secret "&"))
+ (oauth-params
+ (or oauth-parameters
+ `(("oauth_nonce" . ,(twittering-oauth-make-random-string 43))
+ ("oauth_signature_method" . "HMAC-SHA1")
+ ("oauth_timestamp" . ,(format-time-string "%s"))
+ ("oauth_consumer_key" . ,consumer-key)
+ ("oauth_version" . "1.0"))))
+ (query-params
+ (append query-parameters
+ `(("x_auth_mode" . "client_auth")
+ ("x_auth_password"
+ . ,(twittering-oauth-url-encode password))
+ ("x_auth_username"
+ . ,(twittering-oauth-url-encode username))))))
+ (twittering-oauth-auth-str "POST" url query-params oauth-params key)))
+
+;; "OAuth Core 1.0a"
+;; http://oauth.net/core/1.0a/#response_parameters
+(defun twittering-oauth-make-response-alist (str)
+ (mapcar
+ (lambda (entry)
+ (let* ((pair (split-string entry "="))
+ (name-entry (car pair))
+ (value-entry (cadr pair))
+ (name (and name-entry (twittering-oauth-url-decode name-entry)))
+ (value (and value-entry
+ (twittering-oauth-url-decode value-entry))))
+ `(,name . ,value)))
+ (split-string str "&")))
+
+(defun twittering-oauth-get-response-alist (buffer)
+ (with-current-buffer buffer
+ (goto-char (point-min))
+ (when (search-forward-regexp
+ "\\`\\(\\(HTTP/1\.[01]\\) \\([0-9][0-9][0-9]\\) \\(.*?\\)\\)\r?\n"
+ nil t)
+ (let ((status-line (match-string 1))
+ (http-version (match-string 2))
+ (status-code (match-string 3))
+ (reason-phrase (match-string 4)))
+ (cond
+ ((not (string-match "2[0-9][0-9]" status-code))
+ (message "Response: %s" status-line)
+ nil)
+ ((search-forward-regexp "\r?\n\r?\n" nil t)
+ (let ((beg (match-end 0))
+ (end (point-max)))
+ (twittering-oauth-make-response-alist (buffer-substring beg end))))
+ (t
+ (message "Response: %s" status-line)
+ nil))))))
+
+(defun twittering-oauth-get-token-alist-url (url auth-str post-body)
+ (let* ((url-request-method "POST")
+ (url-request-extra-headers
+ `(("Authorization" . ,auth-str)
+ ("Accept-Charset" . "us-ascii")
+ ("Content-Type" . "application/x-www-form-urlencoded")
+ ("Content-Length" . ,(format "%d" (length post-body)))))
+ (url-request-data post-body)
+ (coding-system-for-read 'utf-8-unix))
+ (lexical-let ((result 'queried))
+ (let ((buffer
+ (url-retrieve
+ url
+ (lambda (&rest args)
+ (let* ((status (if (< 21 emacs-major-version)
+ (car args)
+ nil))
+ (callback-args (if (< 21 emacs-major-version)
+ (cdr args)
+ args))
+ (response-buffer (current-buffer)))
+ (setq result
+ (twittering-oauth-get-response-alist response-buffer))
+ )))))
+ (while (eq result 'queried)
+ (sleep-for 0.1))
+ (unless twittering-debug-mode
+ (kill-buffer buffer))
+ result))))
+
+(defun twittering-oauth-get-token-alist (url auth-str &optional post-body)
+ (let ((request
+ (twittering-make-http-request-from-uri
+ "POST"
+ `(("Authorization" . ,auth-str)
+ ("Accept-Charset" . "us-ascii")
+ ("Content-Type" . "application/x-www-form-urlencoded"))
+ url post-body)))
+ (lexical-let ((result 'queried))
+ (let ((proc
+ (twittering-send-http-request
+ request nil
+ (lambda (proc status connection-info header-info)
+ (let ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info))))
+ (case-string
+ status-code
+ (("200")
+ (when twittering-debug-mode
+ (let ((buffer (current-buffer)))
+ (with-current-buffer (twittering-debug-buffer)
+ (insert-buffer-substring buffer))))
+ (setq result
+ (twittering-oauth-make-response-alist
+ (buffer-string)))
+ nil)
+ (t
+ (setq result nil)
+ (format "Response: %s" status-line)))))
+ (lambda (proc status connection-info)
+ (when (and (not (twittering-process-alive-p proc))
+ (eq result 'queried))
+ (setq result nil))))))
+ (twittering-wait-while nil 0.1
+ (and (eq result 'queried)
+ (twittering-process-alive-p proc)))
+ (when (and (eq result 'queried)
+ (not (twittering-process-alive-p proc)))
+ ;; If the process has been dead, wait a moment because
+ ;; Emacs may be in the middle of evaluating the sentinel.
+ (twittering-wait-while 10 0.1
+ (eq result 'queried)
+ nil
+ (setq result nil)))
+ result))))
+
+(defun twittering-oauth-get-request-token (url consumer-key consumer-secret)
+ (let ((auth-str
+ (twittering-oauth-auth-str-request-token
+ url nil consumer-key consumer-secret)))
+ (twittering-oauth-get-token-alist url auth-str)))
+
+(defun twittering-oauth-exchange-request-token (url consumer-key consumer-secret request-token request-token-secret verifier)
+ (let ((auth-str
+ (twittering-oauth-auth-str-exchange-token
+ url nil
+ consumer-key consumer-secret
+ request-token request-token-secret verifier)))
+ (twittering-oauth-get-token-alist url auth-str)))
+
+(defun twittering-oauth-get-access-token (request-token-url authorize-url-func access-token-url consumer-key consumer-secret consumer-name)
+ "Return an alist of authorized access token.
+The function retrieves a request token from the site specified by
+REQUEST-TOKEN-URL. Then, The function asks a WWW browser to authorize the
+token by calling `browse-url'. The URL for authorization is calculated by
+calling AUTHORIZE-URL-FUNC with the request token as an argument.
+AUTHORIZE-URL-FUNC is called as `(funcal AUTHORIZE-URL-FUNC request-token)',
+where the request-token is a string.
+After calling `browse-url', the function waits for user to input the PIN code
+that is displayed in the browser. The request token is authorized by the
+PIN code, and then it is exchanged for the access token on the site
+specified by ACCESS-TOKEN-URL.
+CONSUMER-KEY and CONSUMER-SECRET specify the consumer.
+CONSUMER-NAME is displayed at the guide of authorization.
+
+The access token is returned as a list of a cons pair of name and value
+like following:
+ ((\"oauth_token\"
+ . \"819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw\")
+ (\"oauth_token_secret\"
+ . \"J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA\")
+ (\"user_id\" . \"819797\")
+ (\"screen_name\" . \"episod\"))
+."
+ (let* ((request-token-alist
+ (twittering-oauth-get-request-token
+ request-token-url consumer-key consumer-secret))
+ (request-token (cdr (assoc "oauth_token" request-token-alist)))
+ (request-token-secret
+ (cdr (assoc "oauth_token_secret" request-token-alist)))
+ (authorize-url (funcall authorize-url-func request-token))
+ (str
+ (concat
+ (propertize "Authorization via OAuth\n" 'face 'bold)
+ "\n"
+ "1.Allow access by " consumer-name " on the below site.\n"
+ "\n "
+ (propertize authorize-url 'url authorize-url 'face 'bold)
+ "\n"
+ "\n"
+ (when twittering-oauth-invoke-browser
+ (concat
+ " Emacs invokes your browser by the function `browse-url'.\n"
+ " If the site is not opened automatically, you have to open\n"
+ " the site manually.\n"
+ "\n"))
+ "2.After allowing access, the site will display the PIN code."
+ "\n"
+ " Input the PIN code "
+ (propertize "at the below minibuffer." 'face 'bold))))
+ (cond
+ (request-token-alist
+ (with-temp-buffer
+ (switch-to-buffer (current-buffer))
+ (let* ((str-height (length (split-string str "\n")))
+ (height (max 0 (- (/ (- (window-text-height) 1) 2)
+ (/ str-height 2)))))
+ (insert (make-string height ?\n) str)
+ (if twittering-oauth-invoke-browser
+ (browse-url authorize-url)
+ (when (y-or-n-p "Open authorization URL with browser? (using `browse-url')")
+ (browse-url authorize-url)))
+ (let* ((pin
+ (block pin-input-block
+ (while t
+ (let ((pin-input (read-string "Input PIN code: ")))
+ (when (string-match "^\\s-*\\([0-9]+\\)\\s-*$" pin-input)
+ (return-from pin-input-block
+ (match-string 1 pin-input)))))))
+ (verifier pin))
+ (twittering-oauth-exchange-request-token
+ access-token-url
+ consumer-key consumer-secret
+ request-token request-token-secret verifier)))))
+ (t
+ (error "Failed to retrieve a request token")
+ nil))))
+
+(defun twittering-xauth-get-access-token (access-token-url consumer-key consumer-secret username password)
+ (let ((auth-str
+ (twittering-xauth-auth-str-access-token
+ access-token-url nil consumer-key consumer-secret
+ username password))
+ (post-body
+ (mapconcat (lambda (pair)
+ (format "%s=%s" (car pair)
+ (twittering-oauth-url-encode (cdr pair))))
+ `(("x_auth_mode" . "client_auth")
+ ("x_auth_password" . ,password)
+ ("x_auth_username" . ,username))
+ "&")))
+ (twittering-oauth-get-token-alist access-token-url auth-str post-body)))
+
+;;;;
+;;;; Private storage
+;;;;
+
+(defun twittering-private-info-loaded-p ()
+ twittering-private-info-file-loaded)
+
+(defun twittering-load-private-info ()
+ (let* ((file twittering-private-info-file)
+ (decrypted-str (twittering-read-from-encrypted-file file))
+ (loaded-alist
+ (when decrypted-str
+ (condition-case nil
+ (read decrypted-str)
+ (error
+ nil)))))
+ (when loaded-alist
+ (remove
+ nil
+ (mapcar
+ (lambda (pair)
+ (when (consp pair)
+ (let ((sym (car pair))
+ (value (cdr pair)))
+ (cond
+ ((memq sym twittering-variables-stored-with-encryption)
+ (set sym value)
+ sym)
+ (t
+ nil)))))
+ loaded-alist)))))
+
+(defun twittering-load-private-info-with-guide ()
+ (let ((str (concat
+ "Loading authorized access token for OAuth from\n"
+ (format "%s.\n" twittering-private-info-file)
+ "\n"
+ (propertize "Please input the master password.\n" 'face 'bold)
+ "\n"
+ "To cancel it, you may need to press C-g multiple times.\n"
+ )))
+ (with-temp-buffer
+ (switch-to-buffer (current-buffer))
+ (let* ((str-height (length (split-string str "\n")))
+ (height (max 0 (- (/ (- (window-text-height) 1) 2)
+ (/ str-height 2)))))
+ (insert (make-string height ?\n) str)
+ (set-buffer-modified-p nil)
+ (twittering-load-private-info)))))
+
+(defun twittering-save-private-info ()
+ (let* ((obj (mapcar (lambda (sym)
+ `(,sym . ,(symbol-value sym)))
+ twittering-variables-stored-with-encryption))
+ (str (with-output-to-string (pp obj)))
+ (file twittering-private-info-file))
+ (when (twittering-write-and-encrypt file str)
+ (set-file-modes file #o600)
+ (setq twittering-private-info-file-loaded t))))
+
+(defun twittering-save-private-info-with-guide ()
+ (let ((str (concat
+ "Saving authorized access token for OAuth to "
+ (format "%s.\n" twittering-private-info-file)
+ "\n"
+ (propertize "Please input a master password twice."
+ 'face 'bold))))
+ (with-temp-buffer
+ (switch-to-buffer (current-buffer))
+ (let* ((str-height (length (split-string str "\n")))
+ (height (max 0 (- (/ (- (window-text-height) 1) 2)
+ (/ str-height 2)))))
+ (insert (make-string height ?\n) str)
+ (set-buffer-modified-p nil)
+ (twittering-save-private-info)))))
+
+(defun twittering-capable-of-encryption-p ()
+ (and (or (require 'epa nil t) (require 'alpaca nil t))
+ (executable-find "gpg")))
+
+(eval-when-compile
+ (require 'epa nil t)
+ (require 'alpaca nil t))
+(defun twittering-read-from-encrypted-file (file)
+ "Decrypt contents from FILE and return them.
+Read encrypted contents from FILE and return the decrypted contents.
+This function requires `epa' or `alpaca' library."
+ (cond
+ ((not (file-readable-p file))
+ (error "Failed to read %s" file)
+ nil)
+ ((require 'epa nil t)
+ (let ((context (epg-make-context epa-protocol))
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (epg-context-set-passphrase-callback
+ context #'epa-passphrase-callback-function)
+ (epg-context-set-progress-callback
+ context
+ (cons #'epa-progress-callback-function
+ (format "Decrypting %s..." (file-name-nondirectory file))))
+ (message "Decrypting %s..." (file-name-nondirectory file))
+ (condition-case err
+ (let ((full-path (expand-file-name file)))
+ ;; `epg-decrypt-file' included in EasyPG 1.0.0, which is
+ ;; distributed with Emacs 23.2, requires the expanded full path
+ ;; as the argument CIPHER. This is because CIPHER is directly
+ ;; used as an argument of the command `gpg'.
+ (epg-decrypt-file context full-path nil))
+ (error
+ (message "%s" (cdr err))
+ nil))))
+ ((require 'alpaca nil t)
+ (with-temp-buffer
+ (let ((buffer-file-name (expand-file-name file))
+ (alpaca-regex-suffix ".*")
+ (coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ (temp-buffer (current-buffer))
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (insert-file-contents-literally file)
+ (set-buffer-modified-p nil)
+ (condition-case nil
+ (progn
+ (alpaca-after-find-file)
+ (if (eq temp-buffer (current-buffer))
+ (buffer-string)
+ ;; `alpaca-after-find-file' kills the current buffer
+ ;; if the decryption is failed.
+ nil))
+ (error
+ (when (eq temp-buffer (current-buffer))
+ (delete-region (point-min) (point-max)))
+ nil)))))
+ (t
+ nil)))
+
+(defun twittering-write-and-encrypt (file str)
+ (cond
+ ((require 'epg nil t)
+ (let ((context (epg-make-context epa-protocol))
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (epg-context-set-passphrase-callback
+ context #'epa-passphrase-callback-function)
+ (epg-context-set-progress-callback
+ context (cons #'epa-progress-callback-function "Encrypting..."))
+ (message "Encrypting...")
+ (condition-case err
+ (unwind-protect
+ ;; In order to prevent `epa-file' to encrypt the file double,
+ ;; `epa-file-name-regexp' is temorarily changed into the null
+ ;; regexp that never matches any string.
+ (let ((epa-file-name-regexp "\\`\\'")
+ (coding-system-for-read 'binary)
+ (coding-system-for-write 'binary))
+ (when (fboundp 'epa-file-name-regexp-update)
+ (epa-file-name-regexp-update))
+ (with-temp-file file
+ (set-buffer-multibyte nil)
+ (delete-region (point-min) (point-max))
+ (insert (epg-encrypt-string context str nil))
+ (message "Encrypting...wrote %s" file)
+ t))
+ (when (fboundp 'epa-file-name-regexp-update)
+ (epa-file-name-regexp-update)))
+ (error
+ (message "%s" (cdr err))
+ nil))))
+ ((require 'alpaca nil t)
+ ;; Create the file.
+ ;; This is required because `alpaca-save-buffer' checks its timestamp.
+ (with-temp-file file)
+ (with-temp-buffer
+ (let ((buffer-file-name file)
+ (coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (insert str)
+ (condition-case nil
+ (if (alpaca-save-buffer)
+ t
+ (delete-file file)
+ nil)
+ (error
+ (when (file-exists-p file)
+ (delete-file file))
+ nil)))))
+ (t
+ nil)))
+
+(defun twittering-ensure-private-info ()
+ "Ensure that private information is loaded if necessary.
+Return non-nil if `twittering-use-master-password' is nil or private
+information has been already loaded. Also, return non-nil
+if `twittering-use-master-password' is non-nil and this function succeeded
+in loading private information.
+Return nil if private information cannot be loaded."
+ (if (or (not twittering-use-master-password)
+ (twittering-private-info-loaded-p))
+ ;; The private information is unnecessary or already loaded.
+ t
+ (cond
+ ((not (twittering-capable-of-encryption-p))
+ (message "You need GnuPG and (EasyPG or alpaca.el) for master password!")
+ nil)
+ ((and (memq twittering-auth-method '(oauth xauth))
+ (file-exists-p twittering-private-info-file))
+ (cond
+ ((twittering-load-private-info-with-guide)
+ (setq twittering-private-info-file-loaded t)
+ (message "The authorized token is loaded.")
+ t)
+ (t
+ (message "Failed to load an authorized token from \"%s\"."
+ twittering-private-info-file)
+ nil)))
+ (t
+ ;; The file for private infomation does not exist now.
+ t))))
+
+;;;;
+;;;; Asynchronous retrieval
+;;;;
+
+(defvar twittering-url-data-hash (make-hash-table :test 'equal))
+(defvar twittering-url-request-list nil)
+(defvar twittering-url-request-sentinel-hash (make-hash-table :test 'equal))
+(defvar twittering-internal-url-queue nil)
+(defvar twittering-url-request-resolving-p nil)
+(defvar twittering-url-request-retry-limit 3)
+(defvar twittering-url-request-sentinel-delay 1.0
+ "*Delay from completing retrieval to invoking associated sentinels.
+Sentinels registered by `twittering-url-retrieve-async' will be invoked
+after retrieval is completed and Emacs remains idle a certain time, which
+this variable specifies. The unit is second.")
+
+(defun twittering-remove-redundant-queries (queue)
+ (remove nil
+ (mapcar
+ (lambda (url)
+ (let ((current (gethash url twittering-url-data-hash)))
+ (when (or (null current)
+ (and (integerp current)
+ (< current twittering-url-request-retry-limit)))
+ url)))
+ (twittering-remove-duplicates queue))))
+
+(defun twittering-resolve-url-request ()
+ "Resolve requests of asynchronous URL retrieval."
+ (when (null twittering-url-request-resolving-p)
+ (setq twittering-url-request-resolving-p t)
+ ;; It is assumed that the following part is not processed
+ ;; in parallel.
+ (setq twittering-internal-url-queue
+ (append twittering-internal-url-queue twittering-url-request-list))
+ (setq twittering-url-request-list nil)
+ (setq twittering-internal-url-queue
+ (twittering-remove-redundant-queries twittering-internal-url-queue))
+ (if (null twittering-internal-url-queue)
+ (setq twittering-url-request-resolving-p nil)
+ (let* ((url (car twittering-internal-url-queue))
+ (request (twittering-make-http-request-from-uri "GET" nil url))
+ (additional-info `((uri . ,url))))
+ (twittering-send-http-request
+ request additional-info
+ 'twittering-url-retrieve-async-sentinel
+ 'twittering-url-retrieve-async-clean-up-sentinel)))))
+
+(defun twittering-url-retrieve-async-sentinel (proc status connection-info header-info)
+ (let ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info)))
+ (uri (cdr (assq 'uri (assq 'request connection-info)))))
+ (when (string= status-code "200")
+ (let ((body (string-as-unibyte (buffer-string))))
+ (puthash uri body twittering-url-data-hash)
+ (setq twittering-internal-url-queue
+ (remove uri twittering-internal-url-queue))
+ (let ((sentinels (gethash uri twittering-url-request-sentinel-hash)))
+ (when sentinels
+ (remhash uri twittering-url-request-sentinel-hash))
+ (twittering-run-on-idle twittering-url-request-sentinel-delay
+ (lambda (sentinels uri body)
+ (mapc (lambda (func)
+ (funcall func uri body))
+ sentinels)
+ ;; Resolve the rest of requests.
+ (setq twittering-url-request-resolving-p
+ nil)
+ (twittering-resolve-url-request))
+ sentinels uri body)
+ ;; Without the following nil, it seems that the value of
+ ;; `sentinels' is displayed.
+ nil)))))
+
+(defun twittering-url-retrieve-async-clean-up-sentinel (proc status connection-info)
+ (when (memq status '(exit signal closed failed))
+ (let* ((uri (cdr (assq 'uri connection-info)))
+ (current (gethash uri twittering-url-data-hash)))
+ (when (or (null current) (integerp current))
+ ;; Increment the counter on failure and then retry retrieval.
+ (puthash uri (1+ (or current 0)) twittering-url-data-hash)
+ (setq twittering-url-request-resolving-p nil)
+ (twittering-resolve-url-request)))))
+
+(defun twittering-url-retrieve-async (url &optional sentinel)
+ "Retrieve URL asynchronously and call SENTINEL with the retrieved data.
+The request is placed at the last of queries queue. When the data has been
+retrieved and Emacs remains idle a certain time specified by
+`twittering-url-request-sentinel-delay', SENTINEL will be called as
+ (funcall SENTINEL URL url-data).
+The retrieved data can be referred as (gethash URL twittering-url-data-hash)."
+ (let ((data (gethash url twittering-url-data-hash)))
+ (cond
+ ((or (null data) (integerp data))
+ (add-to-list 'twittering-url-request-list url t)
+ (when sentinel
+ (let ((current (gethash url twittering-url-request-sentinel-hash)))
+ (unless (member sentinel current)
+ (puthash url (cons sentinel current)
+ twittering-url-request-sentinel-hash))))
+ (twittering-resolve-url-request)
+ nil)
+ (t
+ ;; URL has been already retrieved.
+ (twittering-run-on-idle twittering-url-request-sentinel-delay
+ sentinel url data)
+ data))))
+
+;;;;
+;;;; XML parser
+;;;;
+
+(defun twittering-ucs-to-char-internal (code-point)
+ ;; Check (featurep 'unicode) is a workaround with navi2ch to avoid
+ ;; error "error in process sentinel: Cannot open load file:
+ ;; unicode".
+ ;;
+ ;; Details: navi2ch prior to 1.8.3 (which is currently last release
+ ;; version as of 2010-01-18) always define `ucs-to-char' as autoload
+ ;; file "unicode(.el)" (which came from Mule-UCS), hence it breaks
+ ;; `ucs-to-char' under non Mule-UCS environment. The problem is
+ ;; fixed in navi2ch dated 2010-01-16 or later, but not released yet.
+ (if (and (featurep 'unicode) (functionp 'ucs-to-char))
+ (ucs-to-char code-point)
+ ;; Emacs21 have a partial support for UTF-8 text, so it can decode
+ ;; only parts of a text with Japanese.
+ (decode-char 'ucs code-point)))
+
+(defvar twittering-unicode-replacement-char
+ ;; "Unicode Character 'REPLACEMENT CHARACTER' (U+FFFD)"
+ (or (twittering-ucs-to-char-internal #xFFFD)
+ ??)
+ "*Replacement character returned by `twittering-ucs-to-char' when it fails
+to decode a code.")
+
+(defun twittering-ucs-to-char (code-point)
+ "Return a character specified by CODE-POINT in Unicode.
+If it fails to decode the code, return `twittering-unicode-replacement-char'."
+ (or (twittering-ucs-to-char-internal code-point)
+ twittering-unicode-replacement-char))
+
+(defadvice decode-char (after twittering-add-fail-over-to-decode-char)
+ (when (null ad-return-value)
+ (setq ad-return-value twittering-unicode-replacement-char)))
+
+(defun twittering-xml-parse-region (&rest args)
+ "Wrapped `xml-parse-region' in order to avoid decoding errors.
+After activating the advice `twittering-add-fail-over-to-decode-char',
+`xml-parse-region' is called. This prevents `xml-parse-region' from
+exiting abnormally by decoding unknown numeric character reference."
+ (let ((activated (ad-is-active 'decode-char)))
+ (ad-enable-advice
+ 'decode-char 'after 'twittering-add-fail-over-to-decode-char)
+ (ad-activate 'decode-char)
+ (unwind-protect
+ (condition-case err
+ (apply 'xml-parse-region args)
+ (error
+ (message "Failed to parse the retrieved XML.")
+ nil))
+ (ad-disable-advice 'decode-char 'after
+ 'twittering-add-fail-over-to-decode-char)
+ (if activated
+ (ad-activate 'decode-char)
+ (ad-deactivate 'decode-char)))))
+
+;;;;
+;;;; JSON parser with a fallback character
+;;;;
+
+(defconst twittering-surrogate-pair-regexp
+ (if (<= 23 emacs-major-version)
+ ;; Literal strings such as "\uXXXX" is not allowed in Emacs 21
+ ;; and earlier. A character of invalid code point such as U+D800
+ ;; is not allowed in Emacs 22.
+ ;; To avoid errors caused by literal strings invalid in Emacs 22
+ ;; and earlier, the regexp is generated indirectly.
+ (format "[%c-%c][%c-%c]"
+ (decode-char 'ucs #xd800)
+ (decode-char 'ucs #xdbff)
+ (decode-char 'ucs #xdc00)
+ (decode-char 'ucs #xdfff))
+ ;; A regexp that never matches any strings.
+ "\\'\\`")
+ "Regexp to match a surrogate pair for CESU-8.
+In Emacs 22 and earlier, this variable is initialized by a regexp
+that never matches any string because code points for a surrogate pair,
+from U+D800 to U+DFFF, are invalid.")
+
+(defun twittering-decode-surrogate-pairs-as-cesu-8 (str)
+ "Decode surrogate pairs in STR similarly to CESU-8.
+If STR includes surrogate pairs represented by code points from U+D800 to
+U+DFFF, decode them with CESU-8 and return the result.
+
+A character not in the Basic Multilingual Plane is represented by a surrogate
+pair in JSON (RFC4627). This is similar to CESU-8. But the function
+`json-read' in `json.el' does not correctly decode surrogate pairs. Therefore,
+`json-read' may return a string including invalid code points from U+D800 to
+U+DFFF. This function decodes such invalid code points."
+ (let ((str str)
+ (prev 0)
+ (current 0)
+ (result ""))
+ (while (setq current
+ (string-match twittering-surrogate-pair-regexp str prev))
+ (let* ((next (match-end 0))
+ (decoded-str
+ (decode-coding-string
+ (mapconcat
+ (lambda (c)
+ (let* ((code-point (encode-char c 'ucs))
+ (b1 (/ code-point #x100))
+ (b2 (% code-point #x100)))
+ (unibyte-string b1 b2)))
+ (match-string 0 str)
+ "")
+ 'utf-16)))
+ (setq result
+ (concat result
+ (substring str prev current)
+ decoded-str))
+ (setq prev next)))
+ (setq result (concat result (substring str prev)))
+ result))
+
+(defadvice json-read-string (after twittering-decode-surrogate-pairs-as-cesu-8)
+ (when (<= 23 emacs-major-version)
+ (setq ad-return-value
+ (twittering-decode-surrogate-pairs-as-cesu-8 ad-return-value))))
+
+(defun twittering-json-read (&rest args)
+ "Wrapped `json-read' in order to avoid decoding errors.
+`json-read' is called after activating the advice
+`twittering-add-fail-over-to-decode-char'.
+This prevents `json-read' from exiting abnormally by decoding an unknown
+numeric character reference."
+ (let ((activated (ad-is-active 'decode-char))
+ (json-activated (ad-is-active 'json-read-string)))
+ (ad-enable-advice
+ 'decode-char 'after 'twittering-add-fail-over-to-decode-char)
+ (ad-activate 'decode-char)
+ (ad-enable-advice 'json-read-string 'after
+ 'twittering-decode-surrogate-pairs-as-cesu-8)
+ (ad-activate 'json-read-string)
+ (unwind-protect
+ (condition-case err
+ (apply 'json-read args)
+ (error
+ (message "Failed to parse the retrieved JSON.")
+ nil))
+ (ad-disable-advice 'decode-char 'after
+ 'twittering-add-fail-over-to-decode-char)
+ (ad-disable-advice 'json-read-string 'after
+ 'twittering-decode-surrogate-pairs-as-cesu-8)
+ (if activated
+ (ad-activate 'decode-char)
+ (ad-deactivate 'decode-char))
+ (if json-activated
+ (ad-activate 'json-read-string)
+ (ad-deactivate 'json-read-string))
+ )))
+
+;;;;
+;;;; Window configuration
+;;;;
+
+(defun twittering-set-window-end (window pos)
+ (let* ((height (window-text-height window))
+ (n (- (- height 1))))
+ (while (progn (setq n (1+ n))
+ (set-window-start
+ window
+ (with-current-buffer (window-buffer window)
+ (save-excursion
+ (goto-char pos)
+ (line-beginning-position n))))
+ (not (pos-visible-in-window-p pos window))))))
+
+(defun twittering-current-window-config (window-list)
+ "Return window parameters of WINDOW-LIST."
+ (mapcar (lambda (win)
+ (let ((start (window-start win))
+ (point (window-point win)))
+ `(,win ,start ,point)))
+ window-list))
+
+(defun twittering-restore-window-config-after-modification (config beg end)
+ "Restore window parameters changed by modification on given region.
+CONFIG is window parameters made by `twittering-current-window-config'.
+BEG and END mean a region that had been modified."
+ (mapc (lambda (entry)
+ (let ((win (elt entry 0))
+ (start (elt entry 1))
+ (point (elt entry 2)))
+ (when (and (< beg start) (< start end))
+ (set-window-start win start))
+ (when (and (< beg point) (< point end))
+ (set-window-point win point))))
+ config))
+
+(defun twittering-pop-to-buffer (buf)
+ "Select the buffer BUF in some window.
+The behavior is determined by the function specified by
+`twittering-pop-to-buffer-function'."
+ (funcall twittering-pop-to-buffer-function buf))
+
+(defun twittering-pop-to-buffer-simple (buf)
+ "Select the buffer BUF by using `pop-to-buffer'."
+ (let ((win (selected-window)))
+ (pop-to-buffer buf)
+ ;; This is required because the new window generated by `pop-to-buffer'
+ ;; may hide the region following the current position.
+ (twittering-ensure-whole-of-status-is-visible win)))
+
+(defun twittering-pop-to-buffer-in-current-window (buf &optional win)
+ "Select the buffer BUF in the window WIN by splitting it.
+If WIN is nil, the selected window is splitted."
+ (let* ((win (or win (selected-window)))
+ (size
+ (let ((rest (- (window-height win) 15)))
+ (if (<= rest 3)
+ ;; To avoid an error due to a too small window.
+ nil
+ rest)))
+ (new-win (split-window win size)))
+ (select-window new-win)
+ (switch-to-buffer buf)))
+
+(defun twittering-pop-to-buffer-in-largest-window (buf)
+ "Select the buffer BUF in the largest window by splitting it."
+ (let ((win
+ (lexical-let ((max-area 0)
+ (largest-win nil))
+ (walk-windows
+ (lambda (win)
+ (let ((area (* (window-height win) (window-width win))))
+ (when (< max-area area)
+ (setq max-area area)
+ (setq largest-win win)))))
+ largest-win)))
+ (twittering-pop-to-buffer-in-current-window buf win)))
+
+(defun twittering-pop-to-buffer-in-bottom-largest-window (buf)
+ "Select the buffer BUF in the window largest on bottom by splitting it."
+ (let* ((bottom-win-list
+ (lexical-let ((win-list '())
+ (max-bottom 0))
+ (walk-windows
+ (lambda (win)
+ (let ((bottom (nth 3 (window-edges win))))
+ (cond
+ ((< max-bottom bottom)
+ (setq max-bottom bottom)
+ (setq win-list `(,win)))
+ ((= max-bottom bottom)
+ (setq win-list (cons win win-list)))
+ (t
+ nil)))))
+ win-list))
+ (win
+ (lexical-let ((max-area 0)
+ (largest-win nil))
+ (mapc (lambda (win)
+ (let ((area (* (window-height win) (window-width win))))
+ (when (< max-area area)
+ (setq largest-win win)
+ (setq max-area area))))
+ bottom-win-list)
+ largest-win)))
+ (twittering-pop-to-buffer-in-current-window buf win)))
+
+;;;;
+;;;; URI shortening
+;;;;
+
+(defun twittering-tinyurl-get (longurl &optional service)
+ "Shorten LONGURL with the service specified by `twittering-tinyurl-service'."
+ (let* ((service (or service twittering-tinyurl-service))
+ (api (cdr (assq service twittering-tinyurl-services-map)))
+ (request-generator (when (listp api) (elt api 0)))
+ (post-process (when (listp api) (elt api 1)))
+ (encoded-url (twittering-percent-encode longurl))
+ (request
+ (cond
+ ((stringp api)
+ (twittering-make-http-request-from-uri
+ "GET" nil (concat api encoded-url)))
+ ((stringp request-generator)
+ (twittering-make-http-request-from-uri
+ "GET" nil (concat request-generator encoded-url)))
+ ((functionp request-generator)
+ (funcall request-generator service longurl))
+ (t
+ (error "%s is invalid. try one of %s"
+ (symbol-name service)
+ (mapconcat (lambda (x) (symbol-name (car x)))
+ twittering-tinyurl-services-map ", "))
+ nil)))
+ (additional-info `((longurl . ,longurl))))
+ (cond
+ ((null request)
+ (error "Failed to generate a HTTP request for shortening %s with %s"
+ longurl (symbol-name service))
+ nil)
+ (t
+ (lexical-let ((result 'queried))
+ (let ((proc
+ (twittering-send-http-request
+ request additional-info
+ (lambda (proc status connection-info header-info)
+ (let ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info))))
+ (case-string
+ status-code
+ (("200")
+ (setq result (buffer-string))
+ nil)
+ (t
+ (setq result nil)
+ (format "Response: %s" status-line)))))
+ (lambda (proc status connection-info)
+ (when (and (not (twittering-process-alive-p proc))
+ (eq result 'queried))
+ (setq result nil))))))
+ (twittering-wait-while nil 0.1
+ (and (eq result 'queried)
+ (twittering-process-alive-p proc)))
+ (when (and (eq result 'queried)
+ (not (twittering-process-alive-p proc)))
+ ;; If the process has been dead, wait a moment because
+ ;; Emacs may be in the middle of evaluating the sentinel.
+ (twittering-wait-while 10 0.1
+ (eq result 'queried)
+ nil
+ ;; Reset `result' on timeout.
+ (setq result nil))))
+ (let ((processed-result (if (and result (functionp post-process))
+ (funcall post-process service result)
+ result)))
+ (if processed-result
+ processed-result
+ (error "Failed to shorten a URL %s with %s"
+ longurl (symbol-name service))
+ nil)))))))
+
+(defun twittering-tinyurl-replace-at-point ()
+ "Replace the url at point with a tiny version."
+ (interactive)
+ (let ((url-bounds (bounds-of-thing-at-point 'url)))
+ (when url-bounds
+ (let ((url (twittering-tinyurl-get (thing-at-point 'url))))
+ (when url
+ (save-restriction
+ (narrow-to-region (car url-bounds) (cdr url-bounds))
+ (delete-region (point-min) (point-max))
+ (insert url)))))))
+
+(defun twittering-make-http-request-for-bitly (service longurl)
+ "Make a HTTP request for URL shortening service bit.ly or j.mp.
+Before calling this, you have to configure `twittering-bitly-login' and
+`twittering-bitly-api-key'."
+ (let* ((query-string
+ (mapconcat
+ (lambda (entry)
+ (concat (car entry) "=" (cdr entry)))
+ `(("login" . ,twittering-bitly-login)
+ ("apiKey" . ,twittering-bitly-api-key)
+ ("format" . "txt")
+ ("longUrl" . ,(twittering-percent-encode longurl)))
+ "&"))
+ (prefix
+ (cdr (assq service '((bit.ly . "http://api.bit.ly/v3/shorten?")
+ (j.mp . "http://api.j.mp/v3/shorten?")))))
+ (uri (concat prefix query-string)))
+ (twittering-make-http-request-from-uri "GET" nil uri)))
+
+;;;;
+;;;; Timeline spec
+;;;;
+
+;;; Timeline spec as S-expression
+;;; - (user USER): timeline of the user whose name is USER. USER is a string.
+;;; - (list USER LIST):
+;;; the list LIST of the user USER. LIST and USER are strings.
+;;;
+;;; - (direct_messages): received direct messages.
+;;; - (direct_messages_sent): sent direct messages.
+;;; - (favorites): favorites timeline for the current user.
+;;; - (favorites USER): favorites timeline for the specified user.
+;;; - (friends): friends timeline.
+;;; - (home): home timeline.
+;;; - (mentions): mentions timeline.
+;;; mentions (status containing @username) for the authenticating user.
+;;; - (public): public timeline.
+;;; - (replies): replies.
+;;; - (retweeted_by_me): retweets posted by the authenticating user.
+;;; - (retweeted_by_user USER): retweets posted by the user.
+;;; - (retweeted_to_me): retweets posted by the authenticating user's friends.
+;;; - (retweeted_to_user USER): retweets posted to the user.
+;;; - (retweets_of_me):
+;;; tweets of the authenticated user that have been retweeted by others.
+;;; - (single ID): the single tweet specified by ID.
+;;;
+;;; - (search STRING): the result of searching with query STRING.
+;;;
+;;; - (exclude-if FUNC SPEC):
+;;; the same timeline as SPEC, except that it does not include tweets
+;;; that FUNC returns non-nil for.
+;;; - (exclude-re REGEXP-STRING SPEC):
+;;; the same timeline as SPEC, except that it does not include tweets
+;;; that matches the regular expression specified by REGEXP-STRING.
+;;;
+;;; - (merge SPEC1 SPEC2 ...): result of merging timelines SPEC1 SPEC2 ...
+;;;
+
+;;; Timeline spec string
+;;;
+;;; SPEC ::= PRIMARY | COMPOSITE
+;;; PRIMARY ::= USER | LIST | DIRECT_MESSSAGES | DIRECT_MESSSAGES_SENT
+;;; | FRIENDS | HOME | MENTIONS | PUBLIC | REPLIES
+;;; | RETWEETED_BY_ME | RETWEETED_BY_USER
+;;; | RETWEETED_TO_ME | RETWEETED_TO_USER | RETWEETS_OF_ME
+;;; | SEARCH
+;;; COMPOSITE ::= EXCLUDE-IF | EXCLUDE-RE | MERGE
+;;;
+;;; USER ::= /[a-zA-Z0-9_-]+/
+;;; LIST ::= USER "/" LISTNAME
+;;; LISTNAME ::= /[a-zA-Z0-9_-]+/
+;;; DIRECT_MESSSAGES ::= ":direct_messages"
+;;; DIRECT_MESSSAGES_SENT ::= ":direct_messages_sent"
+;;; FAVORITES ::= ":favorites" | ":favorites/" USER
+;;; FRIENDS ::= ":friends"
+;;; HOME ::= ":home" | "~"
+;;; MENTIONS ::= ":mentions"
+;;; PUBLIC ::= ":public"
+;;; REPLIES ::= ":replies" | "@"
+;;; RETWEETED_BY_ME ::= ":retweeted_by_me"
+;;; RETWEETED_BY_USER ::= ":retweeted_by_user/" USER
+;;; RETWEETED_TO_ME ::= ":retweeted_to_me"
+;;; RETWEETED_TO_USER ::= ":retweeted_to_user/" USER
+;;; RETWEETS_OF_ME ::= ":retweets_of_me"
+;;; SINGLE ::= ":single/" ID
+;;; ID ::= /[0-9]+/
+;;;
+;;; SEARCH ::= ":search/" QUERY_STRING "/"
+;;; QUERY_STRING ::= any string, where "/" is escaped by a backslash.
+;;;
+;;; EXCLUDE-IF ::= ":exclude-if/" FUNC "/" SPEC
+;;; FUNC ::= LAMBDA EXPRESSION | SYMBOL
+;;; EXCLUDE-RE ::= ":exclude-re/" REGEXP "/" SPEC
+;;;
+;;; MERGE ::= "(" MERGED_SPECS ")"
+;;; MERGED_SPECS ::= SPEC | SPEC "+" MERGED_SPECS
+;;;
+
+(defvar twittering-regexp-hash
+ (let ((full-width-number-sign (twittering-ucs-to-char #xff03)))
+ ;; Unicode Character 'FULLWIDTH NUMBER SIGN' (U+FF03)
+ (concat "\\(?:#\\|" (char-to-string full-width-number-sign) "\\)")))
+
+(defvar twittering-regexp-atmark
+ (let ((full-width-commercial-at (twittering-ucs-to-char #xff20)))
+ ;; Unicode Character 'FULLWIDTH COMMERCIAL AT' (U+FF20)
+ (concat "\\(?:@\\|" (char-to-string full-width-commercial-at) "\\)")))
+
+(defun twittering-timeline-spec-to-string (timeline-spec &optional shorten)
+ "Convert TIMELINE-SPEC into a string.
+If SHORTEN is non-nil, the abbreviated expression will be used."
+ (let ((type (car timeline-spec))
+ (value (cdr timeline-spec)))
+ (cond
+ ;; user
+ ((eq type 'user) (car value))
+ ;; list
+ ((eq type 'list) (concat (car value) "/" (cadr value)))
+ ;; simple
+ ((eq type 'direct_messages) ":direct_messages")
+ ((eq type 'direct_messages_sent) ":direct_messages_sent")
+ ((eq type 'favorites)
+ (if value
+ (concat ":favorites/" (car value))
+ ":favorites"))
+ ((eq type 'friends) ":friends")
+ ((eq type 'home) (if shorten "~" ":home"))
+ ((eq type 'mentions) (if shorten "@" ":mentions"))
+ ((eq type 'public) ":public")
+ ((eq type 'replies) ":replies")
+ ((eq type 'retweeted_by_me) ":retweeted_by_me")
+ ((eq type 'retweeted_by_user) (concat ":retweeted_by_user/" (car value)))
+ ((eq type 'retweeted_to_me) ":retweeted_to_me")
+ ((eq type 'retweeted_to_user) (concat ":retweeted_to_user/" (car value)))
+ ((eq type 'retweets_of_me) ":retweets_of_me")
+ ((eq type 'single) (concat ":single/" (car value)))
+ ((eq type 'search)
+ (let ((query (car value)))
+ (concat ":search/"
+ (replace-regexp-in-string "\\(\\\\\\|/\\)" "\\\\\\1" query)
+ "/")))
+ ;; composite
+ ((eq type 'exclude-if)
+ (let ((func (car value))
+ (spec (cadr value))
+ (print-level nil))
+ (concat ":exclude-if/" (prin1-to-string func) "/"
+ (twittering-timeline-spec-to-string spec))))
+ ((eq type 'exclude-re)
+ (let ((regexp-str (car value))
+ (spec (cadr value))
+ (print-level nil))
+ (concat ":exclude-re/"
+ (replace-regexp-in-string "/" "\\\\\/" regexp-str)
+ "/"
+ (twittering-timeline-spec-to-string spec))))
+ ((eq type 'merge)
+ (concat "("
+ (mapconcat 'twittering-timeline-spec-to-string value "+")
+ ")"))
+ (t
+ nil))))
+
+(eval-and-compile
+ (defmacro twittering-make-user-timeline-spec-direct (user)
+ `(list 'user ,user))
+ (defmacro twittering-make-list-timeline-spec-direct (owner listname)
+ `(list 'list ,owner ,listname))
+ (defmacro twittering-make-hashtag-timeline-spec-direct (tag)
+ `(list 'search (concat "#" ,tag)))
+ (defmacro twittering-make-hashtag-timeline-spec-string-direct (tag)
+ `(concat "#" ,tag)))
+
+(defun twittering-extract-timeline-spec (str &optional unresolved-aliases)
+ "Extract one timeline spec from STR.
+Return cons of the spec and the rest string."
+ (cond
+ ((null str)
+ (error "STR is nil")
+ nil)
+ ((string-match "^\\([a-zA-Z0-9_-]+\\)/\\([[:word:]_-]+\\)" str)
+ (let ((user (match-string 1 str))
+ (listname (match-string 2 str))
+ (rest (substring str (match-end 0))))
+ `(,(twittering-make-list-timeline-spec-direct user listname) . ,rest)))
+ ((string-match "^\\([a-zA-Z0-9_-]+\\)" str)
+ (let ((user (match-string 1 str))
+ (rest (substring str (match-end 0))))
+ `(,(twittering-make-user-timeline-spec-direct user) . ,rest)))
+ ((string-match "^~" str)
+ `((home) . ,(substring str (match-end 0))))
+ ((string-match (concat "^" twittering-regexp-atmark) str)
+ `((mentions) . ,(substring str (match-end 0))))
+ ((string-match (concat "^" twittering-regexp-hash "\\([[:alpha:]0-9_-]+\\)")
+ str)
+ (let* ((tag (match-string 1 str))
+ (rest (substring str (match-end 0))))
+ `(,(twittering-make-hashtag-timeline-spec-direct tag) . ,rest)))
+ ((string-match "^:\\([a-z_-]+\\)" str)
+ (let ((type (match-string 1 str))
+ (following (substring str (match-end 0)))
+ (alist '(("direct_messages" . direct_messages)
+ ("direct_messages_sent" . direct_messages_sent)
+ ("friends" . friends)
+ ("home" . home)
+ ("mentions" . mentions)
+ ("public" . public)
+ ("replies" . replies)
+ ("retweeted_by_me" . retweeted_by_me)
+ ("retweeted_to_me" . retweeted_to_me)
+ ("retweets_of_me" . retweets_of_me))))
+ (cond
+ ((assoc type alist)
+ (let ((first-spec (list (cdr (assoc type alist)))))
+ (cons first-spec following)))
+ ((string= type "favorites")
+ (if (string-match "^:favorites/\\([a-zA-Z0-9_-]+\\)" str)
+ (let ((rest (substring str (match-end 0))))
+ `((favorites ,(match-string 1 str)) . ,rest))
+ `((favorites) . ,following)))
+ ((string-match "^:retweeted_by_user/\\([a-zA-Z0-9_-]+\\)" str)
+ (let ((user (match-string 1 str))
+ (rest (substring str (match-end 0))))
+ `((retweeted_by_user ,user) . ,rest)))
+ ((string-match "^:retweeted_to_user/\\([a-zA-Z0-9_-]+\\)" str)
+ (let ((user (match-string 1 str))
+ (rest (substring str (match-end 0))))
+ `((retweeted_to_user ,user) . ,rest)))
+ ((string-match "^:single/\\([0-9]+\\)" str)
+ (let ((id (match-string 1 str))
+ (rest (substring str (match-end 0))))
+ `((single ,id) . ,rest)))
+ ((string= type "search")
+ (if (string-match "^:search/\\(\\(.*?[^\\]\\)??\\(\\\\\\\\\\)*\\)??/"
+ str)
+ (let* ((escaped-query (or (match-string 1 str) ""))
+ (query (replace-regexp-in-string "\\\\\\(\\\\\\|/\\)" "\\1"
+ escaped-query))
+ (rest (substring str (match-end 0))))
+ (if (not (string= "" escaped-query))
+ `((search ,query) . ,rest)
+ (error "\"%s\" has no valid regexp" str)
+ nil))))
+ ((string= type "exclude-if")
+ (let ((result-pair
+ (cond
+ ((string-match "^:exclude-if/\\([^(/]+\\)/" str)
+ `(,(intern (match-string 1 str)) . ,(match-end 1)))
+ ((string-match "^:exclude-if/" str)
+ (condition-case err
+ (read-from-string str (match-end 0))
+ (error
+ nil))))))
+ (if result-pair
+ (let ((func (car result-pair))
+ (pos (cdr result-pair)))
+ (cond
+ ((not (functionp func))
+ (error "\"%s\" has an invalid function" str)
+ nil)
+ ((<= (length str) (1+ pos))
+ (error "\"%s\" has no timeline spec" str)
+ nil)
+ ((not (char-equal ?/ (aref str pos)))
+ (error "\"%s\" has no delimiter" str)
+ nil)
+ (t
+ (let* ((pair (twittering-extract-timeline-spec
+ (substring str (1+ pos)) unresolved-aliases))
+ (spec (car pair))
+ (rest (cdr pair)))
+ `((exclude-if ,func ,spec) . ,rest)))))
+ (error "\"%s\" has an invalid function" str)
+ nil)))
+ ((string= type "exclude-re")
+ (cond
+ ((string-match "^:exclude-re/\\(\\(.*?[^\\]\\)??\\(\\\\\\\\\\)*\\)??/"
+ str)
+ (let* ((escaped-regexp (or (match-string 1 str) ""))
+ (regexp
+ (replace-regexp-in-string "\\\\/" "/" escaped-regexp nil t))
+ (following (substring str (match-end 0))))
+ (cond
+ ((string= "" escaped-regexp)
+ (error "\"%s\" has no valid regexp" str)
+ nil)
+ (t
+ (let* ((pair (twittering-extract-timeline-spec
+ following unresolved-aliases))
+ (spec (car pair))
+ (rest (cdr pair)))
+ `((exclude-re ,regexp ,spec) . ,rest))))))
+ (t
+ (error "\"%s\" has no valid regexp" str)
+ nil)))
+ (t
+ (error "\"%s\" is invalid as a timeline spec" str)
+ nil))))
+ ((string-match "^\\$\\([a-zA-Z0-9_-]+\\)\\(?:(\\([^)]*\\))\\)?" str)
+ (let* ((name (match-string 1 str))
+ (rest (substring str (match-end 0)))
+ (value (cdr-safe (assoc name twittering-timeline-spec-alias)))
+ (arg (match-string 2 str)))
+ (if (member name unresolved-aliases)
+ (error "Alias \"%s\" includes a recursive reference" name)
+ (cond
+ ((stringp value)
+ (twittering-extract-timeline-spec
+ (concat value rest)
+ (cons name unresolved-aliases)))
+ ((functionp value)
+ (twittering-extract-timeline-spec
+ (funcall value arg)
+ (cons name unresolved-aliases)))
+ (t
+ (error "Alias \"%s\" is undefined" name))))))
+ ((string-match "^(" str)
+ (let ((rest (concat "+" (substring str (match-end 0))))
+ (result '()))
+ (while (and rest (string-match "^\\+" rest))
+ (let* ((spec-string (substring rest (match-end 0)))
+ (pair (twittering-extract-timeline-spec
+ spec-string unresolved-aliases))
+ (spec (car pair))
+ (next-rest (cdr pair)))
+ (setq result (cons spec result))
+ (setq rest next-rest)))
+ (if (and rest (string-match "^)" rest))
+ (let ((spec-list
+ (twittering-remove-duplicates
+ (apply 'append
+ (mapcar (lambda (x) (if (eq 'merge (car x))
+ (cdr x)
+ (list x)))
+ (reverse result))))))
+ (if (= 1 (length spec-list))
+ `(,(car spec-list) . ,(substring rest 1))
+ `((merge ,@spec-list) . ,(substring rest 1))))
+ (if rest
+ ;; The string following the opening parenthesis `('
+ ;; can be interpreted without errors,
+ ;; but there is no corresponding closing parenthesis.
+ (error "\"%s\" lacks a closing parenthesis" str))
+ ;; Does not display additional error messages if an error
+ ;; occurred on interpreting the string following
+ ;; the opening parenthesis `('.
+ nil)))
+ (t
+ (error "\"%s\" is invalid as a timeline spec" str)
+ nil)
+ ))
+
+(defun twittering-string-to-timeline-spec (spec-str &optional noerror)
+ "Convert SPEC-STR into a timeline spec.
+If SPEC-STR is invalid as a timeline spec string, raise an error or return
+nil if NOERROR is non-nil."
+ (let ((result-pair
+ (condition-case err
+ (twittering-extract-timeline-spec spec-str)
+ (error
+ (if noerror
+ nil
+ (signal (car err) (cdr err))
+ nil)))))
+ (if (and result-pair (string= "" (cdr result-pair)))
+ (car result-pair)
+ nil)))
+
+(defun twittering-timeline-spec-primary-p (spec)
+ "Return non-nil if SPEC is a primary timeline spec.
+`primary' means that the spec is not a composite timeline spec such as
+`merge'."
+ (let ((primary-spec-types
+ '(user list
+ direct_messages direct_messages_sent
+ favorites friends home mentions public replies
+ search
+ retweeted_by_me retweeted_by_user
+ retweeted_to_me retweeted_to_user
+ retweets_of_me
+ single))
+ (type (car spec)))
+ (memq type primary-spec-types)))
+
+(defun twittering-timeline-spec-composite-p (spec)
+ "Return non-nil if SPEC is a composite timeline spec.
+`composite' means that the spec depends on other timelines."
+ (let ((composite-spec-types
+ '(exclude-if exclude-re merge))
+ (type (car spec)))
+ (memq type composite-spec-types)))
+
+(defun twittering-timeline-spec-depending-on-p (spec base-spec)
+ "Return non-nil if SPEC depends on BASE-SPEC."
+ (cond
+ ((twittering-timeline-spec-primary-p spec)
+ (equal spec base-spec))
+ ((equal spec base-spec)
+ t)
+ (t
+ (remove
+ nil
+ (mapcar
+ (lambda (direct-base-spec)
+ (twittering-timeline-spec-depending-on-p direct-base-spec base-spec))
+ (twittering-get-base-timeline-specs spec))))))
+
+(defun twittering-timeline-spec-is-user-p (spec)
+ "Return non-nil if SPEC is a user timeline."
+ (and (consp spec) (eq 'user (car spec))))
+
+(defun twittering-timeline-spec-is-direct-messages-p (spec)
+ "Return non-nil if SPEC is a timeline spec which is related of
+direct_messages."
+ (and spec
+ (memq (car spec) '(direct_messages direct_messages_sent))))
+
+(defun twittering-timeline-spec-is-search-p (spec)
+ "Return non-nil if SPEC is a search timeline spec."
+ (and (consp spec)
+ (eq 'search (car spec))))
+
+(defun twittering-extract-query-string-from-search-timeline-spec (spec)
+ "Return the query string if SPEC is a search timeline spec.
+If SPEC is not a search timeline spec, return nil."
+ (and (eq 'search (car spec))
+ (cadr spec)))
+
+(defun twittering-equal-string-as-timeline (spec-str1 spec-str2)
+ "Return non-nil if SPEC-STR1 equals SPEC-STR2 as a timeline spec.
+If either SPEC-STR1 or SPEC-STR2 is invalid as a timeline spec string,
+return nil."
+ (if (and (stringp spec-str1) (stringp spec-str2))
+ (let ((spec1 (twittering-string-to-timeline-spec spec-str1 t))
+ (spec2 (twittering-string-to-timeline-spec spec-str2 t)))
+ (equal spec1 spec2))
+ nil))
+
+(defun twittering-get-base-timeline-specs (spec)
+ "Return the timeline specs on which the timeline SPEC depends.
+If SPEC is primary, returns a list consisting of itself.
+The result timelines may be a composite timeline."
+ (let ((type (car spec)))
+ (cond
+ ((twittering-timeline-spec-primary-p spec)
+ `(,spec))
+ ((memq type '(exclude-if exclude-re))
+ `(,(elt spec 2)))
+ ((eq type 'merge)
+ (cdr spec))
+ (t
+ nil))))
+
+(defun twittering-get-primary-base-timeline-specs (spec)
+ "Return the primary timeline specs on which the timeline SPEC depends.
+If SPEC is primary, returns a list consisting of itself.
+The result timelines are primary."
+ (if (twittering-timeline-spec-primary-p spec)
+ `(,spec)
+ (twittering-remove-duplicates
+ (apply 'append
+ (mapcar 'twittering-get-primary-base-timeline-specs
+ (twittering-get-base-timeline-specs spec))))))
+
+(defun twittering-get-dependent-timeline-specs (base-spec)
+ "Return a list of timeline specs that depend on BASE-SPEC.
+If BASE-SPEC is a primary timeline spec, the return value consists of
+BASE-SPEC and composite timeline specs that depend on BASE-SPEC and are
+bound to a live buffer.
+If BASE-SPEC is a composite timeline spec, the return value consists of
+composite timeline specs that depend on BASE-SPEC and are bound to a live
+buffer."
+ (twittering-remove-duplicates
+ `(;; BASE-SPEC may not be bound to a live buffer.
+ ,@(when (twittering-timeline-spec-primary-p base-spec)
+ `(,base-spec))
+ ,@(remove
+ nil
+ (mapcar
+ (lambda (spec)
+ (when (twittering-timeline-spec-depending-on-p spec base-spec)
+ spec))
+ (mapcar 'twittering-get-timeline-spec-for-buffer
+ (twittering-get-buffer-list)))))))
+
+(defun twittering-generate-composite-timeline (spec base-spec base-statuses)
+ "Generate statuses for the timeline SPEC from BASE-STATUSES.
+BASE-STATUSES must originate from the BASE-SPEC timeline.
+If SPEC is a primary timeline and equals BASE-SPEC, just return BASE-STATUSES.
+If SPEC is a primary timeline and does not equal BASE-SPEC, return nil."
+ (let ((type (car spec)))
+ (cond
+ ((twittering-timeline-spec-primary-p spec)
+ (if (equal spec base-spec)
+ (let ((pattern-list
+ (twittering-get-filter-list-for-timeline-spec
+ spec)))
+ (if pattern-list
+ (remove
+ nil
+ (mapcar
+ (lambda (status)
+ (if (twittering-match-pattern-list status pattern-list)
+ (progn
+ (debug-printf "Exclude the status: %s" status)
+ nil)
+ status))
+ base-statuses))
+ base-statuses))
+ nil))
+ ((eq type 'exclude-if)
+ (let* ((direct-base (car (twittering-get-base-timeline-specs spec)))
+ (direct-base-statuses
+ (twittering-generate-composite-timeline direct-base
+ base-spec base-statuses))
+ (func (elt spec 1)))
+ (remove nil
+ (mapcar (lambda (status)
+ (unless (funcall func status)
+ status))
+ direct-base-statuses))))
+ ((eq type 'exclude-re)
+ (let* ((direct-base (car (twittering-get-base-timeline-specs spec)))
+ (direct-base-statuses
+ (twittering-generate-composite-timeline direct-base
+ base-spec base-statuses))
+ (regexp (elt spec 1)))
+ (remove nil
+ (mapcar
+ (lambda (status)
+ (unless (string-match regexp (cdr (assq 'text status)))
+ status))
+ direct-base-statuses))))
+ ((eq type 'merge)
+ (sort
+ (apply 'append
+ (mapcar (lambda (direct-base-spec)
+ ;; `copy-sequence' is required because `sort'
+ ;; modifies the appended list that may include
+ ;; `base-statuses' as a tail.
+ ;; `base-statuses' may refer to the original list
+ ;; which already retrieved tweets are registered
+ ;; with. It must not be modified.
+ (copy-sequence
+ (twittering-generate-composite-timeline
+ direct-base-spec base-spec base-statuses)))
+ (twittering-get-base-timeline-specs spec)))
+ (lambda (status1 status2)
+ (let ((id1 (cdr (assq 'id status1)))
+ (id2 (cdr (assq 'id status2))))
+ (twittering-status-id< id2 id1)))))
+ (t
+ nil))))
+
+;;;;
+;;;; Filter
+;;;;
+
+(defun twittering-get-filter-list-for-timeline-spec-string (spec-string)
+ (let ((entry-list twittering-filter-alist))
+ (remove
+ nil
+ (mapcar
+ (lambda (entry)
+ (let ((spec-regexp
+ (if (listp (car entry))
+ (concat "\\(?:"
+ (mapconcat 'identity (car entry) "\\|")
+ "\\)")
+ (car entry)))
+ (pattern-list (cdr entry)))
+ (when (string-match spec-regexp spec-string)
+ pattern-list)))
+ entry-list))))
+
+(defun twittering-get-filter-list-for-timeline-spec (spec)
+ (when twittering-filter-alist
+ (let* ((spec-string (twittering-timeline-spec-to-string spec))
+ (short-spec-string (twittering-timeline-spec-to-string spec t))
+ (regexp-list
+ (twittering-get-filter-list-for-timeline-spec-string
+ spec-string)))
+ (if (string= spec-string short-spec-string)
+ regexp-list
+ (append regexp-list
+ (twittering-get-filter-list-for-timeline-spec-string
+ short-spec-string))))))
+
+(defun twittering-match-pattern (status pattern)
+ (let* ((rest pattern)
+ (matched t))
+ (while (and rest matched)
+ (let* ((current (car rest))
+ (sym (car current))
+ (regexp (cdr current))
+ (value (cdr (assq sym status)))
+ (value
+ (if (eq sym 'text)
+ (twittering-make-fontified-tweet-text-with-entity status)
+ value)))
+ (unless (and (stringp value)
+ (string-match regexp value))
+ (setq matched nil))
+ (setq rest (cdr rest))))
+ matched))
+
+(defun twittering-match-pattern-list (status pattern-list)
+ (let* ((rest pattern-list)
+ (matched nil))
+ (while (and rest (not matched))
+ (let ((current (car rest)))
+ (when (twittering-match-pattern status current)
+ (setq matched t))
+ (setq rest (cdr rest))))
+ matched))
+
+;;;;
+;;;; Retrieved statuses (timeline data)
+;;;;
+
+(defun twittering-current-timeline-id-table (&optional spec)
+ (let ((spec (or spec (twittering-current-timeline-spec))))
+ (if spec
+ (elt (gethash spec twittering-timeline-data-table) 0)
+ nil)))
+
+(defun twittering-current-timeline-referring-id-table (&optional spec)
+ "Return the hash from a ID to the ID of the first observed status
+referring the former ID."
+ (let* ((spec (or spec (twittering-current-timeline-spec)))
+ (type (car spec)))
+ (cond
+ ((null spec)
+ nil)
+ ((memq type '(exclude-if exclude-re merge))
+ ;; Use the first non-nil table instead of merging the all tables
+ ;; because it may take a long time to merge them.
+ (car
+ (remove
+ nil
+ (mapcar (lambda (base-spec)
+ (elt (gethash base-spec twittering-timeline-data-table) 1))
+ (twittering-get-primary-base-timeline-specs spec)))))
+ ((eq type 'single)
+ ;; Single tweet timelines are registered in a special way.
+ ;; See `twittering-retrieve-single-tweet-sentinel'.
+ (elt (gethash '(:single) twittering-timeline-data-table) 1))
+ (t
+ (elt (gethash spec twittering-timeline-data-table) 1)))))
+
+(defun twittering-current-timeline-data (&optional spec)
+ (let* ((spec (or spec (twittering-current-timeline-spec)))
+ (type (car spec)))
+ (cond
+ ((null spec)
+ nil)
+ ((eq type 'single)
+ (let* ((id (cadr spec))
+ (status (twittering-find-status id)))
+ (if status
+ `(,status)
+ nil)))
+ ((memq type '(exclude-if exclude-re merge))
+ (let ((primary-base-specs
+ (twittering-get-primary-base-timeline-specs spec)))
+ (sort
+ (apply
+ 'append
+ (mapcar
+ (lambda (primary-spec)
+ ;; `copy-sequence' is required to prevent `sort'
+ ;; from modifying lists of statuses in the database
+ ;; `twittering-timeline-data-table'.
+ ;; The result of `twittering-generate-composite-timeline'
+ ;; may include a list in the database. If so, the simply
+ ;; appended list include it as a tail.
+ (copy-sequence
+ (twittering-generate-composite-timeline
+ spec
+ primary-spec (twittering-current-timeline-data primary-spec))))
+ primary-base-specs))
+ (lambda (status1 status2)
+ (let ((id1 (cdr (assq 'id status1)))
+ (id2 (cdr (assq 'id status2))))
+ (twittering-status-id< id2 id1))))))
+ ((eq type :single)
+ ;; The timeline spec '(:single) does not correspond to an ordinary
+ ;; timeline. It means an unordered set of tweets retrieved by the
+ ;; 'retrieve-single-tweet command of `twittering-call-api'.
+ ;; If this function is used with the spec '(:single), a specific tweet
+ ;; will be required with the user's intention.
+ ;; In this case, exclusion by patterns does not required.
+ (elt (gethash spec twittering-timeline-data-table) 2))
+ (t
+ (let ((statuses (elt (gethash spec twittering-timeline-data-table) 2))
+ (pattern-list
+ (twittering-get-filter-list-for-timeline-spec spec)))
+ (if pattern-list
+ (remove
+ nil
+ (mapcar
+ (lambda (status)
+ (if (twittering-match-pattern-list status pattern-list)
+ (progn
+ (debug-printf "Exclude the status: %s" status)
+ nil)
+ status))
+ statuses))
+ statuses))))))
+
+(defun twittering-remove-timeline-data (&optional spec)
+ (let ((spec (or spec (twittering-current-timeline-spec))))
+ (remhash spec twittering-timeline-data-table)))
+
+(defun twittering-find-status (id)
+ (let ((result nil))
+ (maphash
+ (lambda (spec pair)
+ (let* ((id-table (car pair))
+ (entry (gethash id id-table)))
+ ;; Take the most detailed status.
+ (when (and entry
+ (or (null result) (< (length result) (length entry))))
+ (setq result entry))))
+ twittering-timeline-data-table)
+ result))
+
+(defun twittering-delete-status-from-data-table (id)
+ (let ((modified-spec nil))
+ (maphash
+ (lambda (spec data)
+ (let* ((id-table (elt data 0))
+ (referring-id-table (elt data 1))
+ (timeline-data (elt data 2))
+ (status (gethash id id-table)))
+ (when status
+ (remhash id id-table)
+ ;; Here, `referring-id-table' is not modified.
+ ;; Therefore, the retweet observed secondly will not appear even
+ ;; if the retweet observed first for the same tweet is deleted.
+ (setq modified-spec
+ (cons `(,spec
+ ,id-table
+ ,referring-id-table
+ ,(remove status timeline-data))
+ modified-spec)))))
+ twittering-timeline-data-table)
+ (mapc
+ (lambda (spec)
+ (let ((buffer (twittering-get-buffer-from-spec spec)))
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (save-excursion
+ (twittering-for-each-property-region
+ 'id
+ (lambda (beg end value)
+ (when (twittering-status-id= id value)
+ (let ((buffer-read-only nil)
+ (separator-pos (min (point-max) (1+ end))))
+ (delete-region beg separator-pos)
+ (goto-char beg))))
+ buffer))))))
+ (twittering-remove-duplicates
+ (apply 'append
+ (mapcar
+ (lambda (data)
+ (let ((spec (car data)))
+ ;; Update the entry for `spec' in
+ ;; `twittering-timeline-data-table' with the new
+ ;; timeline-data that does not include `status'.
+ (puthash spec (cdr data) twittering-timeline-data-table)
+ (twittering-get-dependent-timeline-specs spec)))
+ modified-spec))))))
+
+(defun twittering-get-replied-statuses (id &optional count)
+ "Return a list of replied statuses starting from the status specified by ID.
+Statuses are stored in ascending-order with respect to their IDs."
+ (let ((result nil)
+ (status (twittering-find-status id)))
+ (while
+ (and (if (numberp count)
+ (<= 0 (setq count (1- count)))
+ t)
+ (let ((replied-id (or (cdr (assq 'in-reply-to-status-id status))
+ "")))
+ (unless (string= "" replied-id)
+ (let ((replied-status (twittering-find-status replied-id)))
+ (when replied-status
+ (setq result (cons replied-status result))
+ (setq status replied-status)
+ t))))))
+ result))
+
+(defun twittering-have-replied-statuses-p (id)
+ (let ((status (twittering-find-status id)))
+ (when status
+ (let ((replied-id (cdr (assq 'in-reply-to-status-id status))))
+ (and replied-id (not (string= "" replied-id)))))))
+
+(defun twittering-add-statuses-to-timeline-data (statuses &optional spec)
+ "Add STATUSES as new statuses for SPEC and update derived timelines.
+The function returns a list of lists including an updated timeline spec
+string and the number of new statuses for the timeline."
+ (let* ((spec (or spec (twittering-current-timeline-spec)))
+ (id-table
+ (or (twittering-current-timeline-id-table spec)
+ (make-hash-table :test 'equal)))
+ (referring-id-table
+ (or (twittering-current-timeline-referring-id-table spec)
+ (make-hash-table :test 'equal)))
+ (timeline-data (twittering-current-timeline-data spec)))
+ (let* ((new-statuses
+ (remove nil
+ (mapcar
+ (lambda (status)
+ (let ((id (cdr (assq 'id status)))
+ (retweeted-id (cdr (assq 'retweeted-id status))))
+ (unless (or (not retweeted-id)
+ (gethash retweeted-id referring-id-table))
+ ;; Store the id of the first observed tweet
+ ;; that refers `retweeted-id'.
+ (puthash retweeted-id id referring-id-table))
+ (if (gethash id id-table)
+ nil
+ (puthash id status id-table)
+ (puthash id id referring-id-table)
+ `((source-spec . ,spec)
+ ,@status))))
+ statuses)))
+ (new-statuses
+ ;; Sort tweets by ID.
+ ;; This is necessary because `twittering-render-timeline' assumes
+ ;; that given tweets are ordered.
+ (sort new-statuses
+ (lambda (status1 status2)
+ (let ((id1 (cdr (assq 'id status1)))
+ (id2 (cdr (assq 'id status2))))
+ (twittering-status-id< id2 id1))))))
+ (when new-statuses
+ (let ((new-timeline-data
+ (sort (append new-statuses timeline-data)
+ (lambda (status1 status2)
+ (let ((id1 (cdr (assq 'id status1)))
+ (id2 (cdr (assq 'id status2))))
+ (twittering-status-id< id2 id1))))))
+ (puthash spec `(,id-table ,referring-id-table ,new-timeline-data)
+ twittering-timeline-data-table))
+ (let ((twittering-new-tweets-spec spec)
+ (twittering-new-tweets-statuses new-statuses)
+ (twittering-new-tweets-count (length new-statuses)))
+ (run-hooks 'twittering-new-tweets-hook)))
+ ;; Update timelines derived from SPEC and return the number of
+ ;; new tweets for each updated timeline.
+ (remove
+ nil
+ (mapcar
+ (lambda (buffer)
+ (let ((other-spec (twittering-get-timeline-spec-for-buffer buffer))
+ (other-spec-string
+ (twittering-get-timeline-spec-string-for-buffer buffer)))
+ (when (twittering-timeline-spec-depending-on-p other-spec spec)
+ (let* ((twittering-new-tweets-spec other-spec)
+ (twittering-new-tweets-statuses
+ (twittering-generate-composite-timeline
+ other-spec spec new-statuses))
+ (twittering-new-tweets-count
+ (length twittering-new-tweets-statuses))
+ (rendered-tweets
+ (twittering-render-timeline
+ buffer twittering-new-tweets-statuses t)))
+ (when rendered-tweets
+ (when (not (equal spec other-spec))
+ ;; The hook has been alreadly invoked for `spec'.
+ (run-hooks 'twittering-new-tweets-hook))
+ `(,other-spec-string ,(length rendered-tweets)))))))
+ (twittering-get-buffer-list))))))
+
+;;;;
+;;;; URIs related to a tweet
+;;;;
+
+(defun twittering-get-status-url (username &optional id)
+ "Generate a URL of a user or a specific status."
+ (let ((func
+ (cdr (assq
+ 'status-url
+ (assq twittering-service-method
+ twittering-service-method-table)))))
+ (funcall func username id)))
+
+(defun twittering-get-status-url-from-alist (status)
+ "Generate a URL of a tweet specified by an alist STATUS."
+ (let ((username (cdr (or (assq 'retweeted-user-screen-name status)
+ (assq 'user-screen-name status))))
+ (id (cdr (or (assq 'retweeted-id status)
+ (assq 'id status))))
+ (func
+ (cdr (assq
+ 'status-url
+ (assq twittering-service-method
+ twittering-service-method-table)))))
+ (funcall func username id)))
+
+(defun twittering-get-list-url (username listname)
+ "Generate a URL of a specific list."
+ (let ((func
+ (cdr (assq
+ 'status-url
+ (assq twittering-service-method
+ twittering-service-method-table))))
+ (str (concat username "/" listname)))
+ (funcall func str nil)))
+
+(defun twittering-get-status-url-twitter (username &optional id)
+ "Generate status URL for Twitter."
+ (if id
+ (format "http://%s/%s/status/%s" twittering-web-host username id)
+ (format "http://%s/%s" twittering-web-host username)))
+
+(defun twittering-get-status-url-statusnet (username &optional id)
+ "Generate status URL for StatusNet."
+ (if id
+ (format "http://%s/%s/notice/%s" twittering-web-host twittering-web-path-prefix id)
+ (format "http://%s/%s/%s" twittering-web-host twittering-web-path-prefix username)))
+
+(defun twittering-get-search-url (query-string)
+ "Generate a URL for searching QUERY-STRING."
+ (let ((func (cdr (assq
+ 'search-url (assq twittering-service-method
+ twittering-service-method-table)))))
+ (funcall func query-string)))
+
+(defun twittering-get-search-url-twitter (query-string)
+ (format "http://%s/search?q=%s"
+ twittering-web-host (twittering-percent-encode query-string)))
+
+(defun twittering-get-search-url-statusnet (query-string)
+ (if (string-match "^#\\(.+\\)" query-string)
+ (format "http://%s/%s/tag/%s"
+ twittering-web-host
+ twittering-web-path-prefix
+ (twittering-percent-encode (match-string 1 query-string)))
+ (format "http://%s/search?q=%s"
+ twittering-web-host (twittering-percent-encode query-string))))
+
+(defun twittering-extract-id-from-url (url-string)
+ "Extract the ID from URL-STRING.
+Return nil if URL-STRING cannot be interpreted as a URL pointing a tweet."
+ (when (string-match
+ "\\`https?://twitter.com/\\(?:#!/\\)?[^/]+/status\\(?:es\\)?/\\([0-9]+\\)/?\\'"
+ url-string)
+ (match-string 1 url-string)))
+
+;;;;
+;;;; Utility of status IDs
+;;;;
+
+(defun twittering-status-id< (id1 id2)
+ (let ((len1 (length id1))
+ (len2 (length id2)))
+ (cond
+ ((= len1 len2) (string< id1 id2))
+ ((< len1 len2) t)
+ (t nil))))
+
+(defun twittering-status-id= (id1 id2)
+ (equal id1 id2))
+
+(defun twittering-snowflake-epoch-time ()
+ "Return the epoch time of Snowflake."
+ (require 'calc)
+ (let ((epoch-str
+ ;; This corresponds to 2010-11-04 01:42:54+00:00 in RFC3339.
+ ;; The value comes from the following page.
+ ;; https://github.com/twitter/snowflake/blob/6d4634aa490de26e22425538291fe0a03071a170/src/main/scala/com/twitter/service/snowflake/IdWorker.scala#L22
+ ;; 22 val twepoch = 1288834974657L
+ "1288834974657"))
+ (let ((str
+ (calc-eval `(,(concat "floor(10#" epoch-str "/10#1000)")
+ calc-word-size 64 calc-number-radix 16)))
+ (milisec-str
+ (calc-eval `(,(concat "10#" epoch-str "%10#1000")
+ calc-word-size 64 calc-number-radix 10))))
+ (mapcar (lambda (s) (string-to-number s 16))
+ `(,(substring str 3 7) ,(substring str 7)
+ ,milisec-str)))))
+
+(defun twittering-id-to-time (id)
+ "Return the time corresonding to ID generated by Snowflake.
+If ID is a string consisting of 12 or more digits, return the corresponding
+time in Emacs internal representation the same as `encode-time'.
+Otherwise, return nil.
+
+This is because ID consisting of 11 or less digits may not be generated
+by Snowflake."
+ (require 'calc)
+ (cond
+ ((not (stringp id))
+ nil)
+ ((< (length id) 12)
+ ;; The given ID may not be generated by Snowflake.
+ ;;
+ ;; The first tweet in the example response of
+ ;; https://dev.twitter.com/docs/api/1/get/statuses/home_timeline
+ ;; has "18700887835" as the ID.
+ ;; Assuming that it is generated by Snowflake, it corresponds to
+ ;; "2010-11-04 01:42:58+00:00".
+ ;; However, the created_at is "Fri Jul 16 16:58:46 +0000 2010".
+ ;; It can be confirmed at http://twitter.com/cindyli/status/18700887835 .
+ ;;
+ ;; Therefore we can not suppose that an ID is generated by Snowflake
+ ;; if the ID consists of 11-digits.
+ ;; Assuming that an ID reaches 10^11 before Snowflake is turned on at
+ ;; Nov 04 2010, the average number of tweets per day will exceed
+ ;; 533 million.
+ ;; ( 10^11 - 18,700,887,835 > 80,000,000,000
+ ;; 80 billion / 5 month (from Jul 16 to Nov 4) > 533 million / day )
+ ;;
+ ;; It is impossible.
+ ;; So, I assume that an ID is generated by Snowflake if the ID consists of
+ ;; 12 or more digits.
+ ;; The first ID with 12-digits, 100,000,000,000 (10^11), corresponds to
+ ;; 2010-11-04 01:43:17+00:00.
+ nil)
+ (t
+ (let* ((epoch (twittering-snowflake-epoch-time))
+ (str (calc-eval
+ `(,(format "floor(rsh(10#%s,22)/1000)" id)
+ calc-word-size 64 calc-number-radix 16)))
+ (milisec
+ (string-to-number
+ (calc-eval
+ `(,(format "rsh(10#%s,22)%%1000" id)
+ calc-word-size 64 calc-number-radix 10))
+ 10)))
+ (when (string-match "^16#\\([[:xdigit:]]+\\)" str)
+ (let* ((hex-str (match-string 1 str))
+ (hex-str
+ (if (< (length hex-str) 4)
+ (concat "0000" hex-str)
+ hex-str)))
+ (time-add epoch
+ `(,(string-to-number
+ (substring hex-str 0 (- (length hex-str) 4)) 16)
+ ,(string-to-number
+ (substring hex-str (- (length hex-str) 4)) 16)
+ ,(* milisec 1000)
+ ))))))))
+
+(defun twittering-time-to-id (time)
+ "Return the ID corresponding to TIME by Snowflake.
+Bits other than timestamp are zero. The least significant 22 bits are zero.
+TIME must be an Emacs internal representation as a return value of
+`current-time'."
+ (require 'calc)
+ (let* ((epoch-time (twittering-snowflake-epoch-time))
+ (dt (if (time-less-p epoch-time time)
+ (time-subtract time epoch-time)
+ nil))
+ (sec-high (nth 0 dt))
+ (sec-low (nth 1 dt))
+ (microsec (or (nth 2 dt) "0")))
+ (when dt
+ (calc-eval
+ `(,(format "lsh((16#%04x%04x) * 1000 + floor(%d/1000), 22)"
+ sec-high sec-low microsec)
+ calc-word-size 64 calc-number-radix 10)))))
+
+;;;;
+;;;; Process info
+;;;;
+
+(defun twittering-register-process (proc spec &optional str)
+ (let ((str (or str (twittering-timeline-spec-to-string spec))))
+ (add-to-list 'twittering-process-info-alist `(,proc ,spec ,str))))
+
+(defun twittering-release-process (proc)
+ (let ((pair (assoc proc twittering-process-info-alist)))
+ (when pair
+ (setq twittering-process-info-alist
+ (delq pair twittering-process-info-alist)))))
+
+(defun twittering-get-timeline-spec-from-process (proc)
+ (let ((entry (assoc proc twittering-process-info-alist)))
+ (if entry
+ (elt entry 1)
+ nil)))
+
+(defun twittering-get-timeline-spec-string-from-process (proc)
+ (let ((entry (assoc proc twittering-process-info-alist)))
+ (if entry
+ (elt entry 2)
+ nil)))
+
+(defun twittering-find-processes-for-timeline-spec (spec)
+ (apply 'append
+ (mapcar
+ (lambda (pair)
+ (let ((proc (car pair))
+ (spec-info (cadr pair)))
+ (if (equal spec-info spec)
+ `(,proc)
+ nil)))
+ twittering-process-info-alist)))
+
+(defun twittering-remove-inactive-processes ()
+ (let ((inactive-statuses '(nil closed exit failed signal)))
+ (setq twittering-process-info-alist
+ (apply 'append
+ (mapcar
+ (lambda (pair)
+ (let* ((proc (car pair))
+ (info (cdr pair))
+ (status (process-status proc)))
+ (if (memq status inactive-statuses)
+ nil
+ `((,proc ,@info)))))
+ twittering-process-info-alist)))))
+
+(defun twittering-process-active-p (&optional spec)
+ (twittering-remove-inactive-processes)
+ (if spec
+ (twittering-find-processes-for-timeline-spec spec)
+ twittering-process-info-alist))
+
+;;;;
+;;;; Server info
+;;;;
+
+(defun twittering-update-api-table (spec api-string)
+ "Register a pair of a timeline spec and an API for retrieving the timeline.
+SPEC is a timeline spec. API-STRING is an identifier of an API for retrieving
+the timeline."
+ (let ((current (assoc spec twittering-timeline-spec-to-api-table)))
+ (if (null current)
+ (add-to-list 'twittering-timeline-spec-to-api-table
+ `(,spec . ,api-string))
+ (setcdr current api-string))))
+
+(defun twittering-make-rate-limit-alist (header-info)
+ "Make a rate-limit information alist from HEADER-INFO.
+Key symbols of a returned alist are following; limit, remaining, reset-time.
+Values bound to limit and remaining is a positive integer and
+one bound to reset-time is an Emacs time (result of `seconds-to-time')."
+ (let ((symbol-table
+ '(("X-Rate-Limit-Limit" . limit)
+ ("X-Rate-Limit-Remaining" . remaining)
+ ("X-Rate-Limit-Reset" . reset-time)
+ ;; For Twitter API v1.0.
+ ("X-RateLimit-Limit" . limit)
+ ("X-RateLimit-Remaining" . remaining)
+ ("X-RateLimit-Reset" . reset-time))))
+ (remove
+ nil
+ (mapcar (lambda (entry)
+ (let ((sym
+ (cdr
+ (twittering-assoc-string (car entry) symbol-table t))))
+ (cond
+ ((memq sym '(limit remaining))
+ `(,sym . ,(string-to-number (cdr entry))))
+ ((eq sym 'reset-time)
+ `(,sym
+ . ,(seconds-to-time (string-to-number (cdr entry)))))
+ (t
+ nil))))
+ header-info))))
+
+(defun twittering-update-rate-limit-info (api-string spec header-info)
+ "Register rate-limit information.
+API-STRING is an identifier of an API. SPEC is a timeline spec that had been
+retrieved by the API. HEADER-INFO is an alist generated from the HTTP response
+header of the API."
+ (let* ((api-string
+ (if (eq twittering-service-method 'twitter)
+ ;; The key for Twitter API v1.0 is nil.
+ nil
+ api-string))
+ (current (assoc api-string twittering-api-limit-info-alist))
+ (rate-limit-alist (twittering-make-rate-limit-alist header-info)))
+ (twittering-update-api-table spec api-string)
+ (if (null current)
+ (add-to-list 'twittering-api-limit-info-alist
+ `(,api-string . ,rate-limit-alist))
+ (setcdr current rate-limit-alist))))
+
+(defun twittering-update-server-info (connection-info header-info)
+ (let* ((new-entry-list (mapcar 'car header-info))
+ (account-info (cdr (assq 'account-info connection-info)))
+ (account
+ (twittering-get-from-account-info "screen_name" account-info))
+ (spec (cdr (assq 'timeline-spec connection-info)))
+ (api-string
+ (cdr (assq 'uri-without-query (assq 'request connection-info)))))
+ (twittering-update-rate-limit-info api-string spec header-info)
+ (when (remove t (mapcar
+ (lambda (entry)
+ (equal (assoc entry header-info)
+ (assoc entry twittering-server-info-alist)))
+ new-entry-list))
+ (setq twittering-server-info-alist
+ (append header-info
+ (remove nil (mapcar
+ (lambda (entry)
+ (if (member (car entry) new-entry-list)
+ nil
+ entry))
+ twittering-server-info-alist))))
+ (when twittering-display-remaining
+ (mapc (lambda (buffer)
+ (with-current-buffer buffer
+ (twittering-update-mode-line)))
+ (twittering-get-buffer-list))))
+ ;; cookie
+ (let* ((new-cookies
+ (twittering-extract-cookie connection-info header-info))
+ (old-cookies (cdr (assoc account twittering-cookie-alist)))
+ (updated-cookies
+ (append new-cookies
+ (remove nil
+ (mapcar (lambda (cookie)
+ (unless (assoc (car cookie) new-cookies)
+ cookie))
+ old-cookies)))))
+ (setq twittering-cookie-alist
+ (cons (cons account updated-cookies)
+ (remove nil
+ (mapcar (lambda (entry)
+ (unless (equal account (car entry))
+ entry))
+ twittering-cookie-alist)))))
+ header-info))
+
+(defun twittering-extract-cookie (connection-info header-info)
+ (remove
+ nil
+ (mapcar
+ (lambda (entry)
+ (let ((header-item (car entry))
+ (header-value (cdr entry)))
+ (when (and (string= header-item "Set-Cookie")
+ (string-match "\\([^= ]*\\) *= *\\([^; ]*\\) *;? *"
+ header-value))
+ ;; For ease of implementation, the followings are assumed.
+ ;; 1. Each response header includes only one cookie.
+ ;; 2. `value' of cookie is a token, not a quoted string.
+ ;; 3. Attributes except `domain', `expires' and `path' are ignored.
+ (let* ((name (downcase (match-string 1 header-value)))
+ (value (match-string 2 header-value))
+ (attributes
+ (mapcar
+ (lambda (str)
+ (when (string-match "\\` *\\([^ ]*\\) *= *\\(.*\\)\\'"
+ str)
+ (let ((attr (downcase (match-string 1 str)))
+ (value (match-string 2 str)))
+ (cond
+ ((string= attr "domain")
+ `(domain . ,value))
+ ((string= attr "expires")
+ `(expires
+ . ,(apply 'encode-time
+ (parse-time-string
+ (replace-regexp-in-string
+ "-" " " value)))))
+ ((string= attr "path")
+ `(path . ,value))
+ (t
+ nil)))))
+ (split-string (substring header-value (match-end 0))
+ " *; *")))
+ (additional-attributes
+ `(,@(let* ((domain (cdr (assq 'domain attributes)))
+ (request (cdr (assq 'request connection-info)))
+ (host (cdr (assq 'host request)))
+ (prefix
+ (if domain
+ (regexp-quote domain)
+ (concat "\\`" (regexp-quote host)))))
+ `((domain-regexp . ,(concat prefix "\\'")))))))
+ `(,name
+ (value . ,value)
+ ,@attributes
+ ,@additional-attributes)))))
+ header-info)))
+
+(defun twittering-make-cookie-string (request account-info)
+ (let ((account
+ (twittering-get-from-account-info "screen_name" account-info))
+ (current-time (current-time))
+ (host (cdr (assq 'host request))))
+ (when account
+ (mapconcat
+ 'identity
+ (remove nil
+ (mapcar
+ (lambda (entry)
+ (let* ((expires (cdr (assq 'expires entry)))
+ (not-expired (or (null expires)
+ (time-less-p current-time expires)))
+ (domain-regexp (cdr (assq 'domain-regexp entry))))
+ (when (and not-expired
+ (string-match domain-regexp host))
+ (format "%s=%s" (car entry) (cdr (assq 'value entry))))))
+ (cdr (assoc account twittering-cookie-alist))))
+ ";"))))
+
+(defun twittering-get-ratelimit-alist (&optional spec)
+ (let ((api-string
+ (cdr (assoc spec twittering-timeline-spec-to-api-table))))
+ (cdr (assoc api-string twittering-api-limit-info-alist))))
+
+(defun twittering-get-ratelimit-remaining (&optional spec)
+ (or (cdr (assq 'remaining (twittering-get-ratelimit-alist spec)))
+ 0))
+
+(defun twittering-get-ratelimit-limit (&optional spec)
+ (or (cdr (assq 'limit (twittering-get-ratelimit-alist spec)))
+ 0))
+
+(defun twittering-get-ratelimit-indicator-string (&optional spec)
+ "Make an indicator string of rate-limit information of SPEC."
+ (cond
+ ((eq twittering-service-method 'twitter)
+ ;; Twitter API v1.0.
+ (format "%d/%d"
+ (twittering-get-ratelimit-remaining)
+ (twittering-get-ratelimit-limit)))
+ (t
+ (mapconcat
+ (lambda (api-string)
+ (let* ((alist (cdr (assoc api-string twittering-api-limit-info-alist)))
+ (remaining (cdr (assq 'remaining alist)))
+ (limit (cdr (assq 'limit alist))))
+ (format "%s/%s"
+ (if remaining (number-to-string remaining) "?")
+ (if limit (number-to-string limit) "?"))))
+ (twittering-remove-duplicates
+ (mapcar (lambda (spec)
+ (cdr (assoc spec twittering-timeline-spec-to-api-table)))
+ (twittering-get-primary-base-timeline-specs spec)))
+ "+"))))
+
+;;;;
+;;;; Abstract layer for Twitter API
+;;;;
+
+(defun twittering-api-path (&rest params)
+ (mapconcat 'identity `(,twittering-api-prefix ,@params) ""))
+
+(defun twittering-call-api (command args-alist &optional additional-info)
+ "Call Twitter API and return the process object for the request.
+Invoke `twittering-call-api-with-account' with the main account specified
+by `twittering-get-main-account-info'.
+For details of arguments, see `twittering-call-api-with-account'."
+ (let ((account-info-alist (twittering-get-main-account-info)))
+ (twittering-call-api-with-account account-info-alist command args-alist
+ additional-info)))
+
+(defun twittering-call-api-with-account (account-info-alist command args-alist &optional additional-info)
+ "Call Twitter API and return the process object for the request.
+COMMAND is a symbol specifying API. ARGS-ALIST is an alist specifying
+arguments for the API corresponding to COMMAND. Each key of ARGS-ALIST is a
+symbol.
+ACCOUNT-INFO-ALIST is an alist storing account information, which has
+the following key;
+\"screen_name\", \"oauth_token\" and \"oauth_token_secret\" for OAuth/xAuth,
+\"screen_name\" and \"password\" for basic authentication.
+ADDITIONAL-INFO is used as an argument ADDITIONAL-INFO of
+`twittering-send-http-request'. Sentinels associated to the returned process
+receives it as the fourth argument. See also the function
+`twittering-send-http-request'.
+
+The valid symbols as COMMAND follows:
+retrieve-timeline -- Retrieve a timeline.
+ Valid key symbols in ARGS-ALIST:
+ timeline-spec -- the timeline spec to be retrieved.
+ timeline-spec-string -- the string representation of the timeline spec.
+ format -- (optional) the symbol specifying the format.
+ number -- (optional) how many tweets are retrieved. It must be an integer.
+ If nil, `twittering-number-of-tweets-on-retrieval' is used instead.
+ The maximum for search timeline is 100, and that for other timelines is
+ `twittering-max-number-of-tweets-on-retrieval'.
+ If the given number exceeds the maximum, the maximum is used instead.
+ max_id -- (optional) the maximum ID of retrieved tweets.
+ since_id -- (optional) the minimum ID of retrieved tweets.
+ sentinel -- (optional) the sentinel that processes the buffer consisting
+ of retrieved data.. This is used as an argument SENTINEL of
+ `twittering-send-http-request' via `twittering-http-get'.
+ If nil, `twittering-http-get-default-sentinel' is used.
+ clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
+ the buffer associated to the process. This is used as an argument
+ CLEAN-UP-SENTINEL of `twittering-send-http-request' via
+ `twittering-http-get'.
+ page -- (optional and valid only for favorites timeline) which page will
+ be retrieved.
+retrieve-single-tweet -- Retrieve a single tweet.
+ Valid key symbols in ARGS-ALIST:
+ id -- the ID of the tweet to be retrieved.
+ username -- (optional) the screen name of the author of the tweet.
+ format -- (optional) the symbol specifying the format.
+ sentinel -- (optional) the sentinel that processes the buffer consisting
+ of retrieved data.. This is used as an argument SENTINEL of
+ `twittering-send-http-request' via `twittering-http-get'.
+ If nil, `twittering-http-get-default-sentinel' is used.
+ clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
+ the buffer associated to the process. This is used as an argument
+ CLEAN-UP-SENTINEL of `twittering-send-http-request' via
+ `twittering-http-get'.
+get-list-index -- Retrieve list names owned by a user.
+ Valid key symbols in ARGS-ALIST:
+ username -- the username.
+ sentinel -- the sentinel that processes retrieved strings. This is used
+ as an argument SENTINEL of `twittering-send-http-request'
+ via `twittering-http-get'.
+ clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
+ the buffer associated to the process. This is used as an argument
+ CLEAN-UP-SENTINEL of `twittering-send-http-request' via
+ `twittering-http-get'.
+get-list-subscriptions -- Retrieve list names followed by a user.
+ Valid key symbols in ARGS-ALIST:
+ username -- the username.
+ sentinel -- the sentinel that processes retrieved strings. This is used
+ as an argument SENTINEL of `twittering-send-http-request'
+ via `twittering-http-get'.
+ clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
+ the buffer associated to the process. This is used as an argument
+ CLEAN-UP-SENTINEL of `twittering-send-http-request' via
+ `twittering-http-get'.
+create-friendships -- Follow a user.
+ Valid key symbols in ARGS-ALIST:
+ username -- the username which will be followed.
+destroy-friendships -- Unfollow a user.
+ Valid key symbols in ARGS-ALIST:
+ username -- the username which will be unfollowed.
+create-favorites -- Mark a tweet as a favorite.
+ Valid key symbols in ARGS-ALIST:
+ id -- the ID of the target tweet.
+destroy-favorites -- Remove a mark of a tweet as a favorite.
+ Valid key symbols in ARGS-ALIST:
+ id -- the ID of the target tweet.
+update-status -- Post a tweet.
+ Valid key symbols in ARGS-ALIST:
+ status -- the string to be posted.
+ in-reply-to-status-id -- (optional) the ID of a status that this post is
+ in reply to.
+destroy-status -- Destroy a tweet posted by the authenticated user itself.
+ Valid key symbols in ARGS-ALIST:
+ id -- the ID of the target tweet.
+retweet -- Retweet a tweet.
+ Valid key symbols in ARGS-ALIST:
+ id -- the ID of the target tweet.
+verify-credentials -- Verify the current credentials.
+ Valid key symbols in ARGS-ALIST:
+ sentinel -- the sentinel that processes returned information. This is used
+ as an argument SENTINEL of `twittering-send-http-request'
+ via `twittering-http-get'.
+ clean-up-sentinel -- the clean-up sentinel that post-processes the buffer
+ associated to the process. This is used as an argument CLEAN-UP-SENTINEL
+ of `twittering-send-http-request' via `twittering-http-get'.
+send-direct-message -- Send a direct message.
+ Valid key symbols in ARGS-ALIST:
+ username -- the username who the message is sent to.
+ status -- the sent message.
+mute -- Mute a user.
+ Valid key symbols in ARGS-ALIST:
+ user-id -- the user-id that will be muted.
+ username -- the username who will be muted.
+ This command requires either of the above key. If both are given, `user-id'
+ will be used in REST API.
+unmute -- Un-mute a user.
+ Valid key symbols in ARGS-ALIST:
+ user-id -- the user-id that will be un-muted.
+ username -- the username who will be un-muted.
+ This command requires either of the above key. If both are given, `user-id'
+ will be used in REST API.
+block -- Block a user.
+ Valid key symbols in ARGS-ALIST:
+ user-id -- the user-id that will be blocked.
+ username -- the username who will be blocked.
+ This command requires either of the above key. If both are given, `user-id'
+ will be used in REST API.
+block-and-report-as-spammer -- Block a user and report him or her as a spammer.
+ Valid key symbols in ARGS-ALIST:
+ user-id -- the user-id that will be blocked.
+ username -- the username who will be blocked.
+ This command requires either of the above key. If both are given, `user-id'
+ will be used in REST API.
+get-service-configuration -- Get the configuration of the server.
+ Valid key symbols in ARGS-ALIST:
+ sentinel -- the sentinel that processes retrieved strings. This is used
+ as an argument SENTINEL of `twittering-send-http-request'.
+ clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
+ the buffer associated to the process. This is used as an argument
+ CLEAN-UP-SENTINEL of `twittering-send-http-request'."
+ (let* ((additional-info
+ `(,@additional-info
+ (service-method . ,twittering-service-method))))
+ (cond
+ ((memq twittering-service-method '(twitter statusnet))
+ (twittering-call-api-with-account-in-api1.0
+ account-info-alist command args-alist additional-info))
+ ((eq twittering-service-method 'twitter-api-v1.1)
+ (cond
+ ((not (require 'json nil t))
+ (error "`json.el' is required to use the Twitter REST API v1.1")
+ nil)
+ ((not twittering-use-ssl)
+ (error "SSL is required to use the Twitter REST API v1.1")
+ nil)
+ (t
+ (twittering-call-api-with-account-in-api1.1
+ account-info-alist command args-alist additional-info))))
+ (t
+ (error "`twittering-service-method' is an invalid service method")
+ ))))
+
+(defun twittering-call-api-with-account-in-api1.0 (account-info-alist command args-alist &optional additional-info)
+ "Call the Twitter REST API v1.0 and return the process object for the request."
+ (cond
+ ((eq command 'retrieve-timeline)
+ ;; Retrieve a timeline.
+ (let* ((spec (cdr (assq 'timeline-spec args-alist)))
+ (spec-string (cdr (assq 'timeline-spec-string args-alist)))
+ (spec-type (car-safe spec))
+ (max-number (if (eq 'search spec-type)
+ 100 ;; FIXME: refer to defconst.
+ twittering-max-number-of-tweets-on-retrieval))
+ (number
+ (let ((number
+ (or (cdr (assq 'number args-alist))
+ (let* ((default-number 20)
+ (n twittering-number-of-tweets-on-retrieval))
+ (cond
+ ((integerp n) n)
+ ((string-match "^[0-9]+$" n) (string-to-number n 10))
+ (t default-number))))))
+ (min (max 1 number) max-number)))
+ (number-str (number-to-string number))
+ (max_id (cdr (assq 'max_id args-alist)))
+ (page (cdr (assq 'page args-alist)))
+ (since_id (cdr (assq 'since_id args-alist)))
+ (word (when (eq 'search spec-type)
+ (cadr spec)))
+ (parameters
+ (cond
+ ((eq spec-type 'favorites)
+ `(("include_entities" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ,@(when page `(("page" . ,page)))))
+ ((eq spec-type 'retweeted_by_user)
+ (let ((username (elt spec 1)))
+ `(("count" . ,number-str)
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ("include_entities" . "true")
+ ("screen_name" . ,username)
+ ,@(when since_id `(("since_id" . ,since_id))))))
+ ((eq spec-type 'retweeted_to_user)
+ (let ((username (elt spec 1)))
+ `(("count" . ,number-str)
+ ("include_entities" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ("screen_name" . ,username)
+ ,@(when since_id `(("since_id" . ,since_id))))))
+ (t
+ `(,@(when max_id `(("max_id" . ,max_id)))
+ ,@(when since_id `(("since_id" . ,since_id)))
+ ,@(cond
+ ((eq spec-type 'search)
+ `(("include_entities" . "true")
+ ("q" . ,word)
+ ("rpp" . ,number-str)
+ ("with_twitter_user_id". "true")))
+ ((eq spec-type 'list)
+ (let ((username (elt spec 1))
+ (list-name (elt spec 2)))
+ `(("include_entities" . "true")
+ ("include_rts" . "true")
+ ("owner_screen_name" . ,username)
+ ("per_page" . ,number-str)
+ ("slug" . ,list-name))))
+ ((eq spec-type 'user)
+ (let ((username (elt spec 1)))
+ `(("count" . ,number-str)
+ ("include_entities" . "true")
+ ("include_rts" . "true")
+ ("screen_name" . ,username))))
+ ((memq spec-type '(friends mentions public))
+ `(("include_entities" . "true")
+ ("count" . ,number-str)
+ ("include_rts" . "true")))
+ (t
+ ;; direct_messages
+ ;; direct_messages_sent
+ ;; home
+ ;; replies
+ ;; retweeted_by_me
+ ;; retweeted_to_me
+ ;; retweets_of_me
+ `(("include_entities" . "true")
+ ("count" . ,number-str))))))))
+ (format
+ (let ((format (cdr (assq 'format args-alist))))
+ (cond
+ ((and format (symbolp format))
+ format)
+ ((eq spec-type 'search)
+ 'atom)
+ (t
+ 'xml))))
+ (format-str (symbol-name format))
+ (simple-spec-list
+ '((direct_messages . "direct_messages")
+ (direct_messages_sent . "direct_messages/sent")
+ (friends . "statuses/friends_timeline")
+ (home . "statuses/home_timeline")
+ (mentions . "statuses/mentions")
+ (public . "statuses/public_timeline")
+ (replies . "statuses/replies")
+ (retweeted_by_me . "statuses/retweeted_by_me")
+ (retweeted_to_me . "statuses/retweeted_to_me")
+ (retweets_of_me . "statuses/retweets_of_me")
+ (user . "statuses/user_timeline")))
+ (host (cond ((eq spec-type 'search) twittering-api-search-host)
+ (t twittering-api-host)))
+ (method
+ (cond
+ ((eq spec-type 'list)
+ (twittering-api-path "lists/statuses"))
+ ((eq spec-type 'favorites)
+ (let ((user (elt spec 1)))
+ (if user
+ (twittering-api-path "favorites/" user)
+ (twittering-api-path "favorites"))))
+ ((eq spec-type 'retweeted_by_user)
+ (twittering-api-path "statuses/retweeted_by_user"))
+ ((eq spec-type 'retweeted_to_user)
+ (twittering-api-path "statuses/retweeted_to_user"))
+ ((eq spec-type 'search)
+ twittering-search-api-method)
+ ((assq spec-type simple-spec-list)
+ (twittering-api-path (cdr (assq spec-type simple-spec-list))))
+ (t nil)))
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist)))
+ (additional-info `(,@additional-info (format . ,format))))
+ (cond
+ ((eq spec-type 'single)
+ (let ((id (cadr spec))
+ (sentinel (or sentinel
+ 'twittering-retrieve-single-tweet-sentinel)))
+ (if (twittering-find-status id)
+ ;; If the status has already retrieved, do nothing.
+ nil
+ (twittering-call-api 'retrieve-single-tweet
+ `((id . ,id)
+ (format . ,format)
+ (sentinel . ,sentinel)
+ (clean-up-sentinel . ,clean-up-sentinel))
+ additional-info))))
+ ((and host method)
+ (twittering-http-get account-info-alist host method parameters
+ format-str
+ additional-info sentinel clean-up-sentinel))
+ (t
+ (error "Invalid timeline spec")))))
+ ((eq command 'retrieve-single-tweet)
+ (let* ((id (cdr (assq 'id args-alist)))
+ (user-screen-name (cdr (assq 'username args-alist)))
+ (format
+ (let ((format (cdr (assq 'format args-alist))))
+ (cond
+ ((and format (symbolp format))
+ format)
+ (t
+ 'xml))))
+ (format-str (symbol-name format))
+ (parameters '(("include_entities" . "true")))
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist)))
+ (additional-info `(,@additional-info
+ (id . ,id)
+ (user-screen-name . ,user-screen-name)
+ (format . ,format))))
+ (twittering-http-get account-info-alist twittering-api-host
+ (twittering-api-path "statuses/show/" id)
+ parameters format-str additional-info
+ sentinel clean-up-sentinel)))
+ ((eq command 'get-list-index)
+ ;; Get list names.
+ (let* ((username (cdr (assq 'username args-alist)))
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (format (if (require 'json nil t) 'json 'xml))
+ (format-str (symbol-name format))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
+ (twittering-http-get account-info-alist twittering-api-host
+ (twittering-api-path username "/lists")
+ nil format-str additional-info
+ sentinel clean-up-sentinel)))
+ ((eq command 'get-list-subscriptions)
+ (let* ((username (cdr (assq 'username args-alist)))
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (format (if (require 'json nil t) 'json 'xml))
+ (format-str (symbol-name format))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
+ (twittering-http-get account-info-alist twittering-api-host
+ (twittering-api-path username "/lists/subscriptions")
+ nil format-str additional-info
+ sentinel clean-up-sentinel)))
+ ((eq command 'create-friendships)
+ ;; Create a friendship.
+ (let ((username (cdr (assq 'username args-alist))))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "friendships/create")
+ `(("screen_name" . ,username))
+ nil additional-info)))
+ ((eq command 'destroy-friendships)
+ ;; Destroy a friendship
+ (let ((username (cdr (assq 'username args-alist))))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "friendships/destroy")
+ `(("screen_name" . ,username))
+ nil additional-info)))
+ ((eq command 'create-favorites)
+ ;; Create a favorite.
+ (let ((id (cdr (assq 'id args-alist))))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "favorites/create/" id)
+ nil nil additional-info)))
+ ((eq command 'destroy-favorites)
+ ;; Destroy a favorite.
+ (let ((id (cdr (assq 'id args-alist))))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "favorites/destroy/" id)
+ nil nil additional-info)))
+ ((eq command 'update-status)
+ ;; Post a tweet.
+ (let* ((status (cdr (assq 'status args-alist)))
+ (id (cdr (assq 'in-reply-to-status-id args-alist)))
+ (parameters
+ `(("status" . ,status)
+ ,@(when (eq twittering-auth-method 'basic)
+ '(("source" . "twmode")))
+ ,@(when id `(("in_reply_to_status_id" . ,id))))))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "statuses/update")
+ parameters nil additional-info)))
+ ((eq command 'destroy-status)
+ ;; Destroy a status.
+ (let* ((id (cdr (assq 'id args-alist)))
+ (format (if (require 'json nil t) 'json 'xml))
+ (format-str (symbol-name format)))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "statuses/destroy/" id)
+ nil format-str additional-info
+ 'twittering-http-post-destroy-status-sentinel)))
+ ((eq command 'retweet)
+ ;; Post a retweet.
+ (let ((id (cdr (assq 'id args-alist))))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "statuses/retweet/" id)
+ nil nil additional-info)))
+ ((eq command 'verify-credentials)
+ ;; Verify the account.
+ (let ((sentinel (cdr (assq 'sentinel args-alist)))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
+ (twittering-http-get account-info-alist twittering-api-host
+ (twittering-api-path "account/verify_credentials")
+ nil nil additional-info
+ sentinel clean-up-sentinel)))
+ ((eq command 'send-direct-message)
+ ;; Send a direct message.
+ (let ((parameters
+ `(("screen_name" . ,(cdr (assq 'username args-alist)))
+ ("text" . ,(cdr (assq 'status args-alist))))))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "direct_messages/new")
+ parameters nil additional-info)))
+ ((eq command 'block)
+ ;; Block a user.
+ (let* ((user-id (cdr (assq 'user-id args-alist)))
+ (username (cdr (assq 'username args-alist)))
+ (parameters (if user-id
+ `(("user_id" . ,user-id))
+ `(("screen_name" . ,username)))))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "blocks/create")
+ parameters nil additional-info)))
+ ((eq command 'block-and-report-as-spammer)
+ ;; Report a user as a spammer and block him or her.
+ (let* ((user-id (cdr (assq 'user-id args-alist)))
+ (username (cdr (assq 'username args-alist)))
+ (parameters (if user-id
+ `(("user_id" . ,user-id))
+ `(("screen_name" . ,username)))))
+ (twittering-http-post account-info-alist twittering-api-host
+ (twittering-api-path "report_spam")
+ parameters nil additional-info)))
+ ((eq command 'get-service-configuration)
+ (let* ((format (if (require 'json nil t) 'json 'xml))
+ (format-str (symbol-name format))
+ (request
+ (twittering-make-http-request-from-uri
+ "GET" nil
+ (concat (if twittering-use-ssl
+ "https"
+ "http")
+ "://" twittering-api-host
+ "/"
+ (twittering-api-path "help/configuration." format-str))))
+ (additional-info nil)
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
+ (twittering-send-http-request request additional-info
+ sentinel clean-up-sentinel)))
+ (t
+ nil)))
+
+(defun twittering-call-api-with-account-in-api1.1 (account-info-alist command args-alist &optional additional-info)
+ "Call the Twitter REST API v1.1 and return the process object for the request."
+ (cond
+ ((eq command 'retrieve-timeline)
+ ;; Retrieve a timeline.
+ (let* ((args-alist
+ (let* ((spec (cdr (assq 'timeline-spec args-alist)))
+ (spec-type (car-safe spec))
+ (table '((friends . (home))
+ (replies . (mentions)))))
+ (cond
+ ((memq spec-type '(friends replies))
+ (let* ((alternative (cdr (assq spec-type table)))
+ (alternative-str
+ (twittering-timeline-spec-to-string alternative)))
+ (message
+ "Timeline spec %s is not supported in the Twitter REST API v1.1"
+ spec)
+ `((timeline-spec . ,alternative)
+ (timeline-spec-string . ,alternative-str)
+ ,@args-alist)))
+ (t
+ args-alist))))
+ (spec (cdr (assq 'timeline-spec args-alist)))
+ (spec-string (cdr (assq 'timeline-spec-string args-alist)))
+ (spec-type (car-safe spec))
+ (max-number (if (eq 'search spec-type)
+ 100 ;; FIXME: refer to defconst.
+ twittering-max-number-of-tweets-on-retrieval))
+ (number
+ (let ((number
+ (or (cdr (assq 'number args-alist))
+ (let* ((default-number 20)
+ (n twittering-number-of-tweets-on-retrieval))
+ (cond
+ ((integerp n) n)
+ ((string-match "^[0-9]+$" n) (string-to-number n 10))
+ (t default-number))))))
+ (min (max 1 number) max-number)))
+ (number-str (number-to-string number))
+ (max_id (cdr (assq 'max_id args-alist)))
+ (since_id (cdr (assq 'since_id args-alist)))
+ (word (when (eq 'search spec-type)
+ (cadr spec)))
+ (parameters
+ (cond
+ ((eq spec-type 'user)
+ (let ((username (elt spec 1)))
+ `("api.twitter.com"
+ "1.1/statuses/user_timeline"
+ ("count" . ,number-str)
+ ("include_entities" . "true")
+ ("include_rts" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ("screen_name" . ,username)
+ ,@(when since_id `(("since_id" . ,since_id)))
+ )))
+ ((eq spec-type 'list)
+ (let ((username (elt spec 1))
+ (list-name (elt spec 2)))
+ `("api.twitter.com"
+ "1.1/lists/statuses"
+ ("count" . ,number-str)
+ ("include_entities" . "true")
+ ("include_rts" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ("owner_screen_name" . ,username)
+ ,@(when since_id `(("since_id" . ,since_id)))
+ ("slug" . ,list-name))))
+ ((eq spec-type 'direct_messages)
+ `("api.twitter.com"
+ "1.1/direct_messages"
+ ("count" . ,number-str)
+ ("include_entities" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ,@(when since_id `(("since_id" . ,since_id)))))
+ ((eq spec-type 'direct_messages_sent)
+ `("api.twitter.com"
+ "1.1/direct_messages/sent"
+ ("count" . ,number-str)
+ ("include_entities" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ,@(when since_id `(("since_id" . ,since_id)))))
+ ((eq spec-type 'favorites)
+ (let ((user (elt spec 1)))
+ `("api.twitter.com"
+ "1.1/favorites/list"
+ ("count" . ,number-str)
+ ("include_entities" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ,@(when user `(("screen_name" . ,user)))
+ ,@(when since_id `(("since_id" . ,since_id))))))
+ ((eq spec-type 'home)
+ `("api.twitter.com"
+ "1.1/statuses/home_timeline"
+ ("count" . ,number-str)
+ ("include_entities" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ,@(when since_id `(("since_id" . ,since_id)))))
+ ((eq spec-type 'mentions)
+ `("api.twitter.com"
+ "1.1/statuses/mentions_timeline"
+ ("count" . ,number-str)
+ ("include_entities" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ,@(when since_id `(("since_id" . ,since_id)))))
+ ((eq spec-type 'public)
+ (error
+ "Timeline spec %s is not supported in the Twitter REST API v1.1"
+ spec)
+ nil)
+ ((memq spec-type '(retweeted_by_me
+ retweeted_by_user
+ retweeted_to_me
+ retweeted_to_user))
+ (error
+ "Timeline spec %s is not supported in the Twitter REST API v1.1"
+ spec)
+ nil)
+ ((eq spec-type 'retweets_of_me)
+ `("api.twitter.com"
+ "1.1/statuses/retweets_of_me"
+ ("count" . ,number-str)
+ ("include_entities" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ,@(when since_id `(("since_id" . ,since_id)))))
+ ((eq spec-type 'single)
+ (let ((id (elt spec 1)))
+ `("api.twitter.com"
+ "1.1/statuses/show"
+ ("id" . ,id)
+ ("include_entities" . "true"))))
+ ((eq spec-type 'search)
+ (let ((word (elt spec 1)))
+ `("api.twitter.com"
+ "1.1/search/tweets"
+ ("count" . ,number-str)
+ ("include_entities" . "true")
+ ,@(when max_id `(("max_id" . ,max_id)))
+ ("q" . ,word)
+ ("result_type" . "recent")
+ ,@(when since_id `(("since_id" . ,since_id))))))
+ (t
+ (error
+ "Timeline spec %s is unknown"
+ spec-string)
+ nil)))
+ (format 'json)
+ (format-str (symbol-name format))
+ (host (elt parameters 0))
+ (method (elt parameters 1))
+ (http-parameters (nthcdr 2 parameters))
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist)))
+ (additional-info `(,@additional-info (format . ,format)))
+ ;; special treatment for single timeline.
+ (id (cdr (assoc "id" http-parameters)))
+ (sentinel (or sentinel
+ (when (eq spec-type 'single)
+ 'twittering-retrieve-single-tweet-sentinel))))
+ (cond
+ ((null parameters)
+ nil)
+ ((not (and (string= format-str "json")
+ (require 'json nil t)))
+ (error "The Twitter REST API v1.1 supports only JSON")
+ nil)
+ ((and (eq spec-type 'single)
+ (twittering-find-status id))
+ ;; If the status has already retrieved, do nothing.
+ nil)
+ ((and host method)
+ (twittering-http-get account-info-alist host method http-parameters
+ format-str
+ additional-info sentinel clean-up-sentinel))
+ (t
+ (error "Invalid timeline spec")
+ nil))))
+ ((eq command 'retrieve-single-tweet)
+ (let* ((id (cdr (assq 'id args-alist)))
+ (user-screen-name (cdr (assq 'username args-alist)))
+ (format
+ (let ((format (cdr (assq 'format args-alist))))
+ (cond
+ ((and format (symbolp format))
+ format)
+ (t
+ 'json))))
+ (format-str (symbol-name format))
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist)))
+ (additional-info `(,@additional-info
+ (id . ,id)
+ (user-screen-name . ,user-screen-name)
+ (format . ,format))))
+ (twittering-call-api-with-account-in-api1.1
+ account-info-alist 'retrieve-timeline
+ `((timeline-spec . (single ,id))
+ (format . ,format)
+ (sentinel . ,sentinel)
+ (clean-up-sentinel . ,clean-up-sentinel))
+ additional-info)))
+ ((eq command 'get-list-index)
+ ;; Get list names.
+ (let* ((username (cdr (assq 'username args-alist)))
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (host "api.twitter.com")
+ (method "1.1/lists/list")
+ (http-parameters `(("screen_name" . ,username)))
+ (format-str "json")
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
+ (twittering-http-get account-info-alist host method http-parameters
+ format-str additional-info
+ sentinel clean-up-sentinel)))
+ ((eq command 'get-list-subscriptions)
+ (let* ((username (cdr (assq 'username args-alist)))
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (host "api.twitter.com")
+ (method "1.1/lists/subscriptions")
+ (http-parameters
+ `(("count" . "20")
+ ("screen_name" . ,username)))
+ (format-str "json")
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
+ (twittering-http-get account-info-alist host method http-parameters
+ format-str additional-info
+ sentinel clean-up-sentinel)))
+ ((eq command 'create-friendships)
+ ;; Create a friendship.
+ (let* ((username (cdr (assq 'username args-alist)))
+ (host "api.twitter.com")
+ (method "1.1/friendships/create")
+ (http-parameters
+ `(("screen_name" . ,username)))
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((eq command 'destroy-friendships)
+ ;; Destroy a friendship
+ (let* ((username (cdr (assq 'username args-alist)))
+ (host "api.twitter.com")
+ (method "1.1/friendships/destroy")
+ (http-parameters
+ `(("screen_name" . ,username)))
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((eq command 'create-favorites)
+ ;; Create a favorite.
+ (let* ((id (cdr (assq 'id args-alist)))
+ (host "api.twitter.com")
+ (method "1.1/favorites/create")
+ (http-parameters `(("id" . ,id)))
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((eq command 'destroy-favorites)
+ ;; Destroy a favorite.
+ (let* ((id (cdr (assq 'id args-alist)))
+ (host "api.twitter.com")
+ (method "1.1/favorites/destroy")
+ (http-parameters `(("id" . ,id)))
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((eq command 'update-status)
+ ;; Post a tweet.
+ (let* ((status (cdr (assq 'status args-alist)))
+ (id (cdr (assq 'in-reply-to-status-id args-alist)))
+ (host "api.twitter.com")
+ (method "1.1/statuses/update")
+ (http-parameters
+ `(("status" . ,status)
+ ,@(when id `(("in_reply_to_status_id" . ,id)))))
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((eq command 'destroy-status)
+ ;; Destroy a status.
+ (let* ((id (cdr (assq 'id args-alist)))
+ (host "api.twitter.com")
+ (method (format "1.1/statuses/destroy/%s" id))
+ (http-parameters nil)
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info
+ 'twittering-http-post-destroy-status-sentinel)))
+ ((eq command 'retweet)
+ ;; Post a retweet.
+ (let* ((id (cdr (assq 'id args-alist)))
+ (host "api.twitter.com")
+ (method (format "1.1/statuses/retweet/%s" id))
+ (http-parameters nil)
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((eq command 'verify-credentials)
+ ;; Verify the account.
+ (let* ((host "api.twitter.com")
+ (method "1.1/account/verify_credentials")
+ (http-parameters nil)
+ (format-str "json")
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
+ (twittering-http-get account-info-alist host method http-parameters
+ format-str additional-info
+ sentinel clean-up-sentinel)))
+ ((eq command 'send-direct-message)
+ ;; Send a direct message.
+ (let* ((host "api.twitter.com")
+ (method "1.1/direct_messages/new")
+ (http-parameters
+ `(("screen_name" . ,(cdr (assq 'username args-alist)))
+ ("text" . ,(cdr (assq 'status args-alist)))))
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((memq command '(mute unmute))
+ ;; Mute a user.
+ (let* ((user-id (cdr (assq 'user-id args-alist)))
+ (username (cdr (assq 'username args-alist)))
+ (host "api.twitter.com")
+ (method
+ (cdr (assq command '((mute . "1.1/mutes/users/create")
+ (unmute . "1.1/mutes/users/destroy")))))
+ (http-parameters (if user-id
+ `(("user_id" . ,user-id))
+ `(("screen_name" . ,username))))
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((eq command 'block)
+ ;; Block a user.
+ (let* ((user-id (cdr (assq 'user-id args-alist)))
+ (username (cdr (assq 'username args-alist)))
+ (host "api.twitter.com")
+ (method "1.1/blocks/create")
+ (http-parameters (if user-id
+ `(("user_id" . ,user-id))
+ `(("screen_name" . ,username))))
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((eq command 'block-and-report-as-spammer)
+ ;; Report a user as a spammer and block him or her.
+ (let* ((user-id (cdr (assq 'user-id args-alist)))
+ (username (cdr (assq 'username args-alist)))
+ (host "api.twitter.com")
+ (method "1.1/users/report_spam")
+ (http-parameters (if user-id
+ `(("user_id" . ,user-id))
+ `(("screen_name" . ,username))))
+ (format-str "json"))
+ (twittering-http-post account-info-alist host method http-parameters
+ format-str additional-info)))
+ ((eq command 'get-service-configuration)
+ (let* ((host "api.twitter.com")
+ (method "1.1/help/configuration")
+ (http-parameters nil)
+ (format-str "json")
+ (additional-info nil)
+ (sentinel (cdr (assq 'sentinel args-alist)))
+ (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
+ (twittering-http-get account-info-alist host method http-parameters
+ format-str additional-info
+ sentinel clean-up-sentinel)))
+ (t
+ nil)))
+
+;;;;
+;;;; Service configuration
+;;;;
+
+(defconst twittering-service-configuration-default
+ '((short_url_length . 19)
+ (short_url_length_https . 20))
+ "Default value of `twittering-service-configuration'.")
+(defvar twittering-service-configuration nil
+ "Current server configuration.")
+(defvar twittering-service-configuration-queried nil)
+(defvar twittering-service-configuration-update-interval 86400
+ "*Interval of updating `twittering-service-configuration'.")
+
+(defun twittering-get-service-configuration (entry)
+ (let ((pair (assq entry twittering-service-configuration)))
+ (if (null pair)
+ (cdr (assq entry twittering-service-configuration-default))
+ (cdr pair))))
+
+(defun twittering-update-service-configuration (&optional ignore-time)
+ "Update `twittering-service-configuration' if necessary."
+ (when (and
+ (memq twittering-service-method '(twitter twitter-api-v1.1))
+ (null twittering-service-configuration-queried)
+ (or ignore-time
+ (let ((current (twittering-get-service-configuration 'time))
+ (interval
+ (seconds-to-time
+ twittering-service-configuration-update-interval)))
+ (if (null current)
+ t
+ ;; If time passed more than `interval',
+ ;; update the configuration.
+ (time-less-p interval (time-since current))))))
+ (setq twittering-service-configuration-queried t)
+ (twittering-call-api
+ 'get-service-configuration
+ '((sentinel . twittering-update-service-configuration-sentinel)
+ (clean-up-sentinel
+ . twittering-update-service-configuration-clean-up-sentinel)))))
+
+(defun twittering-update-service-configuration-sentinel (proc status connection-info header-info)
+ (let ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info)))
+ (format
+ (twittering-get-content-subtype-symbol-from-header-info header-info)))
+ (case-string
+ status-code
+ (("200")
+ (let* ((conf-alist
+ (cond
+ ((eq format 'xml)
+ (let ((xml
+ (twittering-xml-parse-region (point-min) (point-max))))
+ (mapcar
+ (lambda (entry)
+ `(,(car entry) . ,(elt entry 2)))
+ (cddr (assq 'configuration xml)))))
+ ((eq format 'json)
+ (twittering-json-read))
+ (t
+ (error "Format \"%s\" is not supported" format)
+ nil)))
+ (entries '(short_url_length short_url_length_https)))
+ (setq twittering-service-configuration
+ `((time . ,(current-time))
+ ,@(mapcar (lambda (entry)
+ (let ((value (cdr (assq entry conf-alist))))
+ (cons
+ entry
+ (cond
+ ((stringp value)
+ (string-to-number value))
+ (t
+ value)))))
+ entries)))
+ (setq twittering-service-configuration-queried nil)
+ nil))
+ (("400")
+ ;; Rate limit exceeded.
+ (setq twittering-service-configuration-queried nil)
+ (format "Response: %s"
+ (twittering-get-error-message header-info connection-info)))
+ (t
+ (setq twittering-service-configuration-queried nil)
+ (format "Response: %s"
+ (twittering-get-error-message header-info connection-info))))))
+
+(defun twittering-update-service-configuration-clean-up-sentinel (proc status connection-info)
+ (when (not (twittering-process-alive-p proc))
+ (setq twittering-service-configuration-queried nil)))
+
+;;;;
+;;;; Account authorization
+;;;;
+
+(defun twittering-register-account-info (account-info)
+ (setq twittering-oauth-access-token-alist account-info))
+
+(defun twittering-get-main-account-info ()
+ (cond
+ ((eq twittering-auth-method 'basic)
+ `(("screen_name" . ,twittering-username)
+ ("password" . ,twittering-password)))
+ ((memq twittering-auth-method '(oauth xauth))
+ twittering-oauth-access-token-alist)))
+
+(defun twittering-get-from-account-info (param account-info)
+ (cdr (assoc param account-info)))
+
+(defun twittering-get-username ()
+ (let ((account-info (twittering-get-main-account-info)))
+ (twittering-get-from-account-info "screen_name" account-info)))
+
+(defun twittering-get-password ()
+ (let ((account-info (twittering-get-main-account-info)))
+ (twittering-get-from-account-info "password" account-info)))
+
+(defun twittering-make-basic-authentication-string (account-info)
+ (concat "Basic "
+ (base64-encode-string
+ (concat (cdr (assoc "screen_name" account-info))
+ ":" (cdr (assoc "password" account-info))))))
+
+(defun twittering-make-oauth-authentication-string (account-info request)
+ (let ((method (cdr (assq 'method request)))
+ (access-token (cdr (assoc "oauth_token" account-info)))
+ (access-token-secret (cdr (assoc "oauth_token_secret" account-info))))
+ (unless (and (stringp access-token)
+ (stringp access-token-secret))
+ (error "`account-info' has no valid OAuth token"))
+ (twittering-oauth-auth-str-access
+ method
+ (cdr (assq 'uri-without-query request))
+ (cdr (assq 'encoded-query-alist request))
+ twittering-oauth-consumer-key twittering-oauth-consumer-secret
+ access-token access-token-secret)))
+
+(defun twittering-account-authorized-p ()
+ (eq twittering-account-authorization 'authorized))
+(defun twittering-account-authorization-queried-p ()
+ (eq twittering-account-authorization 'queried))
+
+(defun twittering-prepare-account-info ()
+ "Return a pair of username and password.
+If `twittering-username' is nil, read it from the minibuffer.
+If `twittering-password' is nil, read it from the minibuffer."
+ (let* ((username (or twittering-username
+ (read-string "your twitter username: ")))
+ (password (or twittering-password
+ (read-passwd (format "%s's twitter password: "
+ username)))))
+ `(,username . ,password)))
+
+(defun twittering-has-oauth-access-token-p ()
+ (let* ((required-entries '("oauth_token"
+ "oauth_token_secret"
+ "user_id"
+ "screen_name"))
+ (value-list
+ (mapcar
+ (lambda (key)
+ (cdr (assoc key twittering-oauth-access-token-alist)))
+ required-entries)))
+ (null (remove t (mapcar 'stringp value-list)))))
+
+(defun twittering-verify-credentials ()
+ "Verify the account.
+
+This function is an internal function, which should be called from
+`twittering-ensure-account-verification'.
+
+If the account has been authorized already, return t.
+Otherwise, this function tries to authorize the account.
+If the authorization succeeded, return t.
+If the authorization failed, return nil."
+ (cond
+ ((twittering-account-authorized-p)
+ ;; The account has been authorized already.
+ t)
+ ((not (twittering-account-authorization-queried-p))
+ ;; This function must be invoked from
+ ;; `twittering-ensure-account-verification', which updates the variable
+ ;; `twittering-account-authorization' into the symbol `queried'.
+ (error "`twittering-verify-credentials' is invoked multiple times.")
+ nil)
+ ((and (memq twittering-auth-method '(oauth xauth))
+ (or (null twittering-oauth-consumer-key)
+ (null twittering-oauth-consumer-secret)))
+ (message "Consumer for OAuth is not specified.")
+ nil)
+ ((twittering-has-oauth-access-token-p)
+ (let* ((username (cdr (assoc "screen_name"
+ (twittering-get-main-account-info))))
+ (proc
+ (twittering-call-api-with-account
+ (twittering-get-main-account-info)
+ 'verify-credentials
+ `((sentinel
+ . twittering-http-get-verify-credentials-sentinel)
+ (clean-up-sentinel
+ . twittering-http-get-verify-credentials-clean-up-sentinel)))))
+ (cond
+ ((null proc)
+ (message "Process invocation for authorizing \"%s\" failed." username)
+ ;; Failed to authorize the account.
+ nil)
+ (t
+ ;; wait for verification to finish.
+ (twittering-wait-while nil 0.1
+ (and
+ (twittering-account-authorization-queried-p)
+ (twittering-process-alive-p proc)))
+ (if (not (twittering-account-authorization-queried-p))
+ ;; The query is completed.
+ (twittering-account-authorized-p)
+ ;; If the process has been dead, wait a moment because
+ ;; Emacs may be in the middle of evaluating the sentinel.
+ (twittering-wait-while
+ 10 0.1
+ (twittering-account-authorization-queried-p)
+ ;; Succeeded in authorizing the account.
+ t
+ ;; Display a message.
+ (message
+ "Status of Authorization process is `%s'. Type M-x twit to retry."
+ (process-status proc))
+ ;; Failed to authorize the account.
+ nil))))))
+ ((eq twittering-auth-method 'oauth)
+ (let* ((scheme (if twittering-oauth-use-ssl
+ "https"
+ "http"))
+ (request-token-url
+ (concat scheme twittering-oauth-request-token-url-without-scheme))
+ (access-token-url
+ (concat scheme twittering-oauth-access-token-url-without-scheme))
+ (token-alist
+ (twittering-oauth-get-access-token
+ request-token-url
+ (lambda (token)
+ (concat scheme
+ twittering-oauth-authorization-url-base-without-scheme
+ token))
+ access-token-url
+ twittering-oauth-consumer-key twittering-oauth-consumer-secret
+ "twittering-mode")))
+ (cond
+ ((and (assoc "oauth_token" token-alist)
+ (assoc "oauth_token_secret" token-alist)
+ (assoc "screen_name" token-alist))
+ (let ((username (cdr (assoc "screen_name" token-alist))))
+ (twittering-register-account-info token-alist)
+ (message "Authorization for the account \"%s\" succeeded."
+ username)
+ (when (and twittering-use-master-password
+ (twittering-capable-of-encryption-p)
+ (not (file-exists-p twittering-private-info-file)))
+ (twittering-save-private-info-with-guide))
+ ;; Succeeded in authorizing the account.
+ t))
+ (t
+ ;; There is no global account info that should be invalidated.
+ ;; Failed to authorize the account.
+ (message "Authorization via OAuth failed. Type M-x twit to retry.")
+ nil))))
+ ((eq twittering-auth-method 'xauth)
+ (let* ((account-info (twittering-prepare-account-info))
+ (scheme (if twittering-oauth-use-ssl
+ "https"
+ "http"))
+ (access-token-url
+ (concat scheme twittering-oauth-access-token-url-without-scheme))
+ (token-alist
+ (twittering-xauth-get-access-token
+ access-token-url
+ twittering-oauth-consumer-key twittering-oauth-consumer-secret
+ (car account-info)
+ (cdr account-info))))
+ ;; Dispose of password as recommended by Twitter.
+ ;; http://dev.twitter.com/pages/xauth
+ (setcdr account-info nil)
+ (cond
+ ((and token-alist
+ (assoc "oauth_token" token-alist)
+ (assoc "oauth_token_secret" token-alist))
+ (twittering-register-account-info token-alist)
+ (message "Authorization for the account \"%s\" succeeded."
+ (twittering-get-username))
+ (when (and twittering-use-master-password
+ (twittering-capable-of-encryption-p)
+ (not (file-exists-p twittering-private-info-file)))
+ (twittering-save-private-info-with-guide))
+ ;; Succeeded in authorizing the account.
+ t)
+ (t
+ ;; Failed to authorize the account.
+ (message "Authorization via xAuth failed. Type M-x twit to retry.")
+ nil))))
+ ((eq twittering-auth-method 'basic)
+ (let* ((account-info
+ (let ((pair (twittering-prepare-account-info)))
+ `(("screen_name" . ,(car pair))
+ ("password" . ,(cdr pair)))))
+ ;; Bind account information locally to ensure that
+ ;; the variables are reset when the verification fails.
+ (twittering-username (car account-info))
+ (twittering-password (cdr account-info))
+ (proc
+ (twittering-call-api-with-account
+ account-info
+ 'verify-credentials
+ `((sentinel . twittering-http-get-verify-credentials-sentinel)
+ (clean-up-sentinel
+ . twittering-http-get-verify-credentials-clean-up-sentinel)))))
+ (cond
+ ((null proc)
+ (message "Process invocation for authorizing \"%s\" failed."
+ (twittering-get-from-account-info "screen_name" account-info))
+ ;; Failed to authorize the account.
+ nil)
+ (t
+ ;; wait for verification to finish.
+ (twittering-wait-while nil 0.1
+ (and
+ (twittering-account-authorization-queried-p)
+ (twittering-process-alive-p proc)))
+ (if (not (twittering-account-authorization-queried-p))
+ ;; The query is finished.
+ (twittering-account-authorized-p)
+ ;; If the process has been dead, wait a moment because
+ ;; Emacs may be in the middle of evaluating the sentinel.
+ (twittering-wait-while
+ 10 0.1
+ (twittering-account-authorization-queried-p)
+ ;; Succeeded in authorizing the account.
+ t
+ ;; Display a message.
+ (message
+ "Status of Authorization process is `%s'. Type M-x twit to retry."
+ (process-status proc))
+ ;; Failed to authorize the account.
+ nil))))))
+ (t
+ (message "%s is invalid as an authorization method."
+ twittering-auth-method)
+ nil)))
+
+(defun twittering-http-get-verify-credentials-sentinel (proc status connection-info header-info)
+ (let* ((status-line (cdr (assq 'status-line header-info)))
+ (status-code (cdr (assq 'status-code header-info)))
+ (account-info (cdr (assq 'account-info connection-info)))
+ (username
+ (twittering-get-from-account-info "screen_name" account-info))
+ (password
+ (twittering-get-from-account-info "password" account-info)))
+ (case-string
+ status-code
+ (("200")
+ (twittering-register-account-info account-info)
+ (setq twittering-account-authorization 'authorized)
+ (message "Authorization for the account \"%s\" succeeded." username)
+ nil)
+ (("401")
+ (setq twittering-account-authorization nil)
+ (let ((error-mes
+ (format "Authorization for the account \"%s\" failed. Type M-x twit to retry with correct information."
+ username)))
+ ;; Invalidate the account info.
+ (twittering-register-account-info nil)
+ (message "%s" error-mes)
+ nil))
+ (t
+ (setq twittering-account-authorization nil)
+ (let ((error-mes
+ (format "Authorization for the account \"%s\" failed due to \"%s\"."
+ username status-line)))
+ (message "%s" error-mes)
+ nil)))))
+
+(defun twittering-http-get-verify-credentials-clean-up-sentinel (proc status connection-info)
+ (when (and (memq status '(exit signal closed failed))
+ (eq twittering-account-authorization 'queried))
+ (setq twittering-account-authorization nil)
+ (let ((exit-status (cond
+ ((processp proc) (process-exit-status proc))
+ (t 0)))
+ (command (process-command proc)))
+ (if (= 0 exit-status)
+ (message "Authorization failed. Type M-x twit to retry.")
+ (message "Authorization failed: %s exited abnormally (exit-status=%s)."
+ (car command) exit-status)))
+ (setq twittering-username nil)
+ (setq twittering-password nil)))
+
+(defun twittering-ensure-account-verification ()
+ "Ensure verification of an account.
+
+If an account has been already authorized, return t.
+If a query of authorization is being processed, return nil.
+
+Otherwise, this function tries to authorize an account by calling
+`twittering-verify-credentials'.
+If the authorization succeeded, return t.
+If the authorization failed, return nil."
+ (cond
+ ((twittering-account-authorized-p)
+ ;; The account has been already authorized.
+ t)
+ ((twittering-account-authorization-queried-p)
+ ;; The account has not been authorized yet.
+ nil)
+ (t
+ (setq twittering-account-authorization 'queried)
+ (let ((result nil))
+ (unwind-protect
+ (setq result (twittering-verify-credentials))
+ (if result
+ (setq twittering-account-authorization 'authorized)
+ (setq twittering-account-authorization nil)))
+ result))))
+
+;;;;
+;;;; Status retrieval
+;;;;
+
+(defun twittering-add-timeline-history (spec-string)
+ (when (or (null twittering-timeline-history)
+ (not (string= spec-string (car twittering-timeline-history))))
+ (twittering-add-to-history 'twittering-timeline-history spec-string))
+ (let ((spec (twittering-string-to-timeline-spec spec-string)))
+ (when (and (twittering-timeline-spec-is-user-p spec)
+ (or (null twittering-user-history)
+ (not (string= spec-string (car twittering-user-history)))))
+ (twittering-add-to-history 'twittering-user-history (cadr spec)))))
+
+(defun twittering-remove-timeline-spec-string-from-history (spec-string)
+ (setq twittering-timeline-history
+ (remove nil
+ (mapcar
+ (lambda (str)
+ (if (twittering-equal-string-as-timeline spec-string str)
+ nil
+ str))
+ twittering-timeline-history))))
+
+(defun twittering-make-alist-of-forbidden-tweet (id &optional user-screen-name)
+ (let ((created-at
+ (or
+ (twittering-id-to-time id)
+ (apply 'encode-time
+ (parse-time-string "Jan 01 00:00:00 +0000 2012")))))
+ `((forbidden . t)
+ (id . ,id)
+ (created-at . ,created-at)
+ (user-name . nil)
+ (user-screen-name . ,user-screen-name)
+ (text . "SORRY, YOU ARE NOT AUTHORIZED TO SEE THIS TWEET.")
+ )))
+
+(defun twittering-make-alist-of-non-existent-tweet (id &optional user-screen-name)
+ (let ((created-at
+ (or
+ (twittering-id-to-time id)
+ (apply 'encode-time
+ (parse-time-string "Jan 01 00:00:00 +0000 2012")))))
+ `((forbidden . t)
+ (id . ,id)
+ (created-at . ,created-at)
+ (user-name . nil)
+ (user-screen-name . ,user-screen-name)
+ (text . ,(format "THE TWEET WITH ID %s DOES NOT EXIST." id))
+ )))
+
+(defun twittering-atom-xmltree-to-status-datum (atom-xml-entry)
+ (let* ((id-str (car (cddr (assq 'id atom-xml-entry))))
+ (time-str (car (cddr (assq 'updated atom-xml-entry))))
+ (author-str (car (cddr (assq 'name (assq 'author atom-xml-entry)))))
+ (formatted-time-str
+ ;; ISO 8601
+ ;; Twitter -> "2010-05-08T05:59:41Z"
+ ;; StatusNet -> "2010-05-08T08:44:39+00:00"
+ (cond
+ ((string-match
+ "\\(.*\\)T\\(.*\\)\\(Z\\|\\([-+][0-2][0-9]\\):?\\([0-5][0-9]\\)\\)"
+ time-str)
+ ;; time-str is formatted as
+ ;; "Combined date and time in UTC:" in ISO 8601.
+ (let ((timezone (match-string 3 time-str)))
+ (format "%s %s %s"
+ (match-string 1 time-str) (match-string 2 time-str)
+ (if (string= "Z" timezone)
+ "+0000"
+ (concat (match-string 4 time-str)
+ (match-string 5 time-str))))))
+ (t
+ ;; unknown format?
+ time-str))))
+ `((created-at . ,(date-to-time formatted-time-str))
+ (id . ,(progn
+ (string-match ":\\([0-9]+\\)$" id-str)
+ (match-string 1 id-str)))
+ ,@(let ((source (twittering-decode-html-entities
+ (car (cddr (assq 'twitter:source atom-xml-entry))))))
+ `(,@(if (string-match "<a href=\"\\(.*?\\)\".*?>\\(.*\\)</a>"
+ source)
+ (let ((uri (match-string-no-properties 1 source))
+ (caption (match-string-no-properties 2 source)))
+ `((source . ,caption)
+ (source-uri . ,uri)))
+ `((source . ,source)
+ (source-uri . "")))))
+ (text . ,(twittering-decode-html-entities
+ (car (cddr (assq 'title atom-xml-entry)))))
+ ,@(cond
+ ((and (eq twittering-service-method 'statusnet)
+ (string-match "^\\([^ ]+\\)\\( (\\(.*\\))\\)?$" author-str))
+ ;; StatusNet
+ `((user-screen-name . ,(match-string 1 author-str))
+ (user-name . ,(or (match-string 3 author-str) ""))))
+ ((string-match "^\\([^ ]+\\) (\\(.*\\))$" author-str)
+ ;; Twitter (default)
+ `((user-screen-name . ,(match-string 1 author-str))
+ (user-name . ,(match-string 2 author-str))))
+ (t
+ '((user-screen-name . "PARSING FAILED!!")
+ (user-name . ""))))
+ (user-profile-image-url
+ . ,(let* ((link-items
+ (mapcar
+ (lambda (item)
+ (when (eq 'link (car-safe item))
+ (cadr item)))
+ atom-xml-entry))
+ (image-urls
+ (mapcar
+ (lambda (item)
+ (cond
+ ((and (eq twittering-service-method 'statusnet)
+ (member '(rel . "related") item))
+ ;; StatusNet
+ (cdr (assq 'href item)))
+ ((member '(rel . "image") item)
+ ;; Twitter (default)
+ (cdr (assq 'href item)))
+ (t
+ nil)))
+ link-items)))
+ (car-safe (remq nil image-urls)))))))
+
+(defun twittering-atom-xmltree-to-status (atom-xmltree)
+ (let ((entry-list
+ (apply 'append
+ (mapcar (lambda (x)
+ (if (eq (car-safe x) 'entry) `(,x) nil))
+ (cdar atom-xmltree)))))
+ (mapcar 'twittering-atom-xmltree-to-status-datum
+ entry-list)))
+
+(eval-and-compile
+ (defsubst twittering-make-gap-list (text)
+ "Return a list representing index gaps between TEXT and the decoded and normalized text.
+Indices included in entities in a response from Twitter are calculated
+with the assumption that \"<\" and \">\" are encoded as \"<\" and \">\"
+respectively and a Unicode combining character is considered as a character.
+On rendering a tweet, twittering-mode decode \"<\" and \">\".
+And also twittering-mode normalize its text into canonically equivalent text
+without combining characters.
+Therefore, the indices in entities differ from the indices of the corresponding
+positions in the decoded text.
+In addition, the normalization to NFC also makes additional gaps between
+the indices in entities and the corresponding positions.
+
+This function assumes that TEXT is already decoded but not normalized.
+From TEXT, the function calculates the gaps between the encoded text and the
+decoded and normalized text.
+This function returns a list of pairs representing the gaps.
+For each pair, the car means the position in the original TEXT and the cdr
+means the gap. The (car pair)-th character in the original TEXT corresponds
+to the (- (car pair) (cdr pair))-th character in the decoded and normalized
+text."
+ (let ((result nil)
+ (regexp
+ (if (require 'ucs-normalize nil t)
+ (concat "\\(?:\\([<>]\\)\\|\\("
+ ucs-normalize-combining-chars-regexp "\\)\\)")
+ "\\([<>]\\)"))
+ (pos 0)
+ (gap 0))
+ (while (string-match regexp text pos)
+ (let ((shift (if (match-beginning 1)
+ 3
+ 1)))
+ (setq result
+ (cons `(,(+ gap (match-end 0)) . ,(+ gap shift)) result))
+ (setq gap (+ shift gap)))
+ (setq pos (match-end 0)))
+ (reverse result)))
+
+ (defun twittering-get-gap (pos gap-list)
+ "Return the gap at the specific position.
+GAP-LIST must be generated by `twittering-make-gap-list'."
+ (let ((rest-gaps gap-list)
+ (gap 0))
+ (while (and rest-gaps (< (caar rest-gaps) pos))
+ (setq gap (cdar rest-gaps))
+ (setq rest-gaps (cdr rest-gaps)))
+ gap)))
+
+(defun twittering-normalize-raw-status (raw-status &optional ignore-retweet)
+ (let* ((status-data (cddr raw-status))
+ (raw-retweeted-status (assq 'retweeted_status status-data)))
+ (cond
+ ((and raw-retweeted-status
+ (not ignore-retweet))
+ (let ((retweeted-status
+ (twittering-normalize-raw-status raw-retweeted-status t))
+ (retweeting-status
+ (twittering-normalize-raw-status raw-status t))
+ (items-overwritten-by-retweet
+ '(id)))
+ `(,@(mapcar
+ (lambda (entry)
+ (let ((sym (car entry))
+ (value (cdr entry)))
+ (if (memq sym items-overwritten-by-retweet)
+ (let ((value-on-retweet
+ (cdr (assq sym retweeting-status))))
+ ;; Replace the value in `retweeted-status' with
+ ;; that in `retweeting-status'.
+ `(,sym . ,value-on-retweet))
+ `(,sym . ,value))))
+ retweeted-status)
+ ,@(mapcar
+ (lambda (entry)
+ (let ((sym (car entry))
+ (value (cdr entry)))
+ `(,(intern (concat "retweeted-" (symbol-name sym)))
+ . ,value)))
+ retweeted-status)
+ ,@(mapcar
+ (lambda (entry)
+ (let ((sym (car entry))
+ (value (cdr entry)))
+ `(,(intern (concat "retweeting-" (symbol-name sym)))
+ . ,value)))
+ retweeting-status))))
+ (t
+ (let ((assq-get (lambda (item seq)
+ (car (cddr (assq item seq))))))
+ `(,@(mapcar
+ (lambda (entry)
+ (let* ((sym (elt entry 0))
+ (sym-in-data (elt entry 1))
+ (encoded (elt entry 2))
+ (data (funcall assq-get sym-in-data status-data)))
+ `(,sym . ,(if encoded
+ (twittering-decode-entities-after-parsing-xml
+ data)
+ data))))
+ '(;; Raw entries.
+ (id id)
+ (in-reply-to-screen-name in_reply_to_screen_name)
+ (in-reply-to-status-id in_reply_to_status_id)
+ (recipient-screen-name recipient_screen_name)
+ ;; Encoded entries.
+ (text text t)
+ ))
+ ;; created_at
+ (created-at
+ . ,(date-to-time (funcall assq-get 'created_at status-data)))
+ ;; Replace "true" and "false" into t and nil.
+ ,@(mapcar (lambda (sym)
+ `(,sym . ,(string= "true"
+ (funcall assq-get sym status-data))))
+ '(favorited truncated))
+ ;; Entities.
+ ,(let* ((entity-data (cddr (assq 'entities status-data)))
+ (encoded-text (funcall assq-get 'text status-data))
+ (text
+ (twittering-decode-entities-after-parsing-xml encoded-text))
+ (gap-list (twittering-make-gap-list text)))
+ (list
+ 'entity
+ ;; hashtags
+ (cons
+ 'hashtags
+ (remove nil
+ (mapcar
+ (lambda (entry)
+ (when (and (consp entry)
+ (eq 'hashtag (car entry)))
+ (let* ((data (cdr entry))
+ (start-str (cdr (assq 'start (car data))))
+ (end-str (cdr (assq 'end (car data))))
+ (start (if (stringp start-str)
+ (string-to-number start-str)
+ 0))
+ (end (if (stringp end-str)
+ (string-to-number end-str)
+ 0))
+ (gap (twittering-get-gap start gap-list)))
+ `((start . ,(- start gap))
+ (end . ,(- end gap))
+ (text . ,(elt (assq 'text data) 2))))))
+ (assq 'hashtags entity-data))))
+ ;; mentions
+ (cons
+ 'mentions
+ (remove nil
+ (mapcar
+ (lambda (entry)
+ (when (and (consp entry)
+ (eq 'user_mention (car entry)))
+ (let* ((data (cdr entry))
+ (start-str (cdr (assq 'start (car data))))
+ (end-str (cdr (assq 'end (car data))))
+ (start (if (stringp start-str)
+ (string-to-number start-str)
+ 0))
+ (end (if (stringp end-str)
+ (string-to-number end-str)
+ 0))
+ (gap (twittering-get-gap start gap-list)))
+ `((start . ,(- start gap))
+ (end . ,(- end gap))
+ (id . ,(elt (assq 'id data) 2))
+ (screen-name
+ . ,(elt (assq 'screen_name data) 2))
+ (name
+ . ,(elt (assq 'name data) 2))))))
+ (assq 'user_mentions entity-data))))
+ ;; urls
+ (cons
+ 'urls
+ (remove nil
+ (mapcar
+ (lambda (entry)
+ (when (and (consp entry)
+ (eq 'url (car entry)))
+ (let* ((data (cdr entry))
+ (start-str (cdr (assq 'start (car data))))
+ (end-str (cdr (assq 'end (car data))))
+ (start (if (stringp start-str)
+ (string-to-number start-str)
+ 0))
+ (end (if (stringp end-str)
+ (string-to-number end-str)
+ 0))
+ (gap (twittering-get-gap start gap-list)))
+ `((start . ,(- start gap))
+ (end . ,(- end gap))
+ (url . ,(elt (assq 'url data) 2))
+ (display-url
+ . ,(elt (assq 'display_url data) 2))
+ (expanded-url
+ . ,(elt (assq 'expanded_url data) 2))))))
+ (assq 'urls entity-data))))))
+ ;; Source.
+ ,@(let ((source (twittering-decode-html-entities
+ (funcall assq-get 'source status-data))))
+ (if (and source
+ (string-match "<a href=\"\\(.*?\\)\".*?>\\(.*\\)</a>"
+ source))
+ (let ((uri (match-string-no-properties 1 source))
+ (caption (match-string-no-properties 2 source)))
+ `((source . ,caption)
+ (source-uri . ,uri)))
+ `((source . ,source)
+ (source-uri . ""))))
+ ;; Items related to the user that posted the tweet.
+ ,@(let ((user-data (cddr (assq 'user status-data))))
+ (mapcar
+ (lambda (entry)
+ (let* ((sym (elt entry 0))
+ (sym-in-user-data (elt entry 1))
+ (encoded (elt entry 2))
+ (value (funcall assq-get sym-in-user-data user-data)))
+ `(,sym . ,(if encoded
+ (twittering-decode-html-entities value)
+ value))))
+ '(;; Raw entries.
+ (user-id id)
+ (user-profile-image-url profile_image_url)
+ (user-url url)
+ ;; Encoded entries.
+ (user-name name t)
+ (user-screen-name screen_name t)
+ (user-location location t)
+ (user-description description t))))
+ ,@(let ((user-data (cddr (assq 'user status-data))))
+ (mapcar (lambda (entry)
+ `(,(car entry)
+ . ,(string=
+ "true"
+ (funcall assq-get (cdr entry) user-data))))
+ '((user-protected . protected))))))))))
+
+(defun twittering-xmltree-to-status (xmltree)
+ (setq xmltree
+ (cond
+ ((eq 'direct-messages (caar xmltree))
+ `(,@(mapcar
+ (lambda (c-node)
+ `(status nil
+ (created_at
+ nil ,(caddr (assq 'created_at c-node)))
+ (id nil ,(caddr (assq 'id c-node)))
+ (text nil ,(caddr (assq 'text c-node)))
+ (source nil ,(format "%s" (car c-node))) ;; fake
+ (truncated nil "false")
+ (in_reply_to_status_id nil)
+ (in_reply_to_user_id
+ nil ,(caddr (assq 'recipient_id c-node)))
+ (favorited nil "false")
+ (recipient_screen_name
+ nil ,(caddr (assq 'recipient_screen_name c-node)))
+ (user nil ,@(cdddr (assq 'sender c-node)))
+ (entities nil ,@(cdddr (assq 'entities c-node)))))
+ (remove nil
+ (mapcar
+ (lambda (node)
+ (and (consp node) (eq 'direct_message (car node))
+ node))
+ (cdr-safe (assq 'direct-messages xmltree))))
+ )))
+ ((eq 'statuses (caar xmltree))
+ (cddr (car xmltree)))
+ (t ;; unknown format?
+ nil)))
+
+ (mapcar #'twittering-normalize-raw-status
+ ;; quirk to treat difference between xml.el in Emacs21 and Emacs22
+ ;; On Emacs22, there may be blank strings
+ (remove nil (mapcar (lambda (x)
+ (if (consp x) x))
+ xmltree))))
+
+(defun twittering-decode-entities-after-parsing-xml (encoded-str)
+ "Decode ENCODED-STR retrieved by parsing XML and return the result.
+On Emacs 22 and later, `xml-parse-region' resolves numeric character
+references. It is redundant to resolve numeric character references
+again. However, in a XML response from Twitter, the two characters,
+\"<\" and \">\", are doubly escaped as \"&lt;\" and \"&gt;\",
+respectively. Then, they are represented as \"<\" and \">\" in
+the result of `xml-parse-region'. This function decodes them.
+
+On Emacs 21, `xml-parse-region' does not resolve numeric character
+references. This function decodes them."
+ (cond
+ ((null encoded-str)
+ "")
+ ((> 22 emacs-major-version)
+ (replace-regexp-in-string
+ "&#\\([0-9]+\\);"
+ (lambda (str)
+ (let ((number-entity
+ (progn
+ (string-match "&#\\([0-9]+\\);" str)
+ (match-string 1 str))))
+ (char-to-string
+ (twittering-ucs-to-char (string-to-number number-entity)))))
+ encoded-str))
+ (t
+ (replace-regexp-in-string
+ "&\\(?:\\(gt\\)\\|\\(lt\\)\\);"
+ (lambda (str)
+ (if (match-beginning 1)
+ ">"
+ "<"))
+ encoded-str))))
+
+(defun twittering-decode-html-entities (encoded-str)
+ (if encoded-str
+ (let ((cursor 0)
+ (found-at nil)
+ (result '()))
+ (while (setq found-at
+ (string-match "&\\(#\\([0-9]+\\)\\|\\([a-zA-Z]+\\)\\);"
+ encoded-str cursor))
+ (when (> found-at cursor)
+ (list-push (substring encoded-str cursor found-at) result))
+ (let ((number-entity (match-string-no-properties 2 encoded-str))
+ (letter-entity (match-string-no-properties 3 encoded-str)))
+ (cond (number-entity
+ (list-push
+ (char-to-string
+ (twittering-ucs-to-char
+ (string-to-number number-entity))) result))
+ (letter-entity
+ (cond ((string= "gt" letter-entity) (list-push ">" result))
+ ((string= "lt" letter-entity) (list-push "<" result))
+ ((string= "quot" letter-entity) (list-push "\"" result))
+ (t (list-push "?" result))))
+ (t (list-push "?" result)))
+ (setq cursor (match-end 0))))
+ (list-push (substring encoded-str cursor) result)
+ (apply 'concat (nreverse result)))
+ ""))
+
+;; JSON
+(defun twittering-extract-common-element-from-json (json-object)
+ "Extract common parameters of a tweet from JSON-OBJECT.
+Return an alist including text, created_at and entities, which are common
+to JSON objects from ordinary timeline and search timeline."
+ (let* ((encoded-text (cdr (assq 'text json-object)))
+ (text
+ (twittering-decode-entities-after-parsing-xml encoded-text))
+ (gap-list (twittering-make-gap-list text))
+ (entities (cdr (assq 'entities json-object)))
+ (urls (cdr (assq 'urls entities)))
+ (hashtags (cdr (assq 'hashtags entities)))
+ (mentions (cdr (assq 'user_mentions entities)))
+ (media (cdr (assq 'media entities)))
+ (func
+ (lambda (entry sym-table)
+ (mapcar (lambda (sym-entry)
+ (let ((sym (car sym-entry))
+ (target (cdr sym-entry)))
+ `(,sym . ,(cdr (assq target entry)))))
+ sym-table))))
+ `((text . ,(twittering-normalize-string text))
+ (created-at
+ . ,(apply 'encode-time
+ (parse-time-string (cdr (assq 'created_at json-object)))))
+ (entity
+ (hashtags . ,(mapcar (lambda (entry)
+ (let* ((indices (cdr (assq 'indices entry)))
+ (start (elt indices 0))
+ (end (elt indices 1))
+ (gap
+ (twittering-get-gap start gap-list)))
+ `((start . ,(- start gap))
+ (end . ,(- end gap))
+ (text
+ . ,(twittering-normalize-string
+ (cdr (assq 'text entry)))))))
+ hashtags))
+ (mentions . ,(mapcar (lambda (entry)
+ (let* ((indices (cdr (assq 'indices entry)))
+ (start (elt indices 0))
+ (end (elt indices 1))
+ (gap
+ (twittering-get-gap start gap-list)))
+ `((start . ,(- start gap))
+ (end . ,(- end gap))
+ (id . ,(cdr (assq 'id_str entry)))
+ (name
+ . ,(twittering-normalize-string
+ (cdr (assq 'name entry))))
+ (screen-name
+ . ,(cdr (assq 'screen_name entry))))))
+ mentions))
+ (urls . ,(mapcar (lambda (entry)
+ (let* ((indices (cdr (assq 'indices entry)))
+ (start (elt indices 0))
+ (end (elt indices 1))
+ (gap (twittering-get-gap start gap-list)))
+ `((start . ,(- start gap))
+ (end . ,(- end gap))
+ (url . ,(cdr (assq 'url entry)))
+ (display-url
+ . ,(cdr (assq 'display_url entry)))
+ (expanded-url
+ . ,(cdr (assq 'expanded_url entry))))))
+ urls))
+ (media . ,(mapcar (lambda (entry)
+ (let* ((indices (cdr (assq 'indices entry)))
+ (start (elt indices 0))
+ (end (elt indices 1))
+ (gap (twittering-get-gap start gap-list)))
+ `((start . ,(- start gap))
+ (end . ,(- end gap))
+ (url . ,(cdr (assq 'url entry)))
+ (raw-entry . ,entry)
+ ,@(funcall func entry
+ '((media-url . media_url)
+ (display-url . display_url)
+ (expanded-url . expanded_url))))))
+ media)))
+ (retweet-count . ,(cdr (assq 'retweet_count json-object)))
+ (favorite-count . ,(cdr (assq 'favorite_count json-object)))
+ )))
+
+(defun twittering-json-object-to-a-status (json-object)
+ "Convert JSON-OBJECT representing a tweet into an alist representation.
+JSON-OBJECT must originate in an ordinary timeline, not a search timeline.
+To convert a JSON object from a search timeline, use
+`twittering-json-object-to-a-status-on-search'."
+ (let* ((raw-retweeted-status (cdr (assq 'retweeted_status json-object))))
+ (cond
+ (raw-retweeted-status
+ (let ((retweeted-status
+ (twittering-json-object-to-a-status-base raw-retweeted-status))
+ (retweeting-status
+ (twittering-json-object-to-a-status-base json-object))
+ (items-overwritten-by-retweet
+ '(id)))
+ `(,@(mapcar
+ (lambda (entry)
+ (let ((sym (car entry))
+ (value (cdr entry)))
+ (if (memq sym items-overwritten-by-retweet)
+ (let ((value-on-retweet
+ (cdr (assq sym retweeting-status))))
+ ;; Replace the value in `retweeted-status' with
+ ;; that in `retweeting-status'.
+ `(,sym . ,value-on-retweet))
+ `(,sym . ,value))))
+ retweeted-status)
+ ,@(mapcar
+ (lambda (entry)
+ (let ((sym (car entry))
+ (value (cdr entry)))
+ `(,(intern (concat "retweeted-" (symbol-name sym)))
+ . ,value)))
+ retweeted-status)
+ ,@(mapcar
+ (lambda (entry)
+ (let ((sym (car entry))
+ (value (cdr entry)))
+ `(,(intern (concat "retweeting-" (symbol-name sym)))
+ . ,value)))
+ retweeting-status))))
+ (t
+ (twittering-json-object-to-a-status-base json-object)))))
+
+(defun twittering-json-object-to-a-status-base (json-object)
+ (let ((user-data (cdr (assq 'user json-object))))
+ `(,@(twittering-extract-common-element-from-json json-object)
+ ,@(let ((symbol-table
+ '((favorited . favorited)
+ (id_str . id)
+ (in_reply_to_screen_name . in-reply-to-screen-name)
+ (in_reply_to_status_id_str . in-reply-to-status-id)
+ (recipient_screen_name . recipient-screen-name)
+ (truncated . truncated))))
+ (remove nil
+ (mapcar
+ (lambda (entry)
+ (let* ((sym (car entry))
+ (value (cdr entry))
+ (value
+ (if (and (memq sym '(favorited truncated))
+ (eq value :json-false))
+ nil
+ value))
+ (dest (cdr (assq sym symbol-table))))
+ (when (and dest value)
+ `(,dest . ,value))))
+ json-object)))
+ ;; source
+ ,@(let ((source (cdr (assq 'source json-object))))
+ (if (and source
+ (string-match "<a href=\"\\(.*?\\)\".*?>\\(.*\\)</a>"
+ source))
+ (let ((uri (match-string-no-properties 1 source))
+ (caption (match-string-no-properties 2 source)))
+ `((source . ,(twittering-normalize-string caption))
+ (source-uri . ,uri)))
+ `((source . ,(twittering-normalize-string source))
+ (source-uri . ""))))
+ ;; user data
+ ,@(let ((symbol-table
+ '((id_str . user-id)
+ (profile_image_url . user-profile-image-url)
+ (url . user-url)
+ (protected . user-protected)
+ (name . user-name)
+ (screen_name . user-screen-name)
+ (location . user-location)
+ (description . user-description))))
+ (remove nil
+ (mapcar (lambda (entry)
+ (let* ((sym (car entry))
+ (value (cdr entry))
+ (value
+ (cond
+ ((and (eq sym 'protected)
+ (eq value :json-false))
+ nil)
+ ((memq sym '(name location description))
+ (twittering-normalize-string value))
+ (t
+ value))))
+ (when value
+ (let ((dest (cdr (assq sym symbol-table))))
+ (when dest
+ `(,dest . ,value))))))
+ user-data))))))
+
+(defun twittering-json-object-to-a-status-on-search (json-object)
+ "Convert JSON-OBJECT representing a tweet into an alist representation.
+JSON-OBJECT must originate in a search timeline.
+To convert a JSON object from other timelines, use
+`twittering-json-object-to-a-status'."
+ `(,@(twittering-extract-common-element-from-json json-object)
+ ,@(let ((symbol-table
+ '((id_str . id)
+ (to_user . in-reply-to-screen-name)
+ (in_reply_to_status_id_str . in-reply-to-status-id)
+ ;; user data
+ (from_user_id_str . user-id)
+ (profile_image_url . user-profile-image-url)
+ (from_user_name . user-name)
+ (from_user . user-screen-name))))
+ (remove nil
+ (mapcar
+ (lambda (entry)
+ (let* ((sym (car entry))
+ (value (cdr entry))
+ (dest (cdr (assq sym symbol-table))))
+ (when (and dest value)
+ `(,dest . ,value))))
+ json-object)))
+ ;; source
+ ,@(let ((source
+ (twittering-decode-html-entities
+ (cdr (assq 'source json-object)))))
+ (if (and source
+ (string-match "<a href=\"\\(.*?\\)\".*?>\\(.*\\)</a>"
+ source))
+ (let ((uri (match-string-no-properties 1 source))
+ (caption (match-string-no-properties 2 source)))
+ `((source . ,caption)
+ (source-uri . ,uri)))
+ `((source . ,source)
+ (source-uri . ""))))))
+
+(defun twittering-json-object-to-a-status-on-direct-messages (json-object)
+ "Convert JSON-OBJECT representing a tweet into an alist representation.
+JSON-OBJECT must originate in timelines related to direct messages.
+To convert a JSON object from other timelines, use
+`twittering-json-object-to-a-status'."
+ `(,@(twittering-extract-common-element-from-json json-object)
+ ,@(let ((symbol-table
+ '((id_str . id)
+ (recipient_screen_name . recipient-screen-name))))
+ (remove nil
+ (mapcar
+ (lambda (entry)
+ (let* ((sym (car entry))
+ (value (cdr entry))
+ (dest (cdr (assq sym symbol-table))))
+ (when (and dest value)
+ `(,dest . ,value))))
+ json-object)))
+ ;; sender
+ ,@(let ((symbol-table
+ '((id_str . user-id)
+ (name . user-name)
+ (profile_image_url . user-profile-image-url)
+ (protected . user-protected)
+ (screen_name . user-screen-name))))
+ (remove nil
+ (mapcar
+ (lambda (entry)
+ (let* ((sym (car entry))
+ (value (cdr entry))
+ (value
+ (cond
+ ((eq sym 'protected)
+ (if (eq value :json-false)
+ nil
+ t))
+ ((eq value :json-false)
+ nil)
+ (t
+ value))))
+ (when value
+ (let ((dest (cdr (assq sym symbol-table))))
+ (when dest
+ `(,dest . ,value))))))
+ (cdr (assq 'sender json-object)))))))
+
+;;;;
+;;;; List info retrieval
+;;;;
+
+(defun twittering-get-list-index (username)
+ (twittering-call-api
+ 'get-list-index
+ `((username . ,username)
+ (sentinel . twittering-http-get-list-index-sentinel))))
+
+(defun twittering-get-list-subscriptions (username)
+ (twittering-call-api
+ 'get-list-subscriptions
+ `((username . ,username)
+ (sentinel . twittering-http-get-list-subscriptions-sentinel))))
+
+(defun twittering-get-list-sync (username function)
+ (setq twittering-list-index-retrieved nil)
+ (let ((proc (funcall function username)))
+ (when proc
+ (twittering-wait-while nil 0.1
+ (and (not twittering-list-index-retrieved)
+ (twittering-process-alive-p proc)))
+ (when (and (not twittering-list-index-retrieved)
+ (not (twittering-process-alive-p proc)))
+ ;; If the process has been dead, wait a moment because
+ ;; Emacs may be in the middle of evaluating the sentinel.
+ (twittering-wait-while 10 0.1
+ (not twittering-list-index-retrieved)))))
+ (cond
+ ((null twittering-list-index-retrieved)
+ (message "Failed to retrieve %s's lists." username)
+ nil)
+ ((stringp twittering-list-index-retrieved)
+ (if (string= "" twittering-list-index-retrieved)
+ (message "%s does not have a list." username)
+ (message "%s" twittering-list-index-retrieved))
+ nil)
+ ((listp twittering-list-index-retrieved)
+ twittering-list-index-retrieved)))
+
+(defun twittering-get-list-index-sync (username)
+ (twittering-get-list-sync username 'twittering-get-list-index))
+
+(defun twittering-get-list-subscriptions-sync (username)
+ (twittering-get-list-sync username 'twittering-get-list-subscriptions))
+
+;;;;
+;;;; Buffer info
+;;;;
+
+(defvar twittering-buffer-info-list nil
+ "List of buffers managed by `twittering-mode'.")
+
+(defun twittering-get-buffer-list ()
+ "Return buffers managed by `twittering-mode'."
+ (twittering-unregister-killed-buffer)
+ twittering-buffer-info-list)
+
+(defun twittering-get-active-buffer-list ()
+ "Return active buffers managed by `twittering-mode', where statuses are
+retrieved periodically."
+ (twittering-unregister-killed-buffer)
+ (remove nil
+ (mapcar (lambda (buffer)
+ (if (twittering-buffer-active-p buffer)
+ buffer
+ nil))
+ twittering-buffer-info-list)))
+
+(defun twittering-buffer-p (&optional buffer)
+ "Return t if BUFFER is managed by `twittering-mode'.
+BUFFER defaults to the the current buffer."
+ (let ((buffer (or buffer (current-buffer))))
+ (and (buffer-live-p buffer)
+ (memq buffer twittering-buffer-info-list))))
+
+(defun twittering-buffer-related-p ()
+ "Return t if current buffer relates to `twittering-mode'."
+ (or (twittering-buffer-p)
+ (eq major-mode 'twittering-edit-mode)
+ (string= (buffer-name (current-buffer))
+ twittering-debug-buffer)))
+
+(defun twittering-buffer-active-p (&optional buffer)
+ "Return t if BUFFER is an active buffer managed by `twittering-mode'.
+BUFFER defaults to the the current buffer."
+ (let ((buffer (or buffer (current-buffer))))
+ (and (twittering-buffer-p buffer)
+ (with-current-buffer buffer
+ twittering-active-mode))))
+
+(defun twittering-get-buffer-from-spec (spec)
+ "Return the buffer bound to SPEC. If no buffers are bound to SPEC,
+return nil."
+ (let* ((spec-string (twittering-timeline-spec-to-string spec))
+ (buffers
+ (remove
+ nil
+ (mapcar
+ (lambda (buffer)
+ (if (twittering-equal-string-as-timeline
+ spec-string
+ (twittering-get-timeline-spec-string-for-buffer buffer))
+ buffer
+ nil))
+ (twittering-get-buffer-list)))))
+ (if buffers
+ ;; We assume that the buffer with the same spec is unique.
+ (car buffers)
+ nil)))
+
+(defun twittering-get-buffer-from-spec-string (spec-string)
+ "Return the buffer bound to SPEC-STRING. If no buffers are bound to it,
+return nil."
+ (let ((spec (twittering-string-to-timeline-spec spec-string)))
+ (and spec (twittering-get-buffer-from-spec spec))))
+
+(defun twittering-get-timeline-spec-for-buffer (buffer)
+ "Return the timeline spec bound to BUFFER. If BUFFER is not managed by
+`twittering-mode', return nil."
+ (when (twittering-buffer-p buffer)
+ (with-current-buffer buffer
+ twittering-timeline-spec)))
+
+(defun twittering-get-timeline-spec-string-for-buffer (buffer)
+ "Return the timeline spec string bound to BUFFER. If BUFFER is not managed
+by `twittering-mode', return nil."
+ (when (twittering-buffer-p buffer)
+ (with-current-buffer buffer
+ twittering-timeline-spec-string)))
+
+(defun twittering-current-timeline-spec ()
+ "Return the timeline spec bound to the current buffer. If it is not managed
+by `twittering-mode', return nil."
+ (twittering-get-timeline-spec-for-buffer (current-buffer)))
+
+(defun twittering-current-timeline-spec-string ()
+ "Return the timeline spec string bound to the current buffer. If it is not
+managed by `twittering-mode', return nil."
+ (twittering-get-timeline-spec-string-for-buffer (current-buffer)))
+
+(defun twittering-unregister-buffer (buffer &optional keep-timer)
+ "Unregister BUFFER from `twittering-buffer-info-list'.
+If BUFFER is the last managed buffer and KEEP-TIMER is nil, call
+`twittering-stop' to stop timers."
+ (when (memq buffer twittering-buffer-info-list)
+ (setq twittering-buffer-info-list
+ (delq buffer twittering-buffer-info-list))
+ (when (and (null twittering-buffer-info-list)
+ (not keep-timer))
+ (twittering-stop))))
+
+(defun twittering-unregister-killed-buffer ()
+ "Unregister buffers which has been killed."
+ (mapc (lambda (buffer)
+ (unless (buffer-live-p buffer)
+ (twittering-unregister-buffer buffer)))
+ twittering-buffer-info-list))
+
+(defun twittering-replace-spec-string-for-buffer (buffer spec-string)
+ "Replace the timeline spec string for BUFFER with SPEC-STRING when
+BUFFER is managed by `twittering-mode' and SPEC-STRING is equivalent
+to the current one."
+ (when (twittering-buffer-p buffer)
+ (let ((current (twittering-get-timeline-spec-string-for-buffer buffer)))
+ (when (and (not (string= current spec-string))
+ (twittering-equal-string-as-timeline current spec-string))
+ (with-current-buffer buffer
+ (rename-buffer spec-string t)
+ (setq twittering-timeline-spec-string spec-string))))))
+
+(defun twittering-set-active-flag-for-buffer (buffer active)
+ "Set ACTIVE to active-flag for BUFFER."
+ (when (twittering-buffer-p buffer)
+ (let ((current (twittering-buffer-active-p buffer)))
+ (when (or (and active (not current))
+ (and (not active) current))
+ (twittering-toggle-activate-buffer buffer)))))
+
+(defun twittering-toggle-activate-buffer (&optional buffer)
+ "Toggle whether to retrieve timeline for the current buffer periodically."
+ (interactive)
+ (let ((buffer (or buffer (current-buffer))))
+ (when (twittering-buffer-p buffer)
+ (with-current-buffer buffer
+ (let* ((new-mode (not twittering-active-mode))
+ (active-buffer-list (twittering-get-active-buffer-list))
+ (start-timer (and new-mode (null active-buffer-list))))
+ (setq twittering-active-mode new-mode)
+ (when start-timer
+ (twittering-start))
+ (twittering-update-mode-line))))))
+
+(defun twittering-activate-buffer (&optional buffer)
+ "Activate BUFFER to retrieve timeline for it periodically."
+ (interactive)
+ (let ((buffer (or buffer (current-buffer))))
+ (twittering-set-active-flag-for-buffer buffer t)))
+
+(defun twittering-deactivate-buffer (&optional buffer)
+ "Deactivate BUFFER not to retrieve timeline for it periodically."
+ (interactive)
+ (let ((buffer (or buffer (current-buffer))))
+ (twittering-set-active-flag-for-buffer buffer nil)))
+
+(defun twittering-kill-buffer (&optional buffer)
+ "Kill BUFFER managed by `twittering-mode'."
+ (interactive)
+ (let ((buffer (or buffer (current-buffer))))
+ (when (twittering-buffer-p buffer)
+ (twittering-deactivate-buffer buffer)
+ (kill-buffer buffer)
+ (twittering-unregister-killed-buffer))))
+
+(defun twittering-get-managed-buffer (spec)
+ "Return the buffer bound to SPEC. If no buffers are bound to SPEC, return
+newly generated buffer.
+SPEC may be a timeline spec or a timeline spec string."
+ (let* ((original-spec spec)
+ (spec-string (if (stringp spec)
+ spec
+ (twittering-timeline-spec-to-string spec)))
+ ;; `spec-string' without text properties is required because
+ ;; Emacs21 displays `spec-string' with its properties on mode-line.
+ ;; In addition, copying `spec-string' keeps timeline-data from
+ ;; being modified by `minibuf-isearch.el'.
+ (spec-string (copy-sequence spec-string))
+ (spec (if (stringp spec-string)
+ (twittering-string-to-timeline-spec spec-string)
+ nil)))
+ (when (null spec)
+ (error "\"%s\" is invalid as a timeline spec"
+ (or spec-string original-spec)))
+ (set-text-properties 0 (length spec-string) nil spec-string)
+ (twittering-add-timeline-history spec-string)
+ (let ((buffer (twittering-get-buffer-from-spec spec)))
+ (if buffer
+ (progn
+ (twittering-replace-spec-string-for-buffer buffer spec-string)
+ (twittering-update-mode-line)
+ buffer)
+ (let ((buffer (generate-new-buffer spec-string))
+ (start-timer (null twittering-buffer-info-list)))
+ (add-to-list 'twittering-buffer-info-list buffer t)
+ (with-current-buffer buffer
+ (twittering-mode-setup spec-string)
+ (twittering-rerender-timeline-all buffer)
+ (when (twittering-account-authorized-p)
+ (when start-timer
+ ;; If `buffer' is the first managed buffer,
+ ;; call `twittering-start' to start timers.
+ (twittering-start))
+ (unless (and start-timer twittering-active-mode)
+ ;; If `buffer' is active and the first managed buffer,
+ ;; `twittering-start' invokes
+ ;; `twittering-get-and-render-timeline' indirectly.
+ ;; Otherwise, `twittering-get-and-render-timeline' should be
+ ;; invoked here.
+ (twittering-get-and-render-timeline))))
+ buffer)))))
+
+;;;;
+;;;; Icon mode
+;;;;
+
+(defvar twittering-icon-mode nil
+ "You MUST NOT CHANGE this variable directly.
+You should change through function `twittering-icon-mode'.")
+
+(defun twittering-icon-mode (&optional arg)
+ "Toggle display of icon images on timelines.
+With a numeric argument, if the argument is positive, turn on
+icon mode; otherwise, turn off icon mode."
+ (interactive "P")
+ (let ((prev-mode twittering-icon-mode))
+ (setq twittering-icon-mode
+ (if (null arg)
+ (not twittering-icon-mode)
+ (< 0 (prefix-numeric-value arg))))
+ (unless (eq prev-mode twittering-icon-mode)
+ (twittering-update-mode-line)
+ (twittering-rerender-timeline-all (current-buffer) t))))
+
+(defvar twittering-icon-prop-hash (make-hash-table :test 'equal)
+ "Hash table for storing display properties of icon. The key is the size of
+icon and the value is a hash. The key of the child hash is URL and its value
+is the display property for the icon.")
+
+(defvar twittering-convert-program (executable-find "convert"))
+(defvar twittering-convert-fix-size 48)
+(defvar twittering-use-convert (not (null twittering-convert-program))
+ "*This variable makes a sense only if `twittering-convert-fix-size'
+is non-nil. If this variable is non-nil, icon images are converted by
+invoking \"convert\". Otherwise, cropped images are displayed.")
+
+(defvar twittering-fallback-image-format 'xpm
+ "*Fallback format used for displaying an image without a supproted format.
+Images which Emacs does not supports are converted into the fallback image
+format.")
+
+(defvar twittering-use-profile-image-api nil
+ "*Whether to use `profile_image' API for retrieving scaled icon images.
+NOTE: This API is rate limited and is obsolete in the Twitter REST API v1.1.")
+
+(defvar twittering-icon-storage-file
+ (expand-file-name "~/.twittering-mode-icons.gz")
+ "*The file to which icon images are stored.
+`twittering-icon-storage-limit' determines the number icons stored in the
+file.
+The file is loaded with `with-auto-compression-mode'.")
+
+(defvar twittering-use-icon-storage nil
+ "*Whether to use the persistent icon storage.
+If this variable is non-nil, icon images are stored to the file specified
+by `twittering-icon-storage-file'.")
+
+(defvar twittering-icon-storage-recent-icons nil
+ "List of recently rendered icons.")
+
+(defvar twittering-icon-storage-limit 500
+ "*How many icons are stored in the persistent storage.
+If `twittering-use-icon-storage' is nil, this variable is ignored.
+If a positive integer N, `twittering-save-icon-properties' saves N icons that
+have been recently rendered.
+If nil, the function saves all icons.")
+
+(defconst twittering-error-icon-data-pair
+ '(xpm . "/* XPM */
+static char * yellow3_xpm[] = {
+\"16 16 2 1\",
+\" c None\",
+\". c #FF0000\",
+\"................\",
+\". .\",
+\". . . .\",
+\". . . .\",
+\". . . .\",
+\". . . .\",
+\". . . .\",
+\". .. .\",
+\". .. .\",
+\". . . .\",
+\". . . .\",
+\". . . .\",
+\". . . .\",
+\". . . .\",
+\". .\",
+\"................\"};
+")
+ "Image used when the valid icon cannot be retrieved.")
+
+(defun twittering-update-icon-storage-recent-icons (size image-url spec)
+ (unless (null twittering-icon-storage-limit)
+ (let ((dummy-icon-properties (twittering-make-display-spec-for-icon
+ twittering-error-icon-data-pair)))
+ (unless (equal spec dummy-icon-properties)
+ (let ((history-delete-duplicates t))
+ (twittering-add-to-history 'twittering-icon-storage-recent-icons
+ (list size image-url)
+ twittering-icon-storage-limit))))))
+
+(defun twittering-get-display-spec-for-icon (image-url)
+ (let ((hash
+ (gethash twittering-convert-fix-size twittering-icon-prop-hash)))
+ (when hash
+ (let ((spec (gethash image-url hash))
+ (size twittering-convert-fix-size))
+ (when spec
+ (twittering-update-icon-storage-recent-icons size image-url spec)
+ spec)))))
+
+(defun twittering-convert-image-data (image-data dest-type &optional src-type)
+ "Convert IMAGE-DATA into XPM format and return it. If it fails to convert,
+return nil."
+ (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (buffer-disable-undo)
+ (let ((coding-system-for-read 'binary)
+ (coding-system-for-write 'binary)
+ (require-final-newline nil)
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (insert image-data)
+ (let* ((args
+ `(,@(when (<= emacs-major-version 22)
+ ;; Emacs22 and earlier raises "Color allocation error"
+ ;; on decoding a XPM image with opacity. To ignore
+ ;; opacity, the option "+matte" is added.
+ '("+matte"))
+ ,@(unless (fboundp 'create-animated-image)
+ '("-flatten"))
+ ,(if src-type (format "%s:-" src-type) "-")
+ ,@(when (integerp twittering-convert-fix-size)
+ `("-resize"
+ ,(format "%dx%d" twittering-convert-fix-size
+ twittering-convert-fix-size)))
+ ,(format "%s:-" dest-type)))
+ (exit-status
+ (apply 'call-process-region (point-min) (point-max)
+ twittering-convert-program t `(t nil) nil args)))
+ (if (equal 0 exit-status)
+ (buffer-string)
+ ;; failed to convert the image.
+ nil)))))
+
+(defun twittering-create-image-pair (image-data)
+ "Return a pair of image type and image data.
+IMAGE-DATA is converted by `convert' if the image type of IMAGE-DATA is not
+available and `twittering-use-convert' is non-nil."
+ (let* ((image-type (and image-data (image-type-from-data image-data)))
+ (image-pair `(,image-type . ,image-data))
+ (converted-size
+ `(,twittering-convert-fix-size . ,twittering-convert-fix-size)))
+ (cond
+ ((null image-data)
+ twittering-error-icon-data-pair)
+ ((and (image-type-available-p image-type)
+ (or (fboundp 'create-animated-image)
+ (not (and twittering-use-convert
+ (eq image-type 'gif))))
+ (or (not (integerp twittering-convert-fix-size))
+ (equal (image-size (create-image image-data image-type t) t)
+ converted-size)))
+ image-pair)
+ (twittering-use-convert
+ (let ((converted-data
+ (twittering-convert-image-data image-data
+ twittering-fallback-image-format)))
+ (if converted-data
+ `(,twittering-fallback-image-format . ,converted-data)
+ twittering-error-icon-data-pair)))
+ (t
+ twittering-error-icon-data-pair))))
+
+(defun twittering-register-image-spec (image-url spec size)
+ (let ((hash (gethash size twittering-icon-prop-hash)))
+ (unless hash
+ (setq hash (make-hash-table :test 'equal))
+ (puthash size hash twittering-icon-prop-hash))
+ (puthash image-url spec hash)))
+
+(defun twittering-register-image-data (image-url image-data &optional size)
+ (let ((image-pair (twittering-create-image-pair image-data))
+ (size (or size twittering-convert-fix-size)))
+ (when image-pair
+ (let ((spec (twittering-make-display-spec-for-icon image-pair)))
+ (twittering-register-image-spec image-url spec size)
+ spec))))
+
+(defun twittering-make-slice-spec (image-spec)
+ "Return slice property for reducing the image size by cropping it."
+ (let* ((size (image-size image-spec t))
+ (width (car size))
+ (height (cdr size))
+ (fixed-length twittering-convert-fix-size)
+ (half-fixed-length (/ fixed-length 2)))
+ (if (or (< fixed-length width) (< fixed-length height))
+ `(slice ,(max 0 (- (/ width 2) half-fixed-length))
+ ,(max 0 (- (/ height 2) half-fixed-length))
+ ,fixed-length ,fixed-length)
+ `(slice 0 0 ,fixed-length ,fixed-length))))
+
+(defun twittering-make-display-spec-for-icon (image-pair)
+ "Return the specification for `display' text property, which
+limits the size of an icon image IMAGE-PAIR up to FIXED-LENGTH. If
+the type of the image is not supported, nil is returned.
+
+If the size of the image exceeds FIXED-LENGTH, the center of the
+image are displayed."
+ (let* ((type (car-safe image-pair))
+ (data (cdr-safe image-pair))
+ (raw-image-spec ;; without margins
+ (create-image data type t))
+ (slice-spec
+ (when (and twittering-convert-fix-size (not twittering-use-convert))
+ (twittering-make-slice-spec raw-image-spec)))
+ (image-spec
+ (if (fboundp 'create-animated-image) ;; Emacs24 or later
+ (create-animated-image data type t :margin 2 :ascent 'center)
+ (create-image data type t :margin 2 :ascent 'center))))
+ (if slice-spec
+ `(display (,image-spec ,slice-spec))
+ `(display ,image-spec))))
+
+(defun twittering-make-icon-string (beg end image-url)
+ (let ((display-spec (twittering-get-display-spec-for-icon image-url))
+ (image-data (gethash image-url twittering-url-data-hash))
+ (properties (and beg (text-properties-at beg)))
+ (icon-string (copy-sequence " ")))
+ (when properties
+ (add-text-properties 0 (length icon-string) properties icon-string))
+ (cond
+ (display-spec
+ (let ((icon-string (apply 'propertize "_"
+ (append properties display-spec))))
+ ;; Remove the property required no longer.
+ (remove-text-properties 0 (length icon-string)
+ '(need-to-be-updated nil)
+ icon-string)
+ icon-string))
+ ((and (integerp image-data)
+ (<= twittering-url-request-retry-limit image-data))
+ ;; Try to retrieve the image no longer.
+ (twittering-register-image-data image-url nil)
+ (twittering-make-icon-string beg end image-url))
+ ((and image-data (not (integerp image-data)))
+ (twittering-register-image-data image-url image-data)
+ (twittering-make-icon-string beg end image-url))
+ (t
+ (put-text-property 0 (length icon-string)
+ 'need-to-be-updated
+ `(twittering-make-icon-string ,image-url)
+ icon-string)
+ (twittering-url-retrieve-async image-url 'twittering-register-image-data)
+ icon-string))))
+
+(defun twittering-save-icon-properties (&optional filename)
+ (let ((filename (or filename twittering-icon-storage-file))
+ (stored-data
+ (cond
+ ((null twittering-icon-storage-limit)
+ (let ((result nil)
+ (dummy-icon-properties (twittering-make-display-spec-for-icon
+ twittering-error-icon-data-pair)))
+ (maphash
+ (lambda (size hash)
+ (maphash (lambda (url properties)
+ (unless (equal properties dummy-icon-properties)
+ (setq result (cons (list size url) result))))
+ hash))
+ twittering-icon-prop-hash)
+ result))
+ (t
+ (reverse twittering-icon-storage-recent-icons))))
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (when (require 'jka-compr nil t)
+ (with-auto-compression-mode
+ (let ((coding-system-for-write 'binary))
+ (with-temp-file filename
+ (insert "( 2 ")
+ (prin1 (cons 'emacs-version emacs-version) (current-buffer))
+ (insert "(icon-list ")
+ (mapc
+ (lambda (entry)
+ (let* ((size (elt entry 0))
+ (url (elt entry 1))
+ (properties
+ (gethash url
+ (gethash size twittering-icon-prop-hash))))
+ (insert (if size
+ (format "(%d " size)
+ "(nil "))
+ (prin1 url (current-buffer))
+ (insert " ")
+ (prin1 properties (current-buffer))
+ (insert ")\n")))
+ stored-data)
+ (insert "))")))))))
+
+(defun twittering-load-icon-properties (&optional filename)
+ (let* ((filename (or filename twittering-icon-storage-file))
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory)
+ (data
+ (with-temp-buffer
+ (condition-case err
+ (cond
+ ((and (require 'jka-compr)
+ (file-exists-p filename))
+ (with-auto-compression-mode
+ (let ((coding-system-for-read 'binary)
+ (coding-system-for-write 'binary))
+ (insert-file-contents filename)))
+ (read (current-buffer)))
+ (t
+ nil))
+ (error
+ (message "Failed to load icon images. %s" (cdr err))
+ nil)))))
+ (cond
+ ((equal 2 (car data))
+ (let ((version (cdr (assq 'emacs-version data))))
+ (cond
+ ((or (equal version emacs-version)
+ (y-or-n-p
+ (format "%s is generated by Emacs %s! Use it?"
+ filename version)))
+ (mapc (lambda (entry)
+ (let ((size (elt entry 0))
+ (url (elt entry 1))
+ (properties (elt entry 2)))
+ (twittering-update-icon-storage-recent-icons size url
+ properties)
+ (twittering-register-image-spec url properties size)))
+ (cdr (assq 'icon-list data))))
+ (t
+ (message "Stopped loading icons")))))
+ (t
+ (mapc (lambda (entry)
+ (let ((size (car entry))
+ (prop-alist (cdr entry)))
+ (mapc (lambda (entry)
+ (let ((url (car entry))
+ (properties (cdr entry)))
+ (twittering-update-icon-storage-recent-icons
+ size url properties)
+ (twittering-register-image-spec url properties
+ size)))
+ prop-alist)))
+ data)))))
+
+;;;;
+;;;; Mode-line
+;;;;
+
+;;; SSL
+(defconst twittering-ssl-indicator-image
+ (when (image-type-available-p 'xpm)
+ '(image :type xpm
+ :ascent center
+ :data
+ "/* XPM */
+static char * lock[] = {
+\"16 16 3 1\",
+\" c None\",
+\". c #000000\",
+\"# c #FFFFFF\",
+\" \",
+\" \",
+\" ........ \",
+\" ..######.. \",
+\" .##....##. \",
+\" .#.. ..#. \",
+\" .#. .#. \",
+\" ..#......#.. \",
+\" .##########. \",
+\" .##########. \",
+\" .####..####. \",
+\" .###....###. \",
+\" .###....###. \",
+\" .##########. \",
+\" ............ \",
+\" \"};
+"
+ ))
+ "Image for indicator of SSL state.")
+
+(defconst twittering-modeline-ssl
+ (if twittering-ssl-indicator-image
+ (propertize "SSL"
+ 'display twittering-ssl-indicator-image
+ 'help-echo "SSL is enabled.")
+ "SSL"))
+
+;;; ACTIVE/INACTIVE
+(defconst twittering-active-indicator-image
+ (when (image-type-available-p 'xpm)
+ '(image :type xpm
+ :ascent center
+ :data
+ "/* XPM */
+static char * connected[] = {
+\"16 16 3 1\",
+\" c None\",
+\". c #000000\",
+\"# c #FFFFFF\",
+\" .##. ... \",
+\" .##. .#. \",
+\" .##...#.. \",
+\" .##..###..\",
+\" .##..###..\",
+\" .##.#####.\",
+\" ... .##.#.#.#.\",
+\" .#. ..#...#...\",
+\"...#...#.. .#. \",
+\".#.#.#.##. .#. \",
+\".#####.##. ... \",
+\"..### .##. \",
+\" .###..##. \",
+\" ..#...##. \",
+\" .#. .##. \",
+\" ... .##. \"};
+"))
+ "Image for indicator of active state."
+)
+
+(defconst twittering-inactive-indicator-image
+ (when (image-type-available-p 'xpm)
+ '(image :type xpm
+ :ascent center
+ :data
+ "/* XPM */
+static char * disconnected[] = {
+\"16 16 3 1\",
+\" c None\",
+\". c #000000\",
+\"# c #FFFFFF\",
+\" .##. \",
+\" .##. \",
+\" . .##. \",
+\" ...##. \",
+\" ..##. \",
+\" ..#. \",
+\" .. ... \",
+\" .. .. \",
+\" .. .. \",
+\" ... .. \",
+\" .#.. \",
+\" .##.. \",
+\" .##... \",
+\" .##. . \",
+\" .##. \",
+\" .##. \"};
+"))
+ "Image for indicator of inactive state."
+)
+
+(defconst twittering-modeline-properties
+ (when (display-mouse-p)
+ `(local-map
+ ,(purecopy (make-mode-line-mouse-map
+ 'mouse-2 #'twittering-toggle-activate-buffer))
+ help-echo "mouse-2 toggles activate buffer")))
+
+(defconst twittering-modeline-active
+ (if twittering-active-indicator-image
+ (apply 'propertize " "
+ `(display ,twittering-active-indicator-image
+ ,@twittering-modeline-properties))
+ " "))
+
+(defconst twittering-modeline-inactive
+ (if twittering-inactive-indicator-image
+ (apply 'propertize "INACTIVE"
+ `(display ,twittering-inactive-indicator-image
+ ,@twittering-modeline-properties))
+ "INACTIVE"))
+
+(defun twittering-mode-line-buffer-identification ()
+ (let ((active-mode-indicator
+ (if twittering-active-mode
+ twittering-modeline-active
+ twittering-modeline-inactive))
+ (enabled-options
+ `(,(if twittering-display-connection-method
+ (concat
+ (when twittering-use-ssl (concat twittering-modeline-ssl ":"))
+ (twittering-get-connection-method-name twittering-use-ssl))
+ (when twittering-use-ssl twittering-modeline-ssl))
+ ,@(when twittering-jojo-mode '("jojo"))
+ ,@(when twittering-icon-mode '("icon"))
+ ,@(when twittering-reverse-mode '("reverse"))
+ ,@(when twittering-proxy-use '("proxy")))))
+ (concat active-mode-indicator
+ (when twittering-display-remaining
+ (let ((spec (twittering-current-timeline-spec)))
+ (twittering-get-ratelimit-indicator-string spec)))
+ (when enabled-options
+ (concat "[" (mapconcat 'identity enabled-options " ") "]")))))
+
+(defun twittering-update-mode-line ()
+ "Update mode line."
+ (force-mode-line-update))
+
+;;;;
+;;;; Format of a status
+;;;;
+
+(eval-and-compile
+ (defsubst twittering-make-common-properties (status)
+ "Generate a property list that tweets should have irrespective of format."
+ (apply 'append
+ (mapcar (lambda (entry)
+ (let ((prop-sym (if (consp entry) (car entry) entry))
+ (status-sym (if (consp entry) (cdr entry) entry)))
+ (list prop-sym (cdr (assq status-sym status)))))
+ '(id retweeted-id source-spec
+ (username . user-screen-name) text)))))
+
+(defun twittering-get-common-properties (pos)
+ "Get a common property list of the tweet rendered at POS.
+The common property list is added to each rendered tweet irrespective
+of format. The common properties follows:
+ properites generated by `twittering-make-common-properties',
+ `field' and `rendered-as' generated by `twittering-render-a-field' or
+ `twittering-make-properties-of-popped-ancestors'."
+ (apply 'append
+ (mapcar (lambda (prop)
+ (let ((value (get-text-property pos prop)))
+ (when value
+ `(,prop ,value))))
+ '(field id rendered-as retweeted-id source-spec
+ text username))))
+
+(defun twittering-format-string (string prefix replacement-table)
+ "Format STRING according to PREFIX and REPLACEMENT-TABLE.
+PREFIX is a regexp. REPLACEMENT-TABLE is a list of (FROM . TO) pairs,
+where FROM is a regexp and TO is a string or a 2-parameter function.
+
+The pairs in REPLACEMENT-TABLE are stored in order of precedence.
+First, search PREFIX in STRING from left to right.
+If PREFIX is found in STRING, try to match the following string with
+FROM of each pair in the same order of REPLACEMENT-TABLE. If FROM in
+a pair is matched, replace the prefix and the matched string with a
+string generated from TO.
+If TO is a string, the matched string is replaced with TO.
+If TO is a function, the matched string is replaced with the
+return value of (funcall TO CONTEXT), where CONTEXT is an alist.
+Each element of CONTEXT is (KEY . VALUE) and KEY is one of the
+following symbols;
+ 'following-string --the matched string following the prefix
+ 'match-data --the match-data for the regexp FROM.
+ 'prefix --PREFIX.
+ 'replacement-table --REPLACEMENT-TABLE.
+ 'from --FROM.
+ 'processed-string --the already processed string."
+ (let ((current-pos 0)
+ (result "")
+ (case-fold-search nil))
+ (while (and (string-match prefix string current-pos)
+ (not (eq (match-end 0) current-pos)))
+ (let ((found nil)
+ (current-table replacement-table)
+ (next-pos (match-end 0))
+ (matched-string (match-string 0 string))
+ (skipped-string
+ (substring string current-pos (match-beginning 0))))
+ (setq result (concat result skipped-string))
+ (setq current-pos next-pos)
+ (while (and (not (null current-table))
+ (not found))
+ (let ((key (caar current-table))
+ (value (cdar current-table))
+ (following-string (substring string current-pos))
+ (case-fold-search nil))
+ (if (string-match (concat "\\`" key) following-string)
+ (let ((next-pos (+ current-pos (match-end 0)))
+ (output
+ (if (stringp value)
+ value
+ (funcall value
+ `((following-string . ,following-string)
+ (match-data . ,(match-data))
+ (prefix . ,prefix)
+ (replacement-table . ,replacement-table)
+ (from . ,key)
+ (processed-string . ,result))))))
+ (setq found t)
+ (setq current-pos next-pos)
+ (setq result (concat result output)))
+ (setq current-table (cdr current-table)))))
+ (if (not found)
+ (setq result (concat result matched-string)))))
+ (let ((skipped-string (substring string current-pos)))
+ (concat result skipped-string))
+ ))
+
+(eval-and-compile
+ (defsubst twittering-make-string-with-user-name-property (str status)
+ (if str
+ (let* ((user-screen-name (cdr (assq 'user-screen-name status)))
+ (uri (twittering-get-status-url user-screen-name))
+ (spec
+ (twittering-make-user-timeline-spec-direct user-screen-name)))
+ (propertize str
+ 'mouse-face 'highlight
+ 'keymap twittering-mode-on-uri-map
+ 'uri uri
+ 'screen-name-in-text user-screen-name
+ 'goto-spec spec
+ 'face 'twittering-username-face
+ 'front-sticky nil
+ 'rear-nonsticky t))
+ ""))
+
+ (defsubst twittering-make-string-with-source-property (str status)
+ (if str
+ (let ((uri (cdr (assq 'source-uri status))))
+ (propertize str
+ 'mouse-face 'highlight
+ 'keymap twittering-mode-on-uri-map
+ 'uri uri
+ 'face 'twittering-uri-face
+ 'source str
+ 'front-sticky nil
+ 'rear-nonsticky t))
+ ""))
+
+ (defsubst twittering-make-string-with-uri-property (str status)
+ (if str
+ (let ((uri
+ (if (assq 'retweeted-id status)
+ (twittering-get-status-url
+ (cdr (assq 'retweeted-user-screen-name status))
+ (cdr (assq 'retweeted-id status)))
+ (twittering-get-status-url
+ (cdr (assq 'user-screen-name status))
+ (cdr (assq 'id status))))))
+ (propertize str
+ 'mouse-face 'highlight
+ 'keymap twittering-mode-on-uri-map
+ 'uri uri
+ 'face 'twittering-uri-face
+ 'front-sticky nil
+ 'rear-nonsticky t))
+ "")))
+
+(defun twittering-make-fontified-tweet-text (str-expr regexp-hash regexp-atmark)
+ (let ((regexp-str
+ (mapconcat
+ 'identity
+ (list
+ ;; hashtag
+ (concat regexp-hash "\\([[:alpha:]0-9_-]+\\)")
+ ;; @USER/LIST
+ (concat regexp-atmark
+ "\\(\\([a-zA-Z0-9_-]+\\)/\\([a-zA-Z0-9_-]+\\)\\)")
+ ;; @USER
+ (concat regexp-atmark "\\([a-zA-Z0-9_-]+\\)")
+ ;; URI
+ "\\(https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+\\)")
+ "\\|")))
+ `(let ((pos 0)
+ (str (copy-sequence ,str-expr)))
+ (while (string-match ,regexp-str str pos)
+ (let* ((beg (match-beginning 0))
+ (end (match-end 0))
+ (range-and-properties
+ (cond
+ ((get-text-property beg 'face str)
+ ;; The matched substring has been already fontified.
+ ;; The fontification with entities must fontify the
+ ;; head of the matched string.
+ nil)
+ ((match-string 1 str)
+ ;; hashtag
+ (let* ((hashtag (match-string 1 str))
+ (spec-string
+ (twittering-make-hashtag-timeline-spec-string-direct
+ hashtag))
+ (url (twittering-get-search-url
+ (concat "#" hashtag))))
+ (list
+ beg end
+ 'mouse-face 'highlight
+ 'keymap twittering-mode-on-uri-map
+ 'uri url
+ 'goto-spec spec-string
+ 'face 'twittering-username-face)))
+ ((match-string 2 str)
+ ;; @USER/LIST
+ (let ((owner (match-string 3 str))
+ (list-name (match-string 4 str))
+ ;; Properties are added to the matched part only.
+ ;; The prefixes `twittering-regexp-atmark' will not
+ ;; be highlighted.
+ (beg (match-beginning 2)))
+ (list
+ beg end
+ 'mouse-face 'highlight
+ 'keymap twittering-mode-on-uri-map
+ 'uri (twittering-get-list-url owner list-name)
+ 'goto-spec
+ (twittering-make-list-timeline-spec-direct owner
+ list-name)
+ 'face 'twittering-username-face)))
+ ((match-string 5 str)
+ ;; @USER
+ (let ((screen-name (match-string 5 str))
+ ;; Properties are added to the matched part only.
+ ;; The prefixes `twittering-regexp-atmark' will not
+ ;; be highlighted.
+ (beg (match-beginning 5)))
+ (list
+ beg end
+ 'mouse-face 'highlight
+ 'keymap twittering-mode-on-uri-map
+ 'uri (twittering-get-status-url screen-name)
+ 'screen-name-in-text screen-name
+ 'goto-spec
+ (twittering-make-user-timeline-spec-direct screen-name)
+ 'face 'twittering-uri-face)))
+ ((match-string 6 str)
+ ;; URI
+ (let ((uri (match-string 6 str)))
+ (list
+ beg end
+ 'mouse-face 'highlight
+ 'keymap twittering-mode-on-uri-map
+ 'uri uri
+ 'uri-origin 'explicit-uri-in-tweet
+ 'face 'twittering-uri-face)))))
+ (beg (if range-and-properties
+ (car range-and-properties)
+ beg))
+ (end (if range-and-properties
+ (cadr range-and-properties)
+ end))
+ (properties
+ `(,@(cddr range-and-properties)
+ front-sticky nil
+ rear-nonsticky t)))
+ (when range-and-properties
+ (add-text-properties beg end properties str))
+ (setq pos end)))
+ str)))
+
+(eval-and-compile
+ (defsubst twittering-make-fontified-tweet-text-with-entity (status)
+ (let* ((text (copy-sequence (cdr (assq 'text status))))
+ (text-length (length text))
+ (entities (cdr (assq 'entity status))))
+ ;; hashtags
+ (mapc (lambda (hashtag)
+ (let* ((start (cdr (assq 'start hashtag)))
+ (end (min (cdr (assq 'end hashtag)) text-length))
+ (tag (cdr (assq 'text hashtag)))
+ (spec-string
+ (twittering-make-hashtag-timeline-spec-string-direct tag)))
+ (set-text-properties
+ start end
+ `(mouse-face
+ highlight
+ keymap ,twittering-mode-on-uri-map
+ uri ,(twittering-get-search-url (concat "#" tag))
+ goto-spec ,spec-string
+ face twittering-username-face
+ front-sticky nil
+ rear-nonsticky t)
+ text)))
+ (cdr (assq 'hashtags entities)))
+ ;; mentions
+ (mapc (lambda (mention)
+ (let ((start (cdr (assq 'start mention)))
+ (end (min (cdr (assq 'end mention)) text-length))
+ (screen-name (cdr (assq 'screen-name mention))))
+ (set-text-properties
+ start end
+ `(mouse-face
+ highlight
+ keymap ,twittering-mode-on-uri-map
+ uri ,(twittering-get-status-url screen-name)
+ screen-name-in-text ,screen-name
+ goto-spec
+ ,(twittering-make-user-timeline-spec-direct screen-name)
+ face twittering-uri-face
+ front-sticky nil
+ rear-nonsticky t)
+ text)))
+ (cdr (assq 'mentions entities)))
+ ;; urls
+ (let ((offset 0))
+ (mapc (lambda (url-info)
+ (let* ((text-length (length text))
+ (start (cdr (assq 'start url-info)))
+ (end (cdr (assq 'end url-info)))
+ (url (cdr (assq 'url url-info)))
+ (expanded-url
+ ;; If the `url' is short and not wrapped,
+ ;; `expanded-url' is nil.
+ (or (cdr (assq 'expanded-url url-info))
+ url))
+ (replacement
+ (propertize
+ expanded-url
+ 'mouse-face 'highlight
+ 'keymap twittering-mode-on-uri-map
+ 'uri url
+ 'uri-origin 'explicit-uri-in-tweet
+ 'expanded-uri expanded-url
+ 'face 'twittering-uri-face
+ 'front-sticky nil
+ 'rear-nonsticky t)))
+ (setq text
+ (concat
+ (substring text 0 (min (+ offset start) text-length))
+ replacement
+ (substring text (min (+ offset end) text-length))))
+ (setq offset
+ (+ offset (- (length expanded-url) (- end start))))))
+ (cdr (assq 'urls entities))))
+ text)))
+
+(defun twittering-generate-format-table (status-sym prefix-sym)
+ `(("%" . "%")
+ ("}" . "}")
+ ("#" . (cdr (assq 'id ,status-sym)))
+ ("'" . (when (cdr (assq 'truncated ,status-sym))
+ "..."))
+ ("c" .
+ (let ((system-time-locale "C"))
+ (format-time-string "%a %b %d %H:%M:%S %z %Y"
+ (cdr (assq 'created-at ,status-sym)))))
+ ("d" . (cdr (assq 'user-description ,status-sym)))
+ ("f" .
+ (twittering-make-string-with-source-property
+ (cdr (assq 'source ,status-sym)) ,status-sym))
+ ("i" .
+ (when (and twittering-icon-mode window-system)
+ (let ((url
+ (cond
+ ((and twittering-use-profile-image-api
+ (eq twittering-service-method 'twitter)
+ (or (null twittering-convert-fix-size)
+ (member twittering-convert-fix-size '(48 73))))
+ (let ((user (cdr (assq 'user-screen-name ,status-sym)))
+ (size
+ (if (or (null twittering-convert-fix-size)
+ (= 48 twittering-convert-fix-size))
+ "normal"
+ "bigger")))
+ (format "http://%s/%s/%s.xml?size=%s" twittering-api-host
+ (twittering-api-path "users/profile_image") user size)))
+ (t
+ (cdr (assq 'user-profile-image-url ,status-sym))))))
+ (twittering-make-icon-string nil nil url))))
+ ("j" . (cdr (assq 'user-id ,status-sym)))
+ ("L" .
+ (let ((location (or (cdr (assq 'user-location ,status-sym)) "")))
+ (unless (string= "" location)
+ (concat " [" location "]"))))
+ ("l" . (cdr (assq 'user-location ,status-sym)))
+ ("p" . (when (cdr (assq 'user-protected ,status-sym))
+ "[x]"))
+ ("r" .
+ (let ((reply-id (or (cdr (assq 'in-reply-to-status-id ,status-sym)) ""))
+ (reply-name (or (cdr (assq 'in-reply-to-screen-name ,status-sym))
+ ""))
+ (recipient-screen-name
+ (cdr (assq 'recipient-screen-name ,status-sym))))
+ (let* ((pair
+ (cond
+ (recipient-screen-name
+ (cons (format "sent to %s" recipient-screen-name)
+ (twittering-get-status-url recipient-screen-name)))
+ ((and (not (string= "" reply-id))
+ (not (string= "" reply-name)))
+ (cons (format "in reply to %s" reply-name)
+ (twittering-get-status-url reply-name reply-id)))
+ (t nil)))
+ (str (car pair))
+ (url (cdr pair))
+ (properties
+ (list 'mouse-face 'highlight 'face 'twittering-uri-face
+ 'keymap twittering-mode-on-uri-map
+ 'uri url
+ 'front-sticky nil
+ 'rear-nonsticky t)))
+ (when (and str url)
+ (concat " " (apply 'propertize str properties))))))
+ ("R" .
+ (let ((retweeted-by
+ (or (cdr (assq 'retweeting-user-screen-name ,status-sym)) "")))
+ (unless (string= "" retweeted-by)
+ (concat " (retweeted by " retweeted-by ")"))))
+ ("S" .
+ (twittering-make-string-with-user-name-property
+ (cdr (assq 'user-name ,status-sym)) ,status-sym))
+ ("s" .
+ (twittering-make-string-with-user-name-property
+ (cdr (assq 'user-screen-name ,status-sym)) ,status-sym))
+ ("T" .
+ ,(twittering-make-fontified-tweet-text
+ `(twittering-make-fontified-tweet-text-with-entity ,status-sym)
+ twittering-regexp-hash twittering-regexp-atmark))
+ ("t" .
+ ,(twittering-make-fontified-tweet-text
+ `(twittering-make-fontified-tweet-text-with-entity ,status-sym)
+ twittering-regexp-hash twittering-regexp-atmark))
+ ("u" . (cdr (assq 'user-url ,status-sym)))))
+
+(defun twittering-generate-formater-for-first-spec (format-str status-sym prefix-sym)
+ (cond
+ ((string-match "\\`}" format-str)
+ ;; "}" at the first means the end of the current level.
+ `(nil . ,(substring format-str (match-end 0))))
+ ((string-match "\\`%" format-str)
+ (let* ((following (substring format-str 1))
+ (table (twittering-generate-format-table status-sym prefix-sym))
+ (regexp (concat "\\`\\(" (mapconcat 'car table "\\|") "\\)"))
+ (case-fold-search nil))
+ (cond
+ ((string-match "\\`@\\({\\([^}]*\\)}\\)?" following)
+ (let ((time-format (or (match-string 2 following)
+ "%I:%M %p %B %d, %Y"))
+ (rest (substring following (match-end 0))))
+ `((let* ((created-at (cdr (assq 'created-at ,status-sym)))
+ (url
+ (if (assq 'retweeted-id ,status-sym)
+ (twittering-get-status-url
+ (cdr (assq 'retweeted-user-screen-name ,status-sym))
+ (cdr (assq 'retweeted-id ,status-sym)))
+ (twittering-get-status-url
+ (cdr (assq 'user-screen-name ,status-sym))
+ (cdr (assq 'id ,status-sym)))))
+ (properties
+ (list 'mouse-face 'highlight 'face 'twittering-uri-face
+ 'keymap twittering-mode-on-uri-map
+ 'uri url
+ 'front-sticky nil
+ 'rear-nonsticky t)))
+ (twittering-make-passed-time-string
+ nil nil created-at ,time-format properties))
+ . ,rest)))
+ ((string-match "\\`C\\({\\([^}]*\\)}\\)?" following)
+ (let ((time-format (or (match-string 2 following) "%H:%M:%S"))
+ (rest (substring following (match-end 0))))
+ `((let* ((created-at (cdr (assq 'created-at ,status-sym))))
+ (twittering-make-string-with-uri-property
+ (format-time-string ,time-format created-at) ,status-sym))
+ . ,rest)))
+ ((string-match "\\`FACE\\[\\([a-zA-Z0-9:-]+\\)\\]{" following)
+ (let* ((face-name-str (match-string 1 following))
+ (str-after-brace (substring following (match-end 0)))
+ (face-sym (intern face-name-str))
+ (pair (twittering-generate-formater-for-current-level
+ str-after-brace status-sym prefix-sym))
+ (braced-body (car pair))
+ (rest (cdr pair)))
+ `((propertize (concat ,@braced-body) 'face ',face-sym)
+ . ,rest)))
+ ((string-match "\\`FIELD\\(\\[\\([^]]*\\)\\]\\)?{\\([a-z_]*\\)}"
+ following)
+ (let* ((format-str (or (match-string 2 following) "%s"))
+ (field-raw-name (match-string 3 following))
+ (field-name (replace-regexp-in-string "_" "-" field-raw-name))
+ (field-symbol (intern field-name))
+ (rest (substring following (match-end 0))))
+ `((let* ((field-value (cdr (assq ',field-symbol ,status-sym))))
+ (if field-value
+ (format ,format-str field-value)
+ ""))
+ . ,rest)))
+ ((string-match "\\`FIELD-IF-NONZERO\\(\\[\\([^]]*\\)\\]\\)?{\\([a-z_]*\\)}"
+ following)
+ (let* ((format-str (or (match-string 2 following) "%s"))
+ (field-raw-name (match-string 3 following))
+ (field-name (replace-regexp-in-string "_" "-" field-raw-name))
+ (field-symbol (intern field-name))
+ (rest (substring following (match-end 0))))
+ `((let* ((field-value (cdr (assq ',field-symbol ,status-sym))))
+ (if (and (integerp field-value)
+ (not (zerop field-value)))
+ (format ,format-str field-value)
+ ""))
+ . ,rest)))
+ ((string-match "\\`\\(FILL\\|FOLD\\)\\(\\[\\([^]]*\\)\\]\\)?{"
+ following)
+ (let* ((str-after-brace (substring following (match-end 0)))
+ (specifier (match-string 1 following))
+ (prefix-str (match-string 3 following))
+ (pair (twittering-generate-formater-for-current-level
+ str-after-brace status-sym prefix-sym))
+ (filled-body (car pair))
+ (formater
+ `(lambda (,status-sym ,prefix-sym)
+ (let ((,prefix-sym (concat ,prefix-sym ,prefix-str)))
+ (concat ,@filled-body))))
+ (keep-newline (string= "FOLD" specifier))
+ (rest (cdr pair)))
+ `((twittering-update-filled-string
+ nil nil ,formater ,status-sym ,prefix-sym ,prefix-str
+ ,keep-newline)
+ . ,rest)))
+ ((string-match "\\`RT{" following)
+ (let* ((str-after-brace (substring following (match-end 0)))
+ (pair (twittering-generate-formater-for-current-level
+ str-after-brace 'retweeting prefix-sym))
+ (braced-body (car pair))
+ (rest (cdr pair)))
+ `((when (assq 'retweeted-id ,status-sym)
+ (let ((retweeting
+ (mapcar (lambda (entry)
+ (let ((key-str (symbol-name (car entry)))
+ (value (cdr entry)))
+ (when (string-match "\\`retweeting-" key-str)
+ (let ((new-key
+ (intern (substring key-str
+ (match-end 0)))))
+ (cons new-key value)))))
+ ,status-sym)))
+ (concat ,@braced-body)))
+ . ,rest)))
+ ((string-match regexp following)
+ (let ((specifier (match-string 1 following))
+ (rest (substring following (match-end 0))))
+ `(,(cdr (assoc specifier table)) . ,rest)))
+ (t
+ `("%" . ,following)))))
+ ((string-match "\\(%\\|}\\)" format-str)
+ (let* ((sep (match-beginning 0))
+ (first (substring format-str 0 sep))
+ (last (substring format-str sep)))
+ ;; Split before "%" or "}".
+ `(,first . ,last)))
+ (t
+ `(,format-str . nil))))
+
+(defun twittering-generate-formater-for-current-level (format-str status-sym prefix-sym)
+ (let ((result nil)
+ (rest format-str)
+ (continue t))
+ (while (and continue rest)
+ (let* ((pair
+ (twittering-generate-formater-for-first-spec
+ rest status-sym prefix-sym))
+ (current-result (car pair)))
+ (if current-result
+ (setq result (append result `(,current-result)))
+ ;; If `result' is nil, it means the end of the current level.
+ (setq continue nil))
+ (setq rest (cdr pair))))
+ `(,result . ,rest)))
+
+(defun twittering-generate-format-status-function (format-str)
+ (let* ((status-sym 'status)
+ (prefix-sym 'prefix)
+ (pair
+ (twittering-generate-formater-for-current-level
+ format-str status-sym prefix-sym))
+ (body (car pair))
+ (rest (cdr pair)))
+ (cond
+ ((null rest)
+ `(lambda (status prefix)
+ (let* ((common-properties (twittering-make-common-properties status))
+ (str (concat ,@body))
+ (str (if prefix
+ (replace-regexp-in-string "^" prefix str)
+ str))
+ (next (next-single-property-change 0 'need-to-be-updated str))
+ (need-to-be-updated
+ (or (get-text-property 0 'need-to-be-updated str)
+ (and next (< next (length str))))))
+ (add-text-properties 0 (length str) common-properties str)
+ (when (and prefix need-to-be-updated)
+ ;; With a prefix, redisplay the total status instead of
+ ;; redisplaying partially.
+ (remove-text-properties 0 (length str)
+ '(need-to-be-updated nil) str)
+ (put-text-property 0 (length str) 'need-to-be-updated
+ `(twittering-format-status-for-redisplay
+ ,status ,prefix)
+ str))
+ str)))
+ (t
+ (message "Failed to generate a status formater for `twittering-mode'.")
+ nil))))
+
+(defun twittering-update-status-format (&optional format-str)
+ "Update the format for rendering a tweet.
+If FORMAT-STR is nil, `twittering-status-format' is used in place of
+FORMAT-STR.
+
+If FORMAT-STR is valid as a format, `twittering-format-status-function'
+is replaced by the result of `twittering-generate-format-status-function'
+for FORMAT-STR.
+If FORMAT-STR is invalid as a format, an error is signaled and
+`twittering-format-status-function' is not updated."
+ (let ((format-str (or format-str twittering-status-format)))
+ (unless (string= format-str twittering-format-status-function-source)
+ (let* ((before (get-buffer "*Compile-Log*"))
+ (func (twittering-generate-format-status-function format-str)))
+ (cond
+ ((and func (functionp func))
+ (setq twittering-format-status-function-source format-str)
+ (setq twittering-format-status-function (byte-compile func))
+ (setq twittering-format-status-function-without-compile func)
+ (setq twittering-status-format format-str)
+ (let ((current (get-buffer "*Compile-Log*")))
+ (when (and (null before) current (= 0 (buffer-size current)))
+ (kill-buffer current))))
+ (t
+ (error "Invalid format: %s" format-str)
+ nil))))))
+
+(defun twittering-format-status (status &optional prefix)
+ "Format a STATUS by using `twittering-format-status-function'.
+Specification of FORMAT-STR is described in the document for the
+variable `twittering-status-format'."
+ (funcall twittering-format-status-function status prefix))
+
+(defun twittering-format-status-for-redisplay (beg end status &optional prefix)
+ (twittering-format-status status prefix))
+
+;;;;
+;;;; Rendering
+;;;;
+
+(defun twittering-field-id< (field1 field2)
+ (string< field1 field2))
+
+(defun twittering-field-id= (field1 field2)
+ (string= field1 field2))
+
+(defun twittering-make-field-id-from-id (id &optional base-id)
+ "Generate a field property for the tweet corresponding to ID.
+Tweets are rendered in order of the field on `twittering-mode'.
+
+If BASE-ID is non-nil, generate a field id for a tweet rendered
+as a popped ancestor tweet by `twittering-show-replied-statuses'.
+In the case, BASE-ID means the ID of the descendant."
+ (let ((format-func (lambda (id) (format "%02d-%s" (length id) id))))
+ (cond
+ (base-id
+ (format "O:%s:5:ancestor:%s"
+ (funcall format-func base-id)
+ (funcall format-func id)))
+ (t
+ (format "O:%s:8" (funcall format-func id))))))
+
+(defun twittering-make-field-id (status &optional base-id)
+ "Generate a field property for STATUS.
+Tweets are rendered in order of the field on `twittering-mode'.
+
+If BASE-ID is non-nil, generate a field id for a tweet rendered
+as a popped ancestor tweet by `twittering-show-replied-statuses'.
+In the case, BASE-ID means the ID of the descendant."
+ (let ((id (cdr (assq 'id status))))
+ (twittering-make-field-id-from-id id base-id)))
+
+(defun twittering-make-properties-of-popped-ancestors (base-id)
+ `(rendered-as ((ancestor-of . ,base-id))))
+
+(defun twittering-make-field-id-of-timeline-oldest-end (spec-string)
+ "Return the field ID for the oldest end.
+This is given to a special field, header or footer, which does not correspond
+to a tweet.
+It must be less than IDs made by `twittering-make-field-id' for any other
+normal fields in the meaning of `twittering-field-id<'."
+ (format "H:%s" spec-string))
+
+(defun twittering-make-field-id-of-timeline-latest-end (spec-string)
+ "Return the field ID for the oldest end.
+This is given to a special field, header or footer, which does not correspond
+to a tweet.
+It must be greater than IDs made by `twittering-make-field-id' for any other
+normal fields in the meaning of `twittering-field-id<'."
+ (format "U:%s" spec-string))
+
+(defun twittering-field-id-is-timeline-oldest-end (field-id)
+ "Return non-nil if FIELD-ID corresponds to the oldest end field.
+Return non-nil if FIELD-ID is made by
+`twittering-make-field-id-of-timeline-oldest-end'."
+ (and (stringp field-id) (string= (substring field-id 0 2) "H:")))
+
+(defun twittering-field-id-is-timeline-latest-end (field-id)
+ "Return non-nil if FIELD-ID corresponds to the latest end field.
+Return non-nil if FIELD-ID is made by
+`twittering-make-field-id-of-timeline-latest-end'."
+ (and (stringp field-id) (string= (substring field-id 0 2) "U:")))
+
+(defun twittering-rendered-as-ancestor-status-p (&optional pos)
+ "Return non-nil if the status at POS is rendered as an ancestor.
+Ancestor statuses are rendered by `twittering-show-replied-statuses'."
+ (let ((pos (or pos (point))))
+ (assq 'ancestor-of (get-text-property pos 'rendered-as))))
+
+(defun twittering-get-base-id-of-ancestor-at (&optional pos)
+ "Return the base ID of a popped ancestor status rendered at POS.
+If the status at POS is not a popped ancestor status or no status is
+rendered at POS, return nil."
+ (let ((pos (or pos (point))))
+ (cdr (assq 'ancestor-of (get-text-property pos 'rendered-as)))))
+
+(eval-and-compile
+ (defsubst twittering-fill-string (str &optional adjustment prefix keep-newline)
+ (when (and (not (boundp 'kinsoku-limit))
+ enable-kinsoku)
+ ;; `kinsoku-limit' is defined on loading "international/kinsoku.el".
+ ;; Without preloading, "kinsoku.el" will be loaded by auto-loading
+ ;; triggered by `fill-region-as-paragraph'.
+ ;; In that case, the local binding of `kinsoku-limit' conflicts the
+ ;; definition by `defvar' in "kinsoku.el".
+ ;; The below warning is displayed;
+ ;; "Warning: defvar ignored because kinsoku-limit is let-bound".
+ ;; So, we load "kinsoku.el" in advance if necessary.
+ (load "international/kinsoku"))
+ (let* ((kinsoku-limit 1)
+ (adjustment (+ (or adjustment 0)
+ (if enable-kinsoku
+ kinsoku-limit
+ 0)))
+ (min-width
+ (apply 'min
+ (or
+ (mapcar 'window-width
+ (get-buffer-window-list (current-buffer) nil t))
+ ;; Use `(frame-width)' if no windows display
+ ;; the current buffer.
+ `(,(frame-width)))))
+ (temporary-fill-column (- (or twittering-fill-column (1- min-width))
+ adjustment)))
+ (with-temp-buffer
+ (let ((fill-column temporary-fill-column)
+ (fill-prefix (or prefix fill-prefix))
+ (adaptive-fill-regexp ""))
+ (if keep-newline
+ (let* ((hard-newline (propertize "\n" 'hard t))
+ (str (mapconcat 'identity (split-string str "\n")
+ (concat hard-newline fill-prefix))))
+ (use-hard-newlines)
+ (insert (concat prefix str))
+ (fill-region (point-min) (point-max) nil t)
+ (remove-text-properties (point-min) (point-max) '(hard nil)))
+ (insert (concat prefix str))
+ (fill-region-as-paragraph (point-min) (point-max)))
+ (buffer-substring (point-min) (point-max))))))
+
+ (defsubst twittering-update-filled-string (beg end formater status prefix local-prefix &optional keep-newline)
+ (let* ((str (twittering-fill-string (funcall formater status prefix)
+ (length prefix) local-prefix
+ keep-newline))
+ (next (next-single-property-change 0 'need-to-be-updated str)))
+ (if (or (get-text-property 0 'need-to-be-updated str)
+ (and next (< next (length str))))
+ (put-text-property 0 (length str) 'need-to-be-updated
+ `(twittering-update-filled-string
+ ,formater ,status ,prefix ,local-prefix
+ ,keep-newline)
+ str)
+ ;; Remove the property required no longer.
+ (remove-text-properties 0 (length str) '(need-to-be-updated nil) str))
+ str))
+
+ (defsubst twittering-make-passed-time-string
+ (beg end encoded-created-at time-format &optional additional-properties)
+ (let* ((now (current-time))
+ (secs (+ (* (- (car now) (car encoded-created-at)) 65536)
+ (- (cadr now) (cadr encoded-created-at))))
+ (time-string
+ (cond
+ ((< secs 5) "less than 5 seconds ago")
+ ((< secs 10) "less than 10 seconds ago")
+ ((< secs 20) "less than 20 seconds ago")
+ ((< secs 30) "half a minute ago")
+ ((< secs 60) "less than a minute ago")
+ ((< secs 150) "1 minute ago")
+ ((< secs 2400) (format "%d minutes ago"
+ (/ (+ secs 30) 60)))
+ ((< secs 5400) "about 1 hour ago")
+ ((< secs 84600) (format "about %d hours ago"
+ (/ (+ secs 1800) 3600)))
+ (t (format-time-string time-format encoded-created-at))))
+ (properties (append additional-properties
+ (and beg (text-properties-at beg))))
+ (time-string
+ ;; Copy a string and restore properties.
+ (apply 'propertize time-string properties)))
+ (if (< secs 84600)
+ (put-text-property 0 (length time-string)
+ 'need-to-be-updated
+ `(twittering-make-passed-time-string
+ ,encoded-created-at ,time-format)
+ time-string)
+ ;; Remove the property required no longer.
+ (remove-text-properties 0 (length time-string)
+ '(need-to-be-updated nil)
+ time-string))
+ time-string)))
+
+(defmacro twittering-render-a-field (pos field-id generator &optional without-separator)
+ "Render a field on the current buffer managed by `twittering-mode'.
+Insert a field to the position pointed by FIELD-ID. The position is searched
+after POS. The string for the field is generated by the GENERATOR expression.
+This function does not render the status if a status with the same field ID
+as FIELD-ID is already rendered.
+Return non-nil if the status is rendered. Otherwise, return nil."
+ `(lexical-let ((pos ,pos)
+ (field-id ,field-id))
+ (while
+ (let ((buf-field-id (get-text-property pos 'field)))
+ (if (and buf-field-id
+ (if twittering-reverse-mode
+ (twittering-field-id< buf-field-id field-id)
+ (twittering-field-id< field-id buf-field-id)))
+ (let ((next-pos
+ (twittering-get-next-status-head pos)))
+ (setq pos (or next-pos (point-max)))
+ next-pos)
+ nil)))
+ (goto-char pos)
+ (unless (twittering-field-id= field-id (get-text-property pos 'field))
+ (let ((formatted-status (propertize ,generator 'field ,field-id))
+ (separator (if ,without-separator
+ ""
+ "\n")))
+ (if (eq pos (point-max))
+ ;; Use `insert' only if no statuses are rendered on the below.
+ (insert formatted-status separator)
+ ;; Use `insert-before-markers' in order to keep
+ ;; which status is pointed by each marker.
+ (insert-before-markers formatted-status separator))
+ t))))
+
+(defun twittering-render-timeline (buffer timeline-data &optional invoke-hook keep-point)
+ "Render statuses for BUFFER and return the list of the rendered statuses.
+TIMELINE-DATA is a list of statuses being rendered.
+If INVOKE-HOOK is non-nil and one or more tweets are rendered, run hooks
+specified by `twittering-new-tweets-rendered-hook'.
+If KEEP-POINT is nil and BUFFER is empty, this function moves cursor positions
+to the latest status.
+
+This function returns a list of the statuses newly rendered by the invocation."
+ (with-current-buffer buffer
+ (let* ((spec (twittering-get-timeline-spec-for-buffer buffer))
+ (referring-id-table
+ (twittering-current-timeline-referring-id-table spec))
+ (timeline-data
+ ;; Collect visible statuses.
+ (let ((prev-id nil))
+ (remove
+ nil
+ (mapcar
+ (lambda (status)
+ (let ((id (cdr (assq 'id status)))
+ (retweeted-id (cdr (assq 'retweeted-id status))))
+ (if (twittering-status-id= prev-id id)
+ ;; `status' is equivalent the previous one.
+ nil
+ (setq prev-id id)
+ (cond
+ ((null retweeted-id)
+ ;; `status' is not a retweet.
+ status)
+ ((and retweeted-id
+ (twittering-status-id=
+ id (gethash retweeted-id referring-id-table)))
+ ;; `status' is the first retweet.
+ status)
+ ((null (gethash retweeted-id referring-id-table))
+ ;; If the first ID referring the retweet is unknown,
+ ;; render it.
+ ;; This is necessary because a referring ID table
+ ;; of a composite timeline may lack information of
+ ;; some component timelines.
+ status)
+ (t
+ ;; Otherwise, do not render it.
+ nil)))))
+ timeline-data))))
+ (timeline-data (if twittering-reverse-mode
+ (reverse timeline-data)
+ timeline-data))
+ (rendering-entire (null (twittering-get-first-status-head)))
+ (result-tweets nil)
+ (buffer-read-only nil))
+ (twittering-update-status-format)
+ (twittering-update-mode-line)
+ (save-excursion
+ (let ((pos (point-min))
+ (spec-string
+ (twittering-get-timeline-spec-string-for-buffer buffer)))
+ (cond
+ (rendering-entire
+ (let* ((latest-id
+ (twittering-make-field-id-of-timeline-latest-end
+ spec-string))
+ (oldest-id
+ (twittering-make-field-id-of-timeline-oldest-end
+ spec-string))
+ (footer-id
+ (if twittering-reverse-mode
+ latest-id
+ oldest-id))
+ (header-id
+ (if twittering-reverse-mode
+ oldest-id
+ latest-id)))
+ (setq
+ pos
+ (let ((footer
+ ;; To avoid adding a face to newlines.
+ (mapconcat
+ (lambda (substr)
+ (propertize substr
+ 'face twittering-timeline-footer-face))
+ (split-string (or twittering-timeline-footer "") "\n")
+ "\n"))
+ (header
+ ;; To avoid adding a face to newlines.
+ (mapconcat
+ (lambda (substr)
+ (propertize substr
+ 'face twittering-timeline-header-face))
+ (split-string (or twittering-timeline-header "") "\n")
+ "\n")))
+ (twittering-render-a-field (point-min) footer-id footer t)
+ (twittering-render-a-field (point-min) header-id header t)
+ (point)))))
+ (t
+ (setq pos (twittering-get-first-status-head))))
+ (goto-char pos)
+ (let* ((rendered-tweets
+ (remove nil
+ (mapcar
+ (lambda (status)
+ (when (twittering-render-a-field
+ (point)
+ (twittering-make-field-id status)
+ (twittering-format-status status))
+ (when twittering-default-show-replied-tweets
+ (twittering-show-replied-statuses
+ twittering-default-show-replied-tweets))
+ status))
+ timeline-data)))
+ (twittering-rendered-new-tweets
+ (if twittering-reverse-mode
+ (reverse rendered-tweets)
+ rendered-tweets))
+ (twittering-rendered-new-tweets-spec spec)
+ (twittering-rendered-new-tweets-spec-string spec-string))
+ (setq result-tweets rendered-tweets)
+ (when (and invoke-hook twittering-rendered-new-tweets)
+ (run-hooks 'twittering-new-tweets-rendered-hook)))))
+ (debug-print (current-buffer))
+ (cond
+ ((and (not keep-point) rendering-entire)
+ ;; Go to the latest status of buffer after full insertion.
+ (let ((dest (if twittering-reverse-mode
+ (or (twittering-get-last-normal-field-head)
+ (twittering-get-last-status-head)
+ (point-max))
+ (or (twittering-get-first-normal-field-head)
+ (twittering-get-first-status-head)
+ (point-min))))
+ (window-list (get-buffer-window-list (current-buffer) nil t)))
+ (if window-list
+ (mapc
+ (lambda (window)
+ (set-window-point window dest)
+ (if twittering-reverse-mode
+ (twittering-set-window-end window (point-max))
+ (set-window-start window (point-min))))
+ window-list)
+ ;; Move the buffer position if the buffer is invisible.
+ (goto-char dest))))
+ )
+ result-tweets)
+ ))
+
+(defun twittering-rerender-timeline-all (buffer &optional restore-point)
+ "Re-render statuses on BUFFER after clearing BUFFER.
+If RESTORE-POINT is non-nil, positions on buffers bound to the same timeline
+will be restored after rendering statuses."
+ (with-current-buffer buffer
+ (let* ((window-list (get-buffer-window-list (current-buffer) nil t))
+ (point-window-list
+ (mapcar (lambda (window)
+ (cons (window-point window) window))
+ window-list))
+ (original-pos (point)))
+ (let ((buffer-read-only nil))
+ (erase-buffer))
+ (twittering-render-timeline
+ (current-buffer) (twittering-current-timeline-data) nil restore-point)
+ (when restore-point
+ ;; Restore points.
+ (mapc (lambda (pair)
+ (let* ((point (car pair))
+ (window (cdr pair))
+ (dest (max (point-max) point)))
+ (set-window-point window dest)))
+ point-window-list)
+ (goto-char original-pos)))))
+
+(defun twittering-retrieve-timeline (spec-string noninteractive api-arguments additional-info)
+ "Retrieve and render a timeline specified by SPEC-STRING.
+Retrieve a timeline specified by SPEC-STRING, which must be a timeline spec
+string. Any timeline spec string including that for composite timeline can be
+used as SPEC-STRING, though the primitive function `twittering-call-api'
+accepts only a spec of a primary timeline.
+
+NONINTERACTIVE is sent to the sentinel as a parameter `noninteractive' via
+an argument `additional-info' of `twittering-call-api'.
+API-ARGUMENTS is also sent to `twittering-call-api' as its argument
+`args-alist'."
+ (let ((spec (twittering-string-to-timeline-spec spec-string)))
+ (cond
+ ((not (twittering-account-authorized-p))
+ ;; ignore any requests if the account has not been authorized.
+ (message "No account for Twitter has been authorized.")
+ t)
+ ((and noninteractive (twittering-process-active-p spec))
+ ;; ignore non-interactive request if a process is waiting for responses.
+ t)
+ ((twittering-timeline-spec-primary-p spec)
+ (let* ((args
+ `(,@api-arguments
+ (timeline-spec . ,spec)
+ (timeline-spec-string . ,spec-string)
+ (format . ,(when (require 'json nil t)
+ 'json))
+ (clean-up-sentinel
+ . ,(lambda (proc status connection-info)
+ (when (memq status '(exit signal closed failed))
+ (twittering-release-process proc))))))
+ (additional-info
+ `(,@additional-info
+ (noninteractive . ,noninteractive)
+ (timeline-spec . ,spec)
+ (timeline-spec-string . ,spec-string)))
+ (proc
+ (twittering-call-api 'retrieve-timeline args additional-info)))
+ (when proc
+ (twittering-register-process proc spec spec-string)
+ (twittering-initialize-retrieval-count spec))))
+ ((twittering-timeline-spec-composite-p spec)
+ (mapc
+ (lambda (spec)
+ (let* ((buffer (twittering-get-buffer-from-spec spec))
+ (spec-string
+ (if buffer
+ (twittering-get-timeline-spec-string-for-buffer buffer)
+ (twittering-timeline-spec-to-string spec))))
+ (twittering-retrieve-timeline spec-string noninteractive
+ api-arguments additional-info)))
+ (twittering-get-base-timeline-specs spec)))
+ (t
+ (let ((type (car spec)))
+ (error "%s has not been supported yet" type))))))
+
+(defun twittering-get-and-render-timeline (&optional noninteractive id spec spec-string)
+ (let* ((spec (or spec (twittering-current-timeline-spec)))
+ (spec-string
+ (or spec-string (twittering-current-timeline-spec-string)))
+ (latest-status
+ ;; Assume that a list which was returned by
+ ;; `twittering-current-timeline-data' is sorted.
+ (car (twittering-current-timeline-data spec)))
+ (since_id (cdr-safe (assq 'id latest-status)))
+ (args `(,@(cond
+ (id `((max_id . ,id)))
+ (since_id `((since_id . ,since_id)))
+ (t nil)))))
+ (twittering-retrieve-timeline spec-string noninteractive args nil)))
+
+;;;;
+;;;; Map function for statuses on buffer
+;;;;
+
+(defun twittering-for-each-property-region (prop func &optional buffer interrupt)
+ "Apply FUNC to each region, where property PROP is non-nil, on BUFFER.
+If INTERRUPT is non-nil, the iteration is stopped if FUNC returns nil."
+ (with-current-buffer (or buffer (current-buffer))
+ (let ((beg (point-min))
+ (end-marker (make-marker)))
+ (set-marker-insertion-type end-marker t)
+ (while
+ (let ((value (get-text-property beg prop)))
+ (if value
+ (let* ((end (next-single-property-change beg prop))
+ (end (or end (point-max)))
+ (end-marker (set-marker end-marker end))
+ (func-result (funcall func beg end value))
+ (end (marker-position end-marker)))
+ (when (or (null interrupt) func-result)
+ (if (get-text-property end prop)
+ (setq beg end)
+ (setq beg (next-single-property-change end prop)))))
+ (setq beg (next-single-property-change beg prop)))))
+ (set-marker end-marker nil))))
+
+;;;;
+;;;; Automatic redisplay of statuses on buffer
+;;;;
+
+(defun twittering-redisplay-status-on-buffer ()
+ (mapc (lambda (buffer)
+ (unless (with-current-buffer buffer
+ (or (and (fboundp 'use-region-p) (use-region-p))
+ (and transient-mark-mode mark-active)))
+ (twittering-redisplay-status-on-each-buffer buffer)))
+ (twittering-get-buffer-list)))
+
+(defun twittering-redisplay-status-on-each-buffer (buffer &optional prop)
+ "Redisplay regions with the text property PROP on BUFFER."
+ (let ((prop (or prop 'need-to-be-updated))
+ (deactivate-mark deactivate-mark)
+ (window-list (get-buffer-window-list buffer nil t))
+ (marker (with-current-buffer buffer (point-marker)))
+ (result nil))
+ (with-current-buffer buffer
+ (save-excursion
+ (twittering-for-each-property-region
+ prop
+ (lambda (beg end value)
+ (let* ((func (car value))
+ (args (cdr value))
+ (current-str (buffer-substring beg end))
+ (updated-str (apply func beg end args))
+ (config (twittering-current-window-config window-list))
+ (buffer-read-only nil))
+ ;; Replace `current-str' if it differs to `updated-str' with
+ ;; ignoring properties. This is an ad-hoc solution.
+ ;; `current-str' is a part of the displayed status, but it has
+ ;; properties which are determined by the whole status.
+ ;; (For example, the `id' property.)
+ ;; Therefore, we cannot compare the strings with their
+ ;; properties.
+ (unless (string= current-str updated-str)
+ ;; If the region to be modified includes the current position,
+ ;; the point moves to the beginning of the region.
+ (when (and (< beg marker) (< marker end))
+ ;; This is required because the point moves to the center if
+ ;; the point becomes outside of the window by the effect of
+ ;; `set-window-start'.
+ (setq result beg))
+ (let ((common-properties
+ (twittering-get-common-properties beg)))
+ ;; Restore common properties.
+ (delete-region beg end)
+ (goto-char beg)
+ (insert (apply 'propertize updated-str common-properties)))
+ (twittering-restore-window-config-after-modification
+ config beg end))))
+ buffer))
+ (set-marker marker nil)
+ (when (and result (eq (window-buffer) buffer))
+ (let ((win (selected-window)))
+ (when (< result (window-start win))
+ (set-window-start win result))
+ (set-window-point win result))))))
+
+;;;;
+;;;; Display replied statuses
+;;;;
+
+(defun twittering-replied-statuses-visible-p (&optional pos)
+ "Return non-nil if a replied status related to POS is visible.
+Return non-nil if a replied status has been rendered at POS by
+`twittering-show-replied-statuses'.
+Return non-nil if a reply is rendered at POS and the replied statuses
+has been rendered by `twittering-show-replied-statuses'.
+Otherwise, return nil."
+ (let* ((pos (twittering-get-current-status-head pos))
+ (id (twittering-get-id-at pos))
+ (prev (twittering-get-previous-status-head pos))
+ (next (twittering-get-next-status-head pos)))
+ (when id
+ ;; If ID is nil, it means that no normal tweets are rendered at POS.
+ (or
+ (twittering-get-base-id-of-ancestor-at pos)
+ (and prev
+ (twittering-status-id=
+ id (twittering-get-base-id-of-ancestor-at prev)))
+ (and next
+ (twittering-status-id=
+ id (twittering-get-base-id-of-ancestor-at next)))))))
+
+(defun twittering-get-beginning-of-visible-replied-statuses (&optional pos)
+ "Return the beginning position of visible replied statuses at POS.
+If POS is nil, the current position is used instead.
+If `twittering-show-replied-statuses' has rendered a replied status at POS,
+return the beginning position of the replied statuses with the common base
+status.
+If a reply is rendered at POS and its ancestors has been rendered by
+`twittering-show-replied-statuses', return the beginning position of the
+replied statuses.
+Otherwise, return nil."
+ (let* ((pos (or pos (point)))
+ (base-id (twittering-get-base-id-of-ancestor-at pos)))
+ (cond
+ (base-id
+ ;; A replied status is rendered at POS.
+ (while
+ (let* ((prev (twittering-get-previous-status-head pos))
+ (prev-base-id
+ (when prev
+ (twittering-get-base-id-of-ancestor-at prev))))
+ (and prev prev-base-id
+ (twittering-status-id= base-id prev-base-id)
+ (setq pos prev))))
+ (or pos (point-min)))
+ ((twittering-replied-statuses-visible-p pos)
+ ;; A reply is rendered at POS and its replied statuses are visible.
+ (if twittering-reverse-mode
+ (twittering-get-beginning-of-visible-replied-statuses
+ (twittering-get-previous-status-head pos))
+ (twittering-get-next-status-head pos)))
+ (t
+ nil))))
+
+(defun twittering-get-end-of-visible-replied-statuses (&optional pos)
+ "Return the end position of visible replied statuses at POS.
+If POS is nil, the current position is used instead.
+If `twittering-show-replied-statuses' has rendered a replied status at POS,
+return the end position of the replied statuses with the common base status.
+If a reply is rendered at POS and its ancestors has been rendered by
+`twittering-show-replied-statuses', return the beginning position of the
+replied statuses.
+Otherwise, return nil."
+ (let* ((pos (or pos (point)))
+ (base-id (twittering-get-base-id-of-ancestor-at pos)))
+ (cond
+ (base-id
+ ;; A replied status is rendered at POS.
+ (while
+ (let ((current-base-id (twittering-get-base-id-of-ancestor-at pos)))
+ (and current-base-id
+ (twittering-status-id= base-id current-base-id)
+ (setq pos (twittering-get-next-status-head pos)))))
+ (or pos (point-max)))
+ ((twittering-replied-statuses-visible-p pos)
+ ;; A reply is rendered at POS and its replied statuses are visible.
+ (if twittering-reverse-mode
+ (twittering-get-current-status-head pos)
+ (twittering-get-end-of-visible-replied-statuses
+ (twittering-get-next-status-head pos))))
+ (t
+ nil))))
+
+(defun twittering-render-replied-statuses (&optional pos count)
+ "Render replied statuses on the position specified by POS.
+If POS is nil, the current position is used instead.
+If COUNT is a positive integer, it specifies the number of rendered statuses.
+If COUNT is nil, all ancestor statuses that have been already retrieved are
+rendered.
+
+Return non-nil if one or more statuses are rendered.
+Return nil if no statuses are rendered."
+ (let* ((pos (or pos (point)))
+ (id
+ ;; nil if no normal statuses are rendered at POS.
+ (twittering-get-id-at pos))
+ (replied-status-are-visible
+ (when id
+ (twittering-replied-statuses-visible-p pos)))
+ (base-id (if replied-status-are-visible
+ (or
+ ;; If a replied status is rendered at POS.
+ (twittering-get-base-id-of-ancestor-at pos)
+ ;; If the base reply is rendered at POS.
+ id)
+ id))
+ (statuses
+ (when base-id
+ (twittering-get-replied-statuses base-id (if (numberp count)
+ count))))
+ (statuses (if twittering-reverse-mode
+ statuses
+ (reverse statuses))))
+ (cond
+ ((null id)
+ ;; No normal statuses are rendered here.
+ nil)
+ (statuses
+ (let ((pos
+ (cond
+ ((twittering-replied-statuses-visible-p pos)
+ ;; Some replied statuses have been already rendered.
+ (twittering-get-beginning-of-visible-replied-statuses pos))
+ (twittering-reverse-mode
+ (twittering-get-current-status-head pos))
+ (t
+ (or (twittering-get-next-status-head pos)
+ (point-max)))))
+ (prefix " ")
+ (buffer-read-only nil))
+ (save-excursion
+ (goto-char pos)
+ (mapc
+ (lambda (status)
+ (twittering-render-a-field
+ (point)
+ (twittering-make-field-id status base-id)
+ (let ((formatted-status (twittering-format-status status prefix))
+ (field-properties
+ (twittering-make-properties-of-popped-ancestors base-id)))
+ (add-text-properties 0 (length formatted-status)
+ field-properties formatted-status)
+ formatted-status)))
+ statuses)
+ t)))
+ (t
+ nil))))
+
+(defun twittering-render-a-status-with-delay (beg end id prefix)
+ "Render a status with a delay.
+It is assumed that this function is used as a property value that is
+processed by the function `twittering-redisplay-status-on-each-buffer'."
+ (let ((status (twittering-find-status id)))
+ (when status
+ (let ((properties (and beg (text-properties-at beg))))
+ (apply 'propertize (twittering-format-status status prefix)
+ properties)))))
+
+(defun twittering-toggle-or-retrieve-replied-statuses ()
+ "Show/Hide all of replied statuses or retrieve a replied status.
+If the cursor points to a reply or one of expanded replied statuses and
+some of ancestor replied statuses have been already retrieved but they have
+not been rendered, render them.
+If the cursor points to a reply or one of expanded replied statuses and
+all of retrieved ancestor statuses have been already rendered but the oldest
+one of them is also a reply, retrieve the replied status.
+If the cursor points to a reply or one of expanded replied statuses and
+all of ancestor replied statuses have been already rendered, hide them by
+`twittering-hide-replied-statuses'."
+ (interactive)
+ (let* ((pos (point))
+ (pos
+ ;; POS points to the head of the direct reply of the status being
+ ;; retrieved.
+ (cond
+ ((twittering-replied-statuses-visible-p pos)
+ ;; If some replied statuses are visible, find the edge.
+ (if twittering-reverse-mode
+ (twittering-get-beginning-of-visible-replied-statuses pos)
+ (twittering-get-previous-status-head
+ (twittering-get-end-of-visible-replied-statuses pos))))
+ (t
+ (twittering-get-current-status-head pos))))
+ (id (twittering-get-id-at pos))
+ (status (twittering-find-status id))
+ (reply-id (cdr (assq 'in-reply-to-status-id status)))
+ (reply-username (cdr (assq 'in-reply-to-screen-name status)))
+ (base-id (or (twittering-get-base-id-of-ancestor-at pos)
+ id)))
+ (cond
+ ((twittering-find-status reply-id)
+ ;; The status corresponding to REPLY-ID has been already retrieved
+ ;; but it has not been rendered.
+ ;;
+ ;; `twittering-render-replied-statuses' additionally renders all
+ ;; of already retrieved statuses.
+ (twittering-render-replied-statuses))
+ (reply-id
+ (let* ((pos
+ ;; POS points to the position where the new field will be
+ ;; inserted.
+ (if twittering-reverse-mode
+ pos
+ (or (twittering-get-next-status-head pos)
+ (point-max))))
+ (field-id (twittering-make-field-id-from-id reply-id base-id))
+ (prefix " ")
+ (label "[RETRIEVING...]")
+ (symbol-for-redisplay 'waiting-for-retrieval)
+ (properties
+ `(,@(twittering-make-properties-of-popped-ancestors base-id)
+ ,symbol-for-redisplay
+ (twittering-render-a-status-with-delay ,reply-id ,prefix)))
+ (str (apply 'propertize (concat prefix label) properties))
+ (buffer-read-only nil))
+ (twittering-call-api
+ 'retrieve-single-tweet
+ `((id . ,reply-id)
+ (username . ,reply-username)
+ (format . ,(when (require 'json nil t)
+ 'json))
+ (sentinel . twittering-retrieve-single-tweet-sentinel))
+ `((buffer . ,(current-buffer))
+ (property-to-be-redisplayed . ,symbol-for-redisplay)))
+ (save-excursion
+ (goto-char pos)
+ (twittering-render-a-field (point) field-id str))
+ (goto-char pos)))
+ ((twittering-replied-statuses-visible-p)
+ ;; All ancestor replied statuses have been rendered.
+ (twittering-hide-replied-statuses))
+ (t
+ ;; The pointed status is not a reply.
+ (message "This status is not a reply.")))))
+
+(defun twittering-show-replied-statuses (&optional count interactive)
+ (interactive)
+ (cond
+ ((twittering-replied-statuses-visible-p)
+ (when interactive
+ (message "The replied statuses were already showed.")))
+ ((twittering-render-replied-statuses (point) count)
+ t)
+ (t
+ ;; Failed to render replied statuses.
+ (when interactive
+ (let ((base-id (twittering-get-id-at)))
+ (if (twittering-have-replied-statuses-p base-id)
+ (message "The status this replies to has not been fetched yet.")
+ (message "This status is not a reply.")))))))
+
+(defun twittering-hide-replied-statuses (&optional interactive)
+ (interactive)
+ (cond
+ ((twittering-replied-statuses-visible-p)
+ (let* ((pos (twittering-get-current-status-head (point)))
+ (base-id (or (twittering-get-base-id-of-ancestor-at pos)
+ (twittering-get-id-at pos)))
+ (pointing-to-base-status
+ (not (twittering-rendered-as-ancestor-status-p pos)))
+ (beg (twittering-get-beginning-of-visible-replied-statuses pos))
+ (end (twittering-get-end-of-visible-replied-statuses pos))
+ (buffer-read-only nil))
+ (unless pointing-to-base-status
+ (goto-char (if twittering-reverse-mode
+ beg
+ (or (twittering-get-previous-status-head beg)
+ (point-min)))))
+ (delete-region beg end)))
+ (interactive
+ (message "The status this replies to was already hidden."))))
+
+(defun twittering-toggle-show-replied-statuses ()
+ (interactive)
+ (if (twittering-replied-statuses-visible-p)
+ (twittering-hide-replied-statuses (interactive-p))
+ (twittering-show-replied-statuses twittering-show-replied-tweets
+ (interactive-p))))
+
+;;;;
+;;;; Unread statuses info
+;;;;
+
+(defvar twittering-unread-status-info nil
+ "A list of (buffer unread-statuses-counter), where `unread-statuses-counter'
+means the number of statuses retrieved after the last visiting of the buffer.")
+
+(defun twittering-reset-unread-status-info-if-necessary ()
+ (when (twittering-buffer-p)
+ (twittering-set-number-of-unread (current-buffer) 0)))
+
+(defun twittering-set-number-of-unread (buffer number)
+ (let* ((entry (assq buffer twittering-unread-status-info))
+ (current (or (cadr entry) 0)))
+ (unless (= number current)
+ (setq twittering-unread-status-info
+ (cons
+ `(,buffer ,number)
+ (if entry
+ (remq entry twittering-unread-status-info)
+ twittering-unread-status-info))))))
+
+(defun twittering-make-unread-status-notifier-string ()
+ "Generate a string that displays unread statuses."
+ (setq twittering-unread-status-info
+ (remove nil
+ (mapcar (lambda (entry)
+ (when (buffer-live-p (car entry))
+ entry))
+ twittering-unread-status-info)))
+ (let ((sum (apply '+ (mapcar 'cadr twittering-unread-status-info))))
+ (if (= 0 sum)
+ ""
+ (format "tw(%d)" sum))))
+
+(defun twittering-update-unread-status-info ()
+ "Update `twittering-unread-status-info' with new tweets."
+ (let* ((buffer (twittering-get-buffer-from-spec
+ twittering-rendered-new-tweets-spec))
+ (current (or (cadr (assq buffer twittering-unread-status-info)) 0))
+ (result (+ current (length twittering-rendered-new-tweets))))
+ (when buffer
+ (twittering-set-number-of-unread buffer result))))
+
+(defun twittering-enable-unread-status-notifier ()
+ "Enable a notifier of unread statuses on `twittering-mode'."
+ (interactive)
+ (setq twittering-unread-status-info
+ (mapcar (lambda (buffer) `(,buffer ,0))
+ (twittering-get-buffer-list)))
+ (add-hook 'twittering-new-tweets-rendered-hook
+ 'twittering-update-unread-status-info)
+ (add-hook 'post-command-hook
+ 'twittering-reset-unread-status-info-if-necessary)
+ (add-to-list 'global-mode-string
+ '(:eval (twittering-make-unread-status-notifier-string))
+ t))
+
+(defun twittering-disable-unread-status-notifier ()
+ "Disable a notifier of unread statuses on `twittering-mode'."
+ (interactive)
+ (setq twittering-unread-status-info nil)
+ (remove-hook 'twittering-new-tweets-hook
+ 'twittering-update-unread-status-info)
+ (remove-hook 'post-command-hook
+ 'twittering-reset-unread-status-info-if-necessary)
+ (setq global-mode-string
+ (remove '(:eval (twittering-make-unread-status-notifier-string))
+ global-mode-string)))
+
+;;;;
+;;;; Timer
+;;;;
+
+(defvar twittering-idle-timer-for-redisplay nil)
+
+(defun twittering-timer-action (func)
+ (let ((buf (twittering-get-active-buffer-list)))
+ (if (null buf)
+ (twittering-stop)
+ (funcall func)
+ )))
+
+(defun twittering-run-on-idle (idle-interval func &rest args)
+ "Run FUNC the next time Emacs is idle for IDLE-INTERVAL.
+Even if Emacs has been idle longer than IDLE-INTERVAL, run FUNC immediately.
+Since immediate invocation requires `current-idle-time', it is available
+on Emacs 22 and later.
+FUNC is called as (apply FUNC ARGS)."
+ (let ((sufficiently-idling
+ (and (fboundp 'current-idle-time)
+ (current-idle-time)
+ (time-less-p (seconds-to-time idle-interval)
+ (current-idle-time)))))
+ (if (not sufficiently-idling)
+ (apply 'run-with-idle-timer idle-interval nil func args)
+ (apply func args)
+ nil)))
+
+(defun twittering-run-repeatedly-on-idle (check-interval var idle-interval func &rest args)
+ "Run FUNC every time Emacs is idle for IDLE-INTERVAL.
+Even if Emacs remains idle longer than IDLE-INTERVAL, run FUNC every
+CHECK-INTERVAL seconds. Since this behavior requires `current-idle-time',
+invocation on long idle time is available on Emacs 22 and later.
+VAR is a symbol of a variable to which the idle-timer is bound.
+FUNC is called as (apply FUNC ARGS)."
+ (apply 'run-at-time "0 sec"
+ check-interval
+ (lambda (var idle-interval func &rest args)
+ (let ((registerd (symbol-value var))
+ (sufficiently-idling
+ (and (fboundp 'current-idle-time)
+ (current-idle-time)
+ (time-less-p (seconds-to-time idle-interval)
+ (current-idle-time)))))
+ (when (or (not registerd) sufficiently-idling)
+ (when (and registerd sufficiently-idling)
+ (cancel-timer (symbol-value var))
+ (apply func args))
+ (set var (apply 'run-with-idle-timer idle-interval nil
+ (lambda (var func &rest args)
+ (set var nil)
+ (apply func args))
+ var func args)))))
+ var idle-interval func args))
+
+(defun twittering-start (&optional action)
+ (interactive)
+ (unless twittering-timer
+ (let ((action (or action #'twittering-update-active-buffers)))
+ ;; Update all active timelines forcibly.
+ (twittering-update-active-buffers t)
+ (setq twittering-timer
+ (run-at-time (format "%d sec" twittering-timer-interval)
+ twittering-timer-interval
+ #'twittering-timer-action action))))
+ (unless twittering-timer-for-redisplaying
+ (setq twittering-timer-for-redisplaying
+ (twittering-run-repeatedly-on-idle
+ (* 2 twittering-timer-interval-for-redisplaying)
+ 'twittering-idle-timer-for-redisplay
+ twittering-timer-interval-for-redisplaying
+ #'twittering-redisplay-status-on-buffer))))
+
+(defun twittering-stop ()
+ (interactive)
+ (when twittering-timer
+ (cancel-timer twittering-timer)
+ (setq twittering-timer nil))
+ (when twittering-timer-for-redisplaying
+ (when twittering-idle-timer-for-redisplay
+ (cancel-timer twittering-idle-timer-for-redisplay)
+ (setq twittering-idle-timer-for-redisplay))
+ (cancel-timer twittering-timer-for-redisplaying)
+ (setq twittering-timer-for-redisplaying nil)))
+
+(defun twittering-get-relative-interval (spec)
+ (let* ((spec-string (twittering-timeline-spec-to-string spec))
+ (normalized-alist
+ (apply 'append
+ (mapcar
+ (lambda (entry)
+ (let ((interval (car (last entry)))
+ (regexp-list (butlast entry 1)))
+ (when (integerp interval)
+ (mapcar (lambda (regexp) `(,regexp . ,interval))
+ regexp-list))))
+ twittering-relative-retrieval-interval-alist)))
+ (rest normalized-alist)
+ (current normalized-alist)
+ (result 0))
+ (while (not
+ (or (and (stringp (car current))
+ (string-match (car current) spec-string))
+ (eq t (car current))))
+ (setq current (car rest))
+ (setq rest (cdr rest)))
+ (if (integerp (cdr current))
+ (cdr current)
+ ;; The default relative interval is 1.
+ 1)))
+
+(defun twittering-get-retrieval-count (spec)
+ (cdr (assoc spec twittering-relative-retrieval-count-alist)))
+
+(defun twittering-set-retrieval-count (spec count)
+ (let ((current (assoc spec twittering-relative-retrieval-count-alist)))
+ (if (null current)
+ (add-to-list 'twittering-relative-retrieval-count-alist
+ `(,spec . ,count))
+ (setcdr current count))))
+
+(defun twittering-initialize-retrieval-count (spec)
+ (twittering-set-retrieval-count spec
+ (twittering-get-relative-interval spec)))
+
+(defun twittering-update-active-buffers (&optional force noninteractive)
+ "Update active buffers managed by `twittering-mode' at a certain interval.
+
+If FORCE is nil, each active buffer is updated at a relative interval
+determined by `twittering-relative-retrieval-interval-alist'.
+If a relative interval of a timeline is 3, the timeline is updated once
+by three invocations of this function.
+
+If FORCE is non-nil, all active buffers are updated forcibly."
+ (when (twittering-account-authorized-p)
+ (twittering-update-service-configuration)
+ (let* ((buffer-list (twittering-get-active-buffer-list))
+ (primary-spec-list
+ (twittering-remove-duplicates
+ (apply 'append
+ (mapcar
+ (lambda (buffer)
+ (twittering-get-primary-base-timeline-specs
+ (twittering-get-timeline-spec-for-buffer buffer)))
+ buffer-list)))))
+ (mapc
+ (lambda (spec)
+ (let ((current
+ (if force
+ 1
+ (twittering-get-retrieval-count spec))))
+ (cond
+ ((null current)
+ ;; Initialize the count if no entry for the primary timeline
+ ;; exists.
+ (twittering-initialize-retrieval-count spec))
+ ((and (integerp current) (= 0 current))
+ ;; Do nothing.
+ )
+ ((and (integerp current) (= 1 current))
+ ;; Retrieve the timeline and initialize count.
+ (let ((spec-string
+ (twittering-timeline-spec-to-string spec)))
+ (twittering-get-and-render-timeline
+ noninteractive nil spec spec-string)
+ (twittering-initialize-retrieval-count spec)))
+ ((and (integerp current) (< 1 current))
+ ;; Decrement count.
+ (twittering-set-retrieval-count spec (1- current)))
+ (t
+ nil))))
+ primary-spec-list))))
+
+;;;;
+;;;; Keymap
+;;;;
+
+(if twittering-mode-map
+ (let ((km twittering-mode-map))
+ (define-key km (kbd "C-c C-f") 'twittering-friends-timeline)
+ (define-key km (kbd "C-c C-r") 'twittering-replies-timeline)
+ (define-key km (kbd "C-c C-u") 'twittering-user-timeline)
+ (define-key km (kbd "C-c C-d") 'twittering-direct-messages-timeline)
+ (define-key km (kbd "C-c C-s") 'twittering-update-status-interactive)
+ (define-key km (kbd "C-c C-e") 'twittering-erase-old-statuses)
+ (define-key km (kbd "C-c C-m") 'twittering-retweet)
+ (define-key km (kbd "C-c C-t") 'twittering-set-current-hashtag)
+ (define-key km (kbd "C-m") 'twittering-enter)
+ (define-key km (kbd "C-c C-l") 'twittering-update-lambda)
+ (define-key km (kbd "<mouse-1>") 'twittering-click)
+ (define-key km (kbd "C-<down-mouse-3>") 'mouse-set-point)
+ (define-key km (kbd "C-<mouse-3>") 'twittering-push-tweet-onto-kill-ring)
+ (define-key km (kbd "C-c C-v") 'twittering-view-user-page)
+ (define-key km (kbd "C-c D") 'twittering-delete-status)
+ (define-key km (kbd "C-c C-w") 'twittering-delete-status)
+ (define-key km (kbd "a") 'twittering-toggle-activate-buffer)
+ (define-key km (kbd "g") 'twittering-current-timeline)
+ (define-key km (kbd "u") 'twittering-update-status-interactive)
+ (define-key km (kbd "U") 'twittering-push-uri-onto-kill-ring)
+ (define-key km (kbd "d") 'twittering-direct-message)
+ (define-key km (kbd "v") 'twittering-other-user-timeline)
+ (define-key km (kbd "V") 'twittering-visit-timeline)
+ (define-key km (kbd "L") 'twittering-other-user-list-interactive)
+ (define-key km (kbd "f") 'twittering-switch-to-next-timeline)
+ (define-key km (kbd "b") 'twittering-switch-to-previous-timeline)
+ ;; (define-key km (kbd "j") 'next-line)
+ ;; (define-key km (kbd "k") 'previous-line)
+ (define-key km (kbd "j") 'twittering-goto-next-status)
+ (define-key km (kbd "k") 'twittering-goto-previous-status)
+ (define-key km (kbd "l") 'forward-char)
+ (define-key km (kbd "h") 'backward-char)
+ (define-key km (kbd "0") 'beginning-of-line)
+ (define-key km (kbd "^") 'beginning-of-line-text)
+ (define-key km (kbd "$") 'end-of-line)
+ (define-key km (kbd "n") 'twittering-goto-next-status-of-user)
+ (define-key km (kbd "p") 'twittering-goto-previous-status-of-user)
+ (define-key km (kbd "C-i") 'twittering-goto-next-thing)
+ (define-key km (kbd "M-C-i") 'twittering-goto-previous-thing)
+ (define-key km (kbd "<backtab>") 'twittering-goto-previous-thing)
+ (define-key km (kbd "<backspace>") 'twittering-scroll-down)
+ (define-key km (kbd "M-v") 'twittering-scroll-down)
+ (define-key km (kbd "SPC") 'twittering-scroll-up)
+ (define-key km (kbd "C-v") 'twittering-scroll-up)
+ (define-key km (kbd "G") 'twittering-goto-last-status)
+ (define-key km (kbd "H") 'twittering-goto-first-status)
+ (define-key km (kbd "i") 'twittering-icon-mode)
+ (define-key km (kbd "r") 'twittering-toggle-show-replied-statuses)
+ (define-key km (kbd "R") 'twittering-toggle-or-retrieve-replied-statuses)
+ (define-key km (kbd "t") 'twittering-toggle-proxy)
+ (define-key km (kbd "C-c C-p") 'twittering-toggle-proxy)
+ (define-key km (kbd "q") 'twittering-kill-buffer)
+ (define-key km (kbd "C-c C-q") 'twittering-search)
+ nil))
+
+(let ((km twittering-mode-menu-on-uri-map))
+ (when km
+ (define-key km [ct] '("Copy tweet" . twittering-push-tweet-onto-kill-ring))
+ (define-key km [cl] '("Copy link" . twittering-push-uri-onto-kill-ring))
+ (define-key km [ll] '("Load link" . twittering-click))
+ (let ((km-on-uri twittering-mode-on-uri-map))
+ (when km-on-uri
+ (define-key km-on-uri (kbd "C-<down-mouse-3>") 'mouse-set-point)
+ (define-key km-on-uri (kbd "C-<mouse-3>") km)))))
+
+(defun twittering-keybind-message ()
+ (let ((important-commands
+ '(("Timeline" . twittering-friends-timeline)
+ ("Replies" . twittering-replies-timeline)
+ ("Update status" . twittering-update-status-interactive)
+ ("Next" . twittering-goto-next-status)
+ ("Prev" . twittering-goto-previous-status))))
+ (mapconcat (lambda (command-spec)
+ (let ((descr (car command-spec))
+ (command (cdr command-spec)))
+ (format "%s: %s" descr (key-description
+ (where-is-internal
+ command
+ overriding-local-map t)))))
+ important-commands ", ")))
+
+;; (run-with-idle-timer
+;; 0.1 t
+;; '(lambda ()
+;; (when (equal (buffer-name (current-buffer)) twittering-buffer)
+;; (message (twittering-keybind-message)))))
+
+
+;;;;
+;;;; Initialization
+;;;;
+
+(defvar twittering-initialized nil)
+(defvar twittering-mode-syntax-table nil "")
+
+(unless twittering-mode-syntax-table
+ (setq twittering-mode-syntax-table (make-syntax-table))
+ ;; (modify-syntax-entry ? "" twittering-mode-syntax-table)
+ (modify-syntax-entry ?\" "w" twittering-mode-syntax-table)
+ )
+
+(defun twittering-initialize-global-variables-if-necessary ()
+ "Initialize global variables for `twittering-mode' if they have not
+been initialized yet."
+ (unless twittering-initialized
+ (defface twittering-username-face
+ `((t ,(append '(:underline t)
+ (face-attr-construct
+ (if (facep 'font-lock-string-face)
+ 'font-lock-string-face
+ 'bold)))))
+ "" :group 'faces)
+ (defface twittering-uri-face `((t (:underline t))) "" :group 'faces)
+ (defface twittering-timeline-header-face
+ `((t ,(face-attr-construct
+ (if (facep 'font-lock-preprocessor-face)
+ 'font-lock-preprocessor-face
+ 'bold))))
+ "Timeline header on twittering-mode" :group 'faces)
+ (defface twittering-timeline-footer-face
+ `((t ,(face-attr-construct
+ (if (facep 'font-lock-preprocessor-face)
+ 'font-lock-preprocessor-face
+ 'bold))))
+ "Timeline footer on twittering-mode" :group 'faces)
+ (twittering-update-status-format)
+ (when twittering-use-convert
+ (if (null twittering-convert-program)
+ (setq twittering-use-convert nil)
+ (with-temp-buffer
+ (let ((coding-system-for-read 'iso-safe)
+ (coding-system-for-write 'iso-safe)
+ ;; Bind `default-directory' to the temporary directory
+ ;; because it is possible that the directory pointed by
+ ;; `default-directory' has been already removed.
+ (default-directory temporary-file-directory))
+ (call-process twittering-convert-program nil (current-buffer) nil
+ "-version")
+ (goto-char (point-min))
+ (if (null (search-forward-regexp "\\(Image\\|Graphics\\)Magick"
+ nil t))
+ (setq twittering-use-convert nil))))))
+ (twittering-setup-proxy)
+ (when twittering-use-icon-storage
+ (cond
+ ((require 'jka-compr nil t)
+ (twittering-load-icon-properties)
+ (add-hook 'kill-emacs-hook 'twittering-save-icon-properties))
+ (t
+ (setq twittering-use-icon-storage nil)
+ (error "Disabled icon-storage because it failed to load jka-compr."))))
+ (cond
+ ((and
+ (boundp 'twittering-sign-simple-string)
+ twittering-sign-simple-string
+ (or (not (boundp 'twittering-sign-string-function))
+ (null twittering-sign-string-function))
+ (eq twittering-edit-skeleton 'none)
+ (or (null twittering-edit-skeleton-footer)
+ (string= twittering-edit-skeleton-footer "")))
+ ;; Configure `twittering-edit-skeleton' as an alternative of
+ ;; `twittering-sign-simple-string'.
+ (twittering-edit-skeleton-change-footer
+ (format " [%s]" twittering-sign-simple-string))
+ (setq twittering-edit-skeleton 'footer)
+ (message "Warning: `twittering-sign-simple-string' is obsolete. Use `twittering-edit-skeleton-footer' instead."))
+ ((or (boundp 'twittering-sign-simple-string)
+ (boundp 'twittering-sign-string-function))
+ (message "Warning: `twittering-sign-simple-string' and `twittering-sign-string-function' are obsolete. Use the new feature `twittering-edit-skeleton'.")
+ ))
+ (add-hook 'twittering-new-tweets-rendered-hook
+ 'twittering-jojo-mode-hook-function)
+ (run-hooks 'twittering-mode-init-hook)
+ (setq twittering-initialized t)))
+
+(defun twittering-mode-setup (spec-string)
+ "Set up the current buffer for `twittering-mode'."
+ (kill-all-local-variables)
+ (setq major-mode 'twittering-mode)
+ (setq buffer-read-only t)
+ (buffer-disable-undo)
+ (setq mode-name "twittering-mode")
+ (setq mode-line-buffer-identification
+ `(,(default-value 'mode-line-buffer-identification)
+ (:eval (twittering-mode-line-buffer-identification))))
+
+ ;; Prevent `global-font-lock-mode' enabling `font-lock-mode'.
+ ;; This technique is derived from `lisp/bs.el' distributed with Emacs 22.2.
+ (make-local-variable 'font-lock-global-modes)
+ (setq font-lock-global-modes '(not twittering-mode))
+
+ ;; Prevent the field property attached to tweets from interfering
+ ;; the cursor motion based on logical lines.
+ (make-local-variable 'inhibit-field-text-motion)
+ (setq inhibit-field-text-motion t)
+
+ (make-local-variable 'twittering-timeline-spec)
+ (make-local-variable 'twittering-timeline-spec-string)
+ (make-local-variable 'twittering-active-mode)
+ (make-local-variable 'twittering-icon-mode)
+ (make-local-variable 'twittering-jojo-mode)
+ (make-local-variable 'twittering-reverse-mode)
+
+ (setq twittering-timeline-spec-string spec-string)
+ (setq twittering-timeline-spec
+ (twittering-string-to-timeline-spec spec-string))
+ (setq twittering-active-mode t)
+
+ (use-local-map twittering-mode-map)
+ (twittering-update-mode-line)
+ (set-syntax-table twittering-mode-syntax-table)
+ (when (and (boundp 'font-lock-mode) font-lock-mode)
+ (font-lock-mode -1))
+ (add-to-list 'twittering-buffer-info-list (current-buffer) t)
+ (run-hooks 'twittering-mode-hook))
+
+(defun twittering-mode ()
+ "Major mode for Twitter
+\\{twittering-mode-map}"
+ (interactive)
+ (let ((timeline-spec-list
+ (if (listp twittering-initial-timeline-spec-string)
+ twittering-initial-timeline-spec-string
+ (cons twittering-initial-timeline-spec-string nil))))
+ (twittering-visit-timeline (car timeline-spec-list))
+ (when (twittering-account-authorized-p)
+ (mapc 'twittering-visit-timeline (cdr timeline-spec-list)))))
+
+;;;;
+;;;; Preparation for invoking APIs
+;;;;
+
+(defun twittering-api-invocation-is-ready-p ()
+ "Return non-nil if the preparation for invoking APIs has been completed."
+ (and
+ ;; The global variables are initialized.
+ twittering-initialized
+ ;; A connection method is prepared.
+ (let ((use-ssl (or twittering-use-ssl twittering-oauth-use-ssl)))
+ (twittering-lookup-connection-type use-ssl))
+ ;; The account has been already authorized.
+ (twittering-account-authorized-p)))
+
+(defun twittering-ensure-preparation-for-api-invocation ()
+ "Ensure prerequisites for invoking APIs. Return non-nil in success.
+If prerequisites has been already satisifed, just return non-nil.
+If prerequisites are not satisfied, this function try to satisfy them.
+Then, return non-nil if they has been satisfied and return nil otherwise."
+ (twittering-initialize-global-variables-if-necessary)
+ (and (twittering-ensure-connection-method)
+ (twittering-ensure-private-info)
+ (twittering-ensure-account-verification)))
+
+;;;;
+;;;; Edit mode skeleton
+;;;;
+
+(defvar twittering-edit-skeleton-footer "")
+(defvar twittering-edit-skeleton-footer-history nil)
+(defvar twittering-edit-skeleton-alist
+ '((none . nil)
+ (footer . ((nil _ twittering-edit-skeleton-footer)))
+ (footer-only-normal
+ . ((nil _ twittering-edit-skeleton-footer) . normal))
+ (inherit-hashtags
+ . [(twittering-edit-skeleton-inherit-hashtags . normal)
+ (twittering-edit-skeleton-inherit-hashtags . reply)])
+ (inherit-mentions
+ . (twittering-edit-skeleton-inherit-mentions . reply))
+ (inherit-any
+ . [(twittering-edit-skeleton-inherit-mentions . reply)
+ (twittering-edit-skeleton-inherit-hashtags . normal)
+ (twittering-edit-skeleton-inherit-hashtags . reply)]))
+ "*Alist of skeletons performed on `twittering-update-status-interactive'.
+A key of the alist is a symbol and each value is nil, (SKELETON . PRED),
+ (FUNC . PRED) or a vector of them.
+
+When invoking `twittering-update-status-interactive', the value corresponding
+to the key specified `twittering-edit-skeleton' are performed.
+
+The value like (SKELETON . PRED) or (FUNC . PRED) is performed when the
+current context matches with PRED.
+PRED is nil, a symbol or a function.
+If PRED is nil, the value is unconditionally performed.
+If PRED is a symbol, the value is performed only when it equals to the
+type of the tweet being edited. The type is one of 'direct-message, 'normal,
+'organic-retweet and 'reply.
+If PRED is a function, the value is performed only when the predicate
+function PRED returns non-nil. PRED is invoked with three arguments
+TWEET-TYPE, IN-REPLY-TO-ID and CURRENT-SPEC.
+TWEET-TYPE is a symbol, which is one of 'direct-message, 'normal,
+'organic-retweet and 'reply, specifying which type of tweet will be edited.
+If the tweet will be edited as a reply or an organic retweet, IN-REPLY-TO-ID
+is a string specifying the replied tweet. Otherwise, IN-REPLY-TO-ID is nil.
+CURRENT-SPEC specifies where the action of posting a tweet is performed.
+If the action is performed on a twittering-mode buffer, CURRENT-SPEC is
+a timeline spec string of the buffer.
+If the action is performed on other buffers, CURRENT-SPEC is nil.
+If the option IGNORE-CURRENT-SPEC for `twittering-update-status' is non-nil,
+CURRENT-SPEC is also nil.
+
+If PRED matches the current context, the value is performed as follows.
+The value like (SKELETON . PRED) is performed by directly using SKELETON as an
+argument of `skeleton-insert'.
+The value like (FUNC . PRED) is performed by invoking FUNC with three
+arguments, TWEET-TYPE, IN-REPLY-TO-ID and CURRENT-SPEC as same as PRED.
+
+If the value is a vector, each element is performed in order of elements
+in the vector.
+
+Note that the effective skeleton is invoked after inserting a
+recipient.")
+(defvar twittering-edit-skeleton 'none
+ "*A symbol specifying an effective skeleton.
+It must be one of a symbol in `twittering-edit-skeleton-alist'.
+When entering `twittering-edit-mode', the skeletons in the specified
+entry in `twittering-edit-skeleton-alist' are performed.")
+
+(defun twittering-switch-edit-skeleton ()
+ (interactive)
+ (let ((skeleton-keys
+ (mapcar (lambda (entry) (symbol-name (car entry)))
+ twittering-edit-skeleton-alist))
+ (current (symbol-name (or twittering-edit-skeleton 'none))))
+ (let ((selected
+ (twittering-completing-read
+ (format "Skeleton (%s): " current)
+ skeleton-keys nil t nil nil current)))
+ (when selected
+ (setq twittering-edit-skeleton (intern selected)))))
+ (when (null twittering-edit-skeleton)
+ (setq twittering-edit-skeleton 'none))
+ (message "Current skeleton: %s" twittering-edit-skeleton))
+
+(defun twittering-edit-skeleton-change-footer (&optional footer-str)
+ (interactive)
+ (let ((footer-str
+ (or footer-str
+ (read-from-minibuffer "Footer: " twittering-edit-skeleton-footer
+ nil nil
+ 'twittering-edit-skeleton-footer-history))))
+ (when footer-str
+ (setq twittering-edit-skeleton-footer footer-str)))
+ (message "Current footer: [%s]" twittering-edit-skeleton-footer))
+
+(defun twittering-edit-skeleton-insert-base (&optional tweet-type in-reply-to-id current-spec)
+ (let ((entry
+ (cdr (assq twittering-edit-skeleton twittering-edit-skeleton-alist))))
+ (when entry
+ (require 'skeleton)
+ (let ((skeletons (if (vectorp entry)
+ entry
+ (list entry))))
+ (mapcar (lambda (def)
+ (let ((skeleton-or-func (car def))
+ (pred (cdr def)))
+ (when (or (null pred)
+ (and (functionp pred)
+ (funcall pred tweet-type in-reply-to-id))
+ (and (symbolp pred)
+ (eq pred tweet-type)))
+ (cond
+ ((functionp skeleton-or-func)
+ (funcall skeleton-or-func tweet-type in-reply-to-id
+ current-spec))
+ (t
+ (skeleton-insert skeleton-or-func))))))
+ skeletons)))))
+
+(defun twittering-edit-skeleton-insert (&optional tweet-type in-reply-to-id current-spec)
+ (if (> 22 emacs-major-version)
+ ;; This prevents Emacs21 from inserting skeletons before the cursor.
+ (let ((current (point))
+ (pair (with-temp-buffer
+ (twittering-edit-skeleton-insert-base tweet-type
+ in-reply-to-id
+ current-spec)
+ `(,(buffer-string) . ,(point)))))
+ (insert (car pair))
+ (goto-char (+ -1 current (cdr pair))))
+ (twittering-edit-skeleton-insert-base tweet-type in-reply-to-id
+ current-spec)))
+
+(defun twittering-edit-skeleton-inherit-hashtags (tweet-type in-reply-to-id current-spec)
+ (cond
+ (in-reply-to-id
+ (let* ((status (twittering-find-status in-reply-to-id))
+ (text (cdr (assq 'text status)))
+ (hashtags
+ (twittering-extract-matched-substring-all
+ (concat twittering-regexp-hash
+ "\\([[:alpha:]0-9_-]+\\)")
+ text))
+ (footer
+ (mapconcat (lambda (tag) (concat "#" tag))
+ hashtags " ")))
+ (when hashtags
+ (skeleton-insert `(nil _ " " ,footer)))))
+ ((twittering-timeline-spec-is-search-p current-spec)
+ (let* ((query-string
+ (twittering-extract-query-string-from-search-timeline-spec
+ current-spec))
+ (hashtag-list
+ (twittering-extract-matched-substring-all
+ (concat "\\(" twittering-regexp-hash "[[:alpha:]0-9_-]+\\)")
+ query-string)))
+ (when hashtag-list
+ (let ((footer (mapconcat 'identity hashtag-list " ")))
+ (skeleton-insert `(nil _ " " ,footer))))))))
+
+(defun twittering-edit-skeleton-inherit-mentions (tweet-type in-reply-to-id current-spec)
+ (when in-reply-to-id
+ (let* ((status (twittering-find-status in-reply-to-id))
+ (text (cdr (assq 'text status)))
+ (recipient (cdr (assq 'user-screen-name status)))
+ (mentions
+ (twittering-extract-matched-substring-all
+ (concat twittering-regexp-atmark
+ "\\([a-zA-Z0-9_-]+\\)")
+ text))
+ (reduced-mentions
+ (remove nil
+ (mapcar
+ (lambda (mention)
+ (unless (or (string= mention recipient)
+ (string= mention (twittering-get-username)))
+ mention))
+ mentions))))
+ (when reduced-mentions
+ (let ((header (mapconcat (lambda (user) (concat "@" user))
+ reduced-mentions " ")))
+ (skeleton-insert `(nil ,header " " _)))))))
+
+;;;;
+;;;; Edit mode
+;;;;
+
+(defvar twittering-edit-buffer "*twittering-edit*")
+(defvar twittering-pre-edit-window-configuration nil)
+(defvar twittering-edit-history nil)
+(defvar twittering-edit-local-history nil)
+(defvar twittering-edit-local-history-idx nil)
+(defvar twittering-warning-overlay nil)
+
+(define-derived-mode twittering-edit-mode nil "twmode-status-edit"
+ (use-local-map twittering-edit-mode-map)
+
+ ;; Prevent `global-font-lock-mode' enabling `font-lock-mode'.
+ ;; This technique is derived from `lisp/bs.el' distributed with Emacs 22.2.
+ (make-local-variable 'font-lock-global-modes)
+ (setq font-lock-global-modes '(not twittering-edit-mode))
+
+ (make-local-variable 'twittering-warning-overlay)
+ (setq twittering-warning-overlay (make-overlay 1 1 nil nil nil))
+ (overlay-put twittering-warning-overlay 'face 'font-lock-warning-face)
+
+ (make-local-variable 'twittering-edit-local-history)
+ (setq twittering-edit-local-history (cons (buffer-string)
+ twittering-edit-history))
+ (make-local-variable 'twittering-edit-local-history-idx)
+ (setq twittering-edit-local-history-idx 0)
+
+ (make-local-variable 'after-change-functions)
+ (add-to-list 'after-change-functions 'twittering-edit-length-check)
+ )
+
+(when twittering-edit-mode-map
+ (let ((km twittering-edit-mode-map))
+ (define-key km (kbd "C-c C-c") 'twittering-edit-post-status)
+ (define-key km (kbd "C-c C-k") 'twittering-edit-cancel-status)
+ (define-key km (kbd "C-c C-r") 'twittering-edit-toggle-reply)
+ (define-key km (kbd "M-n") 'twittering-edit-next-history)
+ (define-key km (kbd "M-p") 'twittering-edit-previous-history)
+ (define-key km (kbd "<f4>") 'twittering-edit-replace-at-point)))
+
+(defun twittering-effective-length (str &optional short-length-http short-length-https)
+ "Return the effective length of STR with taking account of shortening URIs.
+
+The returned length is calculated with taking account of shortening URIs
+if `twittering-service-method' is the symbol `twitter' or `twitter-api-v1.1'.
+It is assumed that a URI via HTTP will be converted into a URI consisting of
+SHORT-LENGTH-HTTP characters.
+It is assumed that a URI via HTTPS will be converted into a URI consisting of
+SHORT-LENGTH-HTTPS characters.
+
+If SHORT-LENGTH-HTTP is nil, the value of
+ (twittering-get-service-configuration 'short_url_length) is used instead.
+If SHORT-LENGTH-HTTPS is nil, the value of
+ (twittering-get-service-configuration 'short_url_length_https) is used
+instead."
+ (cond
+ ((memq twittering-service-method '(twitter twitter-api-v1.1))
+ (let ((regexp "\\(?:^\\|[[:space:]]\\)\\(http\\(s\\)?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+\\)")
+ (short-length-http
+ (or short-length-http
+ (twittering-get-service-configuration 'short_url_length)))
+ (short-length-https
+ (or short-length-https
+ (twittering-get-service-configuration 'short_url_length_https)))
+ (rest str)
+ (pos 0)
+ (len 0))
+ (save-match-data
+ (while (string-match regexp str pos)
+ (let ((beg (match-beginning 1))
+ (end (match-end 1))
+ (short-len (if (match-beginning 2)
+ short-length-https
+ short-length-http)))
+ (let ((additional-length
+ ;; Ignore the original length to follow the change
+ ;; of t.co URL wrapper.
+ ;;
+ ;; https://dev.twitter.com/docs/tco-url-wrapper
+ ;; As of October 10, 2011 the t.co URL wrapper
+ ;; automatically wraps all links submitted to
+ ;; Twitter, regardless of length. This includes
+ ;; so-called URLs without protocols.
+ (+ (- beg pos) short-len)))
+ (setq len (+ len additional-length))
+ (setq pos end)))))
+ (+ len (- (length str) pos))))
+ (t
+ (length str))))
+
+(defun twittering-edit-length-check (&optional beg end len)
+ (let* ((status (twittering-edit-extract-status))
+ (maxlen 140)
+ (length (twittering-effective-length status)))
+ (setq mode-name
+ (format "twmode-status-edit[%d/%d]" length maxlen))
+ (force-mode-line-update)
+ (unless twittering-disable-overlay-on-too-long-string
+ (if (< maxlen length)
+ (move-overlay twittering-warning-overlay
+ (- (point-max) (- length maxlen)) (point-max))
+ (move-overlay twittering-warning-overlay 1 1)))))
+
+(defun twittering-edit-get-help-end ()
+ "Return the end position of the help on `twittering-edit-mode'."
+ (when (eq major-mode 'twittering-edit-mode)
+ (next-single-property-change (point-min) 'read-only nil (point-max))))
+
+(defun twittering-edit-extract-status ()
+ "Return the text of the status being edited on `twittering-edit-mode'."
+ (if (eq major-mode 'twittering-edit-mode)
+ (buffer-substring-no-properties (twittering-edit-get-help-end)
+ (point-max))
+ ""))
+
+(defun twittering-edit-reset-status (str)
+ "Reset the contents of the current `twittering-edit-mode' buffer with STR."
+ (when (eq major-mode 'twittering-edit-mode)
+ (let ((help-end (twittering-edit-get-help-end)))
+ (delete-region help-end (point-max))
+ (goto-char help-end)
+ (insert str)
+ (goto-char help-end))))
+
+(defun twittering-edit-set-help-string (str)
+ "Render STR as a help for `twittering-edit-mode' to the current buffer."
+ (let* ((help-str (propertize str 'read-only t))
+ (len (length help-str)))
+ (add-text-properties 0 1 '(front-sticky (read-only)) help-str)
+ (add-text-properties (1- len) len '(rear-nonsticky t) help-str)
+ (save-excursion
+ (let ((inhibit-read-only t)
+ (inhibit-modification-hooks t)
+ (help-end (twittering-edit-get-help-end)))
+ (goto-char help-end)
+ (if (= (point-min) help-end)
+ ;; When no helps are rendered, the all markers should be
+ ;; placed after the new help.
+ (insert help-str)
+ ;; Use `insert-before-markers' because the marker of the current
+ ;; position should follow the new help.
+ ;; Delete the old help after inserting the new help to make
+ ;; the new help visible if possible.
+ (insert-before-markers help-str)
+ (delete-region (point-min) help-end))))))
+
+(defun twittering-edit-setup-help ()
+ (let* ((direct-message-recipient
+ (cdr (assq 'direct-message-recipient twittering-edit-mode-info)))
+ (tweet-type (cdr (assq 'tweet-type twittering-edit-mode-info)))
+ (cited-id (cdr (assq 'cited-id twittering-edit-mode-info)))
+ (item (cond
+ ((eq tweet-type 'direct-message)
+ (format "a direct message to %s" direct-message-recipient))
+ ((eq tweet-type 'reply)
+ "a reply")
+ (t
+ "a tweet")))
+ (status-format
+ (cond
+ ((eq tweet-type 'direct-message)
+ (format "%%FILL{DIRECT MESSAGE to %s}\n" direct-message-recipient))
+ ((eq tweet-type 'reply)
+ "%FILL{REPLY to the tweet by %s at %C{%y/%m/%d %H:%M:%S};}\n%FILL{%FACE[font-lock-doc-face]{\"%T\"}}\n")
+ (t
+ nil)))
+ (func (when status-format
+ (twittering-generate-format-status-function status-format)))
+ (help-str
+ (apply 'concat
+ `(,@(when func
+ `(,(funcall func
+ (twittering-find-status cited-id)
+ nil)))
+ ,(propertize (format (substitute-command-keys "Keymap:
+ \\[twittering-edit-post-status]: send %s
+ \\[twittering-edit-cancel-status]: cancel %s
+ \\[twittering-edit-toggle-reply]: toggle a normal tweet and a reply.
+ \\[twittering-edit-next-history]: next history element
+ \\[twittering-edit-previous-history]: previous history element
+ \\[twittering-edit-replace-at-point]: shorten URL at point
+
+---- text above this line is ignored ----
+") item item)
+ 'face 'font-lock-comment-face)))))
+ (twittering-edit-set-help-string help-str)))
+
+(defun twittering-edit-close ()
+ (kill-buffer (current-buffer))
+ (when twittering-pre-edit-window-configuration
+ (set-window-configuration twittering-pre-edit-window-configuration)
+ (setq twittering-pre-edit-window-configuration nil)))
+
+(defvar twittering-edit-mode-info nil
+ "Alist of a tweet being edited.
+Pairs of a key symbol and an associated value are following:
+ direct-message-recipient -- the recipient when the edited message is
+ sent as a direct message.
+ cited-id -- the id of the tweet that the edited message refers to.
+ tweet-type -- the type of the edited message, which is one of the
+ following symbol; normal, reply or direct-message.")
+
+(defun twittering-ensure-whole-of-status-is-visible (&optional window)
+ "Ensure that the whole of the tweet on the current point is visible."
+ (interactive)
+ (let* ((window (or window (selected-window)))
+ (buffer (window-buffer window)))
+ (when (twittering-buffer-p buffer)
+ (with-current-buffer buffer
+ (save-excursion
+ (let* ((next-head (or (twittering-get-next-status-head) (point-max)))
+ (current-tail (max (1- next-head) (point-min))))
+ (when (< (window-end window t) current-tail)
+ (twittering-set-window-end window current-tail))))))))
+
+(defun twittering-update-status-from-pop-up-buffer (&optional init-string-or-skeleton reply-to-id username tweet-type current-spec)
+ (interactive)
+ (let ((buf (generate-new-buffer twittering-edit-buffer)))
+ (setq twittering-pre-edit-window-configuration
+ (current-window-configuration))
+ (twittering-pop-to-buffer buf)
+ (twittering-edit-mode)
+ (make-local-variable 'twittering-edit-mode-info)
+ (setq twittering-edit-mode-info
+ `((cited-id . ,reply-to-id)
+ (tweet-type . ,(cdr (assq tweet-type
+ '((direct-message . direct-message)
+ (normal . normal)
+ (organic-retweet . normal)
+ (reply . reply)))))
+ (direct-message-recipient . ,username)))
+ (twittering-edit-setup-help)
+ (setq buffer-undo-list nil)
+ (goto-char (twittering-edit-get-help-end))
+ (if (eq tweet-type 'direct-message)
+ (message "C-c C-c to send, C-c C-k to cancel")
+ (and (null init-string-or-skeleton)
+ twittering-current-hashtag
+ (setq init-string-or-skeleton
+ (format " #%s " twittering-current-hashtag)))
+ (message "C-c C-c to post, C-c C-k to cancel"))
+ (when init-string-or-skeleton
+ (require 'skeleton)
+ (cond
+ ((stringp init-string-or-skeleton)
+ (insert init-string-or-skeleton))
+ ((listp init-string-or-skeleton)
+ (skeleton-insert init-string-or-skeleton))))
+ (twittering-edit-skeleton-insert tweet-type reply-to-id
+ current-spec)
+ (set-buffer-modified-p nil)))
+
+(defun twittering-edit-post-status ()
+ (interactive)
+ (let* ((status (twittering-edit-extract-status))
+ (cited-id (cdr (assq 'cited-id twittering-edit-mode-info)))
+ (cited-tweet (twittering-find-status cited-id))
+ (cited-username (cdr (assq 'user-screen-name cited-tweet)))
+ (direct-message-recipient
+ (cdr (assq 'direct-message-recipient twittering-edit-mode-info)))
+ (tweet-type (cdr (assq 'tweet-type twittering-edit-mode-info))))
+ (cond
+ ((string-match "\\` *\\'" status)
+ (message "Empty tweet!"))
+ ((< 140 (twittering-effective-length status))
+ (message "Tweet is too long!"))
+ ((cond
+ ((and (eq tweet-type 'reply)
+ (not (string-match
+ (concat "@" cited-username "\\(?:[\n\r \t]+\\)*") status)))
+ (y-or-n-p
+ "Send this tweet without mentions as a normal tweet (not a reply)? "))
+ (twittering-request-confirmation-on-posting
+ (y-or-n-p "Send this tweet? "))
+ (t
+ t))
+ (setq twittering-edit-history
+ (cons status twittering-edit-history))
+ (cond
+ ((eq tweet-type 'direct-message)
+ (if direct-message-recipient
+ (twittering-call-api 'send-direct-message
+ `((username . ,direct-message-recipient)
+ (status . ,status)))
+ (message "No username specified")))
+ ((eq tweet-type 'reply)
+ (twittering-call-api 'update-status
+ `((status . ,status)
+ (in-reply-to-status-id . ,cited-id))))
+ (t
+ (twittering-call-api 'update-status `((status . ,status)))))
+ (twittering-edit-close))
+ (t
+ nil))))
+
+(defun twittering-edit-cancel-status ()
+ (interactive)
+ (when (or (not (buffer-modified-p))
+ (prog1 (if (y-or-n-p "Cancel this tweet? ")
+ (message "Request canceled")
+ (message nil))))
+ (twittering-edit-close)))
+
+(defun twittering-edit-next-history ()
+ (interactive)
+ (if (>= 0 twittering-edit-local-history-idx)
+ (message "End of history.")
+ (let ((current-history (nthcdr twittering-edit-local-history-idx
+ twittering-edit-local-history)))
+ (setcar current-history (twittering-edit-extract-status))
+ (decf twittering-edit-local-history-idx)
+ (twittering-edit-reset-status (nth twittering-edit-local-history-idx
+ twittering-edit-local-history)))))
+
+(defun twittering-edit-previous-history ()
+ (interactive)
+ (if (>= twittering-edit-local-history-idx
+ (- (length twittering-edit-local-history) 1))
+ (message "Beginning of history.")
+ (let ((current-history (nthcdr twittering-edit-local-history-idx
+ twittering-edit-local-history)))
+ (setcar current-history (twittering-edit-extract-status))
+ (incf twittering-edit-local-history-idx)
+ (twittering-edit-reset-status (nth twittering-edit-local-history-idx
+ twittering-edit-local-history)))))
+
+(defun twittering-edit-replace-at-point ()
+ (interactive)
+ (when (eq major-mode 'twittering-edit-mode)
+ (twittering-tinyurl-replace-at-point)
+ (twittering-edit-length-check)))
+
+(defun twittering-edit-toggle-reply ()
+ "Toggle whether the tweet being edited will be sent as a reply or not."
+ (interactive)
+ (let ((tweet-type (cdr (assq 'tweet-type twittering-edit-mode-info)))
+ (cited-id (cdr (assq 'cited-id twittering-edit-mode-info))))
+ (cond
+ ((eq tweet-type 'direct-message)
+ (message "The current message is a direct message."))
+ ((null cited-id)
+ (message "The current message does not have a reply target."))
+ (t
+ (setq twittering-edit-mode-info
+ (mapcar (lambda (entry)
+ (if (eq (car entry) 'tweet-type)
+ `(tweet-type
+ . ,(cdr (assq (cdr entry)
+ '((normal . reply)
+ (reply . normal)))))
+ entry))
+ twittering-edit-mode-info))
+ (twittering-edit-setup-help)))))
+
+;;;;
+;;;; Edit a status on minibuffer
+;;;;
+
+(defun twittering-show-minibuffer-length (&optional beg end len)
+ "Show the number of characters in minibuffer."
+ (when (minibuffer-window-active-p (selected-window))
+ (if (and transient-mark-mode deactivate-mark)
+ (deactivate-mark))
+ (let* ((deactivate-mark deactivate-mark)
+ (status-len (- (twittering-effective-length (buffer-string))
+ (minibuffer-prompt-width)))
+ (mes (format "%d" status-len)))
+ (if (<= 23 emacs-major-version)
+ (minibuffer-message mes) ;; Emacs23 or later
+ (minibuffer-message (concat " (" mes ")")))
+ )))
+
+(defun twittering-setup-minibuffer ()
+ (add-hook 'post-command-hook 'twittering-show-minibuffer-length t t))
+
+(defun twittering-finish-minibuffer ()
+ (remove-hook 'post-command-hook 'twittering-show-minibuffer-length t))
+
+(defun twittering-status-not-blank-p (status)
+ (let ((coding-system-for-read 'binary)
+ (coding-system-for-write 'binary))
+ (with-temp-buffer
+ (insert status)
+ (goto-char (point-min))
+ ;; skip user name
+ (re-search-forward "\\`[[:space:]]*@[a-zA-Z0-9_-]+\\([[:space:]]+@[a-zA-Z0-9_-]+\\)*" nil t)
+ (re-search-forward "[^[:space:]]" nil t))))
+
+(defun twittering-update-status-from-minibuffer (&optional init-string-or-skeleton reply-to-id username tweet-type current-spec)
+ (and (not (eq tweet-type 'direct-message))
+ (null init-string-or-skeleton)
+ twittering-current-hashtag
+ (setq init-string-or-skeleton
+ (format " #%s " twittering-current-hashtag)))
+ (let ((status
+ (with-temp-buffer
+ (when init-string-or-skeleton
+ (require 'skeleton)
+ (cond
+ ((stringp init-string-or-skeleton)
+ (insert init-string-or-skeleton))
+ ((listp init-string-or-skeleton)
+ (skeleton-insert init-string-or-skeleton))))
+ (twittering-edit-skeleton-insert tweet-type reply-to-id
+ current-spec)
+ `(,(buffer-string) . ,(point))))
+ (not-posted-p t)
+ (prompt "status: ")
+ (map minibuffer-local-map)
+ (minibuffer-message-timeout nil))
+ (define-key map (kbd "<f4>") 'twittering-tinyurl-replace-at-point)
+ (when twittering-use-show-minibuffer-length
+ (add-hook 'minibuffer-setup-hook 'twittering-setup-minibuffer t)
+ (add-hook 'minibuffer-exit-hook 'twittering-finish-minibuffer t))
+ (unwind-protect
+ (while not-posted-p
+ (setq status (read-from-minibuffer prompt status map nil 'twittering-tweet-history nil t))
+ (let ((status status))
+ (if (< 140 (twittering-effective-length status))
+ (setq prompt "status (too long): ")
+ (setq prompt "status: ")
+ (when (twittering-status-not-blank-p status)
+ (cond
+ ((eq tweet-type 'direct-message)
+ (if username
+ (twittering-call-api 'send-direct-message
+ `((username . ,username)
+ (status . ,status)))
+ (message "No username specified")))
+ (t
+ (let ((parameters `(("status" . ,status)))
+ (as-reply
+ (and reply-to-id
+ username
+ (eq tweet-type 'reply)
+ (string-match
+ (concat "@" username "\\(?:[\n\r \t]+\\)*")
+ status))))
+ ;; Add in_reply_to_status_id only when a posting
+ ;; status begins with @username.
+ (twittering-call-api
+ 'update-status
+ `((status . ,status)
+ ,@(when as-reply
+ `((in-reply-to-status-id
+ . ,(format "%s" reply-to-id))))))
+ )))
+ (setq not-posted-p nil))
+ )))
+ ;; unwindforms
+ (when (memq 'twittering-setup-minibuffer minibuffer-setup-hook)
+ (remove-hook 'minibuffer-setup-hook 'twittering-setup-minibuffer))
+ (when (memq 'twittering-finish-minibuffer minibuffer-exit-hook)
+ (remove-hook 'minibuffer-exit-hook 'twittering-finish-minibuffer))
+ )))
+
+;;;;
+;;;; Reading username/listname with completion
+;;;;
+
+(defun twittering-get-usernames-from-timeline (&optional timeline-data)
+ (let ((timeline-data (or timeline-data (twittering-current-timeline-data))))
+ (twittering-remove-duplicates
+ (mapcar
+ (lambda (status)
+ (let* ((base-str (cdr (assq 'user-screen-name status)))
+ ;; `copied-str' is independent of the string in timeline-data.
+ ;; This isolation is required for `minibuf-isearch.el',
+ ;; which removes the text properties of strings in history.
+ (copied-str (copy-sequence base-str)))
+ (set-text-properties 0 (length copied-str) nil copied-str)
+ copied-str))
+ timeline-data))))
+
+(defun twittering-read-username-with-completion (prompt init-user &optional history)
+ (let ((collection (append twittering-user-history
+ (twittering-get-usernames-from-timeline))))
+ (twittering-completing-read prompt collection nil nil init-user history)))
+
+(defun twittering-read-list-name (username &optional list-index)
+ (let* ((list-index (or list-index
+ (twittering-get-list-index-sync username)))
+ (username (prog1 (copy-sequence username)
+ (set-text-properties 0 (length username) nil username)))
+ (prompt (format "%s's list: " username))
+ (listname
+ (if list-index
+ (twittering-completing-read prompt list-index nil t nil)
+ nil)))
+ (if (string= "" listname)
+ nil
+ listname)))
+
+(defun twittering-read-subscription-list-name (username &optional list-index)
+ (let* ((list-index (or list-index
+ (twittering-get-list-subscriptions-sync username)))
+ (username (prog1 (copy-sequence username)
+ (set-text-properties 0 (length username) nil username)))
+ (prompt (format "%s's subscription: " username))
+ (listname
+ (if list-index
+ (twittering-completing-read prompt list-index nil t nil)
+ nil)))
+ (if (string= "" listname)
+ nil
+ listname)))
+
+(defun twittering-read-timeline-spec-with-completion (prompt initial &optional as-string)
+ (let* ((dummy-hist
+ (append twittering-timeline-history
+ (twittering-get-usernames-from-timeline)
+ '(":direct_messages" ":direct_messages_sent"
+ ":favorites" ":friends"
+ ":home" ":mentions" ":public" ":replies"
+ ":retweeted_by_me" ":retweeted_by_user/"
+ ":retweeted_to_me" ":retweeted_to_user/"
+ ":retweets_of_me")
+ (mapcar (lambda (cell)
+ (concat "$" (car cell) (if (listp (cdr cell)) "()" "")))
+ twittering-timeline-spec-alias)))
+ (spec-with-username
+ '((":favorites/" . "Whose favorites: ")
+ (":retweeted_by_user/" . "Who has retweeted? ")
+ (":retweeted_to_user/" . "Who has received the retweets? ")))
+ (regexp-spec-with-username
+ (concat "\\`\\("
+ (mapconcat (lambda (entry) (car entry))
+ spec-with-username "\\|")
+ "\\)\\'"))
+ (spec-string (twittering-completing-read prompt dummy-hist
+ nil nil initial 'dummy-hist))
+ (spec-string
+ (cond
+ ((string-match regexp-spec-with-username spec-string)
+ (let* ((spec-and-prompt
+ (assoc (match-string 1 spec-string)
+ spec-with-username))
+ (prefix (car spec-and-prompt))
+ (prompt (cdr spec-and-prompt))
+ (username
+ (twittering-read-username-with-completion
+ prompt ""
+ 'twittering-user-history)))
+ (if username
+ (concat prefix username)
+ nil)))
+ ((string-match "^\\([a-zA-Z0-9_-]+\\)/$" spec-string)
+ (let* ((username (match-string 1 spec-string))
+ (list-index (twittering-get-list-index-sync username))
+ (listname
+ (if list-index
+ (twittering-read-list-name username list-index)
+ nil)))
+ (if listname
+ (concat username "/" listname)
+ nil)))
+ (t
+ spec-string)))
+ (spec (if (stringp spec-string)
+ (condition-case error-str
+ (twittering-string-to-timeline-spec spec-string)
+ (error
+ (message "Invalid timeline spec: %s" error-str)
+ nil))
+ nil)))
+ (cond
+ ((null spec)
+ nil)
+ (spec (if as-string
+ spec-string
+ spec))
+ ((string= "" spec-string)
+ (message "No timeline specs are specified.")
+ nil)
+ (t
+ (message "\"%s\" is invalid as a timeline spec." spec-string)
+ nil))))
+
+;;;;
+;;;; Commands
+;;;;
+
+;;;; Commands for changing modes
+(defun twittering-jojo-mode (&optional arg)
+ (interactive "P")
+ (let ((prev-mode twittering-jojo-mode))
+ (setq twittering-jojo-mode
+ (if (null arg)
+ (not twittering-jojo-mode)
+ (< 0 (prefix-numeric-value arg))))
+ (unless (eq prev-mode twittering-jojo-mode)
+ (twittering-update-mode-line))))
+
+(defun twittering-toggle-reverse-mode (&optional arg)
+ (interactive "P")
+ (let ((prev-mode twittering-reverse-mode))
+ (setq twittering-reverse-mode
+ (if (null arg)
+ (not twittering-reverse-mode)
+ (< 0 (prefix-numeric-value arg))))
+ (unless (eq prev-mode twittering-reverse-mode)
+ (twittering-update-mode-line)
+ (twittering-rerender-timeline-all (current-buffer)))))
+
+(defun twittering-set-current-hashtag (&optional tag)
+ (interactive)
+ (unless tag
+ (setq tag (twittering-completing-read "hashtag (blank to clear): #"
+ twittering-hashtag-history
+ nil nil
+ twittering-current-hashtag
+ 'twittering-hashtag-history))
+ (message
+ (if (eq 0 (length tag))
+ (progn (setq twittering-current-hashtag nil)
+ "Current hashtag is not set.")
+ (progn
+ (setq twittering-current-hashtag tag)
+ (format "Current hashtag is #%s" twittering-current-hashtag))))))
+
+;;;; Commands for switching buffers
+(defun twittering-switch-to-next-timeline ()
+ (interactive)
+ (when (twittering-buffer-p)
+ (let* ((buffer-list (twittering-get-buffer-list))
+ (following-buffers (cdr (memq (current-buffer) buffer-list)))
+ (next (if following-buffers
+ (car following-buffers)
+ (car buffer-list))))
+ (unless (eq (current-buffer) next)
+ (switch-to-buffer next)))))
+
+(defun twittering-switch-to-previous-timeline ()
+ (interactive)
+ (when (twittering-buffer-p)
+ (let* ((buffer-list (reverse (twittering-get-buffer-list)))
+ (preceding-buffers (cdr (memq (current-buffer) buffer-list)))
+ (previous (if preceding-buffers
+ (car preceding-buffers)
+ (car buffer-list))))
+ (unless (eq (current-buffer) previous)
+ (switch-to-buffer previous)))))
+
+;;;; Commands for visiting a timeline
+(defun twittering-visit-timeline (&optional timeline-spec initial)
+ (interactive)
+ (cond
+ ((twittering-ensure-preparation-for-api-invocation)
+ (let ((timeline-spec
+ (or timeline-spec
+ (twittering-read-timeline-spec-with-completion
+ "timeline: " initial t))))
+ (when timeline-spec
+ (switch-to-buffer (twittering-get-managed-buffer timeline-spec)))))
+ (t
+ nil)))
+
+(defun twittering-friends-timeline ()
+ (interactive)
+ (twittering-visit-timeline '(friends)))
+
+(defun twittering-home-timeline ()
+ (interactive)
+ (twittering-visit-timeline '(home)))
+
+(defun twittering-replies-timeline ()
+ (interactive)
+ (twittering-visit-timeline '(replies)))
+
+(defun twittering-public-timeline ()
+ (interactive)
+ (twittering-visit-timeline '(public)))
+
+(defun twittering-user-timeline ()
+ (interactive)
+ (twittering-visit-timeline `(user ,(twittering-get-username))))
+
+(defun twittering-direct-messages-timeline ()
+ (interactive)
+ (twittering-visit-timeline '(direct_messages)))
+
+(defun twittering-sent-direct-messages-timeline ()
+ (interactive)
+ (twittering-visit-timeline '(direct_messages_sent)))
+
+(defun twittering-other-user-timeline ()
+ (interactive)
+ (let* ((username (get-text-property (point) 'username))
+ (goto-spec (get-text-property (point) 'goto-spec))
+ (screen-name-in-text
+ (get-text-property (point) 'screen-name-in-text))
+ (uri (or (get-text-property (point) 'expanded-uri)
+ (get-text-property (point) 'uri)))
+ (mentioned-id (when uri
+ (twittering-extract-id-from-url uri)))
+ (spec (cond (goto-spec goto-spec)
+ (screen-name-in-text `(user ,screen-name-in-text))
+ (mentioned-id `(single ,mentioned-id))
+ (username `(user ,username))
+ (t nil))))
+ (if spec
+ (twittering-visit-timeline spec)
+ (message "No user selected"))))
+
+(defun twittering-other-user-timeline-interactive ()
+ (interactive)
+ (let ((username (or (twittering-read-username-with-completion
+ "user: " nil
+ 'twittering-user-history)
+ "")))
+ (if (string= "" username)
+ (message "No user selected")
+ (twittering-visit-timeline `(user ,username)))))
+
+(defun twittering-other-user-list-interactive (&optional subscriptions)
+ (interactive "P")
+ (let* ((username (copy-sequence (get-text-property (point) 'username)))
+ (username (progn
+ (set-text-properties 0 (length username) nil username)
+ (or (twittering-read-username-with-completion
+ (if subscriptions
+ "Whose subscription: "
+ "Whose list: ")
+ username
+ 'twittering-user-history)
+ ""))))
+ (if (string= "" username)
+ (message "No user selected")
+ (let* ((list-name (if subscriptions
+ (twittering-read-subscription-list-name username)
+ (twittering-read-list-name username)))
+ (spec (cond
+ ((null list-name)
+ nil)
+ (subscriptions
+ (and (string-match "\\`\\(.*\\)/\\(.*\\)\\'" list-name)
+ `(list ,(match-string 1 list-name)
+ ,(match-string 2 list-name))))
+ (t
+ `(list ,username ,list-name)))))
+ (if spec
+ (twittering-visit-timeline spec)
+ ;; Don't show message here to prevent an overwrite of a
+ ;; message which is outputted by `twittering-read-list-name'.
+ )))))
+
+(defun twittering-search (&optional word)
+ (interactive)
+ (let ((word (or word
+ (read-from-minibuffer "search: " nil nil nil
+ 'twittering-search-history nil t)
+ "")))
+ (if (string= "" word)
+ (message "No query string")
+ (let ((spec `(search ,word)))
+ (twittering-visit-timeline spec)))))
+
+;;;; Commands for retrieving statuses
+
+(defun twittering-current-timeline-noninteractive ()
+ (twittering-current-timeline t))
+
+(defun twittering-current-timeline (&optional noninteractive)
+ (interactive)
+ (when (twittering-buffer-p)
+ (let ((spec-string (twittering-current-timeline-spec-string)))
+ (twittering-get-and-render-timeline noninteractive))))
+
+(defun twittering-get-tweets-within-specific-time-range (time-beg time-end)
+ "Get tweets within a time range between TIME-BEG and TIME-END.
+TIME-BEG and TIME-END must be nil or an internal representation of time as
+same as the returned value of `current-time'."
+ (let* ((since_id (when time-beg
+ (twittering-time-to-id time-beg)))
+ (max_id (when time-end
+ (twittering-time-to-id time-end)))
+ (spec-string (twittering-current-timeline-spec-string))
+ (noninteractive t)
+ (args
+ `(,@(cond
+ (max_id `((max_id . ,max_id)))
+ (since_id `((since_id . ,since_id)))
+ (t nil)))))
+ (twittering-retrieve-timeline spec-string noninteractive args nil)))
+
+(defun twittering-get-tweets-before (&optional before-str)
+ (interactive)
+ (let* ((id (when (null before-str)
+ (twittering-get-id-at)))
+ (init-str
+ (when id
+ (let* ((status (twittering-find-status id))
+ (init-time
+ (or (cdr (assq 'retweeting-created-at status))
+ (cdr (assq 'created-at status)))))
+ (format-time-string "%Y-%m-%d %T" init-time))))
+ (before-str
+ (or before-str
+ (read-string "before [YYYY-MM-DD [HH:MM:SS]]: " init-str)))
+ (time-beg nil)
+ (time-end
+ (apply 'encode-time (twittering-parse-time-string before-str t))))
+ (twittering-get-tweets-within-specific-time-range time-beg time-end)))
+
+;;;; Commands for posting a status
+
+(defun twittering-update-status (&optional init-string-or-skeleton reply-to-id username tweet-type ignore-current-spec)
+ "Post a tweet.
+The first argument INIT-STRING-OR-SKELETON is nil, an initial text or a
+skeleton to be inserted with `skeleton-insert'.
+REPLY-TO-ID is an ID of a tweet which you are going to cite or reply to.
+USERNAME is a recipient of a direct message.
+TWEET-TYPE is a symbol meaning the type of the tweet being edited. It must
+be one of 'direct-message, 'normal, 'organic-retweet and 'reply.
+If TWEET-TYPE is nil, it is equivalent to 'normal, which means that a tweet
+is edited as a normal tweet.
+If IGNORE-CURRENT-SPEC is non-nil, the timeline spec of the current buffer
+is sent to the function specified by `twittering-update-status-function'.
+
+How to edit a tweet is determined by `twittering-update-status-funcion'."
+ (let ((current-spec (unless ignore-current-spec
+ (twittering-current-timeline-spec)))
+ (tweet-type (or tweet-type 'normal)))
+ (funcall twittering-update-status-function init-string-or-skeleton
+ reply-to-id username
+ tweet-type current-spec)))
+
+(defun twittering-update-status-interactive ()
+ (interactive)
+ (twittering-update-status))
+
+(defun twittering-update-lambda ()
+ (interactive)
+ (when (and (string= "Japanese" current-language-environment)
+ (or (< 21 emacs-major-version)
+ (eq 'utf-8 (terminal-coding-system))))
+ (let ((text (mapconcat
+ 'char-to-string
+ (mapcar 'twittering-ucs-to-char
+ '(955 12363 12431 12356 12356 12424 955)) "")))
+ (twittering-call-api 'update-status `((status . ,text))))))
+
+(defun twittering-post-predicted-message-like-jojo (status)
+ (let ((screen-name (cdr (assq 'user-screen-name status)))
+ (text (cdr (assq 'text status))))
+ (when (and (not (string= screen-name (twittering-get-username)))
+ (string-match
+ (mapconcat 'char-to-string
+ (mapcar
+ 'twittering-ucs-to-char
+ '(#x6b21 #x306b #x005c #x0028 #x304a #x524d
+ #x005c #x007c #x8cb4 #x69d8 #x005c #x0029
+ #x306f #x300c #x005c #x0028 #x005b #x005e
+ #x300d #x005d #x002b #x005c #x0029 #x300d
+ #x3068 #x8a00 #x3046))
+ "")
+ text))
+ (let ((text
+ (concat "@" screen-name " "
+ (match-string-no-properties 2 text)
+ (mapconcat 'char-to-string
+ (mapcar 'twittering-ucs-to-char
+ '(#x3000 #x306f #x3063 #x0021 #x003f))
+ ""))))
+ (twittering-call-api 'update-status `((status . ,text)))))))
+
+(defun twittering-jojo-mode-hook-function ()
+ (when (and twittering-jojo-mode
+ (string= "Japanese" current-language-environment)
+ (or (< 21 emacs-major-version)
+ (eq 'utf-8 (terminal-coding-system))))
+ (mapcar 'twittering-post-predicted-message-like-jojo
+ twittering-rendered-new-tweets)))
+
+(defun twittering-direct-message ()
+ (interactive)
+ (let ((username (twittering-read-username-with-completion
+ "Who would you like to receive the DM? "
+ (get-text-property (point) 'username)
+ 'twittering-user-history)))
+ (if (string= "" username)
+ (message "No user selected")
+ (twittering-update-status nil nil username 'direct-message))))
+
+(defun twittering-reply-to-user ()
+ (interactive)
+ (let ((username (get-text-property (point) 'username)))
+ (if username
+ (twittering-update-status (concat "@" username " "))
+ (message "No user selected"))))
+
+;;;; Command for deleting a status
+
+(defun twittering-delete-status (&optional id)
+ (interactive)
+ (let* ((id (twittering-get-id-at))
+ (status (twittering-find-status id))
+ (is-retweet (assq 'retweeted-id status))
+ (username (if is-retweet
+ (cdr (assq 'retweeting-user-screen-name status))
+ (cdr (assq 'user-screen-name status))))
+ (text (if is-retweet
+ (cdr (assq 'retweeting-text status))
+ (cdr (assq 'text status))))
+ (width (max 40 ;; XXX
+ (- (frame-width)
+ 1 ;; margin for wide characters
+ 11 ;; == (length (concat "Delete \"" "\"? "))
+ 9) ;; == (length "(y or n) ")
+ ))
+ (mes (format "Delete \"%s\"? "
+ (if (< width (string-width text))
+ (concat
+ (truncate-string-to-width text (- width 3))
+ "...")
+ text))))
+ (cond
+ ((not (string= username (twittering-get-username)))
+ (message "The status is not yours!"))
+ ((not id)
+ (message "No status selected"))
+ ((y-or-n-p mes)
+ (twittering-call-api 'destroy-status `((id . ,id))))
+ (t
+ (message "Request canceled")))))
+
+;;;; Commands for retweet
+
+(defun twittering-retweet (&optional arg)
+ (interactive "P")
+ (let ((use-native-retweet-flag (if arg
+ (not twittering-use-native-retweet)
+ twittering-use-native-retweet)))
+ (if use-native-retweet-flag
+ (twittering-native-retweet)
+ (twittering-organic-retweet))))
+
+(defun twittering-organic-retweet ()
+ (interactive)
+ (let* ((id (twittering-get-id-at))
+ (status (twittering-find-status id))
+ (username (cdr (assq 'user-screen-name status)))
+ (text (cdr (assq 'text status)))
+ (retweet-time (current-time))
+ (skeleton-with-format-string
+ (cond
+ ((null twittering-retweet-format)
+ '(nil _ " RT: %t (via @%s)"))
+ ((stringp twittering-retweet-format)
+ `(nil ,twittering-retweet-format _))
+ ((listp twittering-retweet-format)
+ twittering-retweet-format)
+ (t
+ nil))))
+ (cond
+ ((cdr (assq 'user-protected status))
+ (error "Cannot retweet protected tweets."))
+ (username
+ (let ((prefix "%")
+ (replace-table
+ `(("%" . "%")
+ ("s" . ,username)
+ ("t" . ,text)
+ ("#" . ,id)
+ ("u" . ,(twittering-get-status-url-from-alist status))
+ ("C{\\([^}]*\\)}" .
+ (lambda (context)
+ (let ((str (cdr (assq 'following-string context)))
+ (match-data (cdr (assq 'match-data context))))
+ (store-match-data match-data)
+ (format-time-string (match-string 1 str) ',retweet-time))))
+ ))
+ )
+ (twittering-update-status
+ (mapcar (lambda (element)
+ (if (stringp element)
+ (twittering-format-string element prefix replace-table)
+ element))
+ skeleton-with-format-string)
+ id nil 'organic-retweet)
+ )))))
+
+(defun twittering-native-retweet ()
+ (interactive)
+ (let ((id (get-text-property (point) 'id))
+ (text (copy-sequence (get-text-property (point) 'text)))
+ (user (get-text-property (point) 'username))
+ (width (max 40 ;; XXX
+ (- (frame-width)
+ 1 ;; margin for wide characters
+ 12 ;; == (length (concat "Retweet \"" "\"? "))
+ 9) ;; == (length "(y or n) ")
+ )))
+ (set-text-properties 0 (length text) nil text)
+ (if id
+ (if (not (string= user twittering-username))
+ (let ((mes (format "Retweet \"%s\"? "
+ (if (< width (string-width text))
+ (concat
+ (truncate-string-to-width text (- width 3))
+ "...")
+ text))))
+ (if (y-or-n-p mes)
+ (twittering-call-api 'retweet `((id . ,id)))
+ (message "Request canceled")))
+ (message "Cannot retweet your own tweet"))
+ (message "No status selected"))))
+
+;;;; Commands for browsing information related to a status
+
+(defun twittering-click ()
+ (interactive)
+ (let ((uri (get-text-property (point) 'uri)))
+ (if uri
+ (browse-url uri))))
+
+(defun twittering-enter ()
+ (interactive)
+ (let* ((username (get-text-property (point) 'username))
+ (id (twittering-get-id-at (point)))
+ (uri (get-text-property (point) 'uri))
+ (tweet-type
+ (cond
+ ((twittering-timeline-spec-is-direct-messages-p
+ (get-text-property (point) 'source-spec))
+ 'direct-message)
+ (t
+ 'reply)))
+ (screen-name-in-text
+ (get-text-property (point) 'screen-name-in-text))
+ (initial-str
+ (when (and (not (eq tweet-type 'direct-message))
+ (or screen-name-in-text username))
+ (concat "@" (or screen-name-in-text username) " ")))
+ (field-id (get-text-property (point) 'field))
+ (is-latest-end (twittering-field-id-is-timeline-latest-end field-id))
+ (is-oldest-end (twittering-field-id-is-timeline-oldest-end field-id)))
+ (cond
+ (is-latest-end
+ (message "Get more of the recent timeline...")
+ (if twittering-reverse-mode
+ (twittering-goto-last-normal-field)
+ (twittering-goto-first-normal-field))
+ (twittering-get-and-render-timeline))
+ (is-oldest-end
+ (let* ((oldest-status (car (last (twittering-current-timeline-data))))
+ (oldest-id (cdr (assq 'id oldest-status))))
+ (message "Get more of the previous timeline...")
+ (if twittering-reverse-mode
+ (twittering-goto-first-normal-field)
+ (twittering-goto-last-normal-field))
+ (twittering-get-and-render-timeline nil oldest-id)))
+ (screen-name-in-text
+ (twittering-update-status initial-str
+ id screen-name-in-text tweet-type))
+ (uri
+ (browse-url uri))
+ (username
+ (twittering-update-status initial-str id username tweet-type)))))
+
+(defun twittering-view-user-page ()
+ (interactive)
+ (let ((uri (get-text-property (point) 'uri)))
+ (if uri
+ (browse-url uri))))
+
+;;;;
+;;;; Commands corresponding to operations on Twitter
+;;;;
+
+(defun twittering-follow (&optional remove)
+ (interactive "P")
+ (let* ((method (if remove 'destroy-friendships 'create-friendships))
+ (mes (if remove "unfollow" "follow"))
+ (id (twittering-get-id-at))
+ (status (when id (twittering-find-status id)))
+ (username
+ (cond
+ ((assq 'retweeted-id status)
+ (let* ((retweeting-username
+ (cdr (assq 'retweeting-user-screen-name status)))
+ (retweeted-username
+ (cdr (assq 'retweeted-user-screen-name status)))
+ (default (if remove
+ retweeting-username
+ retweeted-username))
+ (prompt (format "Who do you %s? (default:%s): "
+ mes default))
+ (candidates (list retweeted-username retweeting-username)))
+ (twittering-completing-read prompt candidates nil t
+ nil nil default)))
+ (status
+ (cdr (assq 'user-screen-name status)))
+ (t
+ (twittering-read-username-with-completion
+ (format "Who do you %s? " mes) "" 'twittering-user-history)))))
+ (if (string= "" username)
+ (message "No user selected")
+ (if (y-or-n-p (format "%s %s? " (capitalize mes) username))
+ (twittering-call-api method `((username . ,username)))
+ (message "Request canceled")))))
+
+(defun twittering-unfollow ()
+ (interactive)
+ (twittering-follow t))
+
+(defun twittering-favorite (&optional remove)
+ (interactive "P")
+ (let ((id (get-text-property (point) 'id))
+ (text (copy-sequence (get-text-property (point) 'text)))
+ (width (max 40 ;; XXX
+ (- (frame-width)
+ 1 ;; margin for wide characters
+ 15 ;; == (length (concat "Unfavorite \"" "\"? "))
+ 9) ;; == (length "(y or n) ")
+ ))
+ (method (if remove 'destroy-favorites 'create-favorites)))
+ (set-text-properties 0 (length text) nil text)
+ (if id
+ (let ((mes (format "%s \"%s\"? "
+ (if remove "Unfavorite" "Favorite")
+ (if (< width (string-width text))
+ (concat
+ (truncate-string-to-width text (- width 3))
+ "...")
+ text))))
+ (if (y-or-n-p mes)
+ (twittering-call-api method `((id . ,id)))
+ (message "Request canceled")))
+ (message "No status selected"))))
+
+(defun twittering-unfavorite ()
+ (interactive)
+ (twittering-favorite t))
+
+(defun twittering-mute (&optional remove)
+ (interactive "P")
+ (let* ((method (if remove 'unmute 'mute))
+ (mes (if remove "unmute" "mute"))
+ (id (twittering-get-id-at))
+ (status (when id (twittering-find-status id)))
+ (username
+ (cond
+ ((assq 'retweeted-id status)
+ (let* ((retweeting-username
+ (cdr (assq 'retweeting-user-screen-name status)))
+ (retweeted-username
+ (cdr (assq 'retweeted-user-screen-name status)))
+ (default (if remove
+ retweeting-username
+ retweeted-username))
+ (prompt (format "Who do you %s? (default:%s): "
+ mes default))
+ (candidates (list retweeted-username retweeting-username)))
+ (twittering-completing-read prompt candidates nil t
+ nil nil default)))
+ (status
+ (cdr (assq 'user-screen-name status)))
+ (t
+ (twittering-read-username-with-completion
+ (format "Who do you %s? " mes) "" 'twittering-user-history)))))
+ (if (string= "" username)
+ (message "No user selected")
+ (if (y-or-n-p (format "%s %s? " (capitalize mes) username))
+ (twittering-call-api method `((username . ,username)))
+ (message "Request canceled")))))
+
+(defun twittering-unmute ()
+ (interactive)
+ (twittering-mute t))
+
+(defun twittering-block ()
+ "Block a user who posted the tweet at the current position."
+ (interactive)
+ (let* ((id (twittering-get-id-at))
+ (status (when id (twittering-find-status id)))
+ (username
+ (cond
+ ((assq 'retweeted-id status)
+ (let* ((retweeting-username
+ (cdr (assq 'retweeting-user-screen-name status)))
+ (retweeted-username
+ (cdr (assq 'retweeted-user-screen-name status)))
+ (prompt "Who do you block? ")
+ (candidates (list retweeted-username retweeting-username)))
+ (twittering-completing-read prompt candidates nil t)))
+ (status
+ (cdr (assq 'user-screen-name status)))
+ (t
+ nil))))
+ (cond
+ ((or (null username) (string= "" username))
+ (message "No user selected"))
+ ((yes-or-no-p (format "Really block \"%s\"? " username))
+ (twittering-call-api 'block `((username . ,username))))
+ (t
+ (message "Request canceled")))))
+
+(defun twittering-block-and-report-as-spammer ()
+ "Report a user who posted the tweet at the current position as a spammer.
+The user is also blocked."
+ (interactive)
+ (let* ((id (twittering-get-id-at))
+ (status (when id (twittering-find-status id)))
+ (username
+ (cond
+ ((assq 'retweeted-id status)
+ (let* ((retweeting-username
+ (cdr (assq 'retweeting-user-screen-name status)))
+ (retweeted-username
+ (cdr (assq 'retweeted-user-screen-name status)))
+ (prompt "Who do you report as a spammer? ")
+ (candidates (list retweeted-username retweeting-username)))
+ (twittering-completing-read prompt candidates nil t)))
+ (status
+ (cdr (assq 'user-screen-name status)))
+ (t
+ nil))))
+ (cond
+ ((or (null username) (string= "" username))
+ (message "No user selected"))
+ ((yes-or-no-p
+ (format "Really block \"%s\" and report him or her as a spammer? "
+ username))
+ (twittering-call-api 'block-and-report-as-spammer
+ `((username . ,username))))
+ (t
+ (message "Request canceled")))))
+
+;;;; Commands for clearing stored statuses.
+
+(defun twittering-erase-old-statuses ()
+ (interactive)
+ (when (twittering-buffer-p)
+ (let ((spec (twittering-current-timeline-spec)))
+ (twittering-remove-timeline-data spec) ;; clear current timeline.
+ (twittering-rerender-timeline-all (current-buffer)) ;; clear buffer.
+ (twittering-get-and-render-timeline))))
+
+;;;; Cursor motion
+
+(defun twittering-get-id-at (&optional pos)
+ "Return ID of the status at POS. If a separator is rendered at POS, return
+the ID of the status rendered before the separator. The default value of POS
+is `(point)'."
+ (let ((pos (or pos (point))))
+ (or (get-text-property pos 'id)
+ (let ((prev (or (twittering-get-current-status-head pos)
+ (point-min))))
+ (and prev (get-text-property prev 'id))))))
+
+(defun twittering-get-current-status-head (&optional pos)
+ "Return the head position of the status at POS.
+If POS is nil, the value of point is used for POS.
+If a separator is rendered at POS, return the head of the status followed
+by the separator.
+Return POS if no statuses are rendered."
+ (let* ((pos (or pos (point)))
+ (field-id (get-text-property pos 'field))
+ ;; Find the beginning of the field regardless of stickiness.
+ (head (field-beginning pos t)))
+ (cond
+ ((null field-id)
+ ;; A separator is rendered at `pos'.
+ (if (get-text-property head 'field)
+ ;; When `pos' points the head of the separator, `head' points
+ ;; to the beginning of the status followed by the separator.
+ head
+ ;; In the case that `pos' points to a character of the separator,
+ ;; but not to the head of the separator.
+ (field-beginning head t)))
+ ((null (get-text-property head 'field))
+ ;; When `head' points to a separator, `pos' points to the head
+ ;; of a status.
+ pos)
+ ((not (twittering-field-id= field-id (get-text-property head 'field)))
+ ;; When `pos' points to the beginning of the field and it also
+ ;; points to the end of the previous field, `head' points to the
+ ;; head of the previous status.
+ pos)
+ (t
+ head))))
+
+(defun twittering-goto-first-status ()
+ "Go to the first status."
+ (interactive)
+ (goto-char (or (twittering-get-first-status-head)
+ (point-min))))
+
+(defun twittering-get-first-status-head ()
+ "Return the head position of the first status in the current buffer.
+Return nil if no statuses are rendered."
+ (if (get-text-property (point-min) 'field)
+ (point-min)
+ (twittering-get-next-status-head (point-min))))
+
+(defun twittering-goto-last-status ()
+ "Go to the last status."
+ (interactive)
+ (goto-char (or (twittering-get-last-status-head)
+ (point-min))))
+
+(defun twittering-get-last-status-head ()
+ "Return the head position of the last status in the current buffer.
+Return nil if no statuses are rendered."
+ (if (get-text-property (point-max) 'field)
+ (point-max)
+ (twittering-get-previous-status-head (point-max))))
+
+(defun twittering-goto-first-normal-field ()
+ "Go to the first normal field.
+A normal field is a field corresponding to a tweet."
+ (interactive)
+ (goto-char (or (twittering-get-first-normal-field-head)
+ (point-min))))
+
+(defun twittering-goto-last-normal-field ()
+ "Go to the last normal field.
+A normal field is a field corresponding to a tweet."
+ (interactive)
+ (goto-char (or (twittering-get-last-normal-field-head)
+ (point-max))))
+
+(defun twittering-get-first-normal-field-head ()
+ "Return the head position of the first normal field in the current buffer.
+A normal field is a field corresponding to a tweet.
+Return nil if no statuses are rendered."
+ (let ((pos (twittering-get-first-status-head)))
+ (while (and pos
+ (< pos (point-max))
+ (null (get-text-property pos 'id)))
+ (setq pos (twittering-get-next-status-head pos)))
+ (when (and pos (< pos (point-max)) (get-text-property pos 'id))
+ pos)))
+
+(defun twittering-get-last-normal-field-head ()
+ "Return the head position of the last normal field in the current buffer.
+A normal field is a field corresponding to a tweet.
+Return nil if no statuses are rendered."
+ (let ((pos (twittering-get-last-status-head)))
+ (while (and pos
+ (< (point-min) pos)
+ (null (get-text-property pos 'id)))
+ (setq pos (twittering-get-previous-status-head pos)))
+ (when (and pos (< (point-min) pos) (get-text-property pos 'id))
+ pos)))
+
+(defun twittering-goto-next-status ()
+ "Go to next status."
+ (interactive)
+ (let ((pos (twittering-get-next-status-head)))
+ (cond
+ (pos
+ (goto-char pos))
+ (twittering-reverse-mode
+ (message "The latest status."))
+ (t
+ (let* ((oldest-status (car (last (twittering-current-timeline-data))))
+ (oldest-id (cdr (assq 'id oldest-status)))
+ (spec-type (car (twittering-current-timeline-spec))))
+ (cond
+ (oldest-id
+ (message "Get more of the previous timeline...")
+ ;; Here, the cursor points to the footer field or the end of
+ ;; the buffer. It should be moved backward to a normal tweet.
+ (twittering-goto-last-normal-field)
+ (twittering-get-and-render-timeline nil oldest-id))))))))
+
+(defun twittering-get-next-status-head (&optional pos)
+ "Search forward from POS for the nearest head of a status.
+Return nil if there are no following statuses.
+Otherwise, return a positive integer greater than POS."
+ (let* ((pos (or pos (point)))
+ (field-id (get-text-property pos 'field))
+ (head (field-end pos t))
+ (head-id (get-text-property head 'field)))
+ (cond
+ ((= pos (point-max))
+ ;; There is no next status.
+ nil)
+ ((and (null field-id) head-id)
+ ;; `pos' points to a separator and `head' points to a head
+ ;; of a status.
+ head)
+ ((null head-id)
+ ;; `head' points to a head of a separator.
+ (let ((next-head (field-end head t)))
+ (if (get-text-property next-head 'field)
+ next-head
+ ;; There is no next status.
+ nil)))
+ (t
+ head))))
+
+(defun twittering-goto-previous-status ()
+ "Go to previous status."
+ (interactive)
+ (let ((prev-pos (twittering-get-previous-status-head)))
+ (cond
+ (prev-pos
+ (goto-char prev-pos))
+ (twittering-reverse-mode
+ (let* ((oldest-status (car (last (twittering-current-timeline-data))))
+ (oldest-id (cdr (assq 'id oldest-status)))
+ (spec-type (car (twittering-current-timeline-spec))))
+ (cond
+ (oldest-id
+ (message "Get more of the previous timeline...")
+ ;; Here, the cursor points to the header field.
+ ;; It should be moved forward to a normal tweet.
+ (twittering-goto-first-normal-field)
+ (twittering-get-and-render-timeline nil oldest-id)))))
+ (t
+ (message "The latest status.")))))
+
+(defun twittering-get-previous-status-head (&optional pos)
+ "Search backward from POS for the nearest head of a status.
+If POS points to a head of a status, return the head of the *previous* status.
+If there are no preceding statuses, return nil.
+Otherwise, return a positive integer less than POS."
+ (let* ((pos (or pos (point)))
+ (field-id (get-text-property pos 'field))
+ (head (field-beginning pos t))
+ (head-id (get-text-property head 'field)))
+ (cond
+ ((= pos (point-min))
+ ;; There is no previous status.
+ nil)
+ ((and (null field-id) head-id)
+ ;; `pos' points to a separator and `head' points to a head
+ ;; of a status.
+ head)
+ ((null head-id)
+ ;; `head' points to a head of a separator.
+ (let ((prev-head (field-beginning head t)))
+ (if (get-text-property prev-head 'field)
+ prev-head
+ ;; There is no previous status.
+ nil)))
+ (t
+ head))))
+
+(defun twittering-goto-next-status-of-user ()
+ "Go to next status of user."
+ (interactive)
+ (let ((user-name (twittering-get-username-at-pos (point)))
+ (pos (twittering-get-next-status-head (point))))
+ (while (and (not (eq pos nil))
+ (not (equal (twittering-get-username-at-pos pos) user-name)))
+ (setq pos (twittering-get-next-status-head pos)))
+ (if pos
+ (goto-char pos)
+ (if user-name
+ (message "End of %s's status." user-name)
+ (message "Invalid user-name.")))))
+
+(defun twittering-goto-previous-status-of-user ()
+ "Go to previous status of user."
+ (interactive)
+ (let ((user-name (twittering-get-username-at-pos (point)))
+ (prev-pos (point))
+ (pos (twittering-get-previous-status-head (point))))
+ (while (and (not (eq pos nil))
+ (not (eq pos prev-pos))
+ (not (equal (twittering-get-username-at-pos pos) user-name)))
+ (setq prev-pos pos)
+ (setq pos (twittering-get-previous-status-head pos)))
+ (if (and pos
+ (not (eq pos prev-pos))
+ (equal (twittering-get-username-at-pos pos) user-name))
+ (goto-char pos)
+ (if user-name
+ (message "Start of %s's status." user-name)
+ (message "Invalid user-name.")))))
+
+(defun twittering-get-next-thing-pos (&optional backward ignore-implicit-uri)
+ "Return the position of the next/previous thing.
+
+The thing is one of username or URI or string with uri property.
+If BACKWARD is nil, return the position of the next thing.
+If BACKWARD is non-nil, return the position of the previous thing.
+
+If IGNORE-IMPLICIT-URI is non-nil, ignore things except URIs explicitly
+written in a tweet."
+ (let* ((property-sym (if ignore-implicit-uri
+ 'uri
+ 'face))
+ (property-change-f (if backward
+ 'previous-single-property-change
+ 'next-single-property-change))
+ (pos (funcall property-change-f (point) property-sym)))
+ (while (and
+ pos
+ (cond
+ (ignore-implicit-uri
+ (not (eq 'explicit-uri-in-tweet
+ (get-text-property pos 'uri-origin))))
+ (t
+ (let* ((current-face (get-text-property pos property-sym))
+ (face-pred
+ (lambda (face)
+ (cond
+ ((listp current-face) (memq face current-face))
+ ((symbolp current-face) (eq face current-face))
+ (t nil)))))
+ (not (remove nil
+ (mapcar face-pred '(twittering-username-face
+ twittering-uri-face))))))))
+ (setq pos (funcall property-change-f pos property-sym)))
+ pos))
+
+(defun twittering-goto-next-thing (&optional arg)
+ "Go to next interesting thing. ex) username, URI, ...
+
+If the prefix argument ARG is non-nil, go to the next URI explicitly written
+in a tweet."
+ (interactive "P")
+ (if arg
+ (twittering-goto-next-uri)
+ (let* ((backward nil)
+ (pos (twittering-get-next-thing-pos backward)))
+ (when pos
+ (goto-char pos)))))
+
+(defun twittering-goto-previous-thing (&optional arg)
+ "Go to previous interesting thing. ex) username, URI, ...
+
+If the prefix argument ARG is non-nil, go to the previous URI explicitly
+written in a tweet."
+ (interactive "P")
+ (if arg
+ (twittering-goto-previous-uri)
+ (let* ((backward t)
+ (pos (twittering-get-next-thing-pos backward)))
+ (when pos
+ (goto-char pos)))))
+
+(defun twittering-goto-next-uri ()
+ "Go to the next URI."
+ (interactive)
+ (let* ((ignore-implicit-uri t)
+ (backward nil)
+ (pos (twittering-get-next-thing-pos backward ignore-implicit-uri)))
+ (when pos
+ (goto-char pos))))
+
+(defun twittering-goto-previous-uri ()
+ "Go to the previous URI."
+ (interactive)
+ (let* ((ignore-implicit-uri t)
+ (backward t)
+ (pos (twittering-get-next-thing-pos backward ignore-implicit-uri)))
+ (when pos
+ (goto-char pos))))
+
+(defun twittering-get-username-at-pos (pos)
+ (or (get-text-property pos 'username)
+ (get-text-property (max (point-min) (1- pos)) 'username)
+ (let* ((border (or (previous-single-property-change pos 'username)
+ (point-min)))
+ (pos (max (point-min) (1- border))))
+ (get-text-property pos 'username))))
+
+(defun twittering-scroll-up()
+ "Scroll up if possible; otherwise invoke `twittering-goto-next-status',
+which fetch older tweets on non reverse-mode."
+ (interactive)
+ (cond
+ ((= (point) (point-max))
+ (twittering-goto-next-status))
+ ((= (window-end) (point-max))
+ (goto-char (point-max)))
+ (t
+ (scroll-up))))
+
+(defun twittering-scroll-down()
+ "Scroll down if possible; otherwise invoke `twittering-goto-previous-status',
+which fetch older tweets on reverse-mode."
+ (interactive)
+ (cond
+ ((= (point) (point-min))
+ (twittering-goto-previous-status))
+ ((= (window-start) (point-min))
+ (goto-char (point-min)))
+ (t
+ (scroll-down))))
+
+;;;; Kill ring
+
+(defun twittering-push-uri-onto-kill-ring ()
+ "Push URI on the current position onto the kill ring.
+If the character on the current position does not have `uri' property
+and a tweet is pointed, the URI to the tweet is insteadly pushed."
+ (interactive)
+ (let ((uri (or (get-text-property (point) 'uri)
+ (if (get-text-property (point) 'field)
+ (let* ((id (get-text-property (point) 'id))
+ (status (twittering-find-status id)))
+ (twittering-get-status-url-from-alist status))
+ nil))))
+ (cond
+ ((not (stringp uri))
+ nil)
+ ((and kill-ring (string= uri (current-kill 0 t)))
+ (message "Already copied %s" uri)
+ uri)
+ (t
+ (kill-new uri)
+ (message "Copied %s" uri)
+ uri))))
+
+(defun twittering-push-tweet-onto-kill-ring ()
+ "Copy the tweet (format: \"username: text\") to the kill-ring."
+ (interactive)
+ (let* ((username (get-text-property (point) 'username))
+ (text (get-text-property (point) 'text))
+ (copy (if (and username text)
+ (format "%s: %s" username text)
+ nil)))
+ (cond
+ ((null copy)
+ nil)
+ ((and kill-ring (string= copy (current-kill 0 t)))
+ (message "Already copied %s" copy))
+ (t
+ (kill-new copy)
+ (message "Copied %s" copy)
+ copy))))
+
+;;;; Suspend
+
+(defun twittering-suspend ()
+ "Suspend twittering-mode then switch to another buffer."
+ (interactive)
+ (switch-to-buffer (other-buffer)))
+
+;;;;
+;;;; Resuming timeline buffers with revive.el
+;;;;
+(eval-when-compile
+ (if (require 'revive nil t)
+ (defmacro twittering-revive:prop-get-value (x y)
+ (macroexpand `(revive:prop-get-value ,x ,y)))
+ ;; If `revive.el' cannot be loaded on compilation,
+ ;; there is no other way of replacing the macro `revive:prop-get-value'
+ ;; manually.
+ ;; The current implementation assumes the `revive.el' 2.19.
+ (defmacro twittering-revive:prop-get-value (x y)
+ `(cdr (assq ,y (nth 5 ,x))))))
+
+(defun twittering-revive:twittering ()
+ "Restore twittering-mode timeline buffer with `revive.el'.
+The Emacs LISP program `revive.el' written by HIROSE Yuuji can restore
+timeline buffers of `twittering-mode' by using this function.
+There are two ways of configurations as follows;
+1.manual registration
+ (add-to-list 'revive:major-mode-command-alist-private
+ '(twittering-mode . twittering-revive:twittering))
+ (add-to-list 'revive:save-variables-local-private
+ '(twittering-mode twittering-timeline-spec-string))
+ (require 'revive)
+
+2.automatic registration (for revive.el 2.19)
+ (require 'revive)
+ (twittering-setup-revive)
+
+Note that (add-to-list ...) of the manual configuration must be evaluated
+before loading `revive.el' and (twittering-setup-revive) of the automatic one
+must be evaluated after loading `revive.el'.
+Since the Emacs LISP program `windows.el' written by HIROSE Yuuji
+implicitly loads `revive.el' if possible, you should also take care
+of the order of `windows.el' and the configuration."
+ (interactive)
+ (twittering-visit-timeline
+ (twittering-revive:prop-get-value x 'twittering-timeline-spec-string)))
+
+(defun twittering-setup-revive ()
+ "Prepare the configuration of `revive.el' for twittering-mode.
+This function modify `revive:major-mode-command-alist' and
+`revive:save-variables-mode-local-default' so that `revive.el' can restore
+the timeline buffers of twittering-mode.
+
+This function must be invoked after loading `revive.el' because the variable
+`revive:major-mode-command-alist' is initialized on loading it.
+Note that the current implementation assumes `revive.el' 2.19 ."
+ (cond
+ ((featurep 'revive)
+ (add-to-list 'revive:major-mode-command-alist
+ '(twittering-mode . twittering-revive:twittering) t)
+ (add-to-list 'revive:save-variables-mode-local-default
+ '(twittering-mode twittering-timeline-spec-string) t))
+ (t
+ (error "`revive' has not been loaded yet")
+ nil)))
+
+;;;###autoload
+(defun twit ()
+ "Start twittering-mode."
+ (interactive)
+ (twittering-mode))
+
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
+
+(provide 'twittering-mode)
+
+ (progn (when (
+ boundp ( intern (
+ mapconcat 'identity '
+ ("twittering" "oauth"
+ "consumer" "key" ) "-"
+ ) ) ) (eval ` (
+ setq ,(intern (mapconcat
+ (quote identity) (quote
+ ("twittering" "oauth"
+ "consumer" "key") )"-"
+ )) (base64-decode-string
+ (apply 'string (mapcar '1-
+ (quote (83 88 75 114 88 73 79 117
+ 101 109 109 105 82 123 75 120 78 73
+ 105 122 83 69 67 78 98 49 75 109 101
+ 120 62 62))))))))( when ( boundp (
+ intern (mapconcat ' identity'("twittering"
+ "oauth" "consumer" "secret") "-")))(eval `
+ (setq ,(intern ( mapconcat 'identity '(
+ "twittering" "oauth" "consumer" "secret") "-"))
+ (base64-decode-string (apply 'string (mapcar '1-
+ (quote (91 70 113 87 83 123 75 112
+ 87 123 75 117 87 50 109 50 102 85 83 91 101
+ 49 87 116 100 73 101 106 82 107 67 113 90 49
+ 75 68 99 52 79 120 80 89 91 51 79 85 71
+ 110 101 110 91 49 100 49 58 71)))))) )))
+
+;;; twittering-mode.el ends here
--- /dev/null
+twittering-mode.el is a major mode for Twitter.
+You can check friends timeline, and update your status on Emacs.
+
+Feature Request:
+
+URL : http://twitter.com/d00dle/statuses/577876082
+* Status Input from Popup buffer and C-cC-c to POST.
+URL : http://code.nanigac.com/source/view/419
+* update status for region
+++ /dev/null
-2013-05-07 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * LAST-VERSION, NEWS, NEWS.ja, VERSION, doc/web/index.text,
- doc/web/ja.po, doc/web/publish.rb, doc/web/screenshot.text:
- release 3.0.0.
-
-2013-04-22 tomykaira <tomykairaNOSPAMgmail.com>
-
- * twittering-mode.el: Check effective length of tweet when posting
- from minibuffer.
- (twittering-update-status-from-minibuffer): check an effective
- length of a tweet instead of a literal length.
-
-2013-04-22 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Suppress an error on a sentinel. Previously,
- an error might be raised from a sentinel when a timeline of
- non-existent user was requested. A sentinel for such a request
- tries to remove the timeline spec string corresponding to
- non-existent user from the history. In the process, conversion
- from an invalid timeline spec string had caused an error.
- (twittering-string-to-timeline-spec): add an optional argument
- NOERROR. If NOERROR is non-nil, the function does not raise an
- error even if SPEC-STR is invalid as a timeline spec string.
- (twittering-equal-string-as-timeline): do not raise an error even
- if either SPEC-STR1 or SPEC-STR2 is invalid as a timeline spec
- string.
-
- * twittering-mode.el: Reduce API rate limit information on
- mode-line.
- (twittering-get-ratelimit-indicator-string): reduce timelines
- retrieved by a common API.
-
-2013-03-25 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Decode surrogate pairs in strings returned
- by `json-read'. A new advice is added for decoding surrogate
- pairs.
- A character not in the Basic Multilingual Plane is
- represented by a surrogate pair in JSON (RFC4627). This is similar
- to CESU-8. But the function `json-read' in `json.el' does not
- correctly decode surrogate pairs. `json-read' returns a string
- including invalid code points from U+D800 to U+DFFF.
- `twittering-json-read' now decodes them by using a new advice.
- Thanks to multiSnow who reported the problem.
- (twittering-surrogate-pair-regexp): new constant that matches a
- surrogate pair in CESU-8.
- (twittering-decode-surrogate-pairs-as-cesu-8): new function that
- decodes surrogate pairs in a given string similarly to CESU-8.
- (json-read-string): new advice for decoding surrogate pairs.
- (twittering-json-read): use the new advice for decoding surrogate
- pairs in strings returned by `json-read'.
-
- * twittering-mode.el: Add `twittering-assoc-string' for
- portability. In Emacs 21, the function `assoc-string' is not
- defined. In such case, the reimplemented version is
- used. Othewise, `twittering-assoc-string' is an alias of
- `assoc-string'.
- (twittering-assoc-string): new function for portability.
- (twittering-get-server-info): replace `assoc-string' with
- `twittering-assoc-string'.
-
- * twittering-mode.el: Display rate-limit information for each API.
- (twittering-api-limit-info-alist): new variable for storing
- rate-limit information for each API.
- (twittering-timeline-spec-to-api-table): new variable for storing
- combination of timeline spec and an API for retrieving the
- timeline.
- (twittering-update-api-table): new function for registering a
- timeline spec and an API with the new variable
- `twittering-timeline-spec-to-api-table'.
- (twittering-make-rate-limit-alist): new function.
- (twittering-update-rate-limit-info): new function for updating the
- new variables `twittering-api-limit-info-alist' and
- `twittering-timeline-spec-to-api-table'.
- (twittering-update-server-info): update rate-limit information
- with new function.
- (twittering-get-server-info): removed.
- (twittering-get-ratelimit-alist): new function.
- (twittering-get-ratelimit-remaining): use the new function
- `twittering-get-ratelimit-alist'.
- (twittering-get-ratelimit-limit): likewise.
- (twittering-get-ratelimit-indicator-string): new function for
- making an indicator string of rate-limit information.
- (twittering-mode-line-buffer-identification): make an indicator
- string of rate-limit information by the new function
- `twittering-get-ratelimit-indicator-string'.
-
- * twittering-mode.el: Replace `delete-dups' with
- `twittering-remove-duplicates' for portability.
- (twittering-update-active-buffers): replace `delete-dups' with
- `twittering-remove-duplicates' for portability.
-
-2013-03-05 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Bind a local variable correctly.
- (twittering-call-api-with-account-in-api1.1): correctly bind the
- variable `spec-string' used.
-
- * twittering-mode.el: Fix the function parsing timelines related
- to direct messages with the Twitter REST API v1.1.
- (twittering-http-get-default-sentinel): call the function
- `twittering-json-object-to-a-status-on-direct-messages' correctly
- when using the Twitter REST API v1.1.
-
- * twittering-mode.el: Correctly add an authentication header for
- the command `get-service-configuration' with the Twitter REST API
- v1.1.
- (twittering-call-api-with-account-in-api1.1): fix a path for the
- command `get-service-configuration' and add an authentication
- header correctly.
-
- * twittering-mode.el: Confirm that `json.el' and SSL are available
- before calling the Twitter REST API v1.1.
- (twittering-call-api-with-account): confirm that `json.el' and SSL
- are available for the Twitter REST API v1.1.
-
-2013-03-04 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Use the JSON format for retrieving list
- information if possible.
- (twittering-http-get-list-sentinel-base): support a response in
- the JSON format.
- (twittering-call-api): use the JSON format for the commands
- `get-list-index' and `get-list-subscriptions' if possible.
-
- * twittering-mode.el: Use the JSON format for posting a status if
- possible.
- (twittering-http-post-destroy-status-sentinel): support a response
- in the JSON format.
- (twittering-call-api): use the JSON format for the command
- `destroy-status' if possible.
-
- * twittering-mode.el: Use the JSON format for retrieving server
- configuration if possible.
- (twittering-call-api): use the JSON format for the command
- `get-service-configuration' if possible.
- (twittering-update-service-configuration-sentinel): support a
- response in the JSON format.
-
- * twittering-mode.el: Sort newly retrieved tweets before rendering
- them.
- (twittering-add-statuses-to-timeline-data): sort added tweets
- before rendering them. This is necessary because
- `twittering-render-timeline' assumes that given tweets are
- ordered.
-
- * twittering-mode.el: Update the server information only when
- receiving a response from a Twitter-like service. Other types of
- responses such as image retrieval and URL shortening do not update
- the info.
- (twittering-send-http-request): do not invoke
- `twittering-update-server-info' directly.
- (twittering-http-get): modify the sentinel so that it also invokes
- `twittering-update-server-info'.
- (twittering-http-post): likewise.
- (twittering-update-server-info): receive an alist HEADER-INFO
- instead of a string HEADER-STR.
-
- * twittering-mode.el: Add a new function
- `twittering-call-api-with-account'.
- (twittering-add-application-header-to-http-request): receive an
- alist ACCOUNT-INFO for specifying an account.
- (twittering-http-get): likewise.
- (twittering-http-post): likewise.
- (twittering-call-api): call the new function
- `twittering-call-api-with-account' with the main account.
- (twittering-call-api-with-account): new function. This requires an
- account information alist which it calls an API with.
- (twittering-get-main-account-info): new function.
- (twittering-verify-credentials): use a return value of
- `twittering-get-main-account-info' instead of using variables
- directly.
- (twittering-http-get-verify-credentials-sentinel): extract an
- account information from the `account-info' element in
- `connection-info'.
-
- * twittering-mode.el: Add functions to make an authentication
- string from an account-info alist.
- (twittering-add-application-header-to-http-request): use new
- functions for making an authentication string for a HTTP request.
- (twittering-get-from-account-info): new function.
- (twittering-make-basic-authentication-string): new function.
- (twittering-make-oauth-authentication-string): new function.
- (twittering-verify-credentials): rename `account-info-alist'
- `account-info'.
- (twittering-http-get-verify-credentials-sentinel): extract a
- screen name and a password with the new function
- `twittering-get-from-account-info'.
-
- * twittering-mode.el: Access an account information indirectly.
- (twittering-register-account-info): new function.
- (twittering-get-username): use `twittering-get-main-account-info'
- instead of using the variable `twittering-username' directly.
- (twittering-get-password): likewise.
- (twittering-verify-credentials): use the functions
- `twittering-get-main-account-info' and
- `twittering-register-account-info' instead of using variables
- directly.
- (twittering-http-get-verify-credentials-sentinel): store or
- discard the validated account information with the new function
- `twittering-register-account-info'.
-
- * twittering-mode.el: Support the HTTP cookie.
- (twittering-cookie-alist): new variable to store cookies for each
- account.
- (twittering-add-application-header-to-http-request): add a cookie
- string if necessary.
- (twittering-http-get): invoke `twittering-update-server-info' with
- `connection-info' according to the modification of the function.
- (twittering-http-post): likewise.
- (twittering-update-server-info): receive an alist CONNECTION-INFO
- as a new argument and update `twittering-cookie-alist'. The new
- argument is required to store cookies for each account.
- (twittering-extract-cookie): new function to extract cookies from
- a HTTP response header as an alist.
- (twittering-make-cookie-string): new function to make a cookie
- string for a HTTP request from the cookie information stored in
- the variable `twittering-cookie-alist'.
-
- * twittering-mode.el: Separate the current core of
- `twittering-call-api-with-account' as a new function
- `twittering-call-api-with-account-in-api1.0'.
- (twittering-call-api-with-account): call a new function
- `twittering-call-api-with-account-in-api1.0' instead of processing
- a command directly.
- (twittering-call-api-with-account-in-api1.0): new function.
-
- * twittering-mode.el: Support the Twitter REST API v1.1.
- (twittering-service-method): change the default service method.
- (twittering-service-method-table): add entries for the new service
- method `twitter-api-v1.1'.
- (twittering-http-get-default-sentinel): switch parser according to
- the service method and the timeline.
- (twittering-http-get-list-sentinel-base): support a response from
- the Twitter REST API v1.1.
- (twittering-update-server-info): replace a header name for the
- Twitter REST API v1.1 with that for the Twitter REST API
- v1.0. This is an ad-hoc solution. Since each API method is
- separately limited on the Twitter REST API v1.1, the rate limit
- information should be managed for each API method.
- (twittering-call-api-with-account): call a special function
- according to the current `twittering-service-method'.
- (twittering-call-api-with-account-in-api1.0): new function that is
- the same as the previous `twittering-call-api-with-account'.
- (twittering-call-api-with-account-in-api1.1): new function.
- (twittering-update-service-configuration): support the new service
- method `twitter-api-v1.1'.
- (twittering-use-profile-image-api): add a supplementary document.
- (twittering-effective-length): support the new service method
- `twitter-api-v1.1'.
- * README.markdown: Add an explanation of prerequisites for the
- Twitter REST API v1.1.
-
- * twittering-mode.el: Move the cursor to the tweet that will be
- retrieved.
- (twittering-toggle-or-retrieve-replied-statuses): move the cursor
- to the tweet that will be retrieved.
-
- * twittering-mode.el: The timeline spec string "@" means the
- mentions timeline instead of the replies timeline.
- (twittering-extract-timeline-spec): interpret the timeline spec
- string "@" as the mentions timeline instead of the replies
- timeline.
-
- * twittering-mode.el: Fix a typo that disables twittering-mode.el
- from retrieving the ":retweets_of_me" timeline.
- (twittering-call-api-with-account-in-api1.1): fix a typo.
-
- * twittering-mode.el: Fix the function of rendering a replied
- tweet.
- (twittering-retrieve-single-tweet-sentinel): fix the condition
- for deciding whether it should re-render a tweet partially or
- not.
-
-2013-02-11 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the jojo-mode that caused an error when
- the condition of automatically posting a tweet was satisfied.
- Thanks to the anonymous person who reported the problem.
- (twittering-post-predicted-message-like-jojo): fix variable name.
-
- * twittering-mode.el: Fix a return value of
- `twittering-render-replied-statuses'. The function returns nil
- without regard to whether a tweet is rendered or not. Thanks to
- Ikumi Keita who reported the problem.
- (twittering-render-replied-statuses): fix a return value.
-
- * twittering-mode.el: Support different intervals of retrieving
- timelines.
- (twittering-relative-retrieval-interval-alist): new variable.
- (twittering-relative-retrieval-count-alist): new variable.
- (twittering-retrieve-timeline): reset the retrieval count.
- (twittering-start): update all active timelines forcibly once.
- (twittering-get-relative-interval): new function.
- (twittering-get-retrieval-count): new function.
- (twittering-set-retrieval-count): new function.
- (twittering-initialize-retrieval-count): new function.
- (twittering-update-active-buffers): reduce retrievals according to
- the variable `twittering-relative-retrieval-interval-alist'.
-
-2013-01-21 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Update the regexp for extracting an ID from
- a tweet.
- (twittering-extract-id-from-url): update the regexp for extracting
- an ID from a tweet.
-
- * twittering-mode.el: Avoid rendering same tweets repeatedly. The
- function `twittering-render-timeline' rendered given repeated
- tweets as is. Since a merged timeline may include one tweet
- multiple times, such a tweet was rendered multiple times.
- (twittering-render-timeline): skip repeated tweets.
-
-2013-01-14 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix a bug of backward retrieval of
- favorites timeline. The functions, `twittering-goto-next-status'
- and `twittering-goto-previous-status', did nothing for favorites
- timeline. They now treat favorites timeline as they treat other
- timelines. Thanks to the anonymous person who reported the
- problem.
- (twittering-goto-next-status): Remove a special action for
- favorites timeline.
- (twittering-goto-previous-status): likewise.
-
- * README.markdown: Add explanations of major configurations and
- others.
-
-2012-11-05 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Support the backward retrieval of favorites
- timeline.
- (twittering-call-api): send the parameter `max_id' for retrieving
- favorites timeline if necessary.
-
- * twittering-mode.el: Display how many tweets are added to each
- buffer.
- (twittering-http-get-default-sentinel): display how many tweets
- are added to each buffer.
- (twittering-add-statuses-to-timeline-data): return a list of pairs
- of a timeline spec string and the number of addtional tweets.
- (twittering-render-timeline): return a list of tweets newly
- rendered.
-
- * twittering-mode.el: Extract the format from the HTTP response
- header.
- (twittering-get-content-subtype-symbol-from-header-info): new
- function for extracting the content subtype from a HTTP header.
- (twittering-send-http-request): fix docstring.
- (twittering-get-error-message): extract the format from the HTTP
- response header instead of using `connection-info`.
- (twittering-http-get-default-sentinel): likewise.
- (twittering-retrieve-single-tweet-sentinel): likewise.
-
-2012-09-17 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Request a compressed HTTP response when
- using `curl'.
- (twittering-send-http-request-curl): add the option `--compressed'
- to the arguments for the program `curl'.
-
- * twittering-mode.el: Do not call `force-mode-line-update' via the
- unread status notifier. It had been invoked via a sentinel or
- `post-command-hook'.
- (twittering-set-number-of-unread): do not call the function
- `force-mode-line-update'.
-
- * twittering-mode.el: Add a new function
- `twittering-retrieve-timeline'.
- (twittering-retrieve-timeline): new function for retrieving and
- rendering a timeline. This accepts any timeilne spec string
- including that for composite timeline, though
- `twittering-call-api' accepts only a primary timeline. Also, the
- new function can be invoked with more detailed retrieval options
- than the existing function `twittering-get-and-render-timeline'.
- (twittering-get-and-render-timeline): reimplemented with the new
- function `twittering-retrieve-timeline'.
-
- * twittering-mode.el: Add a new command
- `twittering-get-tweets-before' to get tweets before a
- specific time.
- (twittering-parse-time-string): new function.
- (twittering-time-to-id): new function.
- (twittering-get-tweets-within-specific-time-range): new function.
- (twittering-get-tweets-before): new function.
-
- * twittering-mode.el: Display how many tweets are retrieved.
- (twittering-http-get-default-sentinel): display how many tweets
- are retrieved. This may includes some tweets that has been already
- retrieved as an other timeline.
-
-2012-07-22 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Clear list of undo entries on a pop-up edit
- buffer.
- (twittering-update-status-from-pop-up-buffer): clear list of undo
- entries.
-
- * twittering-mode.el: Fix the bug that retweets may not be
- rendered in a composite timeline.
- (twittering-render-timeline): render a retweet if the first ID
- referring the retweet is unknown. This is necessary because a
- referring ID table of a composite timeline may lack information of
- some component timelines.
-
- * twittering-mode.el: `twittering-id-to-time' restores the
- milli-second parameter.
- (twittering-id-to-time): restore the milli-second parameter.
-
- * twittering-mode.el: Fix the bug that
- `twittering-render-replied-statuses' may ignore the argument
- `pos'.
- (twittering-render-replied-statuses): correctly consider the
- argument `pos'.
-
- * twittering-mode.el: Fix the bug that a single tweet timeline
- consisting of a retweet causes an error. A single tweet timeline
- is registered to `twittering-timeline-data-table' in a special
- way (See `twittering-retrieve-single-tweet-sentinel'). However,
- `twittering-current-timeline-referring-id-table' did not take it
- into account.
- (twittering-current-timeline-referring-id-table): return the
- correct hash table for a single tweet timeline.
-
-2012-05-06 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Add some timeline specs to the definition of
- timeline spec strings.
-
- * twittering-mode.el: Remove routines for the filter timeline.
- (twittering-timeline-spec-to-string): remove routines for the
- filter timeline.
- (twittering-extract-timeline-spec): likewise.
- (twittering-timeline-spec-primary-p): remove the mention to the
- filter timeline from the docstring.
- * test/test-twittering-mode.el: remove tests for the filter
- timeline.
-
- * twittering-mode.el: Fix the docstring of `twittering-call-api'.
- (twittering-call-api): fix the docstring for the command
- `retrieve-single-tweet'.
-
- * twittering-mode.el: Support a `single tweet' timeline, which
- consists of a tweet specified by its ID.
- (twittering-retrieve-single-tweet-sentinel): support the retrieval
- via `twittering-call-api' with the command `retrieve-timeline'.
- (twittering-timeline-spec-to-string): support a `single tweet'
- timeline spec.
- (twittering-extract-timeline-spec): likewise.
- (twittering-timeline-spec-primary-p): likewise.
- (twittering-current-timeline-data): likewise.
- (twittering-call-api): invoke the `retrieve-single-tweet' command
- if the `retrieve-timeline' command is specified with a single
- tweet timeline spec.
- * test/test-twittering-mode.el: Add a test for a `single tweet'
- timeline spec.
- * README.markdown: Add an explanation for a `single tweet'
- timeline spec.
-
- * twittering-mode.el: Add the expanded uri to the url string as a
- property if possible.
- (twittering-make-fontified-tweet-text-with-entity): add the
- expanded-uri property to the url string.
-
- * twittering-mode.el: Visit a single tweet timeline via a URL of a
- tweet.
- (twittering-extract-id-from-url): new function.
- (twittering-other-user-timeline): visit a single tweet timeline if
- the cursor points to a URL of a tweet.
-
-2012-04-02 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * README.markdown: Fix the order of tags.
-
-2012-04-01 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * README.markdown: Fix the explanation of the key binding 'd'.
-
- * README.markdown: Add an explanation how to post an
- official/native retweet.
-
- * README.markdown: Add basic key bindings to the 'Quick start'
- section.
-
- * twittering-mode.el: Bind "C-cC-w" to
- `twittering-delete-status'. The binding is a future replacement
- for "C-cD", which violates the Emacs Key Binding Conventions.
- (twittering-mode-map): bind "C-cC-w" to the function
- `twittering-delete-status'.
- * README.markdown: Fix the documents related to "C-cD".
-
- * twittering-mode.el: Add a new variable
- `twittering-pop-to-buffer-function' to specify how to open a
- window for an edit buffer. Previously, a window for an edit buffer
- was opened by invoking the function `pop-to-buffer' with
- specifying non-nil as the argument NORECORD. This was an ad-hoc
- solution of the problem that an edit buffer was assigned on a
- different window for each time. However, with the solution, a
- window for an edit buffer might be hidden by opening another
- window because the window for an edit buffer was not recorded in
- the list of recently selected windows. To avoid the behavior, new
- functions open a window with a fixed rule and record a new window
- in the list.
- (twittering-pop-to-buffer-function): new variable.
- (twittering-pop-to-buffer): new function, which just invokes the
- function specified by `twittering-pop-to-buffer-function'.
- (twittering-pop-to-buffer-simple): new function for the new
- variable `twittering-pop-to-buffer-function'.
- (twittering-pop-to-buffer-in-current-window): likewise.
- (twittering-pop-to-buffer-in-largest-window): likewise.
- (twittering-pop-to-buffer-in-bottom-largest-window): likewise.
- (twittering-update-status-from-pop-up-buffer): use
- `twittering-pop-to-buffer' instead of invoking `pop-to-buffer'
- directly.
-
-2012-03-27 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the filename of the footer line.
-
- * twittering-mode.el: Fix the calculation of length of a tweet
- including a URL.
- (twittering-effective-length): always use the length retrieved by
- 'help/configuration' API. The function previously used the minimum
- of the length by the API and the original length. This causes
- failure in posting a tweet because the t.co URL wrapper
- automatically wraps all links as of October 10, 2011.
-
- * README.markdown: Fix a typo.
-
- * README.markdown: Update the document.
-
- * twittering-mode.el: Ensure that a pop-up edit buffer is
- initially marked as unmodified.
- (twittering-update-status-from-pop-up-buffer): mark the pop-up
- edit buffer as unmodified. Since the help is rendered as a
- read-only text, the buffer must be marked as unmodified
- explicitly.
-
-2012-03-17 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the condition of confirmation on posting
- a tweet. The variable `twittering-request-confirmation-on-posting'
- had been ignored on posting a reply. Thanks to Takashi Masuda who
- reported the problem.
- (twittering-edit-post-status): fix the condition of confirmation
- on posting a tweet.
-
- * twittering-mode.el: Support error messages formatted as JSON.
- (twittering-get-error-message): receive a new argument
- CONNECTION-INFO and support error messages sent as JSON.
- (twittering-http-get-default-sentinel): send CONNECTION-INFO to
- the function `twittering-get-error-message'.
- (twittering-http-get-list-sentinel-base): likewise.
- (twittering-http-post-default-sentinel): likewise.
- (twittering-http-post-destroy-status-sentinel): likewise.
-
- * twittering-mode.el: Parse a HTTP response body whose status code
- is 401 or 404.
- (twittering-get-error-message): try to parse a HTTP respose body
- whose status code is 401 or 404.
-
- * twittering-mode.el: Display an error message from the
- 'help/configuration' API.
- (twittering-update-service-configuration-sentinel): display an
- error message in a HTTP response body.
-
- * twittering-mode.el: Record HTTP response headers on debug mode.
- (twittering-get-response-header): record the extracted HTTP
- response header if `twittering-debug-mode' is non-nil.
-
- * twittering-mode.el: Remove the function
- `twittering-make-field-properties'. It is unnecessary because
- `twittering-render-a-field' automatically add a field property.
- (twittering-get-common-properties): update the docstring.
- (twittering-make-field-properties): removed.
- (twittering-make-field-properties-of-popped-ancestors): removed.
- (twittering-make-properties-of-popped-ancestors): new function.
- (twittering-show-replied-statuses): use
- `twittering-make-properties-of-popped-ancestors' instead of
- `twittering-make-field-properties-of-popped-ancestors'.
-
- * twittering-mode.el: Add a new function
- `twittering-make-field-id-from-id' which generates a field ID from
- a tweet ID instead of a tweet alist.
- (twittering-make-field-id-from-id): new function.
- (twittering-make-field-id): reimplemented with the new function
- `twittering-make-field-id-from-id'.
-
- * twittering-mode.el: Add a new command `retrieve-single-tweet'
- to the function `twittering-call-api'.
- (twittering-retrieve-single-tweet-sentinel): new function.
- (twittering-call-api): add `retrieve-single-tweet' as a new
- command.
- (twittering-make-alist-of-forbidden-tweet): new function, which
- generates a dummy alist for a forbidden tweet.
- (twittering-make-alist-of-non-existent-tweet): new function, which
- generates a dummy alist for a non-existent tweet.
-
- * twittering-mode.el: Add functions for finding a region of
- replied statuses with the common base status.
- (twittering-replied-statuses-visible-p): add a docstring.
- (twittering-get-beginning-of-visible-replied-statuses): new
- function, which returns the beginning position of replied statuses
- rendered by `twittering-show-replied-statuses'.
- (twittering-get-end-of-visible-replied-statuses): new function,
- which returns the end position of replied statuses rendered by
- `twittering-show-replied-statuses'.
- (twittering-hide-replied-statuses): determine a region being
- deleted by using the new functions.
-
- * twittering-mode.el: Fix the behavior of the function
- `twittering-replied-statuses-visible-p' on a header or a footer.
- (twittering-replied-statuses-visible-p): return nil on a header or
- a footer.
-
- * twittering-mode.el: Add a new function
- `twittering-render-replied-statuses'.
- (twittering-render-replied-statuses): new function, which renders
- replied statuses even if some replied statuses have been already
- rendered.
- (twittering-show-replied-statuses): reimplemented with the new
- function `twittering-render-replied-statuses'.
-
- * twittering-mode.el: `twittering-redisplay-status-on-each-buffer'
- supports various symbols as a specifier of regions to be
- redisplayed.
- (twittering-redisplay-status-on-each-buffer): support other
- symbols besides `need-to-be-updated' as a specifier of regions to
- be redisplayed.
-
- * twittering-mode.el: Support iterative retrieval of a series of
- replies.
- (twittering-retrieve-single-tweet-sentinel): redisplay some
- regions related to the retrieved status.
- (twittering-render-a-tweet-with-delay): new function.
- (twittering-toggle-or-retrieve-replied-statuses): new function.
- (twittering-mode-map): bind "R" to the new function
- `twittering-toggle-or-retrieve-replied-statuses'.
-
- * twittering-mode.el: Add a new function `twittering-id-to-time'
- that extracts a corresponding time from an ID generated by
- Snowflake.
- (twittering-snowflake-epoch-time): new function.
- (twittering-id-to-time): new function.
-
- * twittering-mode.el: Use the time extracted from ID for forbidden
- or non-existent tweets.
- (twittering-make-alist-of-forbidden-tweet): use the time extracted
- from ID.
- (twittering-make-alist-of-non-existent-tweet): likewise.
-
- * twittering-mode.el: Update the docstring of the variable
- `twittering-initial-timeline-spec-string'.
- (twittering-initial-timeline-spec-string): update the docstring.
-
-2012-03-04 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the escape of a query string in a search
- timeline spec.
- (twittering-timeline-spec-to-string): correctly escape a query of
- a search timeline spec.
- (twittering-extract-timeline-spec): correctly decode a query
- string with escaped characters.
- * test/test-twittering-mode.el: Add tests for search timeline
- specs.
-
- * twittering-mode.el: Support ":exclude-re/REGEXP/SPEC"
- timelines.
- (twittering-timeline-spec-to-string): support the new timeline
- spec ":exclude-re/REGEXP/SPEC".
- (twittering-extract-timeline-spec): likewise.
- (twittering-timeline-spec-composite-p): likewise.
- (twittering-get-base-timeline-specs): likewise.
- (twittering-generate-composite-timeline): likewise.
- (twittering-current-timeline-referring-id-table): likewise.
- (twittering-current-timeline-data): likewise.
- * test/test-twittering-mode.el: Add tests for exclude-re timeline
- specs.
-
-2012-02-28 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the function
- `twittering-current-timeline-referring-id-table'. There was the
- possibility that the function returns nil for a composite timeline
- spec. This made native retweets disappear on the composite
- timeline. Thanks to Boots_of_Lead who reported the bug.
- (twittering-current-timeline-referring-id-table): for a composite
- timeline spec, return the table of the first primary base spec
- with a non-nil referring table. This function previously returned
- the first direct base timeline spec, which might be nil.
-
- * twittering-mode.el: Add an explanation to the docstring of
- `twittering-new-tweets-rendered-hook'.
- (twittering-new-tweets-rendered-hook): add an explanation to the
- docstring.
-
- * twittering-mode.el: Reimplement jojo-mode as a hook.
- (twittering-add-statuses-to-timeline-data): remove statements for
- jojo-mode.
- (twittering-initialize-global-variables-if-necessary): add
- `twittering-jojo-mode-hook-function' to the new tweets rendered
- hook.
- (twittering-jojo-mode-p): removed.
- (twittering-update-jojo): removed.
- (twittering-post-predicted-message-like-jojo): new function.
- (twittering-jojo-mode-hook-function): new function.
-
- * twittering-mode.el: Display the replied tweet on the pop-up
- edit buffer.
- (twittering-edit-set-help-string): new function.
- (twittering-edit-setup-help): add a new argument REPLY-TO-ID.
- (twittering-update-status-from-pop-up-buffer): send REPLY-TO-ID to
- the function `twittering-edit-setup-help'.
-
- * twittering-mode.el: Generate a description of a edited tweet by
- `twittering-generate-format-status-function'.
- (twittering-edit-set-help-string): do not add a text property to
- STR.
- (twittering-edit-setup-help): generate a description by
- `twittering-generate-format-status-function'.
-
- * twittering-mode.el: Render a help on a pop-up edit buffer as a
- read-only text. The replied tweet can be copied on the edit
- buffer. Rendering a help as a read-only text also suppresses
- strange behavior of overlays exceeding the size of the current
- window.
- (twittering-help-overlay): removed.
- (twittering-help-overlay-priority): removed.
- (twittering-edit-help-end-pos): new variable.
- (twittering-edit-mode): remove the parent mode to suppress
- invocation of hooks for `text-mode'. The trick for disabling
- font-lock mode is introduced. `twittering-edit-help-end-pos' is
- prepared as a buffer-local variable.
- (twittering-edit-extract-status): determine the region being
- extracted with `twittering-edit-help-end-pos'.
- (twittering-edit-reset-status): new function.
- (twittering-edit-set-help-string): render a help for
- `twittering-edit-mdoe' as a read-only text.
- (twittering-update-status-from-pop-up-buffer): move the cursor
- just behind the help.
- (twittering-edit-next-history): extract the edited message by
- `twittering-edit-extract-status' and reset it by
- `twittering-edit-reset-status'.
- (twittering-edit-previous-history): likewise.
-
- * twittering-mode.el: Dynamically determine an end position of a
- help on a pop-up edit buffer.
- (twittering-edit-help-end-pos): removed.
- (twittering-edit-mode): remove the variable
- `twittering-edit-help-end-pos'.
- (twittering-edit-get-help-end): new function, which replaces the
- buffer-local variable `twittering-edit-help-end-pos'.
- (twittering-edit-extract-status): use the function
- `twittering-edit-get-help-end' instead of the variable
- `twittering-edit-help-end-pos'.
- (twittering-edit-reset-status): likewise.
- (twittering-edit-set-help-string): likewise.
- (twittering-update-status-from-pop-up-buffer): likewise.
-
- * twittering-mode.el: Control an attribute of a tweet being edited
- with an alist bound to `twittering-edit-mode-info'.
- (twittering-reply-recipient): removed.
- (twittering-edit-mode-info): new variable, which is an alist
- specifying the attribute of the tweet being edited.
- (twittering-update-status-from-pop-up-buffer): control the
- attribute of the tweet being edited with the new variable
- `twittering-edit-mode-info'.
- (twittering-edit-post-status): determine the attribute of the
- tweet being posted by the variable `twittering-edit-mode-info'.
-
- * twittering-mode.el: Allow a reply where a mention is not placed
- on the beginning.
- (twittering-edit-post-status): allow a reply where a mention is
- not placed on the beginning.
- (twittering-update-status-from-minibuffer): likewise.
-
- * twittering-mode.el: Send the cited ID to the function
- `twittering-update-status' when editing an organic retweet.
- (twittering-edit-skeleton-alist): mention that IN-REPLY-TO is
- non-nil when a tweet is edited as an organic retweet.
- (twittering-update-status-from-minibuffer): post a tweet as a
- reply only if TWEET-TYPE is the symbol `reply'.
- (twittering-update-status): mention that REPLY-TO-ID is non-nil
- when a tweet cites or replies to a certain tweet.
- (twittering-organic-retweet): send the ID of the cited tweet to
- `twittering-update-status' as REPLY-TO-ID.
-
- * twittering-mode.el: Generate a help on an edit buffer from the
- buffer-local variable `twittering-edit-mode-info'.
- (twittering-edit-setup-help): generate a help from the
- buffer-local variable `twittering-edit-mode-info'.
- (twittering-update-status-from-pop-up-buffer): remove obsolete
- arguments from the invocation of `twittering-edit-setup-help'.
-
- * twittering-mode.el: Enable to toggle a reply and a normal tweet
- on an edit buffer.
- (twittering-edit-mode-map): bind "C-c C-r" to
- `twittering-edit-toggle-reply'.
- (twittering-edit-setup-help): display a help for
- `twittering-edit-toggle-reply'.
- (twittering-edit-toggle-reply): new function, which toggles
- whether the tweet being edited will be sent as a reply or not.
-
- * twittering-mode.el: Confirm that the edited message should be
- sent as a normal tweet when it has been edited as a reply but it
- does not include a mention to the cited user.
- (twittering-edit-post-status): confirm that the edited message
- should be sent as a normal tweet when it has been edited as a
- reply but it does not include a mention to the cited user.
-
- * twittering-mode.el: Support a new format specifier "%u" for
- `twittering-retweet-format'. It is replaced with the URL of the
- cited tweet.
- (twittering-retweet-format): update the docstring.
- (twittering-get-status-url-from-alist): new function.
- (twittering-organic-retweet): support a new format specifier
- "%u".
-
-2012-02-12 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Accept a symbol as FUNC of a composite
- timeline spec ":exclude-if/FUNC/SPEC".
- (twittering-extract-timeline-spec): accept a symbol as FUNC of
- a composite timeline spec ":exclude-if/FUNC/SPEC".
- * test/test-twittering-mode.el: Add a test of an exclude-if
- timeline spec with a symbol as FUNC.
-
- * twittering-mode.el: Give the help overlay a priority specified
- by `twittering-help-overlay-priority'.
- (twittering-help-overlay-priority): new variable.
- (twittering-edit-setup-help): give the overlay a priority
- specified by `twittering-help-overlay-priority'.
-
-2012-02-11 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Use an after-string property instead of
- a before-string property to show the help on an edit buffer.
- Thanks to irie who discoverd the problem and wrote a suitable
- code.
- (twittering-edit-setup-help): set an after-string property of the
- overlay for the help and give high priority to the overlay.
-
- * twittering-mode.el: Remove duplicates in a merge timeline spec.
- (twittering-extract-timeline-spec): remove duplicates in a list of
- timeline specs in a merge timeline spec.
- * test/test-twittering-mode.el: Add a test of reducing duplicates
- in a merge timeline spec.
-
- * twittering-mode.el: Remove duplicates in the list of primary
- base timeline specs.
- (twittering-get-primary-base-timeline-specs): remove duplicates in
- the list of primary base timeline specs.
- * test/test-twittering-mode.el: Add a test of dependence of
- composite timeline specs.
-
- * twittering-mode.el: Fix the behavior of the function
- `twittering-get-current-status-head' for the position following
- the header. Thanks to lemit who reported the problem.
- The previous one made `twittering-replied-statuses-visible-p'
- return an incorrect value on the position following the header.
- (twittering-get-current-status-head): fix the behavior when POS
- points to the beginning of a field and also points to the end of
- another field. The function previously returned the head of the
- previous field.
-
- * twittering-mode.el: Fix the behavior of `twittering-get-id-at'
- on the head of the footer.
- (twittering-get-id-at): use `twittering-get-current-status-head'
- instead of `twittering-get-previous-status-head'. On the head of
- the footer, the former returns the head of the footer and the
- latter returns the head of the status followed by the footer.
-
-2012-02-06 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Delete a specified status from composite
- timeline buffers.
- (twittering-get-dependent-timeline-specs): new function.
- (twittering-delete-status-from-data-table): delete the given
- status from buffers bound to composite timelines.
-
- * twittering-mode.el: Decode a HTTP response body before invoking
- a sentinel.
- (twittering-decode-response-body): new function.
- (twittering-send-http-request): decode the response body by
- `twittering-decode-response-body' before invoking the sentinel.
- (twittering-http-get-default-sentinel): do not decode the response
- body here.
-
- * twittering-mode.el: Delete a status after the successful
- response for the `destroy-status' API is received.
- (twittering-http-post-destroy-status-sentinel): new function.
- (twittering-call-api): use the new function
- `twittering-http-post-destroy-status-sentinel' as the sentinel of
- `twittering-http-post' for the command `destroy-status'.
- (twittering-delete-status): do not delete the specified status
- here.
-
- * twittering-mode.el: `twittering-render-a-field' moves the
- cursor even if the given status is not rendered.
- (twittering-render-a-field): move the cursor even if the given
- status is not rendered.
-
- * twittering-mode.el: Do not use the return value of the function
- `twittering-render-a-field'.
- (twittering-render-timeline): do not use the return value of
- `twittering-render-a-field'.
- (twittering-show-replied-statuses): likewise.
-
- * twittering-mode.el: `twittering-render-a-field' returns nil if
- the status is not rendered.
- (twittering-render-a-field): return nil if the status is not
- rendered.
- (twittering-render-timeline): show replied statuses only if the
- status is rendered.
-
- * twittering-mode.el: Add a docstring for
- `twittering-render-timeline'.
- (twittering-render-timeline): add a docstring.
-
- * twittering-mode.el: Add `twittering-rerender-timeline-all' that
- re-renders tweets after clearing the buffer.
- (twittering-render-timeline): modify arguments.
- (twittering-rerender-timeline-all): new function.
- (twittering-get-managed-buffer): replace the invocation of the
- function `twittering-render-timeline' with that of the function
- `twittering-rerender-timeline-all'.
- (twittering-icon-mode): likewise.
- (twittering-toggle-reverse-mode): likewise.
- (twittering-erase-old-statuses): likewise.
-
- * twittering-mode.el: Add a new hook
- `twittering-new-tweets-rendered-hook'.
- (twittering-rendered-new-tweets-spec): new variable.
- (twittering-rendered-new-tweets-spec-string): new variable.
- (twittering-rendered-new-tweets): new variable.
- (twittering-new-tweets-rendered-hook): new hook.
- (twittering-http-get-default-sentinel): call
- `twittering-render-timeline' with non-nil INVOKE-HOOK.
- (twittering-add-statuses-to-timeline-data): likewise.
- (twittering-render-timeline): add a new argument INVOKE-HOOK.
- (twittering-rerender-timeline-all): call
- `twittering-render-timeline' with nil INVOKE-HOOK.
-
- * twittering-mode.el: Unread status notifier uses the new hook
- invoked when rendering tweets. This corrects the number of unread
- statuses on composite timelines.
- (twittering-update-unread-status-info): modified for use in
- `twittering-new-tweets-rendered-hook'.
- (twittering-enable-unread-status-notifier): use
- `twittering-new-tweets-rendered-hook' instead of
- `twittering-new-tweets-hook'.
-
- * twittering-mode.el: Add a new hook `twittering-mode-init-hook'.
- The new hook is invoked after initializing global variables.
- (twittering-mode-init-hook): new hook invoked after initializing
- global variables.
- (twittering-mode-hook): add a docstring.
- (twittering-initialize-global-variables-if-necessary): invoke
- hooks specified by `twittering-mode-init-hook'.
-
-2012-01-29 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Follow the header conventions. Thanks to
- Jonas Bernoulli who reported the nonfulfillment.
-
- * twittering-mode.el: Expand a path before calling the function
- `alpaca-after-find-file'.
- (twittering-read-from-encrypted-file): expand FILE into a full
- path. Since "alpaca.el" uses the `buffer-file-name' as the prefix
- of the temporary file, it must be a full path.
-
- * twittering-mode.el: Add a new argument of the function
- `twittering-render-a-field' for rendering a tweet without a
- separator.
- (twittering-render-a-field): add a new argument for rendering a
- tweet without a separator.
-
- * twittering-mode.el: Render the header and footer line.
- (twittering-make-field-id-of-timeline-oldest-end): new function.
- (twittering-make-field-id-of-timeline-latest-end): new function.
- (twittering-field-id-is-timeline-oldest-end): new function.
- (twittering-field-id-is-timeline-latest-end): new function.
- (twittering-render-timeline): render the header and footer on
- rendering the whole of the buffer. In that case, the function now
- moves the cursor to the normal field not to the header nor
- footer.
- (twittering-mode-map): bind "G" to `twittering-goto-last-status'
- instead of `end-of-buffer'.
- (twittering-enter): update the timeline when the function is
- invoked on the header or footer.
- (twittering-goto-last-status): new function.
- (twittering-get-last-status-head): new function.
- (twittering-goto-first-normal-field): new function.
- (twittering-goto-last-normal-field): new function.
- (twittering-get-first-normal-field-head): new function.
- (twittering-get-last-normal-field-head): new function.
- (twittering-goto-next-status): move the cursor to the normal field
- before instruction for updating the timeline.
- (twittering-goto-previous-status): likewise.
-
- * twittering-mode.el: Add variables for customizing the header and
- footer.
- (twittering-timeline-header-face): new variable.
- (twittering-timeline-footer-face): new variable.
- (twittering-timeline-header): new variable.
- (twittering-timeline-footer): new variable.
- (twittering-render-timeline): render the header and footer
- according to the customization variables.
- (twittering-initialize-global-variables-if-necessary): initialize
- the faces for the header and footer.
-
- * twittering-mode.el: The current version of twittering-mode
- always behaves as the previous version does on scroll-mode. The
- variable `twittering-scroll-mode' is obsolete.
- (twittering-scroll-mode): removed.
- (twittering-mode-line-buffer-identification): ignore the obsolete
- variable `twittering-scroll-mode'.
- (twittering-render-timeline): remove expressions for restoring
- positions on non-scroll-mode.
- (twittering-mode-map): do not bind "s" to the function
- `twittering-scroll-mode'.
- (twittering-mode-setup): do not call `make-local-variable' for the
- variable `twittering-scroll-mode'.
- * test/test-twittering-mode.el: Remove tests related to the
- scroll-mode.
-
- * twittering-mode.el: Remove invalid timeline specs from the
- history after the failure of the retrieval.
- (twittering-http-get-default-sentinel): remove the specified
- timeline spec string from the history after it becomes clear that
- the spec is invalid.
- (twittering-remove-timeline-spec-string-from-history): new
- function.
- (twittering-get-managed-buffer): add the requested timeline spec
- string to the history. It may be removed from the history after if
- it is invalid.
-
- * twittering-mode.el: Support ":exclude-if/FUNC/SPEC" timelines.
- (twittering-http-get-default-sentinel): remove timeline spec
- strings depending the invalid spec.
- (twittering-timeline-spec-to-string): support the new timeline
- spec ":exclude-if/FUNC/SPEC".
- (twittering-extract-timeline-spec): likewise.
- (twittering-timeline-spec-composite-p): new function.
- (twittering-timeline-spec-depending-on-p): new function.
- (twittering-get-base-timeline-specs): new function.
- (twittering-get-primary-base-timeline-specs): new function.
- (twittering-generate-composite-timeline): new function.
- (twittering-current-timeline-referring-id-table): support the new
- timeline spec ":exclude-if/FUNC/SPEC".
- (twittering-current-timeline-data): likewise.
- (twittering-add-statuses-to-timeline-data): update composite
- timelines that depend on the primary timeline.
- (twittering-get-and-render-timeline): add new arguments SPEC and
- SPEC-STRING to retrieve timelines that have no buffers but
- constitute some composite timelines.
- * test/test-twittering-mode.el: Add tests for the timeline spec
- ":exclude-if/FUNC/SPEC".
-
- * twittering-mode.el: Support merge timelines.
- (twittering-timeline-spec-composite-p): support the merge timeline
- spec.
- (twittering-get-base-timeline-specs): likewise.
- (twittering-generate-composite-timeline): likewise.
- (twittering-current-timeline-referring-id-table): likewise.
- (twittering-current-timeline-data): likewise.
-
-2012-01-14 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Do not record the edit buffer in the list of
- recently selected ones. Thanks to tdkn who reported the behavior
- related to the list.
- (twittering-update-status-from-pop-up-buffer): do not put the
- buffer at the front of the list of recently selected ones.
-
- * twittering-mode.el: Add a field property to a tweet on the
- function `twittering-render-a-field'.
- (twittering-make-common-properties): Do not add a field property.
- (twittering-render-a-field): add a field property.
-
-2012-01-08 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Explicitly signal an error when
- twittering-mode fails to retrieve a request token.
- (twittering-oauth-get-access-token): signal an error when
- twittering-mode fails to retrieve a request token.
-
- * test/test-twittering-mode.el: Add a test for parsing JSON with a
- character unsupported by Emacs.
-
- * test/test-twittering-mode.el: Add a test for parsing XML with a
- character unsupported by Emacs.
-
- * twittering-mode.el: Confirm that a file is readable before
- decrypting it.
- (twittering-read-from-encrypted-file): confirm that FILE is
- readable.
-
- * twittering-mode.el: Expand a path before invoking the function
- `epg-decrypt-file'.
- (twittering-read-from-encrypted-file): expand FILE before invoking
- `epg-decrypt-file'.
-
-2011-12-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Retrieve an ID of a tweet replied by a
- tweet on a search timeline. You can display replied tweets on a
- search timeline if they have been retrieved. This is available
- only when tweets are retrieved as the JSON format.
- (twittering-json-object-to-a-status-on-search): extract the
- "in_reply_to_status_id_str" field, which Twitter begins to serve
- recently.
-
- * twittering-mode.el: Replace `json-read' with
- `twittering-json-read' in order to prevent abnormal exit caused by
- decoding an unknown code point. Thanks to lemit who reported the
- problem.
- (twittering-http-get-default-sentinel): use `twittering-json-read'
- instead of `json-read'.
- (twittering-json-read): new function.
-
-2011-12-07 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Rearrange some codes for interpreting a JSON
- object.
- (twittering-json-object-to-a-status-base): rearrange codes for
- interpreting a JSON object.
-
- * twittering-mode.el: Fix the interpretation of JSON objects for
- direct messages. Thanks to Alexis who reported the problem.
- (twittering-http-get-default-sentinel): use
- `twittering-json-object-to-a-status-on-direct-messages' for
- timelines related to direct messages.
- (twittering-json-object-to-a-status-on-direct-messages): new
- function.
-
-2011-11-26 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the strange behavior on moving the
- cursor according to logical lines. Thanks to lemit who reported
- the problem.
- (twittering-mode-setup): bind `inhibit-field-text-motion' to
- non-nil as a buffer-local variable. If it is nil, the field
- property attached tweets interferes with the cursor motion based
- on logical lines.
-
- * twittering-mode.el: Store the tweet parameters, `truncated' and
- `user-protected', as boolean parameters.
- (twittering-normalize-raw-status): store the `truncated' and
- `user-protected' parameters as boolean parameters.
- (twittering-generate-format-table): use the `truncated' and
- `user-protected' parameters as boolean.
- (twittering-organic-retweet): likewise.
- * test/test-twittering-mode.el: Update tests to follow the change
- of internal representation of a tweet.
- * test/fixture/timeline-data.el: Update data to follow the change
- of internal representation of a tweet.
-
- * twittering-mode.el: Store the tweet parameter `created-at' as
- Emacs internal time representation. This avoids parsing a time
- string whenever a tweet is re-rendered.
- (twittering-atom-xmltree-to-status-datum): store `created-at' as
- Emacs internal time representation.
- (twittering-normalize-raw-status): likewise.
- (twittering-created-at-to-seconds): removed.
- (twittering-generate-format-table): use the parameters
- `created-at' as Emacs internal time representation.
- (twittering-generate-formater-for-first-spec): likewise.
- * test/test-twittering-mode.el: Update tests to follow the change
- of internal representation of a tweet.
- * test/fixture/timeline-data.el: Update data to follow the change
- of internal representation of a tweet.
-
- * twittering-mode.el: `twittering-call-api' receives `sentinel' as
- an argument for the command `retrieve-timeline'.
- (twittering-call-api): receive `sentinel' as an argument for
- the command `retrieve-timeline'.
-
- * twittering-mode.el: `twittering-call-api' receives `format' as
- an argument for the command `retrieve-timeline'.
- (twittering-http-get-default-sentinel): refer to `format' in
- `connection-info' for parsing the retrieved content.
- (twittering-call-api): receive `format' as an argument for the
- command `retrieve-timeline'. The `format' is automatically added
- to the last of `additional-info' for `twittering-http-get'.
-
- * twittering-mode.el: Support retrieval of tweets as the JSON
- format.
- (twittering-http-get-default-sentinel): support the JSON format.
- (twittering-extract-common-element-from-json): new function.
- (twittering-json-object-to-a-status): new function.
- (twittering-json-object-to-a-status-base): new function.
- (twittering-json-object-to-a-status-on-search): new function.
-
- * twittering-mode.el: Retrieve tweets as the JSON format if
- possible.
- (twittering-get-and-render-timeline): retrieve tweets as the JSON
- format if possible.
-
- * twittering-mode.el: Render a link wrapped by the t.co service as
- the original URL on a search timeline if possible. This requires
- `json.el'.
- (twittering-call-api): retrieve a search timeline with entities.
-
-2011-11-13 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the bug that unconditionally adds
- `emacs21' and `url-emacs21' into `load-path' on byte-compilation.
- On byte-compilation, the directories `emacs21' and `url-emacs21',
- which are included in the repository of twittering-mode, were
- unconditionally added into `load-path'. Due to this bug, some
- macros were embedded as obsolete definitions for Emacs21 in the
- result of byte-compilation. Some functions in the result cause
- errors on Emacs 22 or later because the obsolete definitions
- conflict with Emacs newer than 21. On Emacs 22 or later, the
- directories are no longer added to `load-path' on
- byte-compilation.
- Thanks to HKey who has discovered the bug.
-
-2011-10-30 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * test/test-twittering-mode.el: Remove obsolete tests of the
- obsolete feature related to `twittering-sign-string-function' and
- `twittering-sign-simple-string'.
- (test-sign-string): removed.
-
- * twittering-mode.el: A tweet has a greater field ID than that of
- its ancestor tweets. The order of field IDs matches with the order
- in which tweets should be rendered.
- (twittering-make-field-id): attach a greater field ID to normal
- tweets than its ancestor tweets.
-
- * twittering-mode.el: Use a common macro for rendering a status.
- (twittering-render-a-field): new macro for rendering a status.
- (twittering-render-timeline): use `twittering-render-a-field'.
- (twittering-show-replied-statuses): use
- `twittering-render-a-field'.
-
- * twittering-mode.el: Accept list names including non-ASCII
- characters.
- (twittering-extract-timeline-spec): accept list names including
- non-ASCII characters.
- * test/test-twittering-mode.el (timeline-spec): add a test for a
- list name including non-ASCII characters.
-
-2011-10-23 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Keep the private information unless the
- server explicitly informs that it is invalid.
- (twittering-verify-credentials): display the reason of
- authorization failure.
- (twittering-http-get-verify-credentials-sentinel): keep the
- private information for authorization unless the server returns
- 401(Unauthorized) as the HTTP response status code.
-
-2011-10-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Bind `default-directory' to the temporary
- directory to avoid problems caused by executing programs on
- a removed directory. Thanks to tomykaira who reported the problem.
- (twittering-send-http-request-internal): locally bind the variable
- `default-directory' to the temporary directory in order to prevent
- Emacs from executing an external program in the invalid condition
- where `default-directory' points to a directory which has been
- already removed.
- (twittering-start-http-session-curl-https-p): likewise.
- (twittering-sha1): likewise.
- (twittering-read-from-encrypted-file): likewise.
- (twittering-write-and-encrypt): likewise.
- (twittering-convert-image-data): likewise.
- (twittering-save-icon-properties): likewise.
- (twittering-load-icon-properties): likewise.
- (twittering-initialize-global-variables-if-necessary): likewise.
-
-2011-10-07 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the argument of the function
- `twittering-read-username-with-completion'. Thanks to Akira
- Tamamori who reported a problem caused by the bug.
- (twittering-read-timeline-spec-with-completion): fix the argument
- of the function `twittering-read-username-with-completion'.
-
- * twittering-mode.el: Search the content-type header from a HTTP
- response in a case-insensitive way according to RFC2616. Thanks to
- luozengbin who reported the bug.
- (twittering-http-get-default-sentinel): fix the check of the
- content-type header of a HTTP response. The content-type is now
- searched in a case-insensitive way according to RFC2616.
-
- * twittering-mode.el: Add new functions related to preparation for
- invoking APIs.
- (twittering-add-application-header-to-http-request): confirm the
- existence of OAuth token.
- (twittering-api-invocation-is-ready-p): new function for checking
- whether prerequisites for invoking APIs have been prepared without
- side effects. Strictly speaking, this function may have a side
- effect because the function `twittering-lookup-connection-type'
- may change some variables.
- (twittering-ensure-preparation-for-api-invocation): new function
- for ensuring prerequisites for invoking APIs.
- (twittering-visit-timeline): use the new function
- `twittering-ensure-preparation-for-api-invocation'.
-
- * twittering-mode.el: Signal an error when no valid connection
- method is found on sending a HTTP request.
- (twittering-send-http-request-internal): signal an error when no
- valid connection method is found.
-
-2011-10-03 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Allow users to supplement a username for
- timeline specs with a following username afterward.
- (twittering-read-timeline-spec-with-completion): allow users to
- supplement a username for timeline specs with a following username
- afterward.
-
- * twittering-mode.el: Add a username to the variable
- `twittering-user-history' after retrieving a user timeline.
- (twittering-timeline-spec-is-user-p): new function.
- (twittering-add-timeline-history): add a username to the history
- bound to `twittering-user-history' if the given spec is a user
- timeline.
-
- * twittering-mode.el: Fix the macro
- `twittering-revive:prop-get-value'.
- (twittering-revive:prop-get-value): use `macroexpand' instead of
- `macroexpand-all'.
-
-2011-09-25 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Users can post a tweet consisting of only
- mentions from the pop-up buffer.
- (twittering-edit-post-status): check a tweet with a simple regexp
- instead of `twittering-status-not-blank-p'.
-
- * twittering-mode.el: Add functions for `revive.el'.
- (twittering-revive:prop-get-value): new macro defined only when
- compiling `twittering-mode.el'.
- (twittering-revive:twittering): new function for restoring a
- timeline buffer with `revive.el'.
- (twittering-setup-revive): new function configuring `revive.el'
- for restoring a timeline buffer.
-
- * twittering-mode.el: `twittering-update-status' receives a
- tweet-type symbol instead of a timeline spec. It replaces a
- timeline spec representing whether the tweet beingedited is a
- direct message or not.
- (twittering-update-status-function): update docstring.
- (twittering-edit-setup-help): receive a tweet-type symbol as the
- second argument instead of a timeline spec.
- (twittering-update-status-from-pop-up-buffer): receive a
- tweet-type symbol as the fourth argument instead of a timeline
- spec.
- (twittering-update-status-from-minibuffer): likewise.
- (twittering-update-status): likewise.
- (twittering-direct-message): invoke `twittering-update-status'
- with a tweet-type symbol `direct-message' instead of a timeline
- spec.
- (twittering-enter): invoke `twittering-update-status' with a
- tweet-type symbol instead of a timeline spec.
-
- * twittering-mode.el: A skeleton can be used as
- `twittering-retweet-format'.
- (twittering-retweet-format): update docstring.
- (twittering-update-status-from-pop-up-buffer): accept a skeleton
- as the first argument.
- (twittering-update-status-from-minibuffer): likewise.
- (twittering-update-status): likewise.
- (twittering-organic-retweet): invoke `twittering-update-status'
- with a skeleton for generating an initial string.
-
- * twittering-mode.el: In default, the cursor is placed on the head
- when editing an organic retweet.
- (twittering-retweet-format): modify the initial value so that the
- cursor will be placed previous to the initial string.
-
- * twittering-mode.el: The symbol `organic-retweet' is added as a
- tweet type referred by edit skeleton.
- (twittering-update-status-function): update docstring.
- (twittering-edit-skeleton-alist): likewise.
- (twittering-update-status): likewise.
- (twittering-organic-retweet): invoke `twittering-update-status'
- with the tweet type symbol `organic-retweet' as the explicit
- fourth argument.
-
-2011-09-05 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix extraction of hashtags from a XML
- response.
- (twittering-normalize-raw-status): Fix extraction of hashtags from
- a XML response.
-
- * twittering-mode.el: The sign string feature is obsolete. The
- feature based on the function `twittering-sign-string-function'
- and the variable `twittering-sign-simple-string' is removed. The
- edit skeleton feature can be used as its alternative.
- (twittering-initialize-global-variables-if-necessary): display a
- warning about obsolete sign string feature. The function also
- translates the configuration of obsolete sign string into that of
- edit skeleton if possible.
- (twittering-sign-simple-string): removed.
- (twittering-sign-string-function): removed.
- (twittering-sign-string-default-function): removed.
- (twittering-sign-string): removed.
- (twittering-edit-length-check): do not use the obsolete function
- `twittering-sign-string'.
- (twittering-show-minibuffer-length): likewise.
- (twittering-update-status-from-minibuffer): likewise.
-
-2011-09-04 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Remove stickiness of text properties.
- (twittering-make-string-with-user-name-property): add front-sticky
- and rear-nonsticky property to STR for removing stickiness.
- (twittering-make-string-with-source-property): likewise.
- (twittering-make-string-with-uri-property): likewise.
- (twittering-generate-format-table): add front-sticky and
- rear-nonsticky property to the string for "%r" in order to remove
- stickiness.
- (twittering-generate-formater-for-first-spec): add front-sticky
- and rear-nonsticky property to the string for "%@" in order to
- remove stickiness.
-
-2011-09-03 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix a comment.
-
- * twittering-mode.el: The properties for hashtags, mentions and
- URIs are non-sticky.
- (twittering-make-fontified-tweet-text): make the properties
- non-sticky for the both direction.
-
- * twittering-mode.el: Render a link wrapped by the t.co service as
- the original URL.
- (twittering-call-api): call APIs with the option
- `include_entities=true' if possible.
- (twittering-normalize-raw-status): extract entities.
- (twittering-xmltree-to-status): extract entities of direct
- messages.
- (twittering-make-fontified-tweet-text): do not fontify a region if
- it has been already fontified.
- (twittering-make-fontified-tweet-text-with-entity): new function.
- (twittering-generate-format-table): try to fontify the text with
- entities first.
-
- * twittering-mode.el: Fix indices in entities of a timeline
- retrieved as XML.
- (twittering-make-gap-list): new function.
- (twittering-get-gap): new function.
- (twittering-normalize-raw-status): correct indices in entities so
- that they mean the position in the decoded text.
-
- * twittering-mode.el: Suppress redundant decoding.
- (twittering-normalize-raw-status): decode entities with
- `twittering-decode-entities-after-parsing-xml'.
- (twittering-decode-entities-after-parsing-xml): new function.
-
-2011-08-27 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: A list timeline includes native retweets.
- (twittering-call-api): retrieve a list timeline with native
- retweets.
-
- * twittering-mode.el: Update the service configuration with the
- 'help/configuration' API periodically.
- (twittering-call-api): add `get-service-configuration' as a new
- command.
- (twittering-service-configuration-default): new constant.
- (twittering-service-configuration): new variable.
- (twittering-service-configuration-queried): new variable.
- (twittering-service-configuration-update-interval): new variable.
- (twittering-get-service-configuration): new function.
- (twittering-update-service-configuration): new function.
- (twittering-update-service-configuration-sentinel): new function.
- (twittering-update-service-configuration-clean-up-sentinel): new
- function.
- (twittering-update-active-buffers): invoke
- `twittering-update-service-configuration'.
-
- * twittering-mode.el: Count characters with considering the t.co
- link wrapper.
- (twittering-effective-length): new function.
- (twittering-edit-length-check): check the length with
- `twittering-effective-length'.
- (twittering-edit-post-status): likewise.
- (twittering-show-minibuffer-length): likewise.
-
- * twittering-mode.el: Ad-hoc support for non-ASCII hashtags.
- (twittering-extract-timeline-spec): support non-ASCII hashtags by
- an ad-hoc way.
- (twittering-make-fontified-tweet-text): likewise.
- (twittering-edit-skeleton-inherit-hashtags): likewise.
-
-2011-08-18 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Display the requested URI if a HTTP request
- has failed.
- (twittering-send-http-request): display the requested method and
- URI if the request has failed.
-
-2011-08-17 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Correctly store icons when
- `twittering-convert-fix-size' is nil.
- (twittering-save-icon-properties): correctly generate stored
- representation of icon images when its size is not specified
- explicitly.
-
-2011-08-14 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Update the API for a list timeline.
- (twittering-call-api): use the current API for retrieving a list
- timeline.
-
- * twittering-mode.el: Support ":retweeted_to_user/USER" timeline.
- (twittering-timeline-spec-to-string): support `retweeted_to_user'
- timeline.
- (twittering-extract-timeline-spec): support a string like
- ":retweeted_to_user/USER" as a `retweeted_by_user' timeline.
- (twittering-timeline-spec-primary-p): add `retweeted_to_user'
- as a primary timeline.
- (twittering-call-api): support `retweeted_to_user' timeline.
- (twittering-read-timeline-spec-with-completion): add
- ":retweeted_to_user/" as a candidate.
-
- * twittering-mode.el: Support ":retweeted_by_user/USER" timeline.
- (twittering-timeline-spec-to-string): support `retweeted_by_user'
- timeline.
- (twittering-extract-timeline-spec): support a string like
- ":retweeted_by_user/USER" as a `retweeted_by_user' timeline.
- (twittering-timeline-spec-primary-p): add `retweeted_by_user'
- as a primary timeline.
- (twittering-call-api): support `retweeted_by_user' timeline.
- (twittering-read-timeline-spec-with-completion): add
- ":retweeted_by_user/" as a candidate.
-
-2011-08-13 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Add `migre.me' as a URL shortening serivce.
- (twittering-tinyurl-services-map): add an entry for `migre.me'.
-
- * twittering-mode.el: Save icons correctly when
- `twittering-icon-storage-limit' is nil. Thanks to HufflepuffBR who
- reported this problem.
- (twittering-save-icon-properties): fix the list representation of
- stored data when `twittering-icon-storage-limit' is nil.
-
-2011-07-29 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: The hash by newer algorithm introduced in
- OpenSSL 1.0.0 is also generated for each certificate. This is
- required because OpenSSL 1.0.0 and later fails to find an
- appropriate certificate if its name is based on the hash by the
- older algorithm which has been used by OpenSSL before 1.0.0.
- Thanks to Sakuma who reported this problem.
- (twittering-ca-cert-alist): redefined as a constant. And each
- entry has the hash generated by OpenSSL 1.0.0 and later.
- (twittering-delete-ca-cert): delete multiple files for each
- certificate.
- (twittering-ensure-ca-cert): generate two files for each
- certificate, where their names are the hash by the older algorithm
- used by OpenSSL before 1.0.0 and the other hash by the newer
- algorithm used by OpenSSL 1.0.0 and later.
-
- * twittering-mode.el: Embed a new root CA certificate to follow
- an update of the server.
- (twittering-ca-cert-alist): add a new root CA certificate,
- `GeoTrust Global CA' in order to follow the update of the server
- certificate of `search.twitter.com'.
-
- * twittering-mode.el: Output embedded certificates as a single
- file instead of a directory including them. This avoids the
- management of multiple hashes for each certificate.
- (twittering-cert-file): new variable replacing
- `twittering-cert-directory'.
- (twittering-cert-directory): removed.
- (twittering-ca-cert-list): new variable replacing
- `twittering-ca-cert-alist'.
- (twittering-ca-cert-alist): removed.
- (twittering-delete-ca-cert): remove a single file including
- multiple certificates.
- (twittering-ensure-ca-cert): prepare a single file including
- multiple certificates instead of a directory including multiple
- files.
- (twittering-make-connection-info): replace the parameter
- `cacert-directory-fullpath' with `cacert-file-fullpath'.
- (twittering-send-http-request-curl): use the option `--cacert'
- instead of `--capath'.
- (twittering-send-http-request-wget): use the option
- `--ca-certificate' instead of `--ca-directory'.
-
-2011-07-25 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the API call for `user_timeline' in
- order to prevent Twitter from confusing a username consisting of
- digits with a user id. Thanks to Makoto Fujiwara who reported this
- problem.
- (twittering-call-api): fix the API call for `user_timeline'. The
- new implementation gives a username as a query parameter. This
- prevents Twitter from confusing a username consisting of digits
- with a user id.
-
- * twittering-mode.el: Fix a bug that moves the cursor by calling
- `twittering-update-status-interactive' from buffers which are not
- managed by `twittering-mode'. Thanks to mofigan who reported this
- problem.
- (twittering-ensure-whole-of-status-is-visible): do not change
- window configuration unless the given window is bound to a buffer
- managed by `twittering-mode'.
-
-2011-07-20 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix indentation of the function
- `twittering-verify-credentials'.
- (twittering-verify-credentials): fix indentation.
-
- * twittering-mode.el: Display exit status of the process for
- authorization if it exited abnormally.
- (twittering-http-get-verify-credentials-clean-up-sentinel):
- display exit status of the process if it exited abnormally.
-
- * twittering-mode.el: Embed another root CA certificate to follow
- an update of the server. Now, the server certificate for
- `api.twitter.com' is updated and it cannot be verified by the
- already embedded certificate `Equifax Secure Certificate
- Authority'. So, a root CA certificate `VeriSign Class 3 Public
- Primary CA - G2' is also embedded, which is used for verifying the
- server `api.twitter.com'.
- (twittering-cert-file): removed.
- (twittering-delete-ca-cert-file): removed.
- (twittering-cert-directory): new variable.
- (twittering-delete-ca-cert): new function.
- (twittering-ensure-ca-cert): prepare a directory including
- multiple CA certificates instead of a single file. Now this
- function generates "VeriSign Class 3 Public Primary CA - G2".
- (twittering-make-connection-info): replace the parameter
- `cacert-fullpath' with `cacert-directory-fullpath'.
- (twittering-send-http-request-native): remove redundant bindings.
- (twittering-send-http-request-curl): follow the modification of
- the parameter generated by `twittering-make-connection-info'.
- (twittering-send-http-request-wget): likewise.
- * cert/equifax.pem: removed. This certificate had not been used.
- * cert/Equifax_Secure_Certificate_Authority.cer: Add a certificate
- that has been used. It was retrieved from
- https://www.geotrust.com/resources/root_certificates/certificates/Equifax_Secure_Certificate_Authority.cer ,
- which is used only for verifying the server `search.twitter.com'.
- * cert/PCA-3G2.pem: Add a root certificate. It is retrieved from
- https://www.verisign.com/repository/roots/root-certificates/PCA-3G2.pem ,
- which is used for verifying the server `api.twitter.com'.
-
-2011-07-16 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * test/test-twittering-mode.el: Add tests for HMAC-SHA1.
-
- * twittering-mode.el: Fix the function for HMAC-SHA1 so that it
- always return a correct digest.
- (twittering-sha1): new function. This function can return a
- correct digest without regard to the current coding system.
- For very long object, the function `sha1' uses an external program
- and coding system for the program is not correctly specified.
- Therefore, the result may depend on the current coding system.
- The new function is an alternative without the above problem.
- (twittering-hmac-sha1): use `twittering-sha1' instead of `sha1'.
-
- * twittering-mode.el: `twittering-wait-while' is reimplemented
- with `lexical-let'.
- (twittering-wait-while): reimplemented with `lexical-let'.
- Redundant statements are no longer added. This suppresses warnings
- on byte-compilation.
-
- * twittering-mode.el: Fix docstring of
- `twittering-edit-skeleton-alist'.
- (twittering-edit-skeleton-alist): fix docstring.
-
- * twittering-mode.el: Load private information before
- initialization.
- (twittering-private-info-file-loaded): new variable.
- (twittering-private-info-loaded-p): new function.
- (twittering-ensure-private-info): new function.
- (twittering-verify-credentials): do not try to load private
- information.
- (twittering-visit-timeline): ensure that private information is
- loaded if necessary.
-
- * twittering-mode.el: Initialize global variables before ensuring
- a connection method.
- (twittering-visit-timeline): invoke
- `twittering-initialize-global-variables-if-necessary' first.
-
- * twittering-mode.el: Open the timeline buffer only if
- authorization succeeded.
- (twittering-verify-credentials): return t or nil according to
- whether the authorization succeeded or not.
- (twittering-visit-timeline): open the timeline buffer only if
- authorization succeeded.
-
- * twittering-mode.el: In `twittering-start', bind a local variable
- only if necessary.
- (twittering-start): bind `action' only if necessary.
-
- * twittering-mode.el: Start timers only when an active timeline
- buffer is opened.
- (twittering-verify-credentials): do not invoke `twittering-start'.
- (twittering-http-get-verify-credentials-sentinel): likewise.
-
- * twittering-mode.el: `twittering-account-authorization' must be
- reset if `twittering-verify-credentials' exited non-locally.
- (twittering-verify-credentials): do not manage the global variable
- `twittering-account-authorization', which will be managed by the
- new function `twittering-ensure-account-verification'.
- `twittering-verify-credentials' raises an error if the function
- `twittering-account-authorization-queried-p` returns non-nil.
- (twittering-ensure-account-verification): new function. This
- function can correctly reset the global variable
- `twittering-account-authorization' if authorization is failed and
- the function `twittering-verify-credentials' exits non-locally.
- (twittering-visit-timeline): call
- `twittering-ensure-account-verification' instead of
- `twittering-verify-credentials'.
-
-2011-06-26 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Revise the routine for the format specifier
- "%C".
- (twittering-make-string-with-uri-property): new function.
- (twittering-generate-formater-for-first-spec): use the function
- `twittering-make-string-with-uri-property' for the format
- specifier "%C".
- (twittering-make-time-string): removed.
-
- * twittering-mode.el: Add a function to go to the next/previous
- URI explicitly written in a tweet.
- (twittering-make-fontified-tweet-text): add uri-origin property to
- URIs explicitly written in a tweet.
- (twittering-get-next-thing-pos): new function.
- (twittering-goto-next-thing): ignore things except URIs explicitly
- written in a tweet if a prefix argument is given.
- (twittering-goto-previous-thing): likewise.
- (twittering-goto-next-uri): new function.
- (twittering-goto-previous-uri): new function.
-
- * twittering-mode.el: Wait a moment after finding that the process
- is dead and the query has not been finished. This prevents Emacs
- from canceling the query on the middle of evaluating the
- sentinel.
- (twittering-wait-while): new macro.
- (twittering-oauth-get-token-alist): wait a moment after finding
- that the process is dead and the query has not been finished. This
- prevents Emacs from canceling the query on the middle of
- evaluating the sentinel.
- (twittering-tinyurl-get): likewise.
- (twittering-verify-credentials): likewise.
- (twittering-get-list-sync): likewise.
-
- * twittering-mode.el: Correctly ensure an available connection
- method even if SSL is unavailable.
- (twittering-ensure-connection-method): return correct value in the
- case with compromise.
-
- * twittering-mode.el: `twittering-ensure-connection-method'
- displays an error message if no connection methods available.
- (twittering-ensure-connection-method): display an error message if
- no connection methods are available.
- (twittering-visit-timeline): do not display an error message if no
- connection methods are available.
-
-2011-06-21 Takashi Masuda <masutakaNOSPAMnifty.com>
-
- * twittering-mode.el: Add text properties to "%C".
- (twittering-generate-formater-for-first-spec): use
- `twittering-make-time-string' instead of `format-time-string'.
- (twittering-make-time-string): new function.
-
- * twittering-mode.el: Add timeline spec aliases as completion
- candidates on specifying a timeline spec.
- (twittering-read-timeline-spec-with-completion): add timeline spec
- aliases, defined in `twittering-timeline-spec-alias', as
- completion candidates.
-
-2011-05-21 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix the message for dead process on basic
- authentication.
- (twittering-verify-credentials): make the message for dead process
- on basic authentication similar as that on OAuth/xAuth
- authentication.
-
- * twittering-mode.el: Fix the display of messages about
- authorization.
- (twittering-send-http-request): do not display a message on
- authorization.
- (twittering-http-get-verify-credentials-sentinel): directly
- display a message whether the authorization succeeded or not.
- `twittering-send-http-request' does not display it.
-
- * twittering-mode.el: Add the variable
- `twittering-disable-overlay-on-too-long-string' in order to avoid
- interference between the update of overlay and some input
- methods.
- (twittering-disable-overlay-on-too-long-string): new variable.
- (twittering-edit-length-check): do not update the overlay if
- `twittering-disable-overlay-on-too-long-string' is non-nil.
-
-2011-05-16 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Ensure that a sentinel is invoked when a
- process is started successfully.
- (twittering-process-alive-p): new function.
- (twittering-start-process-with-sentinel): new function.
- (twittering-send-http-request-native): ensure that the given
- sentinel is invoked when the process is started successfully.
- (twittering-send-http-request-curl): replace `start-process' with
- `twittering-start-process-with-sentinel' in order to ensure that
- the sentinel is invoked.
- (twittering-send-http-request-wget): likewise.
-
- * twittering-mode.el: Confirm that the process is alive on waiting
- for its sentinel.
- (twittering-oauth-get-token-alist): check whether the process is
- alive on waiting for the invocation of the sentinel for the
- process.
- (twittering-tinyurl-get): likewise.
- (twittering-verify-credentials): likewise.
- (twittering-get-list-sync): use `twittering-process-alive-p'.
-
- * twittering-mode.el: Ignore errors on `xml-parse-region'.
- (twittering-xml-parse-region): return nil if an error happens on
- `xml-parse-region'.
-
- * twittering-mode.el: Fix uri property of a list name in a
- tweet. Thanks to Naohiro Aota who reported the problem.
- (twittering-get-list-url): new function.
- (twittering-make-fontified-tweet-text): correctly generate uri
- property for a list name in a tweet.
-
-2011-05-08 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * test/test-twittering-mode.el: Fix and add tests of proxy
- configuration. Now they do not depend on environment variables.
-
-2011-05-06 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Replace the symbol `us-ascii' for a
- coding-system with `iso-safe', which is valid even on Emacs21.
- (twittering-ensure-ca-cert): use `iso-safe' instead of `us-ascii'
- as a coding-system for ASCII.
- (twittering-start-http-session-curl-https-p): likewise.
- (twittering-initialize-global-variables-if-necessary): likewise.
-
- * twittering-mode.el: Add some directories for Emacs21 to
- `load-path' even when byte-compiling the file on Emacs21.
-
- * twittering-mode.el: embed a timeline spec string such as
- "#HASHTAG" for `goto-spec' of a hashtag instead of a search
- timeline spec as an internal representation.
- (twittering-make-hashtag-timeline-spec-string-direct): new macro.
- (twittering-make-fontified-tweet-text): embed a timeline spec
- string such as "#HASHTAG" for `goto-spec' of a hashtag instead of
- a search timeline spec as an internal representation.
-
- * twittering-mode.el: Add `twittering-update-status' as a function.
- (twittering-update-status-function): update docstring.
- (twittering-update-status-from-pop-up-buffer): rename the argument
- `spec' `tweet-type-as-spec'.
- (twittering-update-status-from-minibuffer): likewise.
- (twittering-update-status): new function.
- (twittering-direct-message): call `twittering-update-status'
- instead of referring `twittering-update-status-function'.
- (twittering-reply-to-user): likewise.
- (twittering-organic-retweet): likewise.
- (twittering-enter): likewise.
-
- * twittering-mode.el: Edit skeletons can refer to the current
- timeline spec.
- (twittering-update-status-function): update the docstring to
- follow the additional argument CURRENT-SPEC.
- (twittering-edit-skeleton-alist): update the docstring.
- (twittering-edit-skeleton-insert-base): support the new argument
- CURRENT-SPEC.
- (twittering-edit-skeleton-insert): likewise.
- (twittering-edit-skeleton-inherit-hashtags): likewise.
- (twittering-edit-skeleton-inherit-mentions): likewise.
- (twittering-update-status-from-pop-up-buffer): likewise.
- (twittering-update-status-from-minibuffer): likewise.
- (twittering-update-status): add a new argument
- IGNORE-CURRENT-SPEC.
-
- * twittering-mode.el: The predefined edit skeletons
- `inherit-hashtags' and `inherit-any' insert hashtags if the
- current timeline is a search timeline where the query string
- includes hashtags.
- (twittering-timeline-spec-is-search-p): new function.
- (twittering-extract-query-string-from-search-timeline-spec): new
- function.
- (twittering-edit-skeleton-alist): change the definition of
- `inherit-hashtags' and `inherit-any' so that they add hashtags if
- the current timeline is a search timeline.
- (twittering-edit-skeleton-inherit-hashtags): insert hashtags if
- CURRENT-SPEC is a search timeline where the query string includes
- hashtags.
-
-2011-04-23 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * NEWS, NEWS.ja, LAST-VERSION, VERSION, doc/web/index.text:
- Version 2.0.0 released.
-
- * twittering-mode.el: Fix coding system for some operations so
- that they work well even if the default coding system is
- `utf-16le-dos'. Thanks to Moto_Dong who reported the problem.
- (twittering-ensure-ca-cert): explicitly specify coding-system.
- (twittering-start-http-session-curl-https-p): likewise.
- (twittering-read-from-encrypted-file): likewise.
- (twittering-write-and-encrypt): likewise.
- (twittering-load-icon-properties): likewise.
- (twittering-initialize-global-variables-if-necessary): likewise.
- (twittering-status-not-blank-p): likewise.
-
- * test/test-twittering-mode.el: add a test for a timeline spec
- string like "#hashtag".
-
- * twittering-mode.el: Store the formatter function before
- compilation.
- (twittering-format-status-function-without-compile): new
- variable.
- (twittering-update-status-format): store the formatter function as
- a lambda expression before being compiled.
-
- * twittering-mode.el: Embed expressions for fontification in the
- formatter function instead of calling them as a function.
- (twittering-make-fontified-tweet-text): return an expression that
- fontifies a given string. The regular expressions of strings being
- fontified are concatenated on generating a formatter function.
- (twittering-generate-format-table): embed the expression
- fontifying a string in the formatter function. The expression will
- be byte-compiled by `twittering-update-status-format'.
-
- * twittering-mode.el: Redefine some functions as inline in order
- to make the formatter function more efficient.
- (twittering-make-common-properties): redefined as an inline
- function.
- (twittering-make-string-with-user-name-property): likewise.
- (twittering-make-string-with-source-property): likewise.
- (twittering-fill-string): likewise.
- (twittering-update-filled-string): likewise.
- (twittering-make-passed-time-string): likewise.
-
- * twittering-mode.el: Reduce redundant calls of `string-match' on
- formatting a tweet. When generating a timeline spec from a string
- with obvious meaning, the new macros are used instead of the
- general function, `twittering-extract-timeline-spec'.
- (twittering-make-user-timeline-spec-direct): new macro.
- (twittering-make-list-timeline-spec-direct): new macro.
- (twittering-make-hashtag-timeline-spec-direct): new macro.
- (twittering-extract-timeline-spec): use new macros.
- (twittering-make-string-with-user-name-property): call the new
- macro `twittering-make-user-timeline-spec-direct' instead of
- calling `twittering-extract-timeline-spec'.
- (twittering-make-fontified-tweet-text): call the new macros
- `twittering-make-{user,list,hashtag}-timeline-spec-direct' instead
- of calling `twittering-extract-timeline-spec'.
-
-2011-04-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix headers for a proxy.
- (twittering-make-connection-info): extract proxy information from
- `connection-info' instead of directly referring to
- `twittering-http-proxy-user', `twittering-http-proxy-password',
- etc.
- (twittering-send-http-request-native): generate the
- "Proxy-Authorization" header correctly and give the absolute URI
- as the request URI when the connection is peformed via a proxy.
- (twittering-send-http-request-urllib): add "Proxy-Authorization"
- header if necessary.
- (twittering-http-application-headers): do not add headers related
- to a proxy. They are added in functions for each connection
- method.
-
- * twittering-mode.el: "U" pushes a URI of a tweet on text without
- a uri property.
- (twittering-push-uri-onto-kill-ring): push a URI of a tweet unless
- the currently pointed character has a uri property.
-
- * twittering-mode.el: `twittering-direct-message' always posts a
- tweet with direct message API.
- (twittering-direct-message): always post a tweet with direct
- message API.
-
- * twittering-mode.el: Introduce "edit skeleton".
- (twittering-edit-skeleton-footer): new variable.
- (twittering-edit-skeleton-footer-history): new variable.
- (twittering-edit-skeleton-alist): new variable.
- (twittering-switch-edit-skeleton): new function.
- (twittering-edit-skeleton-change-footer): new function.
- (twittering-edit-skeleton-insert-base): new function.
- (twittering-edit-skeleton-insert): new function.
- (twittering-update-status-from-pop-up-buffer): insert the current
- edit skeleton before editing a tweet.
- (twittering-update-status-from-minibuffer): likewise.
-
- * twittering-mode.el: Add pre-defined edit skeletons.
- (twittering-extract-matched-substring-all): new function.
- (twittering-edit-skeleton-alist): add some examples of edit
- skeletons.
- (twittering-edit-skeleton-inherit-hashtags): new function for an
- edit skeleton.
- (twittering-edit-skeleton-inherit-mentions): likewise.
-
- * twittering-mode.el: Add the variable
- `twittering-fallback-image-format'.
- (twittering-fallback-image-format): new variable.
- (twittering-create-image-pair): use the value of
- `twittering-fallback-image-format' as the fallback format instead
- of directly using 'xpm.
-
-2011-03-27 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Discard standard error of the program
- "convert". On an environment where the option "-flatten" cause a
- warning for a non-animated image, Emacs must exclude such
- warnings.
- (twittering-convert-image-data): discard standard error of the
- program "convert".
-
- * twittering-mode.el: Entrust image type estimation to the command
- "convert".
- (twittering-create-image-pair): do not send image type estimated by
- Emacs to the function `twittering-convert-image-data'.
-
-2011-03-26 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: `twittering-other-user-list-interactive'
- works well when the specified user follows no list.
- (twittering-other-user-list-interactive): fix an error occurring
- when the specified user follows no list or selection is
- cancelled.
-
- * twittering-mode.el: `twittering-other-user-list-interactive'
- displays a subscription as a string like timeline spec string.
- (twittering-http-get-list-subscriptions-sentinel): exclude
- preceding "@" from a string corresponding to a subscription.
- (twittering-other-user-list-interactive): follow the above
- modification.
-
- * twittering-mode.el: Modify the prompts for subscription.
- (twittering-read-subscription-list-name): modify the prompt for
- subscription.
- (twittering-other-user-list-interactive): likewise.
-
- * twittering-mode.el: Add an advice for avoiding an error occuring
- when `getenv' returns an empty string on Emacs21. The bug had been
- fixed on Emacs22 and later.
-
- * test/test-twittering-mode.el: Fix a test of formating a status
- according to a change of behavior of `fill-region'. It does not
- keep white spaces and tabs adjacent to hard newlines on Emacs21,
- but it keeps them on Emacs22 and later.
-
- * twittering-mode.el: Remove opacity on converting an image into
- a XPM image on Emacs22 and earlier.
- (twittering-convert-image-data): add an option "+matte" to the
- command "convert" in order to avoid color allocation error
- occurring when Emacs22 and earlier try to decode a XPM image with
- opacity.
-
- * twittering-mode.el: Convert an image, which may be animated,
- into a single static image if Emacs does not support animated
- images.
- (twittering-convert-image-data): add an option "-flatten" to the
- command "convert" unless `create-animated-image'.
-
- * twittering-mode.el: Always convert a GIF image into a XPM image
- if Emacs does not support animated images.
- (twittering-create-image-pair): always convert a GIF image into a
- XPM image if Emacs does not support animated images.
-
-2011-03-26 Naohiro Aota <naotaNOSPAMelisp.net>
-
- * twittering-mode.el (twittering-http-get-list-sentinel-base): New
- macro: from `twittering-http-get-list-index-sentinel'.
- (twittering-http-get-list-index-sentinel): Use it.
- (twittering-http-get-list-subscriptions-sentinel): Ditto.
- (twittering-call-api): Add `get-list-subscriptions' description;
- Implement `get-list-subscriptions'.
- (twittering-get-list-subscriptions): New function.
- (twittering-get-list-sync): New function from
- `twittering-get-list-index-sync'.
- (twittering-get-list-index-sync): Rewrite to use it.
- (twittering-get-list-subscriptions-sync): New function. Use it.
- (twittering-read-timeline-spec-with-completion): New function.
- (twittering-other-user-list-interactive): Accept prefix to read
- other users' subscription list.
-
-2011-03-15 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Support cancel of retweets posted by the
- authenticated user.
- (twittering-delete-status): cancel a retweet if it has been
- retweeted by the authenticated user.
-
- * twittering-mode.el: Explicitly use binary coding system on I/O
- of icon properties. Thanks to Naohiro Aota.
- (twittering-save-icon-properties): explicitly use binary coding
- system on writing icon properties.
- (twittering-load-icon-properties): likewise.
-
-2011-02-19 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Disable the persistent icon storage if
- `jka-compr' is unavailable.
- (twittering-save-icon-properties): confirm that `jka-compr' is
- available.
- (twittering-load-icon-properties): likewise.
- (twittering-initialize-global-variables-if-necessary): disable
- the persistent icon storage if `jka-compr' is unavilable.
-
- * twittering-mode.el: Add `twittering-add-to-history' for
- Emacs21.
- (twittering-add-to-history): new function.
- (twittering-add-timeline-history): use
- `twittering-add-to-history'.
-
- * twittering-mode.el: Introduce the limit of number of
- icons being stored persistently.
- (twittering-icon-storage-file): add docstring about
- `twittering-icon-storage-limit'.
- (twittering-icon-storage-recent-icons): new variable to which
- properties of recently rendered icons are stored.
- (twittering-icon-storage-limit): new variable.
- (twittering-update-icon-storage-recent-icons): new function.
- (twittering-get-display-spec-for-icon): invoke
- `twittering-update-icon-storage-recent-icons' whenever this
- function is invoked.
- (twittering-save-icon-properties): write properties of icons
- within the limit specified by `twittering-icon-storage-limit'. In
- addition, this function records properties in the new format.
- (twittering-load-icon-properties): support the new format for
- storing properties of icons.
-
-2011-02-15 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Confirm validity of a format string before
- updating the function formatting a tweet.
- (twittering-update-status-format): update the function only if the
- given format string is valid.
-
- * twittering-mode.el: Support a new format specifier "%RT{...}".
- (twittering-status-format): update docstring.
- (twittering-generate-formater-for-first-spec): support a new
- format specifier "%RT{...}".
-
-2011-02-13 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * test/test-twittering-mode.el (test-hmac-sha1): Fix a typo.
-
- * twittering-mode.el: Rearrange internal representation of a
- retweet.
- (twittering-add-statuses-to-timeline-data): use `retweeted-id'
- instead of `source-id'.
- (twittering-normalize-raw-status): rearrange internal
- representation of a retweet. The information as a tweet posted by
- the retweeter is stored with keys prefixed with `retweeting-'. The
- information as a tweet posted by the original author is stored
- with keys prefixed with `retweeted-'. Keys prefixed with
- `original-' or `source-' are obsolete.
- (twittering-make-common-properties): use `retweeted-id' instead of
- `source-id'.
- (twittering-get-common-properties): likewise.
- (twittering-generate-format-table): use
- `retweeting-user-screen-name' instead of
- `original-user-screen-name'.
- (twittering-generate-formater-for-first-spec): use `retweeted-id'
- instead of `source-id'.
- (twittering-render-timeline): likewise.
- (twittering-native-retweet): likewise.
-
- * twittering-mode.el: `created_at' for an official retweet means
- when the original tweet was posted instead of when it was
- retweeted.
- (twittering-normalize-raw-status): do not override
- `created_at'. The key `created_at' in an alist representing a
- retweet means when the original tweet was posted.
-
- * twittering-mode.el: When `twittering-follow' is invoked on an
- official retweet, ask a subject.
- (twittering-follow): ask a subject when this function is invoked
- on an official retweet.
-
- * twittering-mode.el: Add a function to report a user as a spammer.
- (twittering-call-api): support a new command
- `block-and-report-as-spammer'.
- (twittering-block-and-report-as-spammer): new function.
-
- * twittering-mode.el: Add a function to block a user.
- (twittering-call-api): support a new command `block'.
- (twittering-block): new function.
-
- * twittering-mode.el: Support persistent icon storage.
- (twittering-icon-storage-file): new variable.
- (twittering-use-icon-storage): new variable.
- (twittering-register-image-spec): new function.
- (twittering-register-image-data): reimplemented with
- `twittering-register-image-spec'.
- (twittering-save-icon-properties): new function.
- (twittering-load-icon-properties): new function.
-
-2011-02-05 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Remove a trailing newline from strings
- received from `bit.ly' and `j.mp'. Thanks to mm_o_ig.
- (twittering-tinyurl-services-map): add a post-processing function
- that removes a trailing newline from result of `bit.ly' and
- `j.mp'.
-
- * twittering-mode.el: Revise some messages. Thanks to Server.
- (twittering-http-get-default-sentinel): revise messages.
- (twittering-show-replied-statuses): likewise.
- (twittering-hide-replied-statuses): likewise.
- (twittering-edit-post-status): likewise.
- (twittering-read-timeline-spec-with-completion): likewise.
- (twittering-other-user-list-interactive): likewise.
- (twittering-direct-message): likewise.
- (twittering-goto-next-status): likewise.
- (twittering-goto-previous-status): likewise.
-
-2011-01-29 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Reimplement `twittering-tinyurl-get' with
- `twittering-send-http-request'.
- (twittering-url-wrapper): removed.
- (twittering-url-insert-file-contents): removed.
- (twittering-url-retrieve-synchronously): removed.
- (twittering-tinyurl-get): reimplemented with
- `twittering-send-http-request'. In addition, the query parameter
- is correcly encoded by `twittering-percent-encode'.
-
- * twittering-mode.el: Add `is.gd' as a URL shortening service.
- Thanks to Michael Kohl.
- (twittering-tinyurl-service): update the document.
- (twittering-tinyurl-services-map): add an entry for `is.gd'.
-
- * twittering-mode.el: Extend the format of
- `twittering-tinyurl-services-map'. One can register a service that
- requires a special HTTP request and/or post-processing.
- (twittering-tinyurl-services-map): extend the meaning of the
- variable.
- (twittering-tinyurl-get): support new format of
- `twittering-tinyurl-services-map'.
-
- * twittering-mode.el: Add `goo.gl' as a URL shortening service.
- (twittering-tinyurl-services-map): add an entry for `goo.gl'.
-
- * twittering-mode.el: Add `bit.ly' and `j.mp' as URL shortening
- services. Thanks to Lars Gregori.
- (twittering-tinyurl-services-map): add entries for `bit.ly' and
- `j.mp'.
- (twittering-bitly-login): new variable.
- (twittering-bitly-api-key): new variable.
- (twittering-make-http-request-for-bitly): new function.
-
- * twittering-mode.el: Reimplement normalization of alists from XML
- structure.
- (twittering-atom-xmltree-to-status-datum): change the value
- corresponding to the key `source' into a URL with a tag.
- (twittering-status-to-status-datum): removed.
- (twittering-normalize-raw-status): new function to generate
- normalized alist representing a tweet.
- (twittering-xmltree-to-status): use
- `twittering-normalize-raw-status' instead of
- `twittering-status-to-status-datum'.
-
- * twittering-mode.el: `twittering-make-clickable-status-datum'
- does not redefine `source'.
- (twittering-atom-xmltree-to-status-datum): define `source' as
- a text surrounded by A-tag.
- (twittering-normalize-raw-status): likewise.
- (twittering-make-clickable-status-datum): do not redefine
- `source'.
-
- * twittering-mode.el: Add text properties to tweets on rendering.
- (twittering-http-get-default-sentinel): do not call
- `twittering-make-clickable-status-datum'.
- (twittering-make-clickable-status-datum): removed.
- (twittering-make-string-with-user-name-property): new function.
- (twittering-make-string-with-source-property): new function.
- (twittering-make-fontified-tweet-text): new function.
- (twittering-generate-format-table): add text properties.
-
-2011-01-23 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * test/test-twittering-mode.el: Add some tests for the format
- specifiers "%FILL[prefix]{...}" and "%FOLD[prefix]{...}".
- * twittering-mode.el (twittering-status-format): add a document
- for the format specifier "%FOLD[prefix]{...}".
-
- * test/test-twittering-mode.el: Fix an error of
- `url-generic-parse-url' on Emacs21 by calling
- `url-scheme-get-property' before `url-generic-parse-url' is called.
-
-2011-01-21 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Decode received XML document as UTF-8 before
- parsing it.
- (twittering-http-get-default-sentinel): decode received XML
- document as UTF-8 before parsing it if Content-Type in response
- header has a parameter "charset=utf-8".
-
- * twittering-mode.el: The format specifier "%FOLD[prefix]{...}"
- does not squeeze white spaces.
- (twittering-fill-string): does not squeeze white spaces if
- `keep-newline' is non-nil.
-
-2011-01-16 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Ensure that the pointed tweet is visible on
- editing a tweet.
- (twittering-ensure-whole-of-status-is-visible): new function.
-
- * twittering-mode.el: Isolate addition of text properties from a
- function parsing XML.
- (twittering-http-get-default-sentinel): call
- `twittering-make-clickable-status-datum' here.
- (twittering-atom-xmltree-to-status): do not add text properties to
- statuses.
- (twittering-status-to-status-datum): likewise.
-
- * twittering-mode.el: Render statuses in order of field property
- instead of id property.
- (twittering-make-common-properties): add field property as a
- common property.
- (twittering-get-common-properties): likewise.
- (twittering-field-id<): new function.
- (twittering-field-id=): new function.
- (twittering-make-field-id): new function.
- (twittering-make-field-properties): new function.
- (twittering-render-timeline): render statuses in order of their
- field properties.
- (twittering-show-replied-statuses): add special field property to
- replied statuses.
-
- * twittering-mode.el: Move point by using field property instead
- of id property.
- (twittering-get-current-status-head): redefined with field
- property instead of id property.
- (twittering-get-first-status-head): likewise.
- (twittering-get-next-status-head): likewise.
- (twittering-get-previous-status-head): likewise.
-
- * twittering-mode.el: Use rendered-as property for rendering
- replied statuses instead of a trick with id and original-id
- properties.
- (twittering-get-common-properties): add rendered-as property as a
- common property.
- (twittering-make-field-properties): add rendered-as property if
- necessary.
- (twittering-make-field-properties-of-popped-ancestors): new
- function.
- (twittering-rendered-as-ancestor-status-p): new function.
- (twittering-get-base-id-of-ancestor-at): new function.
- (twittering-replied-statuses-visible-p): use the new function
- `twittering-get-base-id-of-ancestor-at' instead of directly
- referring id and original-id properties.
- (twittering-hide-replied-statuses): likewise.
- (twittering-show-replied-statuses): use
- `twittering-make-field-properties-of-popped-ancestors'.
-
- * twittering-mode.el: Remove a trick using id and original-id
- properties for rendering replied statuses.
- (twittering-get-common-properties): remove original-id from common
- properties.
- (twittering-show-replied-statuses): do not overwrite id and
- original-id properties.
- (twittering-enter): do not refer original-id property.
-
- * twittering-mode.el: Support favorites timeline.
- (twittering-timeline-spec-to-string): support favorites timeline
- spec.
- (twittering-extract-timeline-spec): likewise.
- (twittering-timeline-spec-primary-p): add favorites timeline spec
- is a primary timeline spec.
- (twittering-call-api): support favorites timeline spec.
- (twittering-read-timeline-spec-with-completion): add ":favorites"
- as a candidate of completion. In addition, one can input a
- username with completion for ":favorites/".
- (twittering-goto-next-status): display an error message on the
- oldest tweet on favorites timeline.
- (twittering-goto-previous-status): likewise.
- * test/test-twittering-mode.el: Add tests for favorites timeline
- spec.
-
-2011-01-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Ensure that encrypted strings are written
- with no conversion. Thanks to Sakuma.
- (twittering-write-and-encrypt): ensure that encrypted strings are
- written with no conversion.
-
-2010-12-17 Yuto HAYAMIZU <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-organic-retweet): prohibit
- retweeting protected tweets.
-
-2010-11-30 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Ensure that the methods using url library
- works well for HTTP redirection.
- (twittering-send-http-request-urllib): make the variable,
- `url-http-attempt-keepalives', buffer-local in order to send the
- local value to the sentinel invoked for HTTP redirection. If the
- variable is not made buffer-local, the connection with redirection
- may not be closed according to its global value.
-
- * twittering-mode.el: Introduce an ad-hoc treatment for url
- library on Emacs21 again. This ensures that the sentinel for an
- redirect HTTP request, such as asynchronous retrieval of icon
- images, works well.
- (twittering-send-http-request): introduce an ad-hoc treatment for
- the url library again. It is required because the process for a
- redirected HTTP request is alive when the url library for Emacs21
- invokes the callback.
- (twittering-send-http-request-urllib): add an ad-hoc treatment for
- HTTP redirection on Emacs21.
-
-2010-11-27 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix a bug of retrieving a URI repeatedly.
- (twittering-resolve-url-request): bind `additional-info' to the
- appropriate alist storing the URI that will be retrieved. The
- alist is referred by `twittering-url-retrieve-async-sentinel' and
- `twittering-url-retrieve-async-clean-up-sentinel'. Since the alist
- was null, a URI might be retrieved repeatedly.
-
-2010-11-25 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Delay next asynchronous retrieval until all
- sentinels for the current retrieval finish.
- (twittering-url-retrieve-async-sentinel): call
- `twittering-resolve-url-request' after sentinels finish.
- (twittering-url-retrieve-async-clean-up-sentinel): call
- `twittering-resolve-url-request' only when the current retrieval
- is failed.
-
- * twittering-mode.el: Periodically invoke actions associated with
- idle-timer even if Emacs remains idle long time.
- (twittering-timer-interval-for-redisplaying): extended to 5.0.
- (twittering-url-retrieve-async-sentinel): use
- `twittering-run-on-idle' instead of `run-with-idle-timer'.
- (twittering-idle-timer-for-redisplay): new variable.
- (twittering-run-on-idle): new function.
- (twittering-run-repeatedly-on-idle): new function.
- (twittering-start): use `twittering-run-repeatedly-on-idle'
- instead of `run-with-idle-timer'.
- (twittering-stop): also cancel the idle timer for redisplaying.
-
- * twittering-mode.el: Add retrieved timeline spec string to
- history even if it includes no new statuses.
- (twittering-http-get-default-sentinel): add `spec-string' on
- successful retrieval even if there are no new statuses.
-
- * twittering-mode.el: `twittering-url-retrieve-async' immediately
- invokes the sentinel if the url has been already retrieved.
- (twittering-url-retrieve-async): immediately invoke the sentinel
- if the given url has been already retrieved.
-
- * twittering-mode.el: Call `url-retrieve' without attempting
- keep-alive.
- (twittering-send-http-request): remove special treatment according
- to `status-str' for the connection method by url library. It was
- necessary because `url-retrieve' invoked its sentinel before the
- process exits.
- (twittering-send-http-request-urllib): call `url-retrieve' with
- binding `url-http-attempt-keepalives' to nil.
-
- * twittering-mode.el: The property symbol `belongs-to' is renamed
- `source-spec'.
- (twittering-render-timeline): add `source-spec' to each status
- instead of `belongs-to'.
- (twittering-direct-message): use `source-spec' instead of
- `belongs-to'.
- (twittering-enter): likewise.
-
- * twittering-mode.el: Fix a bug that some text properties of a
- tweet rendered on a buffer may be lost by redisplaying it.
- (twittering-make-common-properties): new function.
- (twittering-get-common-properties): new function.
- (twittering-generate-format-status-function): use
- `twittering-make-common-properties'.
- (twittering-format-status-for-redisplay): use
- `twittering-get-common-properties'.
- (twittering-update-filled-string): likewise.
-
- * twittering-mode.el: `twittering-redisplay-status-on-each-buffer'
- restores common properties of re-rendered tweets.
- (twittering-format-status-for-redisplay): do not restore
- properties.
- (twittering-update-filled-string): likewise.
- (twittering-redisplay-status-on-each-buffer): restore common
- properties.
-
- * twittering-mode.el: Add `source-spec' as an entry of alist
- storing a tweet.
- (twittering-add-statuses-to-timeline-data): add the `source-spec'
- property to each new status.
- (twittering-make-common-properties): add `source-spec' as a common
- property.
- (twittering-get-common-properties): update docstring.
- (twittering-render-timeline): do not add the `source-spec'
- property.
-
- * twittering-mode.el: Correctly define the alias of
- `open-ssl-stream' for Emacs21 even if `url-gw.el' has been already
- loaded and unavailable autoload has been declared.
- (twittering-start-http-session-urllib-https-p): ignore the
- autoload declaration of `open-ssl-stream' in `url-gw.el' if
- "ssl.el" is unavailable.
-
- * twittering-mode.el: Fix a bug that `twittering-username' is not
- initialized when using encryption of authorized token with OAuth.
- (twittering-http-get-verify-credentials-sentinel): apropriately
- initialize `twittering-username' even if encryption of authorized
- token is used with OAuth.
-
-2010-11-14 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix a bug in registration of a sentinel for
- asynchronous retrieval.
- (twittering-url-retrieve-async): fix registration of sentinels to
- avoid registering a sentinel repeatedly.
-
- * twittering-mode.el: Contents retrieved by url library are copied
- as unibyte string. Without this modification, binary data may be
- retrieved incorrectly.
- (twittering-send-http-request-urllib): copy contents retrieved by
- url library as unibyte string. Without this modification, binary
- data may be retrieved incorrectly.
-
- * twittering-mode.el: Sentinels for `twittering-send-http-request'
- are called with a process status symbol instead of a process
- status symbol. This is necessary for faking a status of a process
- generated by url library.
- (twittering-send-http-request): call sentinels with a process
- status symbol instead of a process status string.
- (twittering-http-get-default-sentinel): receives `status' instead
- of `status-str'.
- (twittering-http-get-list-index-sentinel): likewise.
- (twittering-http-post-default-sentinel): likewise.
- (twittering-http-get-verify-credentials-sentinel): likewise.
- (twittering-http-get-verify-credentials-clean-up-sentinel):
- likewise.
- (twittering-oauth-get-token-alist): define sentinels so that they
- receive `status' instead of `status-str'.
- (twittering-get-and-render-timeline): likewise.
-
- * twittering-mode.el: Redisplay tweets with idle timer.
- (twittering-timer-interval-for-redisplaying): change the meaning.
- (twittering-start): `twittering-redisplay-status-on-buffer' is
- called by `run-with-idle-timer'.
-
- * twittering-mode.el: `twittering-resolve-url-request' uses
- `twittering-send-http-request' instead of `url-retrieve'.
- (twittering-resolve-url-request): use
- `twittering-send-http-request' instead of `url-retrieve'.
- (twittering-url-retrieve-async-sentinel): new function.
- (twittering-url-retrieve-async-clean-up-sentinel): new function.
-
- * twittering-mode.el: Sentinels for asynchronous retrieval are
- invoked with `run-with-idle-timer'. The delay will prevent Emacs
- from stucking on inputting characters on other buffer.
- (twittering-url-request-sentinel-delay): new variable.
- (twittering-url-retrieve-async-sentinel): invoke sentinels with
- `run-with-idle-timer'.
-
-2010-11-13 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: `twittering-send-http-request' correctly
- transfer `additional-info'.
- (twittering-send-http-request): call
- `twittering-send-http-request-internal' with correct arguments.
-
- * twittering-mode.el: Remove redundant entries from an argument of
- `twittering-send-http-request'.
- (twittering-http-get): remove redundant entries from
- `additional-info', an argument of `twittering-send-http-request'.
- (twittering-http-post): likewise.
-
- * twittering-mode.el: Fix docstring of `twittering-call-api'.
- (twittering-call-api): fix docstring.
-
- * twittering-mode.el: `twittering-call-api' extracts a query
- string from the given timeline spec.
- (twittering-call-api): extract a query string of search timeline
- from the given timeline spec.
- (twittering-get-and-render-timeline): remove a query string
- from the second argument of `twittering-call-api'.
-
- * twittering-mode.el: `twittering-call-api' can calculate how many
- tweets should be retrieved.
- (twittering-call-api): let the argument `number' of the command
- `retrieve-timeline' be optional.
- (twittering-get-and-render-timeline): remove explicit calculation
- of number of tweets which will be retrieved.
-
- * twittering-mode.el: Add a new argument `additional-info' to
- `twittering-http-{get,put}'. It can be used to send information to
- generated processes.
- (twittering-http-get): replace the argument `noninteractive' with
- a new argument `additional-info', which will be sent to
- `twittering-send-http-request'.
- (twittering-http-post): add a new argument `additional-info',
- which will be sent to `twittering-send-http-request'.
- (twittering-call-api): send the information of `noninteractive' as
- a member of `additional-info' to `twittering-http-get'.
-
- * twittering-mode.el: Timeline spec is sent to a sentinel via
- `connection-info' instead of `twittering-process-info-alist'.
- (twittering-http-get-default-sentinel): receive the timeline spec
- from `connection-info' instead of `twittering-process-info-alist'
- via `twittering-get-timeline-spec-from-process'.
- (twittering-get-and-render-timeline): send timeline spec to the
- sentinel via `additional-info', which is an argument of
- `twittering-call-api'.
-
- * twittering-mode.el: Confirm that `twittering-proxy-use' is nil
- when trying the connection method `native'.
- (twittering-start-http-session-native-tls-p): return nil if
- `twittering-proxy-use' is non-nil.
-
- * twittering-mode.el: Display the current connection method on the
- mode-line.
- (twittering-display-connection-method): new variable.
- (twittering-lookup-connection-type): add the entry `display-name'
- if necessary.
- (twittering-get-connection-method-name): new function.
- (twittering-mode-line-buffer-identification): display the current
- connection method on the mode-line.
-
- * twittering-mode.el: The default value of
- `twittering-url-show-status' is changed to nil.
- (twittering-url-show-status): initialized as nil.
-
- * twittering-mode.el: Postpone configuring the global variables
- `twittering-username' and `twittering-password' until the account
- is authenticated.
- (twittering-prepare-account-info): return a pair of username and
- password instead of setting them as global variables.
- (twittering-verify-credentials): do not set the global variables
- `twittering-username' and `twittering-password' until the account
- is authenticated.
- (twittering-http-get-verify-credentials-sentinel): set the global
- variables `twittering-username' and `twittering-password' if
- necessary.
-
- * twittering-mode.el: Add new connection method `urllib-http' and
- `urllib-https'.
- (twittering-connection-type-order): add `urllib-http' and
- `urllib-https'.
- (twittering-connection-type-table): add new entries for
- `urllib-http' and `urllib-https'.
- (twittering-send-http-request): add special treatment for the
- connection method using the url library.
- (twittering-start-http-session-urllib-p): new function.
- (twittering-start-http-session-urllib-https-p): new function.
- (twittering-send-http-request-urllib): new function.
- (twittering-pre-process-buffer-urllib): new function.
-
-2010-10-14 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: `twittering-get-error-message' generates an
- error message with explanation if possible.
- (twittering-get-error-message): generate an error message with
- explanation if possible. `twittering-xml-parse-region' is called
- only when it is required. It is determined by the new argument
- `header-info'.
- (twittering-http-get-default-sentinel): use
- `twittering-get-error-message' for generating a total error
- message, not only explanation.
- (twittering-http-get-list-index-sentinel): likewise.
- (twittering-http-post-default-sentinel): likewise.
-
- * twittering-mode.el: The second argument of `twittering-call-api'
- is replaced with `additional-info', which is sent to
- `twittering-send-http-request' via `twittering-http-get' or
- `twittering-http-put'.
- (twittering-call-api): replace the argument `noninteractive' with
- `additional-info', which is sent to `twittering-send-http-request'
- via `twittering-http-get' or `twittering-http-put'.
- (twittering-get-and-render-timeline): send `noninteractive' via
- the new argument `additional-info' of `twittering-call-api'.
-
-2010-10-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Correctly render the format specifier "%L"
- with a preceding whitespace. Thanks to Tom X. Tobin.
- (twittering-generate-format-table): add a preceding whitespace to
- the format specifier "%L". The previous routine contradicts the
- docstring of `twittering-status-format'.
- * test/test-twittering-mode.el: Correct the test for the format
- specifier "%L".
-
- * test/test-twittering-mode.el: Fix the test for HMAC.
-
- * twittering-mode.el (twittering-connection-type-table): remove
- obsolete entries.
-
- * twittering-mode.el: `twittering-release-process' is called as a
- clean-up sentinel.
- (twittering-call-api): accept new option `clean-up-sentinel' for
- `retrieve-timeline'.
- (twittering-http-default-sentinel): do not call
- `twittering-release-process'.
- (twittering-get-and-render-timeline): explicitly register
- `twittering-release-process' as a clean-up sentinel.
-
- * twittering-mode.el: Classify functions into some groups.
-
- * twittering-mode.el: Add a new function
- `twittering-send-http-request-with-default-sentinel'.
- (twittering-send-http-request-with-default-sentinel): new function.
-
- * twittering-mode.el: Adapt some functions to
- `twittering-send-http-request-with-default-sentinel'.
- (twittering-get-response-body): removed.
- (twittering-start-http-session): use
- `twittering-send-http-request-with-default-sentinel' instead of
- `twittering-send-http-request' and
- `twittering-http-default-sentinel'.
- (twittering-get-error-message): assume that the given buffer
- consists of HTTP response body without headers.
- (twittering-http-default-sentinel): removed.
- (twittering-http-get-default-sentinel): modified so that it can be
- invoked via `twittering-send-http-request-with-default-sentinel'.
- (twittering-http-get-list-index-sentinel): likewise.
- (twittering-http-post-default-sentinel): likewise.
- (twittering-oauth-get-token-alist): likewise.
- (twittering-http-get-verify-credentials-sentinel): likewise.
- (twittering-http-get-verify-credentials-clean-up-sentinel):
- likewise.
- (twittering-get-status-from-http-response): removed.
- (twittering-get-and-render-timeline): modify arguments of
- `clean-up-sentinel' to adapt it to
- `twittering-send-http-request-with-default-sentinel'.
-
- * twittering-mode.el: Rename
- `twittering-send-http-request-with-default-sentinel'
- `twittering-send-http-request'.
- (twittering-send-http-request-internal): renamed from
- `twittering-send-http-request'.
- (twittering-send-http-request): renamed from
- `twittering-send-http-request-with-default-sentinel'.
- (twittering-start-http-session): use
- `twittering-send-http-requeset' instead of
- `twittering-send-http-request-with-default-sentinel'.
- (twittering-oauth-get-token-alist): likewise.
-
- * twittering-mode.el: Validity of a HTTP request is confirmed by
- `twittering-make-http-request'.
- (twittering-make-http-request): check the validity of arguments.
- (twittering-start-http-session): remove validity check.
-
- * twittering-mode.el: Remove `twittering-start-http-session'.
- (twittering-start-http-session): removed.
- (twittering-http-get): use `twittering-send-http-request' instead
- of `twittering-start-http-session'.
- (twittering-http-post): likewise.
-
- * twittering-mode.el: "Content-Length" for OAuth is calculated by
- `twittering-make-http-request'.
- (twittering-oauth-get-token-alist): remove explicit specification
- of "Content-Length". The header value is determined by
- `twittering-make-http-request'.
-
- * twittering-mode.el: Add `encoded-query-alist' entry to an alist
- of a HTTP request. This is required for generating "Authorization"
- header of OAuth.
- (twittering-make-http-request): add `encoded-query-alist' entry to
- an alist corresponding to a HTTP request.
-
- * twittering-mode.el: Add `uri-without-query' entry to an alist of
- a HTTP request. This is required for generating "Authorization"
- header of OAuth.
- (twittering-make-http-request): add `uri-without-query' entry to
- an alist corresponding to a HTTP request.
-
- * twittering-mode.el: Introduce
- `twittering-add-application-header-to-http-request'.
- (twittering-http-application-headers-with-auth): removed.
- (twittering-add-application-header-to-http-request): new
- function.
- (twittering-http-get): use
- `twittering-add-application-header-to-http-request' instead of
- `twittering-http-application-headers-with-auth'.
- (twittering-http-post): likewise.
-
- * twittering-mode.el: Fix `twittering-buffer-related-p' in order
- to support multiple edit buffers.
- (twittering-buffer-related-p): fix a condition so that it works
- well even when multiple edit buffer exists.
-
- * twittering-mode.el: Solve cyclic reference on definition of
- `twittering-unicode-replacement-char'.
- (twittering-ucs-to-char-internal): new function.
- (twittering-unicode-replacement-char): initialized by
- `twittering-ucs-to-char-internal'.
- (twittering-ucs-to-char): redefined with
- `twittering-unicode-replacement-char' and
- `twittering-ucs-to-char-internal'.
-
- * twittering-mode.el: Modify some codes to avoid warnings on
- byte-compile.
- (twittering-start-http-session-native-tls-p): load the tls library
- before byte-compiling this function. This avoids a warning of the
- reference to `tls-program' on byte-compile.
- (twittering-read-from-encrypted-file): likewise. The epa library
- and "alpaca.el" are loaded before byte-compiling this function.
- (twittering-modeline-properties): new constant.
- (twittering-modeline-active): defined with
- `twittering-modeline-properties'.
- (twittering-modeline-inactive): likewise.
-
-2010-09-26 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Remove redundant pre-processing of HTTP
- response buffer for SSL via a proxy.
- (twittering-oauth-get-response-alist): remove redundant
- pre-processing of HTTP response buffer for SSL via proxy. Instead
- of it, `twittering-oauth-get-token-alist' invokes an appropriate
- function for pre-processing.
-
- * twittering-mode.el: Correct schemes of URIs used in OAuth/xAuth
- procedures.
- (twittering-oauth-request-token-url): removed.
- (twittering-oauth-authorization-url-base): removed.
- (twittering-oauth-access-token-url): removed.
- (twittering-oauth-request-token-url-without-scheme): new variable.
- (twittering-oauth-authorization-url-base-without-scheme): new
- variable.
- (twittering-oauth-access-token-url-without-scheme): new variable.
- (twittering-oauth-get-token-alist): refer to the scheme of the
- given URI instead of `twittering-oauth-use-ssl'.
- (twittering-verify-credentials): make a URI with correct scheme
- for OAuth or xAuth procedure. The scheme is determined by
- `twittering-oauth-use-ssl'.
-
- * twittering-mode.el: A HTTP request alist is included in the
- connection info for the request.
- (twittering-oauth-get-token-alist): add an HTTP request alist into
- `connection-info'.
- (twittering-send-http-request-curl): extract the HTTP request
- alist from `connection-info' instead of an argument.
- (twittering-send-http-request-wget): likewise.
- (twittering-send-http-request-native): likewise.
- (twittering-make-connection-info): generate connection info
- according to an arugment `request'.
- (twittering-send-http-request): register the sentinel so that it
- will be invoked with three arguments, process, status-string and
- connection-info. The connection-info is automatically generated
- from the given HTTP request alist.
- (twittering-start-http-session): do not bind `connection-info'.
-
- * twittering-mode.el: `twittering-send-http-request' receives
- optional arguments for connection method.
- (twittering-send-http-request): add two optional arguments for
- customizing connection method.
-
- * twittering-mode.el: Fix docstring of
- `twittering-make-http-request'.
- (twittering-make-http-request): fix docstring.
-
- * twittering-mode.el: `twittering-make-http-request' automatically
- adds the header field "Content-Length" if necessary.
- (twittering-make-http-request): add the header field
- "Content-Length" if it is missing on "POST" method.
- (twittering-http-application-headers): do not add the header field
- "Content-Length".
-
- * twittering-mode.el: Add `twittering-make-http-request-from-uri'.
- (twittering-make-http-request): accept a string as the argument
- `query-parameters', which is treated as an encoded query string.
- (twittering-make-http-request-from-uri): new function, which
- generates a HTTP request alist from URI.
-
- * twittering-mode.el: Rearrange `twittering-oauth-get-token-alist'.
- (twittering-oauth-get-token-function-table): removed. Instead of
- the variable, `twittering-connection-type-table' is used.
- (twittering-oauth-get-token-function-type): removed. Instead of
- the variable, `twittering-connection-type-order' is used.
- (twittering-oauth-get-token-alist): use
- `twittering-make-http-request-from-uri' and
- `twittering-send-http-request'.
- (twittering-verify-credentials): remove unnecessary statements.
- (twittering-ensure-connection-method): take account of
- `twittering-oauth-use-ssl'.
-
- * twittering-mode.el: Transfer sentinel functions to
- `twittering-default-sentinel' via `connection-info'.
- (twittering-start-http-session): transfer the variable `sentinel'
- to `twittering-http-default-sentinel' via `connection-info'.
- (twittering-http-default-sentinel): remove the arguments `func'
- and `clean-up-sentinel'. The sentinel functions are retrieved from
- `connection-info'.
-
-2010-09-19 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix `twittering-push-uri-onto-kill-ring'.
- (twittering-push-uri-onto-kill-ring): confirm that `kill-ring' is
- non-nil before calling `current-kill'.
-
- * twittering-mode.el: Copy tweets by "C-<mouse-3>".
- Thanks to Faried Nawaz.
- (twittering-mode-menu-on-uri-map): new keymap for menu on URI.
- (twittering-mode-on-uri-map): new keymap used on URI.
- (twittering-mode-map): bind "C-<down-mouse-3>" to
- `mouse-set-point' to move the point and bind "C-<mouse-3>" to
- `twittering-push-tweet-onto-kill-ring'.
- (twittering-make-clickable-status-datum): embed new keymap
- `twittering-mode-on-uri-map' in texts that have `uri' property.
- (twittering-generate-format-table): likewise.
- (twittering-generate-formater-for-first-spec): likewise.
- (twittering-push-tweet-onto-kill-ring): new function.
-
- * twittering-mode.el: Introduce a function sending a HTTP requests
- with `curl'.
- (twittering-connection-type-table): use new functions
- `twittering-start-http-session-generic' and
- `twittering-send-http-request-curl' for connection-type `curl'.
- (twittering-oauth-get-token-function-table): register the
- pre-processing function for `curl'.
- (twittering-oauth-get-token-alist-generic): new function. This
- works with a function sending HTTP request.
- (twittering-oauth-get-token-alist-curl): removed. The function is
- replaced with the combination of
- `twittering-oauth-get-token-alist-generic' and
- `twittering-send-http-request-curl'.
- (twittering-oauth-get-token-alist): use
- `twittering-oauth-get-token-alist-generic' if the found entry is a
- cons pair of functions.
- (twittering-send-http-request-curl): new function. This is
- abstract interface for sending HTTP request via `curl'.
- (twittering-start-http-session): add more entries to
- `connection-info'. `twittering-send-http-request-curl' requires
- them.
- (twittering-start-http-session-generic): new function.
- (twittering-start-http-session-curl): removed. The function is
- replaced with the combination of
- `twittering-start-http-session-generic' and
- `twittering-send-http-request-curl'.
-
- * twittering-mode.el: Introduce a function sending a HTTP request
- with native functions.
- (twittering-connection-type-table): use generic function for
- connection-type `native'.
- (twittering-oauth-get-token-function-table): likewise.
- (twittering-oauth-get-token-alist-native): removed. The function
- is replaced with the combination of
- `twittering-oauth-get-token-alist-generic' and
- `twittering-send-http-request-native'.
- (twittering-start-http-session-native): removed. The function is
- replaced with the combination of
- `twittering-start-http-session-generic' and
- `twittering-send-http-request-native'.
-
- * twittering-mode.el: Integrate generic function into
- `twittering-start-http-session'.
- (twittering-connection-type-table): remove the entry `start' and
- rename `start-process' `send-http-request'.
- (twittering-lookup-http-start-function): use `send-http-request'
- instead of `start-process'.
- (twittering-start-http-session): unified with
- `twittering-start-http-session-generic'.
- (twittering-start-http-session-generic): removed.
-
- * twittering-mode.el: The HTTP header field "Expect" will be added
- only when using `curl'.
- (twittering-send-http-request-curl): add the field "Expect".
- (twittering-start-http-session): remove the field "Expect".
-
- * twittering-mode.el: Integrate generic function into
- `twittering-oauth-get-token-alist'.
- (twittering-oauth-get-token-alist): unified with
- `ftwittering-oauth-get-token-alist-generic'.
- (twittering-oauth-get-token-alist-generic): removed.
-
- * twittering-mode.el: Add new connection method `wget'.
- (twittering-wget-program): new variable.
- (twittering-connection-type-order): add an entry for `wget'.
- (twittering-connection-type-table): add entries for
- new connection-method `wget'.
- (twittering-oauth-get-token-function-table): likewise.
- (twittering-find-wget-program): new function.
- (twittering-start-http-session-wget-p): new function.
- (twittering-send-http-request-wget): new function.
- (twittering-pre-process-buffer-wget): new function.
-
- * twittering-mode.el: Use an alist for representing parameters of
- a HTTP request.
- (twittering-oauth-get-token-alist): use an alist for representing
- a HTTP request.
- (twittering-send-http-request-curl): receive a HTTP request as an
- alist.
- (twittering-send-http-request-wget): likewise.
- (twittering-send-http-request-native): likewise.
-
- * twittering-mode.el: Rearrange `twittering-make-http-request'.
- (twittering-make-http-request): return an alist representing
- parameters of a HTTP request instead of a function.
- (twittering-start-http-session): generate a HTTP request alist by
- `twittering-make-http-request'.
-
- * twittering-mode.el: Ensure an available connection method before
- visiting a timeline.
- (twittering-lookup-http-start-function): do not retry finding
- connection-method with compromise. It is assumed that an available
- connection method is already determined here.
- (twittering-ensure-connection-method): new function.
- (twittering-visit-timeline): ensure that an available connection
- method is determined.
-
- * twittering-mode.el: Add `twittering-make-connection-info'.
- (twittering-make-connection-info): new function.
- (twittering-send-http-request): new function.
- (twittering-start-http-session): use new functions.
-
-2010-09-12 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Add an edited tweet into the history without
- text properties.
- (twittering-edit-extract-status): extract a status without text
- properties. They may cause `session.el' to fail to save
- `twittering-edit-history' because
- `twittering-make-clickable-status-datum' adds text properties with
- self-reference to tweets.
-
- * twittering-mode.el (twittering-auth-method): fix docstring.
- (twittering-timeline-spec-alias): likewise.
-
-2010-09-04 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-push-uri-onto-kill-ring): avoid
- pushing the same URL repeatedly.
-
- * twittering-mode.el: Fix xAuth with `gnutls-cli'.
- (twittering-oauth-get-token-alist-native): add a CRLF following
- the POST body. `gnutls-cli', which may be invoked by
- `open-tls-stream', requires the CRLF at the end of input.
-
- * twittering-mode.el: Introduce `connection-info', which is
- transferred to a sentinel.
- (twittering-start-http-session): introduce the variable
- `connection-info' to transfer the connection information to a
- sentinel. Since `connection-info' includes `noninteractive', the
- argument `noninteractive' is replaced with `connection-info'.
- (twittering-start-http-session-curl): likewise.
- (twittering-start-http-session-native): likewise.
- (twittering-http-default-sentinel): use `connection-info' instead
- of the current `twittering-use-ssl' and `twittering-proxy-use'.
-
- * twittering-mode.el (twittering-http-post): remove use of unbound
- variable `noninteractive'.
-
- * twittering-mode.el (twittering-call-api): use the argument
- `noninteractive' correctly.
-
- * twittering-mode.el: Introduce a framework to pre-process HTTP
- response buffer.
- (twittering-connection-type-table): add the entries for
- `pre-process-buffer'.
- (twittering-oauth-get-response-alist): remove redundant
- pre-processing for `openssl s_client'.
- (twittering-oauth-get-token-alist-native): pre-process buffer
- according to the variable `connection-info'.
- (twittering-oauth-get-token-alist-curl): likewise.
- (twittering-pre-process-buffer-curl): new function.
- (twittering-pre-process-buffer-native): new function.
- (twittering-http-default-sentinel): pre-process buffer with the
- function registered as `pre-process-buffer' in `connection-info'.
-
- * twittering-mode.el: Fix replying to tweets displayed as replied
- tweets. Thanks to Naohiro Aota.
- (twittering-enter): correctly use `original-id' for tweets
- displayed by `twittering-show-replied-statuses'.
-
-2010-08-25 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Confirm that a buffer associated with a
- process hs not been killed.
- (twittering-oauth-get-token-alist-native): confirm that the buffer
- associated with the process has not been killed.
- (twittering-oauth-get-token-alist-curl): likewise.
-
- * twittering-mode.el: Verify an account synchronously.
- (twittering-verify-credentials): wait for the authorization to
- finish.
-
-2010-08-22 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-atom-xmltree-to-status-datum):
- retrieve `user-screen-name' and optional `user-name' from XML for
- StatusNet correctly. Thanks to Takashi Masuda.
-
- * twittering-mode.el: Introduce `clean-up-sentinel' to
- `twittering-call-api'. It is executed whenever the process
- sentinel is invoked.
- (twittering-call-api): add new argument `clean-up-sentinel' for
- the command `get-list-index' and `verify-credentials'.
- (twittering-start-http-session): add new argument
- `clean-up-sentinel' executed whenever the process sentinel is
- invoked.
- (twittering-start-http-session-curl): likewise.
- (twittering-start-http-session-native): likewise.
- (twittering-http-get): likewise.
- (twittering-http-post): likewise.
- (twittering-http-default-sentinel): invoke `clean-up-sentinel' if
- it is non-nil.
-
- * twittering-mode.el: Fix the race condition on resetting
- authorization information when the process exits abnormally.
- (twittering-verify-credentials): use `clean-up-sentinel' for
- resetting variables when the process exits abnormally or the HTTP
- response is invalid.
- (twittering-http-get-verify-credentials-clean-up-sentinel): new
- function for resetting some variables when the process for
- `verify-credentials' API exits abnormally.
-
-2010-08-21 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Restore `twittering-get-{search,status}-url'.
- (twittering-lookup-get-status-url): removed.
- (twittering-lookup-get-search-url): removed.
- (twittering-get-status-url): look up a function suitable for
- `twittering-service-method' and call it.
- (twittering-get-search-url): likewise.
- (twittering-make-clickable-status-datum): directly call
- `twittering-get-status-url' and `twittering-get-search-url'
- instead of calling them via `twittering-lookup-get-status-url' or
- `twittering-lookup-get-search-url'.
- (twittering-generate-format-table): likewise.
- (twittering-generate-formater-for-first-spec): likewise.
-
- * twittering-mode.el: Switch ways to parse XML depending on
- `twittering-service-method'.
- (twittering-atom-xmltree-to-status-datum): switch ways to parse
- XML depending on `twittering-service-method'.
-
- * twittering-mode.el: Simplify `twittering-call-api'.
- (twittering-call-api): reduce calls of `twittering-api-path'.
-
- * twittering-mode.el: Replace direct calls of
- `twittering-http-post' with calls of `twittering-call-api'.
- (twittering-update-status-from-minibuffer): use
- `twittering-call-api' instead of `twittering-http-post'.
-
-2010-08-20 Takashi Masuda <masutakaNOSPAMnifty.com>
-
- * twittering-mode.el: Support StatusNet.
- (twittering-api-prefix): new variable.
- (twittering-search-api-method): new variable.
- (twittering-web-path-prefix): new variable.
- (twittering-service-method): new variable.
- (twittering-service-method-table): new variable.
- (twittering-api-path): new function.
- (twittering-lookup-get-status-url): new function.
- (twittering-get-status-url-twitter): new function.
- (twittering-get-status-url-statusnet): new function.
- (twittering-lookup-get-search-url): new function.
- (twittering-get-search-url-twitter): new function.
- (twittering-get-search-url-statusnet): new function.
- (twittering-call-api): generate a path of API by
- `twittering-api-path'. (API のパスは twittering-api-path から取得
- するようにした。)
- (twittering-edit-post-status): likewise.
- (twittering-update-status-from-minibuffer): likewise.
- (twittering-atom-xmltree-to-status-datum): support the format
- used in StatusNet.(いずれも検索関連の修正。
- 「interpret-time-diff.patch」「user-name が設定されていないユーザ
- に対応」「検索時のユーザアイコンを取得出来るように修正」)
- (twittering-make-clickable-status-datum): retrieve `status-url'
- and `search-url' via `twittering-lookup-get-status-url' and
- `twittering-lookup-get-search-url'. (twittering-lookup-get-status-url
- と twittering-lookup-get-search-url を介して status-url と
- search-url を取得するようにした。
- (twittering-generate-format-table): likewise.
- (twittering-generate-formater-for-first-spec): likewise.
-
- * twittering-mode.el: fix statusnet user URL
- (twittering-get-status-url-statusnet): fix user URL
-
- * twittering-mode.el (twittering-generate-format-table):
- Do not use icon images scaled by API unless Twitter.
-
- * twittering-mode.el: fix statusnet URL
- (twittering-get-status-url-statusnet): fix id URL
- (twittering-get-status-url-statusnet): fix hashtag URL
-
-2010-08-20 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-edit-post-status): call
- `twittering-call-api' instead of calling `twittering-http-post'
- directly.
-
- * twittering-mode.el: Do not add unnecessary parameter `source' to
- API calls.
- (twittering-http-post): do not add unnecessary parameter `source'.
- (twittering-call-api): add the parameter `source' when using BASIC
- authentication.
-
- * twittering-mode.el (twittering-call-api): Change parameters in
- order to follow the update of Twitter API.
-
- * twittering-mode.el: Add `twittering-push-uri-onto-kill-ring' and
- bind "U" to it. Thanks to Faried Nawaz.
- (twittering-push-uri-onto-kill-ring): new function for pushing the
- uri property of the current position onto the kill-ring.
- (twittering-mode-map): bind "U" to
- `twittering-push-uri-onto-kill-ring'.
-
- * twittering-mode.el: Add `twittering-new-tweets-statuses' for the
- hook functions of `twittering-new-tweets-hook'. Thanks to Faried
- Nawaz.
- (twittering-new-tweets-statuses): new variable.
- (twittering-add-statuses-to-timeline-data): bind
- `twittering-new-tweets-statuses' to `new-statuses' so that the
- hook functions can refer to the new tweets.
-
-2010-08-15 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Confirm that sufficient information is
- loaded from the private file.
- (twittering-load-private-info): load only variables that are
- enumerated in `twittering-variables-stored-with-encryption'.
- (twittering-has-oauth-access-token-p): new function for checking
- whether `twittering-oauth-access-token-alist' has sufficient
- information.
- (twittering-verify-credentials): confirm that sufficient
- information is loaded from the private file.
-
-2010-08-06 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix options of `curl' for POST with an empty
- body.
- (twittering-start-http-session-curl): add an option "-d" whenever
- `method' equals to "POST".
-
- * twittering-mode.el: Use the ID of the retweeted original tweet
- on generating a URL or retweeting it.
- (twittering-status-to-status-datum): add new property `source-id'
- specifying a source tweet of a retweet.
- (twittering-generate-formater-for-first-spec): generate a URL for
- a retweet from the ID of its source.
- (twittering-generate-format-status-function): add `source-id' as a
- common property.
- (twittering-native-retweet): use `source-id' for a retweet.
-
- * twittering-mode.el: Update the embedded CA certificate into
- `Equifax Secure Certificate Authority'.
- (twittering-ensure-ca-cert): replace the CA certificate with
- `Equifax Secure Certificate Authority' currently referred by
- `api.twitter.com' and `search.twitter.com'.
-
-2010-07-25 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-mode): avoid repeating
- authorization when `twittering-initial-timeline-spec-string' is a
- list of multiple timeline spec strings.
-
- * twittering-mode.el (twittering-http-default-sentinel): display
- an error message when waiting for a response of an authorization
- query.
-
- * twittering-mode.el: Replace functions `mapcan' and `map' defined
- in `cl-extra' with built-in functions in order to prevent the
- byte-compiled `twittering-mode' from depending on `cl-extra'.
- (twittering-oauth-get-token-alist-curl): replace `mapcan' with a
- combination of `apply', `append' and `mapcar'.
- (twittering-start-http-session-curl): likewise.
-
-2010-07-04 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-redisplay-status-on-buffer): Fix
- the condition of redisplaying a timeline.
-
- * twittering-mode.el: If it fails to retrieve an image a certain
- times, retry no longer.
- (twittering-create-image-pair): return
- `twittering-error-icon-data-pair' if the argument `image-data' is
- nil.
- (twittering-make-icon-string): fix the condition of
- `image-data'. If it is an integer, it means the time of retries.
-
- * twittering-mode.el: Use icon images scaled by API if possible.
- (twittering-generate-format-table): generate the URL of the scaled
- icon image by API.
-
- * twittering-mode.el: Use `GET users/profile_image' API only if
- the variable `twittering-use-profile-image-api' is non-nil. Since
- the API is rate limited, it may cause troubles on other API calls.
- (twittering-use-profile-image-api): new variable.
- (twittering-generate-format-table): call `GET users/profile_imagne'
- API only if `twittering-use-profile-image-api' is non-nil.
-
-2010-07-03 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Replace `xml-parse-region' with
- `twittering-xml-parse-region' in order to prevent abnormal exit
- caused by decoding unknown numeric character references.
- (twittering-unicode-replacement-char): new variable.
- (twittering-ucs-to-char): return
- `twittering-unicode-replacement-char' if decoding failed.
- (decode-char): new advice in order to return
- `twittering-unicode-replacement-char' for unknown code-points.
- (twittering-xml-parse-region): new function. This function does
- not exit abnormally even if given XML includes unknown numeric
- references. Unknown numeric references are replaced with
- `twittering-unicode-replacement-char'.
- (twittering-get-error-message): replace `xml-parse-region' with
- `twittering-xml-parse-region'.
- (twittering-http-get-list-index-sentinel): likewise.
- (twittering-get-status-from-http-response): likewise.
-
- * twittering-mode.el (twittering-oauth-get-token-alist-url): fix a
- list of bindings.
-
-2010-07-02 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-oauth-get-token-alist-native):
- use `twittering-tls-program' correctly.
-
- * twittering-mode.el: Detect abnormal exit of an invoked process.
- (twittering-oauth-get-token-alist-native): confirm the exit
- status of the invoked process.
- (twittering-oauth-get-token-alist-curl): likewise.
- (twittering-http-default-sentinel): likewise.
-
- * twittering-mode.el: Allow insecure server certificates if
- `twittering-allow-insecure-server-cert' is non-nil.
- (twittering-allow-insecure-server-cert): new variable.
- (twittering-oauth-get-token-alist-curl): add "--insecure" option
- to the arguments for `curl' if
- `twittering-allow-insecure-server-cert' is non-nil.
- (twittering-start-http-session-curl): likewise.
- (twittering-start-http-session-native-tls-p): add options to the
- programs in `tls-program' in order to allow insecure server
- certificates if `twittering-allow-insecure-server-cert' is
- non-nil.
-
- * twittering-mode.el (twittering-verify-credentials): display an
- error message if the variable `twittering-auth-method' is
- invalid.
-
-2010-07-01 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Support the url library included in Emacs 23
- and later.
- (twittering-oauth-get-token-alist-native): support the function
- `url-generic-parse-url' that returns parsed URL object generated
- as `structure'.
- (twittering-oauth-get-token-alist-curl): likewise.
-
- * twittering-mode.el (twittering-call-api): `user', `friends',
- `mentions' and `public' timelines include native retweets.
-
-2010-06-30 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-verify-credentials): reset
- `twittering-username' when authentication via xAuth failed.
-
- * twittering-mode.el (twittering-verify-credentials): invoke
- `twittering-prepare-account-info' before authentication method
- requiring account information.
- (twittering-visit-timeline): invoke
- `twittering-verify-credentials' before reading timeline spec.
-
-2010-06-29 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Confirm process status for avoiding
- dead-lock.
- (twittering-oauth-get-token-alist-native): confirm the process
- status in order to avoid dead-lock. If the process exited
- abnormally, the variable `result' becomes nil.
- (twittering-oauth-get-token-alist-curl): likewise.
- (twittering-verify-credentials): wait for the process to exit
- in order to avoid dead-lock.
- (twittering-get-list-index-sync): likewise.
-
- * twittering-mode.el (twittering-verify-credentials): wait for the
- process to exit in order to avoid dead-lock.
-
- * twittering-mode.el: Support authentication via xAuth.
- (twittering-get-list-index-sync): likewise.
- (twittering-xauth-auth-str-access-token): new function.
- (twittering-oauth-get-token-alist-url): add an argument
- `post-body'.
- (twittering-oauth-get-token-alist-native): likewise.
- (twittering-oauth-get-token-alist-curl): likewise.
- (twittering-oauth-get-token-alist): add an optional argument
- `post-body'.
- (twittering-xauth-get-access-token): new function.
- (twittering-prepare-account-info): support xAuth.
- (twittering-verify-credentials): likewise.
- (twittering-http-application-headers-with-auth): likewise.
- (twittering-visit-timeline): call
- `twittering-prepare-account-info' for xAuth.
-
-2010-06-13 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-write-and-encrypt): fix arguments
- of `epg-context-set-progress-callback' because of the difference
- between EasyPG 0.0.16 and that included in Emacs23.
-
- * twittering-mode.el (twittering-save-private-info): change the
- permission of the encrypted file in order to prevent others from
- reading the file.
- (twittering-write-and-encrypt): return t explicitly when it
- succeeded in encrypting private information.
-
- * twittering-mode.el (twittering-write-and-encrypt): In order to
- prevent `epa-file' to encrypt the file double,
- `epa-file-name-regexp' is temorarily changed into the null regexp
- that never matches any string.
-
-2010-06-12 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix bugs.
- (twittering-hmac-sha1): remove invalid arguments.
- (twittering-oauth-auth-str): correct a variable.
-
- * twittering-mode.el: Support master password for storing private
- information in an encrypted file.
- (twittering-use-master-password): new variable.
- (twittering-private-info-file): new variable.
- (twittering-variables-stored-with-encryption): new variable.
- (twittering-load-private-info): new function.
- (twittering-load-private-info-with-guide): new function.
- (twittering-save-private-info): new function.
- (twittering-save-private-info-with-guide): new function.
- (twittering-capable-of-encryption-p): new function.
- (twittering-read-from-encrypted-file): new function.
- (twittering-write-and-encrypt): new function.
- (twittering-verify-credentials): support master password.
-
- * twittering-mode.el: Add codes for debugging functions for
- OAuth.
- (twittering-oauth-get-token-alist-url): add codes for debug.
- (twittering-oauth-get-token-alist-native): likewise.
- (twittering-oauth-get-token-alist-curl): likewise.
-
-2010-06-09 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-oauth-get-access-token): reject
- invalid PIN code input and strip extra white spaces.
-
-2010-06-05 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: confirm that a valid access token has been
- retrieved.
- (twittering-oauth-make-response-alist): do not decode a null entry.
- (twittering-verify-credentials): confirm that the retrieved
- `token-alist' is valid as an access token.
-
-2010-06-04 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el: removed (set-terminal-coding-system 'utf-8)
- (twittering-mode-map): changed key bindings:
- twittering-public-timeline: C-c C-g -> C-c C-p,
- twittering-set-current-hashtag: C-c C-h -> C-c C-t
-
-
-2010-06-03 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el: add encrypted oauth consumer key/secret
- (twittering-auth-method): changed default value to 'oauth
- (twittering-oauth-get-access-token): give users a choise to open
- authrization URL with browser or not when
- twittering-oauth-invoke-browser is nil.
-
-2010-06-03 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Use `twittering-oauth-use-ssl' instead of
- `twittering-use-ssl' on functions for OAuth.
- (twittering-oauth-use-ssl): add docstring.
- (twittering-oauth-get-response-alist): use
- `twittering-oauth-use-ssl' instead of `twittering-use-ssl'.
- (twittering-oauth-get-token-alist-native): likewise.
- (twittering-oauth-get-token-alist-curl): likewise.
- (twittering-verify-credentials): likewise.
-
- * twittering-mode.el: Restore window parameters after automatic
- redisplaying.
- (twittering-current-window-config): new function.
- (twittering-restore-window-config-after-modification): new function.
- (twittering-redisplay-status-on-each-buffer): restore window
- parameters after redisplaying.
-
- * twittering-mode.el: Suppress automatic redisplaying if
- unnecessary.
- (twittering-redisplay-status-on-each-buffer): do not modify buffer
- if updated string is same as the current string in the meaning of
- `string='.
- (twittering-make-icon-string): give different strings for
- displayed and undisplayed icon.
-
- * twittering-mode.el: Stop automatic redisplaying of buffers in
- which the mark and region are active.
- (twittering-redisplay-status-on-buffer): do not update buffer
- in which the mark and region are active.
-
- * twittering-mode.el: Reimplement the status formater that allows
- recursive specifiers such as "%FILL{%FACE[bold]{%C{%m/%d}}: %T}".
- (twittering-parse-format-string): removed.
- (twittering-generate-formater): removed.
- (twittering-generate-status-formater-base): removed.
- (twittering-generate-format-table): new function.
- (twittering-generate-formater-for-first-spec): new function.
- (twittering-generate-formater-for-current-level): new function.
- (twittering-generate-format-status-function): new function.
- (twittering-generate-format-status-function): use new
- implementation.
-
- * twittering-mode.el: Add an optional argument for the format
- specifier `FILL'. The argument specifies the prefix for the filled
- region.
- (twittering-status-format): use 2 white spaces as fill-prefix in
- default.
- (twittering-fill-string): use an additional argument `prefix' as
- `fill-prefix' for `fill-region-as-paragraph' if the argument is
- non-nil.
- (twittering-update-filled-string): transfer the local prefix for
- `twittering-fill-string'.
- (twittering-generate-formater-for-first-spec): recognize an
- optional argument for the format specifier `FILL'.
-
- * twittering-mode.el: Add a new format specifier
- "%FOLD[prefix]{...}".
- (twittering-fill-string): add an argument `keep-newline'. If it is
- non-nil, do not remove newlines in given string.
- (twittering-update-filled-string): add an argument
- `keep-newline'.
- (twittering-generate-formater-for-first-spec): add a new specifier
- "%FOLD[prefix]{...}".
-
- * twittering-mode.el: Fix unintended cursor motion caused by
- automatic redisplaying.
- (twittering-redisplay-status-on-each-buffer): fix the incorrect
- cursor motion occurring when it points the beginning of region
- that will be be modified.
-
-2010-05-27 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-toggle-activate-buffer): restart
- the timer if it is not active when activating a buffer.
-
-2010-05-24 Naohiro Aota <naotaNOSPAMelisp.net>
-
- * twittering-mode.el (twittering-native-retweet): Check if tweet
- is my own one.
-
-2010-05-22 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Use the coding-system `utf-8-unix' for
- reading data retrieved from Twitter.
- (twittering-start-http-session-curl): use the coding-system
- `utf-8-unix' for reading data retrieved from Twitter.
- (twittering-start-http-session-native): likewise.
-
- * twittering-mode.el: Omit a successful HTTP response and headers
- if they seem to be sent from a proxy for CONNECT method.
- (twittering-http-default-sentinel): omit a successful HTTP
- response and headers from a proxy if using SSL via the proxy.
- (twittering-get-response-header): do not remove headers from a
- proxy.
-
- * twittering-mode.el: Do not initialize `twittering-tls-program'
- multiple times.
- (twittering-start-http-session-native-tls-p): check `tls-program'
- only if `twittering-tls-program' is nil.
-
- * twittering-mode.el: Cache the result of capability confirmation
- for `curl'.
- (twittering-start-http-session-curl-p): do not initialize
- `twittering-curl-program' multiple times.
- (twittering-start-http-session-curl-https-p): do not execute
- `curl' multiple times.
-
- * twittering-mode.el: Look-up of connection type is rearranged.
- (twittering-lookup-http-start-function): reimplemented.
- (twittering-lookup-connection-type): new function.
-
- * twittering-mode.el: Confirm an available connection method
- before visiting a timeline.
- (twittering-visit-timeline): confirm connection method.
-
- * twittering-mode.el: Support authentication via OAuth. The
- authentication requires a consumer information registered with
- Twitter and an external WWW browser to authorize a request token.
- (twittering-auth-method): new variable.
- (twittering-oauth-consumer-key, twittering-oauth-consumer-secret):
- new variables for specifying an OAuth consumer.
- (twittering-oauth-access-token-alist): new variable for storing
- access token.
- (twittering-oauth-url-encode): new function.
- (twittering-oauth-unhex): new function.
- (twittering-oauth-url-decode): new function.
- (twittering-oauth-make-signature-base-string): new function.
- (twittering-oauth-make-random-string): new function.
- (twittering-hmac-sha1): imported from
- http://www.emacswiki.org/emacs/HmacShaOne .
- (twittering-oauth-auth-str): new function.
- (twittering-oauth-auth-str-request-token): new function.
- (twittering-oauth-auth-str-exchange-token): new function.
- (twittering-oauth-auth-str-access): new function.
- (twittering-oauth-make-response-alist): new function.
- (twittering-oauth-get-response-alist): new function.
- (twittering-oauth-get-token-alist-url): new function.
- (twittering-oauth-get-token-alist-native): new function.
- (twittering-oauth-get-token-alist-curl): new function.
- (twittering-oauth-get-token-function-table): new variable.
- (twittering-oauth-get-token-function-type): new variable.
- (twittering-oauth-invoke-browser): new variable.
- (twittering-oauth-get-token-alist): new function.
- (twittering-oauth-get-request-token): new function.
- (twittering-oauth-exchange-request-token): new function.
- (twittering-oauth-get-access-token): new function.
- (twittering-prepare-account-info): acquire username and password
- only if `twittering-auth-method' is symbol `basic'.
- (twittering-verify-credentials): support Authentication via OAuth.
- (twittering-http-application-headers): do not add Authorization
- header.
- (twittering-http-application-headers-with-auth): new function for
- generating headers adapted for each authentication method.
- (twittering-http-get): use
- `twittering-http-application-headers-with-auth'.
- (twittering-http-post): likewise.
- (twittering-percent-encode): encode a string according to
- Percent-Encoding defined in RFC3986 instead of RFC1738. It simply
- calls `twittering-oauth-url-encode'.
- (twittering-url-reserved-p): removed.
- * test/test-twittering-mode.el: add new test `test-oauth'.
- * emacs21/hex-util.el: imported from Emacs22.
- * emacs21/sha1.el: imported from Emacs22.
-
- * twittering-mode.el (twittering-oauth-get-access-token): fix the
- guide string of authorization via OAuth.
-
- * twittering-mode.el (twittering-hmac-sha1): fix indentation.
-
- * twittering-mode.el: Fix `twittering-hmac-sha1' so that it works
- well on Emacs23 and later.
- (twittering-hmac-sha1): ensure that internal variables are unibyte
- strings even on Emacs23 and later.
- * test/test-twittering-mode.el: add new test `test-hmac-sha1'.
-
- * emacs21/sha1.el: Imported from Gnus distributed with Emacs
- 22.2.1 on Debian 5.0 for Emacs21 that does not include `sha1.el'.
- * emacs21/hex-util.el: Imported from Gnus distributed with Emacs
- 22.2.1 on Debian 5.0 for Emacs21 that does not include
- `hex-util.el'.
-
-2010-05-20 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: The configuration of a proxy is referred via
- the function `twittering-proxy-info'.
- (twittering-proxy-info): return all configuration of the proxy for
- the scheme.
-
- * twittering-mode.el: Give priority to the variable
- `twittering-proxy-*' over `twittering-http-proxy-*' and
- `twittering-https-proxy-*'.
- (twittering-proxy-server): defined as a variable.
- (twittering-proxy-port): likewise.
- (twittering-proxy-keep-alive): likewise.
- (twittering-proxy-user): likewise.
- (twittering-proxy-password): likewise.
- (twittering-normalize-proxy-vars): normalize
- `twittering-proxy-port'.
- (twittering-proxy-info): return configuration generated from
- `twittering-proxy-*' regardless of the scheme (HTTP or HTTPS) if
- `twittering-proxy-server' and `twittering-proxy-port' are
- non-nil.
-
-2010-05-17 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-start-http-session-curl): fix
- extraction of the scheme from the variable `request'.
-
- * twittering-mode.el: Use a relative path to specify the temporary
- cert file for `curl' to ignore the difference of path
- representation between Windows and Cygwin.
- (twittering-start-http-session-curl): change directory before
- invoking `curl' and specify the temporary cert file with relative
- path.
-
-2010-05-15 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Add copyright of the ACTIVE/INACTIVE
- indicators derived from Wanderlust.
- (twittering-active-indicator-image): add the copyright as a
- comment.
- (twittering-inactive-indicator-image): likewise.
-
- * twittering-mode.el: The function `twittering-icon-mode' keeps
- the current cursor point.
- (twittering-render-timeline): add a new argument `keep-point'.
- (twittering-icon-mode): keep the current cursor point.
-
- * test/test-twittering-mode.el: Remove an obsolete test and update
- `test-format-status'.
-
- * twittering-mode.el: The proxies for HTTP and HTTPS can be
- configured individually. The variables
- `twittering-proxy-{server,port,user,password,keep-alive}' are now
- aliases.
- (twittering-http-proxy-server): new variable.
- (twittering-http-proxy-port): new variable.
- (twittering-http-proxy-user): new variable.
- (twittering-http-proxy-password): new variable.
- (twittering-http-proxy-keep-alive): new variable.
- (twittering-https-proxy-server): new variable.
- (twittering-https-proxy-port): new variable.
- (twittering-https-proxy-user): new variable.
- (twittering-https-proxy-password): new variable.
- (twittering-https-proxy-keep-alive): new variable.
- (twittering-proxy-server): changed into an alias to
- `twittering-http-proxy-server'.
- (twittering-proxy-port): changed into an alias to
- `twittering-http-proxy-port.
- (twittering-proxy-user): changed into an alias to
- `twittering-http-proxy-user.
- (twittering-proxy-password): changed into an alias to
- `twittering-http-proxy-password.
- (twittering-proxy-keep-alive): changed into an alias to
- `twittering-http-proxy-keep-alive.
- (twittering-normalize-proxy-vars): new function.
- (twittering-proxy-info): new function.
- (twittering-url-proxy-services): new function.
- (twittering-setup-proxy): initialize individual proxy
- configurations for HTTP and HTTPS.
-
- * twittering-mode.el: Enable to retrieve icon images silently.
- (twittering-url-show-status): new variable.
- (twittering-url-wrapper): control display of status even if the
- retrieval is asynchronous.
-
-2010-05-11 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix initialization of `twittering-tls-program'.
- (twittering-start-http-session-native-tls-p): use
- `twittering-tls-program' if it is non-nil.
-
-2010-05-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Use "\\`" as the regexp for the head of a
- tweet instead of "^". This prevents misinterpretation of tweets
- including multiple lines.
- (twittering-edit-post-status): correct the regexp for determining
- whether the "in-reply-to" ID should be attached or not.
- (twittering-update-status-from-minibuffer): likewise.
- (twittering-status-not-blank-p): correct the regexp for
- distinguish a blank tweet from a non-blank tweet.
-
- * twittering-mode.el: Prevent applying improper functions to a
- failed connection.
- (twittering-verify-credentials): give up authorization if
- `twittering-call-api' returns nil.
- (twittering-start-http-session-curl): return nil if it failed to
- open a connection.
- (twittering-start-http-session-native): likewise.
-
- * twittering-mode.el: Support HTTPS with `tls' library.
- (twittering-tls-program): new variable.
- (twittering-connection-type-table): register
- `twittering-start-http-session-native-tls-p' as the "https" entry
- for "native".
- (twittering-start-http-session-native-tls-p): new function.
- (twittering-start-http-session-native): call `open-tls-stream' if
- `twittering-use-ssl' is non-nil.
- * emacs21/tls.el: Imported from Emacs 22.2.1 on Debian 5.0 for
- Emacs21 that does not include `tls.el'.
-
-2010-05-08 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Add an abstract layer for Twitter API.
- (twittering-call-api): new function.
- (twittering-timeline-spec-to-host-method): removed.
- (twittering-host-method-to-timeline-spec): removed.
- (twittering-manage-friendships): removed.
- (twittering-manage-favorites): removed.
- (twittering-get-tweets): removed.
- (twittering-verify-credentials): use `twittering-call-api' instead
- of calling `twittering-http-get' directly.
- (twittering-get-list-index): likewise.
- (twittering-get-and-render-timeline): use `twittering-call-api'
- instead of calling `twittering-get-tweets'. The function also
- calculates how many tweets should be retrieved.
- (twittering-update-lambda): use `twittering-call-api' instead of
- calling `twittering-http-post' directly.
- (twittering-update-jojo): likewise.
- (twittering-native-retweet): likewise.
- (twittering-follow): use `twittering-call-api'.
- (twittering-favorite): likewise.
-
- * twittering-mode.el: Bind "C-c D" to `twittering-delete-status',
- which is a new function deleting a tweet.
- (twittering-delete-status): new function.
- (twittering-call-api): add a new command `destroy-status'.
- (twittering-delete-status-from-data-table): new function.
- (twittering-mode-map): bind "C-c D" to `twittering-delete-status'.
-
-2010-05-08 Takashi Masuda <masutakaNOSPAMnifty.com>
-
- * twittering-mode.el (twittering-update-jojo): 自分のツイートには返
- 信しないようにした。
- * twittering-mode.el (twittering-update-jojo): do not reply to
- tweets posted by the current user itself.
-
-2010-05-08 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-jojo-mode-p): confirm that the
- buffer has not been killed.
-
-2010-05-06 Tadashi MATSUO <tad@mymail.twin.jp>
-
- * twittering-mode.el: Fix the format specifier "%r" for direct
- message.
- (twittering-status-to-status-datum): add `recipient-screen-name'
- as a element of a status.
- (twittering-xmltree-to-status): store `recipient_screen_name'
- without modificaiton.
- (twittering-generate-status-formater-base): replace "%r" with
- `recipient-screen-name' if it exists.
-
-2010-05-05 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Use a dummy buffer to prevent the cursor
- from moving without intention after invoking `url-retrieve'.
- (twittering-url-request-dummy-buffer-name): new constant for dummy
- buffer.
- (twittering-resolve-url-request): switch to the dummy buffer just
- after killing the content buffer generated by `url-retrieve'. This
- prevents multiple threads from having different cursor points for
- the same buffer.
-
-2010-05-05 Takashi Masuda <masutakaNOSPAMnifty.com>
-
- * twittering-mode.el: twittering-jojo-mode の判定ミスを修正。
- (twittering-add-statuses-to-timeline-data): 判定方法を変更した。
- (twittering-jojo-mode-p): new function
- * twittering-mode.el: `twittering-jojo-mode' for each spec is
- correctly referred in order to decide whether to invoke
- `twittering-update-jojo'.
- (twittering-add-statuses-to-timeline-data): correct the condition
- for invoking `twittering-update-jojo'.
- (twittering-jojo-mode-p): new function.
-
-2010-05-04 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-ask-post): renamed
- `twittering-request-confirmation-on-posting'.
-
- * twittering-mode.el (twittering-edit-post-status): correct the
- condition for requesting confirmation on posting a status.
-
-2010-05-03 Takashi Masuda <masutakaNOSPAMnifty.com>
-
- * twittering-mode.el: Tweet する時に y-or-n-p で問い合わせを出来る
- ようにした。デフォルトは聞かれない。
- (twittering-ask-post): new variable
- * twittering-mode.el: Add confirmation on posting a status edited
- in pop-up buffer. It is disabled on default.
- (twittering-ask-post): new variable.
-
- * twittering-mode.el: `V' の補完対象に :direct_messages や :home を
- 追加した。
- (twittering-read-timeline-spec-with-completion): dummy-hist に追加。
- * twittering-mode.el: Add some primary timeline specs, such as
- ":direct_messages" and ":home", to candidates of completion.
- (twittering-read-timeline-spec-with-completion): add some timeline
- specs to dummy-hist.
-
-2010-05-03 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-edit-setup-help): generate help
- message by using `substitute-command-keys'.
-
- * twittering-mode.el: The format specifier "@" can receive the
- time format string, which is used to format the time of
- sufficiently old statuses.
- (twittering-generate-status-formater-base): add new parameter
- 'time-format' to the specifier "@".
- (twittering-make-passed-time-string): receive new argument
- `time-format'.
-
- * twittering-mode.el: Functions for retrieving URLs asynchronously
- are added.
- (twittering-url-data-hash): new variable for retrieved data.
- (twittering-url-request-list): new variable for additional requests.
- (twittering-url-request-sentinel-hash): new variable for sentinels.
- (twittering-internal-url-queue): new variable.
- (twittering-url-request-resolving-p): new variable.
- (twittering-url-request-retry-limit): new variable.
- (twittering-remove-redundant-queries): new function.
- (twittering-resolve-url-request): new function.
- (twittering-url-retrieve-async): new function.
-
- * twittering-mode.el: Icons are retrieved asynchronously.
- (twittering-icon-prop-hash): new variable.
- (twittering-image-data-table): removed.
- (twittering-get-display-spec-for-icon): new function.
- (twittering-convert-image-data): new function.
- (twittering-error-icon-data-pair): new constant.
- (twittering-create-image-pair): new function.
- (twittering-register-image-data): new function.
- (twittering-make-slice-spec): new function.
- (twittering-make-display-spec-for-icon): rearranged.
- (twittering-make-icon-string): new function.
- (twittering-retrieve-image): removed.
- (twittering-generate-status-formater-base): use
- `twittering-make-icon-string'.
- (twittering-image-stack): removed.
- (twittering-image-type): removed.
- (twittering-image-type-cache): removed.
-
-2010-05-01 Immad Naseer <immad.naseerNOSPAMgmail.com>
-
- * twittering-mode.el: New interactive functions for direct
- messages are added.
- (twittering-direct-messages-timeline): new function.
- (twittering-sent-direct-messages-timeline): new function.
-
-2010-04-25 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix mode-line to display the rate limit.
- (twittering-mode-line-buffer-identification): add the remaining
- number of API requests if `twittering-display-remaining' is
- non-nil.
-
- * twittering-mode.el: Stop keeping undo information for buffers
- managed by `twittering-mode'. Thanks to irie for pointing it out.
- (twittering-mode-setup): call `buffer-disable-undo'.
-
- * twittering-mode.el: Verify the account in advance of retrieving
- statuses.
- (twittering-account-authorization): new variable.
- (twittering-account-authorized-p): new function.
- (twittering-account-authorization-queried-p): new function.
- (twittering-prepare-account-info): new function for completing
- username and password.
- (twittering-verify-credentials): new function.
- (twittering-http-get-verify-credentials-sentinel): new function.
- (twittering-get-managed-buffer): start the timer after
- authorization.
- (twittering-mode-init-global): initialize neither
- `twittering-username' nor `twittering-password'.
- (twittering-mode): call `twittering-prepare-account-info'.
- (twittering-get-and-render-timeline): ignore requests unless
- authorization is completed.
- (twittering-update-active-buffers): do not retrieve statuses
- unless authorization is completed.
- (twittering-visit-timeline): verify the account.
- (twittering-get-username): use `twittering-username' directly.
- (twittering-get-password): use `twittering-password' directly.
- (twittering-username-active): removed.
- (twittering-password-active): removed.
-
- * twittering-mode.el: `twittering-visit-timeline' initializes
- global variables if necessary.
- (twittering-visit-timeline): initialize global variables and
- prepare account information.
- (twittering-mode): delegate the initialization to
- `twittering-visit-timeline'.
- (twittering-mode-init-global): renamed
- `twittering-initialize-global-variables-if-necessary'.
-
- * twittering-mode.el: Support multiple timelines on initialization.
- (twittering-initial-timeline-spec-string): mean multiple timelines
- if the value is a list of strings.
- (twittering-mode): support multiple timeline specs on
- initialization.
-
-2010-04-24 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Reimplement indicators.
- (twittering-ssl-indicator-image): new constant.
- (twittering-modeline-ssl): defined as a constant, which is
- initialized on loading `twittering-mode.el'.
- (twittering-ssl-image, twittering-ssl-indicator): removed.
- (twittering-ssl-icon): removed.
- (twittering-active-image, twittering-inactive-image): removed.
- (twittering-active-indicator, twittering-inactive-indicator):
- removed.
- (twittering-icon-directory): removed.
- (twittering-active-icon, twittering-inactive-icon): removed.
- (twittering-display-image-p): removed.
- (twittering-init-mode-line-icons): removed. Images are initialized
- as constants on loading `twittering-mode.el'.
- (twittering-active-indicator-image): new constant.
- (twittering-inactive-indicator-image): new constant.
- (twittering-modeline-active): defined as a constat.
- (twittering-modeline-inactive): likewise.
- (twittering-mode-init-global): remove the call of
- `twittering-init-mode-line-icons'.
-
- * twittering-mode.el: Display the buffer state as
- `mode-line-buffer-identification' instead of `mode-name'.
- (twittering-mode-line-buffer-identification): new function for
- generating a mode-line string for `twittering-mode'.
- (twittering-mode-string): removed.
- (twittering-modeline-ssl): remove brackets from the mode-line
- string.
- (twittering-modeline-active): use a whitespace with `display' face
- as a mode-line string.
- (twittering-modeline-inactive): remove brackets from the mode-line
- string.
- (twittering-update-mode-line): call `force-mode-line-update' only.
- (twittering-mode-setup): initialize `mode-name' and
- `mode-line-buffer-identification'.
-
-2010-04-19 Takashi Masuda <masutakaNOSPAMnifty.com>
-
- * twittering-mode.el : 関数名が古かったので、リネーム。
- (twittering-init-mode-line-icons):
- (twittering-mode-init-global):
- twittering-init-active-inactive-icons から
- twittering-init-mode-line-icons にリネーム。
- * twittering-mode.el : rename old functions.
- (twittering-init-mode-line-icons): rename
- `twittering-init-active-inactive-icons'
- `twittering-init-mode-line-icons'.
-
- * twittering-mode.el : SSL と ACTIVE/INACTIVE の状態をモードライン
- アイコンに表示するようにした。-nw 時は文字列を表示する。
- (twittering-update-mode-line): mode-line-buffer-identification の設
- 定を追加。INACTIVE と ssl の mode-name への設定を削除した。
- (twittering-display-image-p): 新規マクロ
- (twittering-init-active-inactive-icons): 新規関数
- (twittering-mode-init-global):
- twittering-init-active-inactive-icons を呼ぶように修正。
- * twittering-mode.el : display graphical indicators for SSL and
- ACTIVE/INACTIVE state on mode-line.
- (twittering-update-mode-line): add graphical indicators to
- `mode-line-buffer-identification' instead of `mode-name'.
- (twittering-display-image-p): new macro.
- (twittering-init-active-inactive-icons): new function.
- (twittering-mode-init-global): call
- `twittering-init-active-inactive-icons'.
-
- * icons/ssl.xpm: 上記に伴い Mew から拝借。
- * icons/ssl.xpm: imported from Mew.
-
- * offline.patch: 上記に伴い削除。元々私がブログに公開したものを
- Hayamizu 氏が拾って下さったもの。
- * offline.patch: removed. (Mr.Hayamizu imported it, which
- originated from Masuda's blog.)
-
-2010-04-19 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-buffer-from-spec): return nil
- if the corresponding buffer has been already killed.
- (twittering-update-unread-status-info): do not count statuses for
- a killed buffer.
- (twittering-http-get-default-sentinel): do not render a timeline
- for a killed buffer.
-
-2010-04-17 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Reimplement support of multiple buffers. The
- timeline spec and active-mode flag of each managed buffer are
- stored as buffer-local variables.
- (twittering-timeline-spec): new buffer-local variable.
- (twittering-timeline-spec-string): new buffer-local variable.
- (twittering-active-mode): new buffer-local variable.
- (twittering-buffer-info-list): redefined as a list of buffers.
- (twittering-get-buffer-list): follow the redefinition of
- `twittering-buffer-info-list'.
- (twittering-get-active-buffer-list): likewise.
- (twittering-buffer-p): likewise.
- (twittering-get-buffer-from-spec): likewise.
- (twittering-unregister-buffer): likewise.
- (twittering-unregister-killed-buffer): likewise.
- (twittering-buffer-active-p): use buffer-local
- `twittering-active-mode'.
- (twittering-get-timeline-spec-for-buffer): use buffer-local
- `twittering-timeline-spec'.
- (twittering-get-timeline-spec-string-for-buffer): use buffer-local
- `twittering-timeline-spec-string'.
- (twittering-register-buffer): removed. Its body is integrated into
- `twittering-get-managed-buffer'.
- (twittering-replace-spec-string-for-buffer): set buffer-local
- `twittering-timeline-spec-string' directly.
- (twittering-set-active-flag-for-buffer): use
- `twittering-toggle-activate-buffer'.
- (twittering-toggle-activate-buffer): set buffer-local
- `twittering-active-mode' directly.
- (twittering-get-managed-buffer): rearranged.
- (twittering-mode-setup): set up `twittering-timeline-spec',
- `twittering-timeline-spec-string' and `twittering-active-mode'.
- And register the current buffer to `twittering-buffer-info-list'.
-
- * twittering-mode.el: Add functions to switch timelines.
- (twittering-switch-to-next-timeline): new function.
- (twittering-switch-to-previous-timeline): new function.
- (twittering-mode-map): bind "f" and "b" to
- `twittering-switch-to-next-timeline' and
- `twittering-switch-to-previous-timeline', respectively.
-
-2010-04-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-mode-init-global): initialize
- faces without using `copy-face' because it does not change the
- default face for new frames.
-
-2010-04-07 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Fix a bug on updating timeline history.
- (twittering-http-get-default-sentinel): call
- `twittering-add-timeline-history' with correct timeline spec
- string.
- (twittering-add-timeline-history): receive timeline spec string
- instead of timeline spec.
-
- * twittering-mode.el (twittering-mode-setup): omit redundant call
- of `run-hook'.
-
- * twittering-mode.el (twittering-direct-message): fix a lack of
- separator. Thanks to Takashi Masuda.
-
-2010-04-06 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-new-tweets-spec): new variable
- for timeline spec on running `twittering-new-tweets-hook'.
-
- * twittering-mode.el: Add an experimental notifier for unread
- statuses on mode-line. You can enable it by invoking
- `twittering-enable-unread-status-notifier'. To disable it, invoke
- `twittering-disable-unread-status-notifier'.
- (twittering-unread-status-info): new variable.
- (twittering-reset-unread-status-info-if-necessary): new function.
- (twittering-set-number-of-unread): new function.
- (twittering-make-unread-status-notifier-string): new function.
- (twittering-update-unread-status-info): new function.
- (twittering-enable-unread-status-notifier): new function.
- (twittering-disable-unread-status-notifier): new function.
-
- * twittering-mode.el: Support fixed fill-column for the format
- specifier "%FILL{...}". Thanks to William Xu.
- (twittering-fill-column): new variable.
-
-2010-04-04 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el: Improve compatibility with global-font-lock mode.
- (twittering-mode-init-global): use `bold' instead of
- `font-lock-string-face' if it has not been bound yet.
- `twittering-mode' does not require loading `font-lock'.
- (twittering-mode-setup): prevent `global-font-lock-mode' enabling
- `font-lock-mode' by using buffer-local `font-lock-global-modes'.
- `twittering-mode' can be used with/without any configuration for
- font-lock mode.
-
- * twittering-mode.el: Replace hard-coded hostnames with
- variables and functions. Thanks to William Xu.
- (twittering-api-host): new variable.
- (twittering-api-search-host): new variable.
- (twittering-web-host): new variable.
- (twittering-get-search-url): new function.
- (twittering-make-clickable-status-datum): call
- `twittering-get-search-url' instead of using hard-coded hostname.
-
- * twittering-mode.el (twittering-start-http-session-curl): do not
- overwrite headers that `curl' will define internally. Thanks to
- William Xu.
-
-2010-04-03 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-buffer-active-p): renamed
- `twittering-buffer-related-p'.
-
- * twittering-mode.el (twittering-start): check the value of
- `twittering-timer-for-redisplaying' before setting timer.
-
- * twittering-mode.el: Multiple buffers are supported.
- (twittering-buffer-info-list): new variable for managing multiple
- buffers.
- (twittering-buffer): both of the function and the variable are
- removed.
- (twittering-update-mode-line): remove timeline spec from mode-line
- because it is displayed as the name of buffer.
- (twittering-switch-timeline): removed.
- (twittering-get-buffer-list): new function.
- (twittering-get-active-buffer-list): new function.
- (twittering-buffer-related-p): modified to support multiple buffers.
- (twittering-buffer-p): new function.
- (twittering-buffer-active-p): new function.
- (twittering-get-buffer-from-spec): new function.
- (twittering-get-buffer-from-spec-string): new function.
- (twittering-get-timeline-spec-for-buffer): new function.
- (twittering-get-timeline-spec-string-for-buffer): new function.
- (twittering-current-timeline-spec): return timeline spec for the
- current buffer.
- (twittering-current-timeline-spec-string): return timeline spec
- string for the current buffer.
- (twittering-register-buffer): new function.
- (twittering-unregister-buffer): new function.
- (twittering-unregister-killed-buffer): new function.
- (twittering-replace-spec-string-for-buffer): new function.
- (twittering-set-active-flag-for-buffer): new function.
- (twittering-toggle-activate-buffer): new function.
- (twittering-activate-buffer): new function.
- (twittering-deactivate-buffer): new function.
- (twittering-kill-buffer): new function.
- (twittering-generate-new-buffer): new function.
- (twittering-switch-timeline): removed.
- (twittering-get-managed-buffer): new function.
- (twittering-mode-map): `twittering-toggle-activate-buffer' is
- bound to "a". `twittering-kill-buffer' is bound to "q" instead of
- `twittering-suspend'.
- (twittering-mode-init-global): new function for initializing
- global variables.
- (twittering-initialized): new variable.
- (twittering-mode-setup): new function for initializing a buffer
- being managed by `twittering-mode'.
- (twittering-mode): reimplemented.
- (twittering-icon-mode): support multiple buffers.
- (twittering-http-get-default-sentinel): render the retrieved
- statuses on the buffer bound to the timeline spec.
- (twittering-redisplay-status-on-buffer): support multiple buffers.
- (twittering-redisplay-status-on-each-buffer): new function.
- (twittering-render-timeline): require the target buffer.
- (twittering-timer-action): support multiple buffers.
- (twittering-get-tweets): support multiple buffers.
- (twittering-get-and-render-timeline): retrieve and render the
- timeline bound to the current buffer.
- (twittering-start): use `twittering-update-active-timeline'
- instead of `twittering-current-timeline-noninteractive' for
- `twittering-timer'.
- (twittering-toggle-reverse-mode): support multiple buffers.
- (twittering-friends-timeline): call `twittering-visit-timeline'
- instead of `twittering-get-and-render-timeline'.
- (twittering-home-timeline): likewise.
- (twittering-replies-timeline): likewise.
- (twittering-public-timeline): likewise.
- (twittering-user-timeline): likewise.
- (twittering-other-user-timeline): likewise.
- (twittering-other-user-timeline-interactive): likewise.
- (twittering-other-user-list-interactive): likewise.
- (twittering-search): likewise.
- (twittering-update-active-buffers): new function for retrieving
- timelines for active buffers.
- (twittering-current-timeline): retrieve statuses for current
- buffer.
- (twittering-erase-old-statuses): erase statuses of the timeline
- bound to the current buffer.
- (twittering-visit-timeline): switch to the buffer generated by
- `twittering-get-managed-buffer'.
-
- * twittering-mode.el (twittering-update-server-info): update
- mode-lines for all buffers managed by `twittering-mode' if
- `twittering-display-remaining' is non-nil.
-
-2010-03-30 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-response-header): return nil
- if an empty line as a separater is not found in the given buffer.
- (twittering-http-default-sentinel): generate `header-info' only if
- `header' is non-nil.
-
-2010-03-29 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-url-wrapper): new wrapper
- function for using URL library with proxy configuration for
- `twittering-mode'.
- (twittering-url-insert-file-contents): likewise.
- (twittering-url-retrieve-synchronously): likewise.
- (twittering-setup-proxy): call `url-scheme-get-property' to avoid
- `url-proxy-services' to be reset.
- (twittering-retrieve-image): use the wrapper function instead of
- a function in URL library.
- (twittering-tinyurl-get): likewise.
-
- * twittering-mode.el (twittering-update-status-from-minibuffer):
- fix infinite loop on updating a status from minibuffer.
-
- * twittering-mode.el (twittering-start-http-session-curl): modify
- the order of arguments for `curl', where the URL is placed last.
-
-2010-03-25 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-status-url): change the
- format of a URL of a certain status into that used in the web
- interface on `http://twitter.com/'.
-
-2010-03-24 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-register-process): store timeline
- spec string.
- (twittering-get-and-render-timeline): register a process together
- with timeline spec string.
- (twittering-release-process): use `delq' instead of `delete'.
- (twittering-get-timeline-spec-string-from-process): new function
- for registered timeline spec string.
-
- * twittering-mode.el (twittering-http-get-default-sentinel):
- display the timeline spec string in notification.
-
-2010-03-23 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-mode-map): bind "SPC" and "C-v" to
- `twittering-scroll-up', and bind "<backspace>" and "M-v" to
- `twittering-scroll-down'.
- (twittering-scroll-up): new function. Thanks to Jim Crossley.
- (twittering-scroll-down): new function.
-
-2010-03-20 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-edit-post-status): Don't add
- parameter `in_reply_to_status_id' if the tweet does not begin with
- `@' and username which is passed from callers.
- (twittering-update-status-from-minibuffer): Likewise.
- (twittering-generate-status-formater-base): Make the specifier
- "%r" work similarly to web interface.
-
-2010-03-19 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-retrieve-image): Use
- `create-image'.
-
-2010-03-19 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-regexp-hash): New defvar.
- (twittering-regexp-atmark): Likewise.
- (twittering-extract-timeline-spec): Use these.
- (twittering-make-clickable-status-datum): Likewise.
-
-2010-03-19 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-remove-inactive-processes): add
- `exit' and `signal' to `inactive-statuses'.
-
-2010-03-18 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-other-user-list-interactive):
- Revert part of 2010-03-12 change to prevent an overwrite of a
- message which is outputted by `twittering-read-list-name'.
-
- * twittering-mode.el (twittering-http-default-sentinel): Check
- process-status before processing sentinel.
-
- * twittering-mode.el (twittering-make-clickable-status-datum): Add
- a text property `goto-spec'.
- (twittering-other-user-timeline): Refer it.
- (twittering-make-clickable-status-datum): Add a text property
- `screen-name-in-text' to both `user-name' and `user-screen-name'.
- (twittering-make-clickable-status-datum): No longer add text
- properties `hashtag-in-text' and `uri-in-text'.
- (twittering-enter): Don't refer these properties.
- (twittering-make-clickable-status-datum): Reduce loops.
-
- * twittering-mode.el (twittering-follow): Copy username and clear
- its text properties before using it for display on minibuffer.
- (twittering-other-user-list-interactive): Likewise.
- (twittering-read-list-name): Likewise.
- (twittering-native-retweet): Likewise for text.
- (twittering-favorite): Likewise for text.
-
-2010-03-17 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-generate-status-formater-base):
- fix the formater for "%FACE[...]{...}".
-
-2010-03-13 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el: Improve a support of sending direct
- messages.
-
- * twittering-mode.el (twittering-update-status-from-pop-up-buffer):
- Use twitter API which is related of direct_messages if necessary.
- (twittering-update-status-from-minibuffer): Likewise.
- (twittering-timeline-spec-is-direct-messages-p): New defun.
- (twittering-reply-recipient): Rename from
- `twittering-reply-to-id'.
- (twittering-update-status-from-pop-up-buffer): Adjust callers.
- (twittering-render-timeline): Add a text property `belongs-spec'.
- (twittering-update-status-from-pop-up-buffer): Add optional
- arguments `username' and `spec'.
- (twittering-update-status-from-minibuffer): Likewise.
- (twittering-enter): Adjust callers.
-
- * twittering-mode.el (twittering-edit-setup-help): Add optional
- arguments `username' and `spec'.
- (twittering-update-status-from-pop-up-buffer): Call it here.
- (twittering-edit-mode): Don't call it here.
-
- * twittering-mode.el (twittering-direct-message): Call
- `twittering-read-username-with-completion'.
-
- * twittering-mode.el (twittering-make-display-spec-for-icon): Use
- `create-animated-image' if present (on Emacs24 or later).
-
-2010-03-12 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-get-default-sentinel):
- Revert part of 2010-03-06 change because the scheduled removing of
- public_timeline from twitter API had been canceled on 2010-03-11.
-
- * twittering-mode.el (twittering-other-user-list-interactive): Fix
- condition to detect a null string.
- (twittering-other-user-timeline-interactive): Likewise.
- (twittering-extract-timeline-spec): Modify the condition for
- detecting a null string same as others.
- (twittering-get-replied-statuses): Likewise.
- (twittering-generate-status-formater-base): Likewise.
- (twittering-search): Likewise.
- (twittering-follow): Likewise.
- (twittering-direct-message): Add the condition for `username' is
- nil.
- (twittering-reply-to-user): Likewise.
- (twittering-other-user-list-interactive): Likewise for
- `list-name'.
-
-2010-03-11 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-update-status-format): kill
- newly generated `*Compile-Log*' buffer if it is empty.
-
- * twittering-mode.el (twittering-mode-init-variables): initialize
- account information explicitly.
- (twittering-get-username): simplified.
- (twittering-get-password): simplified.
-
-2010-03-11 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-render-timeline): Call
- `twittering-show-replied-statuses' if necessary.
- (twittering-show-replied-tweets): New defvar.
- (twittering-get-replied-statuses): Add optional argument `count'.
- (twittering-show-replied-statuses): Likewise.
- (twittering-have-replied-statuses-p): New defun.
- (twittering-show-replied-statuses): Add optional argument
- `interactive'.
- (twittering-hide-replied-statuses): Likewise.
- (twittering-toggle-show-replied-statuses): Adjust callers.
- (twittering-show-replied-statuses): Show a reason to do nothing.
- (twittering-hide-replied-statuses): Likewise.
-
- * twittering-mode.el (twittering-get-replied-statuses): Fix
- condition because `replied-id' always non-nil.
- (twittering-hide-replied-statuses): Fix condition to avoid an
- infinite loop.
-
- * twittering-mode.el (twittering-hide-replied-statuses): Go to the
- head of parent status before hiding replied statuses.
-
- * twittering-mode.el (twittering-default-show-replied-tweets): New
- defvar.
- (twittering-render-timeline): Use it instead of
- `twittering-show-replied-tweets'.
- (twittering-toggle-show-replied-statuses): Pass
- `twittering-show-replied-tweets' into
- `twittering-show-replied-statuses'.
- (twittering-show-replied-tweets): Add a docstring.
-
-2010-03-11 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-lookup-http-start-function):
- rearranged.
-
-2010-03-10 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-lookup-http-start-function):
- Don't use `booleanp' to work on Emacs21.
-
- * twittering-mode.el (twittering-mode-map): Use `kbd' macro same
- as other keymaps.
-
- * twittering-mode.el (twittering-goto-next-status): Show a
- progress message.
- (twittering-goto-previous-status): Likewise.
-
-2010-03-10 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-fill-string): receive adjustment
- width as the second argument.
- (twittering-update-status-format): support formating status with a
- prefix.
- (twittering-generate-formater): likewise.
- (twittering-generate-status-formater-base): likewise.
- (twittering-generate-format-status-function): likewise.
- (twittering-update-filled-string): likewise.
- (twittering-format-status-for-redisplay): new function for
- redisplaying a formated status with a prefix.
-
- * twittering-mode.el (twittering-find-status): new function for
- finding a status from an ID.
- (twittering-get-replied-statuses): new function for making a list
- of replied statuses.
- (twittering-mode-map): add
- `twittering-toggle-show-replied-statuses' to keymap as "r".
- (twittering-replied-statuses-visible-p): new function.
- (twittering-show-replied-statuses): new function.
- (twittering-hide-replied-statuses): new function.
- (twittering-toggle-show-replied-statuses): new function.
- (twittering-get-id-at): new function.
- (twittering-get-current-status-head): new function.
-
-2010-03-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-redisplay-status-on-buffer): call
- `func' with the region.
- (twittering-make-passed-time-string): restore the original
- properties.
-
- * twittering-mode.el (twittering-timeline-data-table): store ID
- table and referring ID table, too.
- (twittering-current-timeline-id-table): new function.
- (twittering-add-statuses-to-timeline-data): store updated ID
- tables.
-
- * twittering-mode.el (twittering-generate-status-formater-base):
- redisplay filled string including substring that should be
- redisplayed.
- (twittering-update-filled-string): new function for updating
- filled string with `need-to-be-update' property.
-
-2010-03-07 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-edit-replace-at-point): New defun
- to call `twittering-edit-length-check' forcefully.
- (twittering-edit-mode-map): Bind F4 to it instead of
- `twittering-tinyurl-replace-at-point'.
- (twittering-edit-length-check): Make all arguments optional.
-
-2010-03-06 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-server-info-alist): new variable
- for storing server information.
- (twittering-http-status-line-regexp): removed.
-
- * twittering-mode.el (twittering-display-remaining): new variable
- for specifying whether the remaining of rate limit should be
- displayed on the mode line or not.
- (twittering-update-mode-line): display the remaining of rate limit
- if `twittering-display-remaining' is non-nil.
- (twittering-get-ratelimit-remaining): new function.
- (twittering-get-ratelimit-limit): new function.
-
-2010-03-06 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el: Use the new versioned API endpoint at
- "api.twitter.com/1" instead of the legacy API endpoint to fit
- twitter API specification as of 2010-02-17.
- (twittering-timeline-spec-to-host-method): Likewise.
- (twittering-host-method-to-timeline-spec): Likewise.
- (twittering-edit-post-status): Likewise.
- (twittering-update-status-from-minibuffer): Likewise.
- (twittering-manage-friendships): Likewise.
- (twittering-manage-favorites): Likewise.
- (twittering-update-lambda): Likewise.
- (twittering-update-jojo): Likewise.
- (twittering-http-post): Update a comment.
-
- * twittering-mode.el (twittering-http-get-default-sentinel): Add
- an additional information which is related to obsolete
- public_timeline.
-
- * twittering-mode.el (twittering-http-post): Set parameter
- `source' here.
- (twittering-edit-post-status): Adjust callers.
- (twittering-update-status-from-minibuffer): Likewise.
- (twittering-manage-friendships): Likewise.
- (twittering-manage-favorites): Likewise.
- (twittering-update-lambda): Likewise.
- (twittering-update-jojo): Likewise.
- (twittering-native-retweet): Likewise.
-
- * twittering-mode.el (twittering-http-default-sentinel): Call
- `twittering-switch-timeline' and `twittering-release-process' only
- when `proc' is non-nil.
-
- * twittering-mode.el (twittering-http-get-default-sentinel):
- Change style of an additional error message.
- (twittering-http-get-list-index-sentinel): Likewise.
- (twittering-http-post-default-sentinel): Likewise.
-
-2010-03-03 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-toggle-reverse-mode): invoke
- `twittering-render-timeline' correctly.
-
- * twittering-mode.el (twittering-make-display-spec-for-icon): add
- 2 pixels margin to icons in order to make the cursor stand out.
-
-2010-03-01 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el: Add a support of direct messages (which was
- originally written by me in 2010-02-16)
-
- * twittering-mode.el (twittering-xmltree-to-status): Convert a XML
- tree retrieved with "direct_messages{,/sent}" request into a list
- of status alists which is retrieved from a standard timeline.
- (twittering-host-method-to-timeline-spec): Add condition for
- `direct_messages' and `direct_messages_sent'.
- (twittering-timeline-spec-to-host-method): Modify condition for
- `direct_messages' and `direct_messages_sent'.
-
- * twittering-mode.el (twittering-status-format): Modify the
- meaning of the specifier "%r" to display a recipient on both
- `direct_messages' and `direct_messages_sent'.
-
- * twittering-mode.el (twittering-format-status): Add `url'
- property for `direct_messages' and `direct_messages_sent'.
- (twittering-get-status-url): Change the second argument ID as
- optional.
- (twittering-make-clickable-status-datum): Call it.
-
-2010-03-01 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-generate-formater): changed into
- a function.
- (twittering-generate-status-formater-base): likewise.
- (twittering-generate-format-status-function): likewise.
-
- * twittering-mode.el (twittering-find-curl-program): replace
- `find' with `memq' in order to execute this function without
- loading `cl-seq.el' .
- (twittering-start-http-session): likewise.
- (twittering-goto-next-thing): likewise.
-
-2010-02-28 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-format-status-function-source):
- new variable for the status format used for generating
- `twittering-format-status-function'.
- (twittering-format-status-function): new variable for
- byte-compiled formating function.
- (twittering-parse-format-string): new function.
- (twittering-generate-formater): new macro for generating a lambda
- expression for given a format string and specifiers.
- (twittering-generate-status-formater-base): new macro for
- generating a lambda expression for given a format string.
- (twittering-generate-format-status-function): new macro for
- generating format status function.
- (twittering-update-status-format): new function for adjusting
- `twittering-format-status-function' with the current value of
- `twittering-status-format'.
- (twittering-mode-init-variables): invoke
- `twittering-update-status-format'.
- (twittering-render-timeline): call
- `twittering-update-status-format' before rendering statuses.
- (twittering-format-status): changed into a function receiving one
- argument. It only calls `twittering-format-status-function'.
-
-2010-02-27 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-retweet): If `C-u' prefix is
- given, `twittering-use-native-retweet' is temporarily reversed
- before use.
- (twittering-follow): Handle a prefix `C-u' correctly.
- (twittering-favorite): Likewise.
-
- * twittering-mode.el (twittering-edit-cancel-status): Show a
- message when cancelling a request.
- (twittering-native-retweet): Likewise.
- (twittering-follow): Likewise.
- (twittering-favorite): Likewise.
-
-2010-02-26 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-fill-string): Calculate a column
- with `fill-prefix'.
-
-2010-02-25 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-format-status): Use the return
- value of the flet'ed function `attr' directly for the specifier
- "%L", forgotten in the 2010-02-18 changing.
-
- * twittering-mode.el (twittering-retrieve-image): Check the return
- value of `call-process-region'.
- (twittering-make-display-spec-for-icon): Check the return value of
- `twittering-retrieve-image'.
-
- * twittering-mode.el (twittering-format-status): Don't check
- `twittering-image-data-table' here.
- (twittering-format-status): Don't define `profile-image' as
- flet'ed function for the specifier "%i".
-
- * twittering-mode.el (twittering-get-tweets): Don't call
- `twittering-retrieve-image' here.
-
- * twittering-mode.el (twittering-retrieve-image): Bind
- `url-show-status' locally to inhibit showing a progress message.
- (twittering-tinyurl-get): Likewise.
-
- * twittering-mode.el (twittering-image-type): Don't use the
- external command `file' because Emacs can display only an image
- which is recongnized by `image-type-from-data'.
- (twittering-retrieve-image): Don't look up
- `twittering-image-data-table' here.
- (twittering-make-display-spec-for-icon): Call
- `twittering-retrieve-image' only when `gethash' returns nil.
-
-2010-02-22 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-atom-xmltree-to-status-datum):
- Call `twittering-decode-html-entities' to decode entities
- properly.
-
- * twittering-mode.el (twittering-get-error-message): Change the
- first argument to `buffer' from `proc'.
- (twittering-http-get-default-sentinel): Adjust callers.
- (twittering-http-get-list-index-sentinel): Likewise.
- (twittering-http-post-default-sentinel): Likewise.
-
-2010-02-20 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-current-timeline-spec): Check
- `spec-string' is a string before calling
- `twittering-string-to-timeline-spec'.
- (twittering-get-and-render-timeline): Likewise.
- (twittering-read-timeline-spec-with-completion): Likewise.
-
- * twittering-mode.el (twittering-read-timeline-spec-with-completion):
- Return nil explicitly when `twittering-string-to-timeline-spec'
- return nil.
-
- * twittering-mode.el (twittering-retrieve-image): Use `unless'
- instead of `when'.
- (twittering-icon-mode): Likewise.
- (twittering-scroll-mode): Likewise.
- (twittering-jojo-mode): Likewise.
- (twittering-toggle-reverse-mode): Likewise.
-
-2010-02-19 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-delete-ca-cert-file): New defun.
- (twittering-ensure-ca-cert): Add it as a hook into
- `kill-emacs-hook'.
-
- * twittering-mode.el (twittering-get-error-message): New defun to
- pickup an error message from a xmltree.
- (twittering-http-get-default-sentinel): Use it.
- (twittering-http-get-list-index-sentinel): Likewise.
- (twittering-http-post-default-sentinel): Likewise.
-
- * twittering-mode.el (twittering-http-get-list-index-sentinel):
- Call `twittering-get-response-body' instead of `xml-parse-region'.
-
-2010-02-19 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-set-window-end): use
- `window-text-height' instead of `window-body-height' for Emacs21.
-
-2010-02-18 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-native-retweet): Add a margin for
- wide characters.
- (twittering-favorite): Likewise.
-
- * twittering-mode.el (twittering-extract-timeline-spec): Delete an
- unused argument to `error'.
-
- * twittering-mode.el (twittering-format-status): Use the return
- value of the flet'ed function `attr' directly for the specifier
- "%r".
- (twittering-format-status): Reverse condition for the specifier
- "%R".
-
- * twittering-mode.el (twittering-lookup-http-start-function): New
- defun to decide a connection method from currently available
- methods.
- (twittering-connection-type-table): New defvar.
- (twittering-connection-type-order): Likewise.
-
- * twittering-mode.el (twittering-curl-program): New defvar to
- cache a result of `twittering-find-curl-program'.
- (twittering-start-http-session-curl-p): New defun.
- (twittering-start-http-session-curl-https-p): Likewise.
- (twittering-start-http-session-curl): Rename from
- `twittering-start-http-ssl-session'.
- (twittering-start-http-session-native): Rename from
- `twittering-start-http-non-ssl-session'.
-
-2010-02-18 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-current-timeline-spec): return
- nil if `twittering-current-timeline-spec-string' returns nil.
- (twittering-current-timeline-data): return nil if
- `twittering-current-timeline-spec' returns nil.
- (twittering-extract-timeline-spec): raise an error if the argument
- `str' is nil.
-
-2010-02-17 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-extract-timeline-spec): Check STR
- is non-nil first for avoiding an error caused by `string-match'.
-
- * twittering-mode.el (twittering-icon-mode): Add an argument "P"
- to `interactive'.
- (twittering-scroll-mode): Likewise.
- (twittering-jojo-mode): Likewise.
- (twittering-toggle-reverse-mode): Likewise.
-
-2010-02-16 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-timeline-spec-to-string): Replace
- `-' with `_' in symbol name `direct-messages' and
- `direct-messages-sent' to fit the parameters of twitter API.
- (twittering-extract-timeline-spec): Likewise.
- (twittering-timeline-spec-primary-p): Likewise.
- (twittering-timeline-spec-to-host-method): Likewise.
- (twittering-timeline-spec-alias): Likewise in a comment.
-
- * twittering-mode.el (twittering-icon-mode): Call
- `twittering-update-mode-line' and `twittering-render-timeline'
- only when mode was changed.
- (twittering-scroll-mode): Likewise.
- (twittering-jojo-mode): Likewise.
- (twittering-toggle-reverse-mode): Likewise.
-
-2010-02-16 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-first-status-head): return
- nil if no statuses are rendered in the current buffer.
- (twittering-goto-first-status): go to the beginning of buffer if
- no statuses are rendered in the current buffer.
- (twittering-render-timeline): render tweets from the beginning of
- buffer if no statuses are rendered.
-
- * twittering-mode.el (twittering-reverse-mode): new variable for
- reverse alignment of tweets in timeline.
- (twittering-update-mode-line): add "reverse" to mode-line.
- (twittering-render-timeline): support reverse alignment of
- statuses.
- (twittering-toggle-reverse-mode): new interactive function to
- toggle reverse mode.
- (twittering-goto-next-status): support reverse mode.
- (twittering-goto-previous-status): likewise.
- (twittering-set-window-end): add new function.
-
-2010-02-15 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-get-list-index-sentinel):
- Get a listname from `slug' element which is only in `list' node.
-
-2010-02-15 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-and-render-timeline): copy
- spec-string and clear its text properties.
-
- * twittering-mode.el (twittering-http-default-sentinel): use
- buffer object directly.
- (twittering-http-get-default-sentinel): likewise.
-
- * twittering-mode.el (twittering-current-timeline): keep the
- current timeline spec string.
-
- * twittering-mode.el (twittering-switch-timeline): adjust the
- current timeline spec string to the given `spec-string' even if
- they mean the same timeline.
-
- * twittering-mode.el (twittering-http-get-default-sentinel):
- invoke `twittering-render-timeline' only if necessary.
- (twittering-add-statuses-to-timeline-data): return newly retrieved
- statuses.
-
- * twittering-mode.el (twittering-render-timeline): receive
- `timeline-data' as an optional argument.
- (twittering-http-get-default-sentinel): invoke
- `twittering-render-timeline' with new statuses.
-
-2010-02-14 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-usernames-from-timeline): new
- function for collecting user screen names in a timeline.
- (twittering-make-list-from-assoc): removed.
- (twittering-read-username-with-completion): use
- `twittering-get-usernames-from-timeline' instead of
- `twittering-make-list-from-assoc'.
- (twittering-read-timeline-spec-with-completion): likewise.
-
-2010-02-14 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-get-list-index-sentinel):
- Parse current-buffer as a xmltree.
-
-2010-02-14 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-current-timeline-spec-string):
- new variable for storing the current timeline spec string.
- (twittering-last-requested-timeline-spec-string): removed.
- (twittering-last-retrieved-timeline-spec-string): removed.
- (twittering-set-current-timeline-spec-string): new function for
- referring the current timeline spec string.
- (twittering-current-timeline-spec-string): new function for
- referring the current timeline spec.
- (twittering-switch-timeline-if-necessary): new function for
- switching timeline.
- (twittering-mode-init-variables): explicitly initialize the
- current timeline spec.
- (twittering-http-get-default-sentinel): store the retrieved
- timeline even if it is not the current timeline.
- (twittering-get-and-render-timeline): switch timeline just after
- requested.
- (twittering-erase-old-statuses): reimplemented.
- (twittering-update-mode-line): use
- `twittering-current-timeline-spec-string'.
- (twittering-add-timeline-history): likewise.
- (twittering-current-timeline): likewise.
- (twittering-goto-next-status): likewise.
-
- * twittering-mode.el (twittering-add-statuses-to-timeline-data):
- integrated with `twittering-cache-status-datum'.
- (twittering-cache-status-datum): removed.
-
-2010-02-13 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-mode-init-variables): make local
- variables by using `make-local-variable' in order to initialize
- the variables with the global values when invoking
- `twittering-mode'. You can initialize `twittering-icon-mode',
- `twittering-jojo-mode' and `twittering-scroll-mode' by using
- `setq' in your `.emacs'.
-
-2010-02-12 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-format-status): remove a newline
- from `icon-string' that underlies the icon image.
- (twittering-status-format): add a newline to the default value in
- order to keep the interval of displayed tweets.
-
-2010-02-12 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-get-tweets): Add optional
- argument `since_id'.
- (twittering-get-and-render-timeline): Adjust callers.
- (twittering-get-tweets): Set parameter `since_id' instead of
- `since' because twitter API had dropped support for `since'
- parameter on 2009-04-08.
- (twittering-http-get-default-sentinel): Modify the condition for
- if retrieving statuses is nil.
- (twittering-erase-old-statuses): Don't add parameter `since'.
- (twittering-status-to-status-datum): No longer use
- `twittering-timeline-last-update'.
- (twittering-get-and-render-timeline): Likewise.
- (twittering-timeline-last-update): Delete variable.
- (twittering-local-strftime, twittering-global-strftime): Delete
- functions.
- (twittering-setftime): Delete function.
-
- * twittering-mode.el (twittering-get-status-from-http-response):
- No longer make a reverse list.
- (twittering-http-get-default-sentinel): Adjust callers.
-
-2010-02-12 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el
- (twittering-find-processes-for-timeline-spec): new function for
- finding processes retrieving a specific timeline spec.
- (twittering-remove-inactive-processes): new function for removing
- inactive processes from `twittering-process-info-alist'.
- (twittering-process-active-p): new function for checking whether
- the processes for a specific timeline spec are active or not.
- (twittering-get-and-render-timeline): use
- `twittering-process-active-p' instead of referring
- `twittering-process-info-alist' directly.
-
- * twittering-mode.el (twittering-http-get-default-sentinel): run
- `twittering-new-tweets-hook' even if the retrieval is
- non-interactive.
-
- * twittering-mode.el (twittering-timeline-data): removed.
- (twittering-current-timeline-spec): new function for the current
- timeline spec.
- (twittering-current-timeline-data): new function for the current
- timeline data.
- (twittering-remove-timeline-data): new function for clearing a
- specific timeline data from `twittering-timeline-data-table`.
- (twittering-add-statuses-to-timeline-data): new function for
- adding statuses to `twittering-timeline-data-table'.
- (twittering-http-get-default-sentinel): use
- `twittering-add-statuses-to-timeline-data'.
- (twittering-cache-status-datum): change the third argument into
- non-optional because the global `twittering-timeline-data' is
- obsoleted.
- (twittering-get-and-render-timeline): do not modify
- `twittering-timeline-data'.
- (twittering-render-timeline): use
- `twittering-current-timeline-data' instead of
- `twittering-timeline-data'.
- (twittering-erase-old-statuses): likewise.
- (twittering-read-username-with-completion): likewise.
- (twittering-read-timeline-spec-with-completion): likewise.
-
-2010-02-11 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-fill-string): load "kinsoku.el"
- in advance if necessary.
-
-2010-02-11 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el: No longer clear fetched timeline when
- switching to another timeline.
-
- * twittering-mode.el (twittering-timeline-data-table): New defvar.
- (twittering-http-get-default-sentinel): Save current timeline into
- `twittering-timeline-data-table' when retrieving it successfully.
- (twittering-get-and-render-timeline): Load target timeline from
- `twittering-timeline-data-table' when switching to another
- timeline.
-
-2010-02-10 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-status-not-blank-p): Fix the
- regexp for case of "text @user".
-
- * test/test-twittering-mode.el (test-status-not-blank-p): Add a
- testcase.
-
- * twittering-mode.el (twittering-setup-proxy): Return t explicitly
- when the proxy related configurations are consistent.
- (twittering-toggle-proxy): Call `twittering-setup-proxy'.
-
-2010-02-09 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-get-default-sentinel): Get a
- buffer associate with the process from calling `process-buffer'
- instead of `current-buffer'.
-
- * twittering-mode.el (twittering-edit-cancel-status): Confirm
- before calling `twittering-edit-close' when an edit buffer was
- modified.
- (twittering-update-status-from-pop-up-buffer): Mark an edit buffer
- as unmodified.
-
- * twittering-mode.el (twittering-edit-length-check): Calculate
- length of a tweet with a sign string.
-
- * twittering-mode.el (twittering-native-retweet): Truncate a tweet
- by width instead of length.
- (twittering-favorite): Likewise.
-
- * twittering-mode.el (twittering-http-default-sentinel): Get a
- buffer associate with the process from calling `process-buffer'
- instead of taking from an argument.
- (twittering-http-default-sentinel): Delete an unnecessary
- argument.
- (twittering-start-http-ssl-session): Adjust callers.
- (twittering-start-http-non-ssl-session): Likewise.
-
-2010-02-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-goto-previous-status): simplified.
-
- * twittering-mode.el (twittering-goto-next-status): retrieve
- additional statuses if the function is called at the end of the
- buffer.
-
- * twittering-mode.el (twittering-render-timeline): use `insert'
- when inserting a status at the end of the buffer in order to keep
- the marker pointing the end of the buffer.
-
- * twittering-mode.el (twittering-render-timeline): move the
- position correctly even if the buffer is invisible.
-
-2010-02-08 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-default-sentinel): Delete a
- call to `twittering-release-process' in the BODYFORM to avoid a
- double release.
-
-2010-02-08 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-http-default-sentinel): call
- `twittering-release-process' even if some errors happen.
- (twittering-http-get-default-sentinel): remove invocation of
- `twittering-release-process'.
-
-2010-02-08 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-get-default-sentinel): Call
- `twittering-release-process' when status code is not equal to
- "200", forgotten in the 2010-02-06 changing.
-
- * twittering-mode.el (twittering-status-to-status-datum): Change
- `regex-index' variable to local scope from global one.
- (twittering-status-to-status-datum): Rename `regex-index' to
- `regexp-index'.
-
- * twittering-mode.el (debug-print): Reduce redundant calls of
- `insert' because it can take multiple arguments.
- (debug-printf): Remove an unnecessary call to `concat' because
- `insert' can take multiple arguments.
-
- * twittering-mode.el (twittering-extract-timeline-spec): Fix the
- regexp for "search" timeline spec; same as for "filter".
-
- * twittering-mode.el (twittering-make-clickable-status-datum):
- When trying to add a text property to `source', check it is
- non-nil first for avoiding an error caused by `string-match'.
-
-2010-02-07 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * test/test-twittering-mode.el (test-format-status): replace the
- format specifier "%t" with "%T".
-
- * twittering-mode.el (twittering-extract-timeline-spec): fix the
- regexp for "filter" timeline spec.
- * test/test-twittering-mode.el (timeline-spec): add a test for
- trailing backslashes.
-
- * twittering-mode.el (twittering-extract-timeline-spec): add error
- messages for some conditions.
-
- * twittering-mode.el
- (twittering-read-timeline-spec-with-completion): fix the regexp
- for judging whether a list name is required or not.
-
- * twittering-mode.el
- (twittering-read-timeline-spec-with-completion): catch errors on
- interpreting timeline spec string.
-
-2010-02-07 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-get): Add an optional
- argument for a response data format.
- (twittering-http-post): Likewise.
- (twittering-get-list-index): Adjust callers.
- (twittering-http-post): Delete unused argument `contents'.
-
- * twittering-mode.el (twittering-http-get-default-sentinel): Check
- status-code here instead of `twittering-http-default-sentinel'.
- (twittering-http-get-list-index-sentinel): Likewise.
- (twittering-http-post-default-sentinel): Likewise.
- (twittering-http-default-sentinel): Adjust callers.
-
- * twittering-mode.el (twittering-http-get-list-index-sentinel):
- Set a null string explicitly if user does not have a list.
-
-2010-02-06 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-default-sentinel): New defun
- to share code between `twittering-http-get-default-sentinel',
- `twittering-http-get-list-index-sentinel', and
- `twittering-http-post-default-sentinel'.
- (twittering-http-get-default-sentinel): Adjust function.
- (twittering-http-get-list-index-sentinel): Likewise.
- (twittering-http-post-default-sentinel): Likewise.
- (twittering-start-http-ssl-session): Adjust callers.
- (twittering-start-http-non-ssl-session): Likewise.
-
-2010-02-06 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-edit-post-status): Don't add
- parameter `in_reply_to_status_id' if the tweet does not begin
- with `@'.
- (twittering-update-status-from-minibuffer): Likewise.
-
- * twittering-mode.el (twittering-status-not-blank-p): Fix a regexp
- pattern for USER.
- (twittering-status-to-status-datum): Likewise.
- (twittering-http-get-list-index-sentinel): Change a regexp pattern
- for LISTNAME.
-
-2010-02-06 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-and-render-timeline): ignore
- non-interactive request if a process is waiting for responses.
-
- * twittering-mode.el (twittering-mode): set `buffer-read-only' to
- t explicitly.
- (twittering-render-timeline): bind `buffer-read-only' with `let*'
- locally.
-
-2010-02-05 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-update-status-from-pop-up-buffer):
- Use the current hashtag if set; same as
- `twittering-update-status-from-minibuffer'.
-
-2010-02-05 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-format-status): replace a lacked
- property by an empty string.
-
- * twittering-mode.el (twittering-get-status-from-http-response):
- use ATOM format instead of JSON format.
- (twittering-atom-xmltree-to-status-datum): new function for
- converting an entry of ATOM into a status alist.
- (twittering-atom-xmltree-to-status): new function for converting a
- XML tree of ATOM into a list of status alists.
- (twittering-json-to-status-datum): removed.
- (twittering-json-to-status): removed.
- (twittering-get-tweets): retrieve "search" timeline in ATOM format
- instead of JSON format.
- (twittering-get-and-render-timeline): remove dependence on
- `json.el'.
- (twittering-search): likewise.
-
-2010-02-04 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-status-to-status-datum): assign a
- retweet the ID issued when it is retweeted. `source-id', which is
- the ID of the original tweet, is also assigned to the retweet.
- (twittering-cache-status-datum): do not register multiple retweets
- referring the same tweet.
-
- * twittering-mode.el (twittering-http-get-default-sentinel): make
- a hash table for already retrieved IDs.
- (twittering-cache-status-datum): use a hash table of IDs to avoid
- registering redundant tweets.
-
- * twittering-mode.el (twittering-status-to-status-datum): fix
- lacked binding of `source-id' and `source-created-at'.
-
- * twittering-mode.el (twittering-cache-status-datum): register IDs
- with ID-TABLE when a tweet is added to DATA-VAR. This prevents
- duplicated tweets in one retrieval from being registered.
-
-2010-02-03 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-http-get-default-sentinel): sort
- `twittering-timeline-data' by ID.
-
-2010-02-03 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-status-to-status-datum): Don't
- rewrite `created-at' by a same name element in `retweeted_status'
- node.
-
-2010-02-02 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-get-response-body): Add an
- optional second argument to share code between this and
- `twittering-get-response-body-string'.
- (twittering-get-response-body-string): Delete function.
- (twittering-get-status-from-http-response): Adjust callers.
-
-2010-02-02 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-http-get-default-sentinel): use
- `twittering-get-status-from-http-response'.
- (twittering-get-status-from-http-response): new function for
- extracting statuses from HTTP response.
- (twittering-get-tweets): use
- `twittering-http-get-default-sentinel' for the "search" timeline
- spec.
- (twittering-http-get-search-sentinel): removed.
-
-2010-01-31 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-http-get-default-sentinel):
- rearranged.
-
- * twittering-mode.el (twittering-start-http-ssl-session): return
- the process object.
- (twittering-start-http-non-ssl-session): likewise.
- (twittering-get-tweets): likewise.
-
- * twittering-mode.el (twittering-process-info-alist): new variable
- for managing active process and timeline spec being retrieved by
- the process.
- (twittering-register-process): new function for registering a pair
- of process and timeline spec.
- (twittering-release-process): new function for releasing a process.
- (twittering-get-timeline-spec-from-process): new function for
- getting timeline spec retrieved by the given process.
- (twittering-http-get-default-sentinel): discard statuses if
- the retrieved spec differs from the last requested one.
- (twittering-get-and-render-timeline): register a pair of the
- requested timeline spec and process for retrieving it.
-
-2010-01-30 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-fill-string): use `frame-width'
- only if no windows display the `*twittering*' buffer.
-
- * twittering-mode.el (twittering-for-each-property-region): new
- function to process each region with a certain property.
-
- * twittering-mode.el (twittering-timer-for-redisplaying): new
- variable for timer of redisplaying statuses.
- (twittering-timer-interval-for-redisplaying): new variable
- specifying the interval of redisplaying statuses.
- (twittering-redisplay-status-on-buffer): new function to redisplay
- statuses on buffer.
- (twittering-format-status): append `need-to-be-update' property to
- the specifier "%@" and "%FILL{...}" including "%@".
- (twittering-start): start the timer of redisplaying statuses.
- (twittering-stop): stop the timer of redisplaying statuses.
-
- * twittering-mode.el (twittering-make-passed-time-string): new
- function to generate a string displayed as passed time of a
- status.
- (twittering-format-status): use
- `twittering-make-passed-time-string' for the specifier "%@".
-
-2010-01-29 Daiji Kanematsu <daijikNOSPAMgmail.com>
-
- * twittering-mode.el (toplevel): add `easy-menu-define' in order
- to add the menu `Twitter'.
-
-2010-01-29 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-fill-string): Add an extra
- argument to `min' for avoiding error "Wrong number of arguments:
- min, 0".
-
- * twittering-mode.el (twittering-extract-timeline-spec): On
- search-mode, return a spec only when the length of `escaped-query'
- is greater than zero.
-
-2010-01-28 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-render-timeline): simplified by
- using `insert-before-markers' instead of `insert'. This removes
- additional movement of points for scroll-mode.
-
-2010-01-26 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-status-to-status-datum): Add
- `original-user-name' and `original-user-screen-name' to return
- an alist; fix an incomplete merge on 2010-01-22.
- (twittering-json-to-status-datum): Likewise.
-
- * twittering-mode.el (twittering-json-to-status-datum): Use
- `retweeted-status-data' as variable instead of `retweeted-status';
- same as `twittering-status-to-status-datum'.
-
-2010-01-26 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (toplevel): Require 'unicode explicitly on
- Emacs21. See a comment of `twittering-ucs-to-char' for more
- details.
- (twittering-ucs-to-char): Check (featurep 'unicode) instead of
- (featurep 'mucs).
- (twittering-ucs-to-char): Update comment.
-
- * twittering-mode.el (toplevel): On Emacs21, always call
- `set-terminal-coding-system'.
-
-2010-01-25 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-format-status): Call
- `twittering-make-display-spec-for-icon' only when `window-system'
- is non-nil to avoid error "Non-X frame used" under Emacs which is
- using a text-only terminal.
-
-2010-01-25 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-extract-timeline-spec): add new
- timeline spec string for hashtag.
-
-2010-01-23 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-json-to-status-datum): Don't
- refer to `twittering-use-native-retweet'; same as
- `twittering-status-to-status-datum'.
-
-2010-01-23 Naohiro Aota <naotaNOSPAMelisp.net>
-
- * twittering-mode.el (twittering-home-timeline): Add new funciton.
-
-2010-01-23 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-fill-string): adjust
- `fill-column' to the minimum width of windows displaying
- `*twittering*' buffer. Thanks to Naohiro Aota.
-
- * twittering-mode.el (twittering-render-timeline): take account of
- multiple windows displaying `*twittering*' buffer.
- Thanks to Naohiro Aota.
-
- * twittering-mode.el (twittering-format-status): fix an incorrect
- index on filling text for the specifier "%t".
-
-2010-01-24 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-extract-timeline-spec): support
- functional alias.
-
-2010-01-23 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-timeline-spec-to-host-method):
- return query string as a element of returned list.
- (twittering-host-method-to-timeline-spec): receive query string as
- a optional argument.
- (twittering-http-get): remove special adjustment for search
- method, which is now unnecessary.
- (twittering-get-tweets): always receive query string as an
- argument for search method.
- (twittering-get-search): removed.
- (twittering-get-and-render-timeline): send query string if the
- given spec is `search'.
- (twittering-search): execute search via
- `twittering-get-and-render-timeline'.
-
- * twittering-mode.el (twittering-timeline-spec-to-string): modify
- the string format of `search' spec.
- (twittering-extract-timeline-spec): likewise.
-
-2010-01-22 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-initial-timeline-spec-string):
- Change value to ":home" from ":friends".
-
- * twittering-mode.el (twittering-status-to-status-datum): Don't
- refer to `twittering-use-native-retweet'.
-
- * twittering-mode.el (twittering-http-get-list-index-sentinel):
- Fix a reference to `mes' as a variable, not as a function.
-
-2010-01-22 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-fill-string): add new function
- for generating filled string.
- (twittering-format-status): use `twittering-fill-string'.
- (twittering-render-timeline): remove unnecessary binding of the
- variable `fill-column'.
-
-2010-01-22 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el: Add search support (which was originally
- written by Kensuke Matsuzaki in December 2009)
-
- * twittering-mode.el (twittering-json-to-status-datum): Add code
- for native retweets.
- (twittering-http-get-search-sentinel): Sync with HEAD.
- (twittering-get-response-body-string): Likewise.
-
- * twittering-mode.el (twittering-get-tweets): Rewrite to match
- this to the new-timeline spec.
- (twittering-get-search): Call `twittering-get-tweets' instead of
- `twittering-http-get'
- (twittering-search): Call `twittering-get-search' instead of
- `twittering-get-tweets'.
-
- * twittering-mode.el (twittering-timeline-spec-to-string): Add a
- condition for search-mode.
- (twittering-extract-timeline-spec): Likewise.
- (twittering-timeline-spec-to-host-method): Likewise.
- (twittering-host-method-to-timeline-spec): Likewise.
-
- * twittering-mode.el (twittering-http-get): Add an adjusting code.
- In search-mode, a `method' variable is now contains a query word
- for internal use. For this reason, we must adjust it before pass
- it into `twittering-start-http-session'.
-
-2010-01-21 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el: Add a fail statement to work again under
- Emacs21 without Mule-UCS.
- (toplevel): Don't abort if require failed.
- (twittering-ucs-to-char): Return `?' explicitly if `decode-char'
- failed.
-
- * twittering-mode.el (twittering-get-tweets): Rename from
- `twittering-get-twits'.
- (twittering-get-and-render-timeline): Adjust callers.
- (twittering-new-tweets-hook): Fix a docstring.
-
-2010-01-21 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-render-timeline): reduce
- redundant calls of `goto-char'.
-
- * twittering-mode.el (twittering-render-timeline): fix logic for
- inserting statuses not to duplicate the last status.
-
-2010-01-20 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-get-default-sentinel): Show
- the reason phrase with status code if status code is not equal to
- "200"; same as `twittering-http-post-default-sentinel'.
- (twittering-http-get-list-index-sentinel): Likewise.
-
- * twittering-mode.el (twittering-http-status-line-regexp): New
- defconst to share this between several functions. The regexp
- pattern to obey to RFC 2616.
- (twittering-http-get-default-sentinel): Use it.
- (twittering-http-post-default-sentinel): Likewise.
- (twittering-http-get-list-index-sentinel): Likewise.
-
- * twittering-mode.el (twittering-tinyurl-get): Remove an
- unnecessary call to `concat'.
-
- * twittering-mode.el (twittering-update-jojo): Make a tweet by
- `twittering-ucs-to-char' instead of `string-as-multibyte'.
-
-2010-01-19 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-first-status-head): add.
- (twittering-goto-first-status): add.
- (twittering-mode-map): bind `twittering-goto-first-status' to "H"
- instead of `begininng-of-buffer'.
- (twittering-render-timeline): use `twittering-goto-first-status'.
-
-2010-01-18 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-ucs-to-char): Add a workaround
- with navi2ch prior to 1.8.3, which is currently last release
- version as of 2010-01-18. The problem is fixed in navi2ch dated
- 2010-01-16 or later, but not released yet.
-
-2010-01-17 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-format-status): fix the regexp
- for the specifier "%FILL{...}" to accept pairs of braces inside of
- "{...}".
-
- * twittering-mode.el (twittering-format-status): add new format
- decorator "%FACE[face-name]{...}", which decorates braced strings
- with the specified face.
-
- * twittering-mode.el (twittering-render-timeline): support
- additional rendering.
- (twittering-http-get-default-sentinel): send the additional
- argument `same-timeline' to `twittering-render-timeline'.
- (twittering-status-id<): add new function for comparing two ids.
- (twittering-status-id=): likewise.
-
-2010-01-16 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-get-response-header): Delete an
- adjusting code bacause `with-current-buffer' that can accept both
- a buffer and a buffer name.
- (twittering-get-response-body): Likewise.
-
-2010-01-16 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-format-status): fix incorrect
- destructive modification of the replacement table for the
- specifier "%FILL{...}".
-
-2010-01-16 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-edit-setup-help): use 0-witdh
- overlay to display help.
- (twittering-edit-mode, twittering-edit-post-status): do not use
- newline chars for help-overlay anymore.
- (twittering-edit-post-status): probihit posting over 140 chars
- tweets.
-
-2010-01-15 Yuto Hayamizu <y.hayamizu@gmail.com>
-
- * twittering-mode.el: changed URL
-
-2010-01-15 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-edit-buffer): New defvar.
- (twittering-update-status-from-pop-up-buffer): Use it.
-
- * twittering-mode.el (twittering-buffer-active-p): New defun.
- (twittering-http-get-default-sentinel): Call it to show a
- non-critical message on minibuffer only when current buffer is
- twittering-mode related buffer.
- (twittering-http-post-default-sentinel): Likewise.
- (twittering-get-response-body): Likewise.
-
- * twittering-mode.el (twittering-buffer-active-p): Delete an
- unnecessary code which is added for keep a backward compatibility.
-
-2010-01-15 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-next-status-head): add a
- function finding the next head of status with `id' property. This
- replaces `twittering-get-next-username-face-pos'.
- (twittering-goto-next-status): use
- `twittering-get-next-status-head' instead of
- `twittering-get-next-username-face-pos'.
- (twittering-goto-next-status-of-user): likewise.
-
- * twittering-mode.el (twittering-get-previous-status-head): add a
- function finding the previous head of status with `id'
- property. This replaces
- `twittering-get-previous-username-face-pos'.
- (twittering-goto-previous-status): use
- `twittering-get-previous-status-head' instead of
- `twittering-get-previous-username-face-pos'.
- (twittering-goto-previous-status-of-user): likewise.
-
-2010-01-15 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-mode-identity): add. Identify
- 'twittering-mode.el' by $Id$ tag.
-
-2010-01-14 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-remove-duplicates): check
- availability of `delete-dups' by `fboundp' instead of
- `emacs-major-version'.
-
-2010-01-14 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-format-status): add docstring
-
-2010-01-15 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-update-status-function): add
- (twittering-update-status-from-pop-up-buffer): renamed from
- twittering-edit-status
- (twittering-update-status-interactive, twittering-enter)
- (twittering-organic-retweet, twittering-direct-message): use
- twittering-update-status-function
- (twittering-mode-map): bind 'u' to
- twittering-update-status-interactive
-
-2010-01-13 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-format-string): fix the search of
- the key string following the prefix from a string including
- newlines.
-
- * twittering-mode.el (twittering-format-status): remove a
- newline as a separator of tweets.
- (twittering-render-timeline): insert a newline as a separator of
- tweets.
-
- * twittering-mode.el (twittering-format-status): add new format
- specifier "%T", which is converted to the raw text.
-
- * twittering-mode.el (twittering-format-status): add new format
- specifier "%FILL{...}", which applies `fill-region-as-paragraph'
- to the strings in braces.
-
- * twittering-mode.el (twittering-status-format): use '%FILL{...}'
- and '%T' for the default value instead of '%t'.
-
-2010-01-12 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * test/run-test.sh (exit_status): add 'emacs' command to test
- target emacsen
-
-2010-01-12 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-format-status): fill the text
- with strings following "%t".
-
-2010-01-12 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * test/test-twittering-mode.el (test-icon-mode): removed use of
- twittering-tmp-dir
-
-2010-01-12 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-start-http-session): Call
- `twittering-find-curl-program' only when `twittering-use-ssl' is
- non-nil.
-
- * twittering-mode.el (twittering-wget-buffer): Delete function.
- (twittering-wget-buffer): Delete variable.
-
-2010-01-11 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-convert-program): initialize
- without confirming whether `convert' comes from ImageMagick.
- (twittering-mode-init-variables): confirm whether the found
- `convert' is a part of ImageMagick or GraphicsMagick if
- `twittering-use-convert' is non-nil. If the program does not come
- from ImageMagick or GraphicsMagick, `twittering-use-convert' is
- changed into nil.
-
-2010-01-10 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-convert-program): checks whether
- 'convert' is a part of ImageMagick. Windows XP has 'convert.exe'
- in WINDOWS/system32, which is a partition converter.
- (twittering-use-convert): use the value of
- twittering-convert-program
-
-2010-01-11 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-status-format): modify the
- meaning of the specifier "%t" to remove implicit filling as a
- paragraph.
- (twittering-render-timeline): remove implicit filling a text as a
- paragraph. In addition, a newline as a delimiter is added by
- `twittering-format-status'.
- (twittering-format-status): with "%t", fill a text as a paragraph.
- This function adds a newline at the end of status instead of
- `twittering-render-timeline'. Then, the newline as a delimiter
- also has the same text properties as the body of the tweet.
-
-2010-01-10 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-remove-duplicates): add for
- portability.
- (twittering-completing-read): add a modified version of
- `completing-read' that can accept candidates as a list of a string
- on Emacs21.
- (twittering-set-current-hashtag): use `twittering-completing-read'
- instead of `completing-read'.
- (twittering-read-username-with-completion): likewise.
- (twittering-read-list-name): likewise.
- (twittering-read-timeline-spec-with-completion): likewise.
-
-2010-01-10 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * test/test-twittering-mode.el (test-status-not-blank-p): add a
- testcase reproducing the bug of twittering-status-not-blank-p.
-
- * twittering-mode.el (twittering-use-native-retweet): renamed from
- twittering-use-native-retweets
- (twittering-status-not-blank-p): bug fix: return nil if a status
- is ended by '@foo'.
-
- * twittering-mode.el (twittering-edit-post-status): add trailing
- newlines to new history element because help-overlay need it.
-
- * twittering-mode.el (twittering-make-display-spec-for-icon):
- returns nil if the type of the image is not supported.
-
-2010-01-09 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-status-to-status-datum): Change
- retweet related variables to local scope from global one.
-
- * twittering-mode.el (twittering-extract-timeline-spec): Change
- syntax of error message to fit the GNU Emacs Lisp convention.
- (twittering-timeline-spec-to-host-method): Likewise.
- (twittering-get-and-render-timeline): Likewise.
-
- * twittering-mode.el (twittering-extract-timeline-spec): Remove an
- unnecessary call to `format' because all arguments of `error' pass
- to `format'.
- (twittering-timeline-spec-to-host-method): Likewise.
- (twittering-get-and-render-timeline): Likewise.
-
- * twittering-mode.el (twittering-read-username-with-completion):
- Convert a list of username strings to an alist before calling
- `completing-read' to work on Emacs21; same as
- `twittering-read-timeline-spec-with-completion'.
-
- * twittering-mode.el (twittering-icon-path): Delete function.
-
-2010-01-09 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-edit-mode): setup
- twittering-warning-overlay and after-change-functions
- (twittering-edit-length-check): add. check length and set warning
- overlay if the length exceeds 140 chars.
- (twittering-edit-mode-map): fix keymap
- (twittering-edit-extract-status): add. extract status from pop-up
- buffer by removing trailing whitespace chars.
- (twittering-edit-post-status): use edit-extract-status.
- (twittering-edit-status): takes reply-to-id as a second argument
- (twittering-enter, twittering-organic-retweet)
- (twittering-direct-message, twittering-reply-to-user): use
- twittering-edit-status
- (twittering-edit-post-status): bug fix.
-
-2010-01-09 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-http-get-list-index-sentinel):
- `save-excursion' had no effect because of the following
- `set-buffer'. This is fixed so that `save-excursion' saves the
- state of `temp-buffer'.
- (twittering-get-response-header): Likewise.
- (twittering-get-response-body): Likewise.
- (twittering-tinyurl-get): Likewise.
- (twittering-tinyurl-get): `buffer' are killed even if
- `search-forward-regexp' fails.
-
-2010-01-09 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-edit-setup-help): add to setup
- help overlay in pop-up buffer
- (twittering-edit-next-history, twittering-edit-previous-history):
- use twittering-edit-setup-help
-
-2010-01-08 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-percent-encode): bug fix:
- '\n','\r','\t' were not encoded correctly.
-
-2010-01-08 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-use-show-minibuffer-length): Add
- suggestion into a docstring.
-
-2010-01-08 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-status-not-blank-p): bug fix:
- always return nil with strings with trailing newline.
- (twittering-edit-next-history): add.
- (twittering-edit-previous-history, twittering-edit-history): add
- history for pop-up buffer
- (twittering-edit-mode-map): defined key for next/previous-history
- (twittering-edit-mode): initialize local variables for history
- (twittering-edit-mode): setup help string overlay
- (twittering-edit-post-status): don't close buffer if tweet is
- empty
-
-2010-01-08 Tadashi MATSUO <tad@mymail.twin.jp>
-
- * twittering-mode.el (twittering-image-type): Try to detect image
- type with `image-type-from-data' at first.
- (twittering-retrieve-image): Do not invoke `convert' if Emacs
- supports the image type and resize is not required.
-
-2010-01-08 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-tmp-dir): delete
- (twittering-icon-mode): don't make temp dir
- (twittering-image-data-table): add. hash table where image data
- are stored. key:(<url> . <size>),value:(<type> . <binary-data>)
- (twittering-use-wget): delete
- (twittering-image-type): re-implemented. Now it just returns a
- type of a given image.
- (twittering-make-display-spec-for-icon): Now it receives image URL
- as an argument.
- (twittering-retrieve-image): Now it receives image URL as an
- argument.
- (twittering-url-copy-file-async): delete
- (twittering-retrieve-image-without-wget): delete
- (twittering-retrieve-image-with-wget): delete
- (twittering-retrieve-image): changed default image type from png
- to xpm
- (twittering-image-type): bug fix in the case of bitmap
- (twittering-retrieve-image): handle error of determining image
- type.
- (twittering-image-type): let case-fold-search is t.
-
- * url-emacs21/*: add url library for emacs21
-
-2010-01-07 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-url-reserved-p): bug fix: some
- reserved characters considered unreserved. Thanks to IMAI
- Toshiyuki
- (twittering-cert-file): add
- (twittering-ensure-ca-cert): generate temporary file for CA certificate
-
-2010-01-06 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-get-default-sentinel): Move
- `debug-printf' to outside of `unwind-protect' because we expect
- that mostly code of this function should be executed by way of
- BODYFORM of `unwind-protect', not UNWINDFORM.
- (twittering-http-post-default-sentinel): Likewise.
-
- * twittering-mode.el (twittering-http-get-list-index-sentinel): Add
- `debug-printf' same as `twittering-http-get-default-sentinel'.
-
- * twittering-mode.el (twittering-status-not-blank-p): Fix and
- modify a regexp pattern.
-
-2010-01-06 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el
- (twittering-read-timeline-spec-with-completion): return nil for
- an invalid timeline spec string. The function is unified with
- `twittering-read-timeline-spec-string-with-completion'. If the
- argument `as-string' is non-nil, it returns a spec string.
- (twittering-update-mode-line): the delimiter followed by a
- timeline spec string on mode-line is changed to a whitespace.
- (twittering-timeline-spec-bookmark): new variable for timeline
- spec bookmark.
- (twittering-extract-timeline-spec): support timeline spec
- bookmark.
- (twittering-equal-string-as-timeline): add.
- (twittering-get-and-render-timeline): accept a timeline spec
- string as well as a S-expression.
- `twittering-last-requested-timeline-spec' will be updated even if
- the requested spec essentially equals to the current one.
- (twittering-initial-timeline-spec): replaced by
- `twittering-initial-timeline-spec-string'.
- (twittering-last-requested-timeline-spec): replaced by
- `twittering-last-requested-timeline-spec-string'.
- (twittering-last-retrieved-timeline-spec): replaced by
- `twittering-last-retrieved-timeline-spec-string'.
- (twittering-initial-timeline-spec-string): added to replace
- `twittering-initial-timeline-spec'.
- (twittering-last-requested-timeline-spec-string): added to replace
- `twittering-last-requested-timeline-spec'.
- (twittering-last-retrieved-timeline-spec-string): added to replace
- `twittering-last-retrieved-timeline-spec'.
- (twittering-last-timeline-spec-string): removed.
- (twittering-visit-timeline): call
- `twittering-get-and-render-timeline' with a timeline spec string
- just as it has been input by the user.
- (twittering-extract-timeline-spec): `bookmark' is renamed `alias'.
- (twittering-timeline-spec-alias): this variable replaces
- `twittering-timeline-spec-bookmark'.
-
- * test/test-twittering-mode.el (timeline-spec): add tests of
- timeline spec normalization.
-
-2010-01-04 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-get-response-header): Change
- syntax of error message to fit the GNU Emacs Lisp convention.
- (twittering-get-response-body): Likewise.
- (twittering-tinyurl-get): Likewise.
-
- * twittering-mode.el (twittering-start-http-session): Change
- syntax of question message to fit the GNU Emacs Lisp convention.
-
- * twittering-mode.el (twittering-user-agent-default-function): Use
- `format' instead of `concat' to easy understand.
- (twittering-sign-string-default-function): Likewise.
-
- * twittering-mode.el (twittering-start-http-session): Remove an
- unnecessary call to `format' because all arguments of `error' pass
- to `format'.
- (twittering-make-http-request): Likewise.
- (twittering-url-copy-file-async): Likewise.
-
-2010-01-04 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-last-requested-timeline-spec):
- new variable storing the last requested timeline spec.
- (twittering-last-retrieved-timeline-spec): new variable storing
- the last successfully retrieved timeline spec.
- (twittering-last-timeline-retrieved): removed.
- (twittering-last-host): removed.
- (twittering-last-method): removed.
- (twittering-convert-last-timeline-retrieved): removed.
- (twittering-last-timeline-spec): removed.
- (twittering-get-twits): do not update the information of the last
- request.
- (twittering-get-and-render-timeline): update the information of
- the last request instead of `twittering-get-twits'.
- (twittering-current-timeline): replace `twittering-get-twits' by
- `twittering-get-and-render-timeline'.
- (twittering-erase-old-statuses): replace `twittering-get-twits' by
- `twittering-get-and-render-timeline'.
- (twittering-initial-timeline-spec): new variable.
-
-2010-01-03 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el, test/test-twittering-mode.el: rebase the
- `timeline-spec' branch. The new timeline spec based on
- S-expression is introduced.
-
- * twittering-mode.el (twittering-timeline-spec-to-string): add.
- (twittering-extract-timeline-spec): add.
- (twittering-string-to-timeline-spec): add.
- (twittering-timeline-spec-singlep): add.
- (twittering-timeline-spec-to-host-method): add.
- (twittering-host-method-to-timeline-spec): add.
- (twittering-last-timeline-spec): add.
- (twittering-last-timeline-spec-string)
- (twittering-add-timeline-history): modified for new timeline spec.
- (twittering-update-mode-line): modified for new timeline spec.
- (twittering-get-twits-with-timeline-spec): modified for new
- timeline spec.
- (twittering-read-timeline-spec-string-with-completion): add.
- (twittering-read-timeline-spec-with-completion): modified for new
- timeline spec.
- (twittering-get-timeline, twittering-get-list): replaced with
- `twittering-get-twits-with-timeline-spec'.
- (twittering-get-and-render-timeline): renamed from
- `twittering-get-twits-with-timeline-spec'.
-
- * test/test-twittering-mode.el (timeline-spec): add tests for new
- timeline spec.
-
-2010-01-03 Michael D. Ivey <iveyNOSPAMgweezlebur.com>
-
- * twittering-mode.el (twittering-retweet): Add support for native
- retweets
-
-2010-01-03 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-tinyurl-get): more descriptive
- error message
- (twittering-url-copy-file-async): more descriptive error message
-
-2010-01-02 Alberto Garcia <agarciaNOSPAMigalia.com>
-
- * twittering-mode.el (twittering-start-http-ssl-session):
- Set noninteractive using lexical-let so the HTTP sentinel can
- receive its value and `twittering-new-tweets-hook' works
- correctly.
-
-2010-01-02 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-use-show-minibuffer-length): New
- defvar to enable/disable a function which is show the number of
- charactors in minibuffer.
- (twittering-update-status-from-minibuffer): Refer it to add/remove
- hooks.
-
-2009-12-30 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * test/server.rb: add. Twitter API and Proxy mock server
-
- * twittering-mode.el (twittering-get-response-header)
- (twittering-get-response-body): Raise an error on broken
- responses.
-
-2009-12-30 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-get-response-header): On failure,
- the function returns an empty string instead of the whole contents
- of the buffer.
- (twittering-get-response-body): When the function fails to find
- the tail of header, it returns nil without trying to parse a
- region.
- (twittering-find-proxy): add new function for
- finding proxy.
- (twittering-setup-proxy): add new function for configuring
- `twittering-proxy-server' and `twittering-proxy-port' if they have
- not been configured yet.
- (twittering-mode-init-variables): invokes
- `twittering-setup-proxy'.
-
-2009-12-30 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-get-response-header): Correct a
- reference to an unbound object. This problem was found by highmt.
-
-2009-12-30 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * test/el-test-runner.el (with-network): add macro. body of
- with-network is executed only when 'NETWORK' env var is set.
- * twittering-mode.el (twittering-image-type): No temporary files
- for resing images. Use standard in/out and temporary buffers
- instead.
- (twittering-convert-fix-size): set 48px as the default size of
- icon images.
-
-2009-12-30 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-image-type): Don't generate
- redundant temporary files. The image format is specified by
- the command line instead of a file extension.
-
-2009-12-30 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-image-type): Don't set a third
- argument of `make-temp-file' to work on Emacs21.
-
-2009-12-29 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-get-response-header): Add an
- optional third argument for `search-forward-regexp'.
-
-2009-12-29 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode 0.9.0 release
-
- * twittering-mode.el (twittering-start-http-session): check if
- curl can use https or not.
- (twittering-get-response-body): bug fix: goto the beginning of
- buffer before search-forward. 'xml-parse-region' doesn't return
- when parsing unbalanced XML.
- (twittering-start-http-session): Use call-process instead of
- shell-command-to-string. If 'curl-program' contains space
- characters, shell-command fails.
-
-2009-12-29 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-get-response-body): Return nil
- explicitly when a broken XML data passed into `xml-parse-region'.
- (twittering-http-get-default-sentinel): Adjust callers.
- (twittering-http-post-default-sentinel): Likewise.
-
- * twittering-mode.el (twittering-http-post-default-sentinel): Add
- `debug-printf' same as `twittering-http-get-default-sentinel'.
-
- * twittering-mode.el (twittering-http-post-default-sentinel):
- Change a regexp pattern for HTTP response status line; same as
- `twittering-http-get-default-sentinel'.
- (twittering-http-get-list-index-sentinel): Likewise.
-
-2009-12-29 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el: load mule-ucs if needed (emacs21)
- (twittering-start-http-ssl-session): add 'Expect: ' header field
- for avoiding '417 Expectation Failed' HTTP response error. See
- http://d.hatena.ne.jp/imait/20091228/1262004813 and
- http://www.escafrace.co.jp/blog/09/10/16/1008
-
- * twittering-mode.el: load 'cl' only at compile
- time. cf. http://www.gnu.org/software/emacs/manual/html_node/cl/Overview.html
-
-2009-12-28 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-get-response-header)
- (twittering-get-response-body): inefficient code were
- replaced. thanks to Tadashi MATSUO
-
-2009-12-27 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-show-minibuffer-length): keeps
- activated mark from being forcefully deactivated.
-
-2009-12-27 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * test/run-test.sh: add. invoke unit test for each emacsen
-
- * Makefile (check): add check rule.
-
- * test/el-test-runner.el (twittering-run-test): exit with
- appropriate status code.
-
- * test.el (test-transform-body): add. transforms the body of
- `defcase' recursively
- (defcase): use `test-transform-body'
-
- * test/run-test.el (twittering-run-test): colorize resulting
- outputs
-
-2009-12-27 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-http-post-default-sentinel):
- Check if buffer live-p before killing it.
- (twittering-http-get-list-index-sentinel): Likewise.
-
- * twittering-mode.el (twittering-setup-minibuffer): Remove an
- unnecessary call.
-
- * twittering-mode.el (twittering-other-user-list-interactive): Fix
- condition to detect a cancel.
-
- * twittering-mode.el (twittering-http-get-list-index-sentinel):
- Use `search-forward-regexp' instead of `search-forward' to fix a
- meaningless search.
-
-2009-12-26 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-format-string): reimplement
- without `block'.
- (twittering-format-string): invokes a function in replacement
- table with a context alist.
- (twittering-retweet): replacement table is adapted to the new
- `twittering-format-string'.
- (twittering-format-status): reimplement with
- `twittering-format-string'.
-
-2009-12-26 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-ensure-ca-cert): kludge for ssl
- certificate problem.
- (twittering-start-http-ssl-session): use
- `twittering-ensure-ca-cert'
-
-2009-12-25 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-show-minibuffer-length): Replace
- `minibufferp' by `minibuffer-window-active-p' to work this on
- Emacs21.
- (twittering-show-minibuffer-length): Change a message style for
- Emacs23.
- (twittering-setup-minibuffer, twittering-finish-minibuffer): Hook
- `post-command-hook' instead of `after-change-functions' to work in
- cooperation with SKK.
-
-2009-12-25 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-tinyurl-get): Fix typo to resolve
- error "Symbol's value as variable is void". This problem was found
- by naota.
-
-2009-12-25 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-show-minibuffer-length): disabled
- on Emacs21 because `minibufferp' is not available.
- (twittering-update-status-from-minibuffer): set
- `minibuffer-message-timeout' to `nil'. `t' causes error on
- Emacs23.
-
-2009-12-23 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-show-minibuffer-length): New
- defun to show the number of charactors in minibuffer.
- (twittering-setup-minibuffer): New defun to add it to
- `after-change-functions'; invoke via `minibuffer-setup-hook'.
- (twittering-finish-minibuffer): New defun to remove it from
- `after-change-functions'; invoke via `minibuffer-exit-hook'.
-
- * twittering-mode.el (twittering-update-status-from-minibuffer):
- Set `minibuffer-setup-hook' and `minibuffer-exit-hook' temporarily.
-
-2009-12-23 Yuto Hayamizu <y.hayamizu@gmail.com>
-
- * test/test-twittering-mode.el (tinyurl): add test for tinyurl
-
- * twittering-mode.el (twittering-tinyurl-get): fix for emacs22.
- In emacs22, there's "^M" at the end of a buffer created by
- url-retrieve
- (twittering-tinyurl-get): fix by cvmat
-
- * twittering-mode.el (twittering-edit-mode-map): keybind 'u' to
- twittering-edit-status. F4 to tinyurl
-
-2009-12-22 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-tinyurl-get): retrieves a
- shortened URL without `url-insert'.
- (twittering-url-copy-file-async): add new
- function for downloading a file asynchronously.
- (twittering-retrieve-image-without-wget): retrieves images
- asynchronously with `twittering-url-copy-file-async'.
-
-2009-12-22 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-ucs-to-char): turned into
- function from macro
- (twittering-update-lambda, twittering-update-jojo): more portable
- string expression. Executable only in Japanese environment.
- (twittering-tinyurl-get): use with-temp-buffer with url-insert
-
-2009-12-21 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-icon-path): `require' is added.
- (twittering-tinyurl-get, twittering-retrieve-image-without-wget):
- The dependency on `mm-url' is removed by using `url' library.
- (twittering-http-application-headers):
- `Content-Length' is added to `headers'.
-
-2009-12-22 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-get-host-method-from-timeline-spec)
- (twittering-get-timeline-spec): Add more timeline specification.
-
- * test/test-twittering-mode.el (timeline-spec): add more tests for
- timeline specification.
-
-2009-12-20 Tadashi Matsuo <tadNOSPAMmymail.twin.jp>
-
- * test/test-twittering-mode.el (timeline-spec): add tests for
- timeline specification.
- * twittering-mode.el (twittering-get-host-method-from-timeline-spec)
- (twittering-get-timeline-spec): Add new functions for timeline
- specification.
- (twittering-update-mode-line): Shows timeline specification.
- (twittering-render-timeline): Invokes
- `twittering-update-mode-line' to update the mode-line.
- (twittering-timeline-history): Add new variable for history of
- timeline specifications.
- (twittering-add-timeline-history): Add new function for adding
- timeline history.
- (twittering-http-get-default-sentinel): Invokes
- `twittering-add-timeline-history' to update history when
- retrieving tweets successfully.
- (twittering-other-user-list-interactive): The codes for retrieving
- list index synchronously are extracted as the new function
- `twittering-get-list-sync'.
- (twittering-get-list-index-sync): Add new function for retrieving
- list synchronously.
- (twittering-read-list-name): Add new function for reading a list
- name from the minibuffer.
- (twittering-read-timeline-spec-with-completion): Add new function
- for reading timeline specification from the minibuffer.
- (twittering-get-twits-with-timeline-spec): Add new function for
- retrieving tweets with timeline specification.
- (twittering-visit-timeline): Add new function for visiting a
- timeline.
- (twittering-mode-map): The key "V" is bound to
- 'twittering-visit-timeline'.
-
-2009-12-20 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-update-mode-line): add
- (twittering-toggle-proxy, twittering-icon-mode)
- (twittering-scroll-mode, twittering-jojo-mode): use
- update-mode-line
-
-2009-12-19 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-use-ssl): add
- (twittering-find-curl-program): add
- (twittering-start-http-ssl-session): add
- (twittering-start-http-non-ssl-session): add
- (twittering-http-application-headers): add
- (twittering-http-get): rewritten by using start-http-session
- (twittering-http-post): rewritten by using start-http-session
- (twittering-http-post-default-sentinel): use the same argument
- format of http-get-default-sentinel
-
-2009-12-16 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-tinyurl-replace-at-point):
- distinguish between URL and others based on
- `bounds-of-thing-at-point'.
-
-2009-12-15 haya <hayaNOSPAMstarfish.unicus.ddo.jp>
-
- * twittering-mode.el (twittering-status-not-blank-p): fix invalid escape sequence
- (twittering-tinyurl-replace-at-point): disabled when 'mm-url' doesn't exist.
-
-2009-12-12 Alberto Garcia <agarciaNOSPAMigalia.com>
-
- * twittering-mode.el (twittering-retrieve-image-without-wget):
- Kill buffer after retrieving the image
-
-2009-12-11 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-tinyurl-get): Call
- `mm-url-insert' only if argument `longurl' is non-nil to avoid
- error "Wrong type argument", otherwise return nil explicitly.
- (twittering-tinyurl-replace-at-point): Replace a region with
- newurl when `newurl' is non-nil.
-
-2009-12-07 Naohiro Aota <naotaNOSPAMelisp.net>
-
- * twittering-mode.el (twittering-http-get-default-sentinel): Check
- if buffer live-p before killing it.
-
-2009-12-07 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-read-username-with-completion):
- rename from `twittering-get-username-with-completion'
- (twittering-make-list-from-assoc): simplified
- (twittering-other-user-timeline-interactive): changed init string
- to nil
-
-2009-12-06 NAKAYA Toshiharu <toshiharu.nakayaNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-retrieve-image-without-wget): set
- require-final-newline is nil locally since emacs can not save icon
- images because of "error in process filter: save-buffer: Text is
- read-only".
-
-2009-12-06 Tadashi MATSUO <matsuoNOSPAMi.ci.ritsumei.ac.jp>
-
- * twittering-mode.el (twittering-use-wget): new variable for
- specifying whether the external command `wget' should be used.
- (twittering-retrieve-image): new function for retrieving icon
- images with/without wget.
- (twittering-get-twits): retrieve images with
- `twittering-retrieve-image'.
- (twittering-use-convert): add a new variable specifying whether
- the external command `convert' should be used.
- (twittering-make-display-spec-for-icon): new function for
- generating properties for icon with/without cropping the image.
- (twittering-retrieve-image-without-wget): write an image as binary
- explicitly.
-
-2009-12-05 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-get-username-with-completion):
- New defun as a wrapper function for read-from-minibuffer.
- (twittering-follow): Call it instead of read-from-minibuffer.
- (twittering-other-user-timeline-interactive): Likewise.
- (twittering-other-user-list-interactive): Likewise.
-
- * twittering-mode.el (twittering-make-list-from-assoc): New defun.
-
-2009-12-04 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * test/test-twittering-mode.el (sign-string): add test
-
- * twittering-mode.el (twittering-current-hashtag): docstring
- (twittering-idle-time): removed (unused?)
-
-2009-12-03 Tadasohi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-mode-map): define bindings so
- as to be also valid even on non-window terminal.
-
-2009-12-02 Naohiro Aota <naotaNOSPAMelisp.net>
-
- * twittering-mode.el (twittering-icon-path): New funciton.
- (twittering-format-status): Use it.
- (twittering-get-twits): Ditto; wget now invoked for each icon.
-
-2009-12-01 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-update-status-from-minibuffer):
- Add more strict length check for status.
-
- * twittering-mode.el (twittering-status-not-blank-p): New defun to
- separate a check code from twittering-update-status-if-not-blank.
- (twittering-update-status-from-minibuffer): Integrate a post code
- from twittering-update-status-if-not-blank.
- (twittering-update-status-if-not-blank): Remove.
-
-2009-11-30 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-max-number-of-tweets-on-retrieval)
- (twittering-number-of-tweets-on-retrieval): add
- (twittering-http-get-list-index-sentinel): restore the variable
- 'indexes' removed by mistake
- (twittering-get-twits): use 'twittering-number-of-tweets-on-retrieval'
- These changes were made by cvmat. thanks.
-
-2009-11-29 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-status-to-status-datum): defined
- screen-name-in-text property
- (twittering-enter)
- (twittering-other-user-timeline-interactive)
- (twittering-other-user-timeline):
- put a screen-name-in-text ahead of other elements(uri, ...)
-
-2009-11-28 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * test/run-test.el (twittering-run-test): use test.el
-
- * twittering-mode.el (twittering-http-get, twittering-http-post):
- use a temp-buffer for each connection. This change solved the
- problem caused by concurrent HTTP request.
- (twittering-get-response-header, twittering-get-response-body):
- requires 'buffer' because now each http request is associated with
- its temp buffer
- (twittering-http-buffer): removed
-
-2009-11-19 Tadashi MATSUO <tadNOSPAMmymail.twin.jp>
-
- * twittering-mode.el (twittering-format-string): Add new function
- to format strings with a user-defined table.
- (twittering-retweet): Use 'twittering-format-string'.
-
-2009-11-18 Alberto Garcia <agarciaNOSPAMigalia.com>
-
- * twittering-mode.el
- (+twittering-direct-message, twittering-mode-map):
- New `twittering-direct-message' function to send direct messages.
-
-2009-11-15 Naohiro Aota <naotaNOSPAMelisp.net>
-
- * twittering-mode.el (twittering-convert-fix-size): New variable.
- (twittering-image-type): Use it; Resize icons to fix size if the
- above variable is set.
-
-2009-11-15 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * test/test-twittering-mode.el, test/run-test.el, test/elunit.el: add unit testing framework elunit.
-
- * twittering-mode.el (twittering-goto-next-thing,
- (twittering-goto-previous-thing): add new commands.
- (twittering-goto-previous-status): check whether prev-pos is not nil.
- (twittering-set-current-hashtag, twittering-hashtag-history): add functions to support hashtag. Set the current hashtag with C-c C-h.
- (twittering-update-status-from-minibuffer): use the current hashtag if set.
-
-2009-11-13 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-convert-last-timeline-retrieved):
- New defun to keep a backward compatibility.
- (twittering-last-host, twittering-last-method): Call it.
-
-2009-11-10 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-follow): New command.
- (twittering-unfollow): Likewise.
- (twittering-manage-friendships): New defun.
-
- * twittering-mode.el (twittering-favorite): New command.
- (twittering-unfavorite): Likewise.
- (twittering-manage-favorites): New defun.
-
-2009-11-09 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-mode-map): Bind "L" to
- `twittering-other-user-list-interactive'.
-
- * twittering-mode.el (twittering-other-user-list-interactive): Set
- default username interactively.
- (twittering-other-user-list-interactive): Fix typo.
-
- * twittering-mode.el (twittering-make-http-request): Use let
- instead of let*.
-
-2009-11-07 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el: Add (preliminary) Lists support.
-
- * twittering-mode.el (twittering-other-user-list-interactive): New
- command.
-
- * twittering-mode.el (twittering-get-list): New defun.
- (twittering-get-list-index): Likewise.
- (twittering-http-get-list-index-sentinel): Likewise.
-
- * twittering-mode.el (twittering-last-timeline-retrieved): Now it
- expects a list, not a string.
- (twittering-last-host, twittering-last-method): New defuns.
- (twittering-list-index-retrieved): New defvar.
-
- * twittering-mode.el (twittering-get-twits): Rename from
- twittering-get-timeline.
- (twittering-get-timeline): Call twittering-get-twits instead
- of (previous) twittering-get-timeline.
- (twittering-current-timeline): Likewise.
- (twittering-erase-old-statuses): Likewise.
- (twittering-goto-next-status): Likewise.
-
- * twittering-mode.el (twittering-make-http-request): New defun.
- (twittering-http-get): Use it.
- (twittering-http-post): Likewise.
-
- * twittering-mode.el (twittering-http-get): Add new local variable
- `server' which point to "twitter.com", "api.twitter.com", or your
- nearest proxy server. Otherwise `host' always point to
- "twitter.com" or "api.twitter.com".
- (twittering-http-post): Likewise.
-
- * twittering-mode.el (twittering-http-post): Add new argument
- `host'.
- (twittering-http-post): Change handling of the argument
- `method'. Now it expects `(concat method-class "/" method)'.
-
- * twittering-mode.el (twittering-update-status-if-not-blank):
- Adjust for change to twittering-http-post.
- (twittering-update-lambda): Likewise.
- (twittering-update-jojo): Likewise.
-
- * twittering-mode.el (twittering-get-twits): Set parameter `count'
- from twittering-get-count if existing.
-
-2009-11-06 Naohiro Aota <naotaNOSPAMelisp.net>
-
- * twittering-mode.el (twittering-image-type): Support bitmap type
- using `convert'.
- (twittering-convert-program): New varibale.
-
-2009-11-05 Satoshi Yatagawa <yata_githubNOSPAMy.hauN.org>
-
- * twittering-mode.el (twittering-render-timeline): Set the
- `fill-column' locally.
-
-2009-09-01 Alberto Garcia <agarciaNOSPAMigalia.com>
-
- * twittering-mode.el (twittering-retweet):
- Don't set the original status ID when retweeting.
-
-2009-08-23 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-keybind-message): add. displaying important keybindings in minibuffer
-
-2009-08-22 Yuto Hayamizu <y.hayamizuNOSPAMgmail.com>
-
- * twittering-mode.el (twittering-get-username): add
- (twittering-get-password): changed prompt
- (twittering-status-to-status-datum): added a new text property 'uri-in-text'
- (twittering-enter): use 'uri-in-text'
-
-2009-08-19 Alberto Garcia <agarciaNOSPAMigalia.com>
-
- * twittering-mode.el
- (twittering-image-type):
- Use external 'file' program if available to detect image types,
- and store the results in memory to avoid having to call it once
- and again.
- (twittering-format-status):
- Pass full image path to `twittering-image-type'
-
-2009-06-18 Alberto Garcia <agarciaNOSPAMigalia.com>
-
- * twittering-mode.el (twittering-http-get)
- (twittering-http-get-default-sentinel)
- (twittering-get-timeline, twittering-mode-map)
- (twittering-current-timeline-noninteractive)
- (twittering-current-timeline, twittering-erase-old-statuses):
- Get rid of the `twittering-last-timeline-interactive' global
- variable.
-
-2009-06-18 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el (twittering-sign-simple-string)
- (twittering-sign-string-default-function)
- (twittering-sign-string-function, twittering-sign-string): Add
- new.
- (twittering-update-status-if-not-blank): Fix params, support sign.
-
-2009-06-18 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el (twittering-mode-map)
- (twittering-format-status, twittering-retweet): Add new feature
- ReTweet
-
-2009-06-18 Alberto Garcia <agarciaNOSPAMigalia.com>
-
- * twittering-mode.el
- (twittering-status-to-status-datum):
- Read 'in_reply_to_status_id' and 'in_reply_to_user_id' attributes.
- (twittering-format-status):
- Add new '%r' format string for " in reply to user".
- (twittering-update-status-if-not-blank):
- Code refactoring. No need to use (format) to convert a string.
-
-2009-06-18 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el (twittering-status-format)
- (twittering-format-status, twittering-status-to-status-datum)
- (twittering-update-status-if-not-blank, twittering-enter): Fix
- in_reply_to_status_id support not work problem, and marge Alberl
- patch below.
-
-2009-06-17 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el (twittering-last-timeline-interactive): New
- add variable.
- (twittering-new-tweets-count): Ditto.
- (twittering-new-tweets-hook): Ditto.
- (twittering-mode-map): Add new binding v/V
- (twittering-http-get-default-sentinel): Add new hook support
- `twittering-new-tweets-hook'.
- (twittering-render-timeline, twittering-get-timeline): Support
- console emacs.
- (twittering-current-timeline-interactive): Add new function.
- (twittering-current-timeline-noninteractive): Ditto.
- (twittering-other-user-timeline): Ditto.
- (twittering-other-user-timeline-interactive): Ditto.
- (twittering-status-to-status-datum): Add support status id and
- reply to id.
- (twittering-update-status-if-not-blank): Ditto.
- (twittering-update-status-from-minibuffer): Ditto.
-
-2009-03-12 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el (twittering-start): Update target chagne to
- current.
-
-2009-03-12 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el: Append new methods by Alberto Garcia
- <agarciaNOSPAMigalia.com>'s patch.
- (twittering-get-timeline): Add new general method. Old name is
- `twittering-friends-timeline'.
- (twittering-friends-timeline): Renew use general method.
- (twittering-replies-timeline): Add new.
- (twittering-public-timeline): Ditto.
- (twittering-user-timeline): Ditto.
- (twittering-current-timeline): Ditto.
- (twittering-last-timeline-retrieved): Add new variable.
- (twittering-mode-map): Add new key binding.
- (twittering-erase-old-statuses): Support multi method.
-
- (twittering-timer): Comment update.
- (twittering-icon-mode): Ditto.
- (twittering-http-post): Ditto.
- (twittering-get-response-body): Ditto.
- (twittering-cache-status-datum): Ditto and Fix renaming.
- (twittering-timeline-data, twittering-timeline-last-update):
- Rename.
- (twittering-render-timeline): Ditto.
- (twittering-icon-mode): Fix renaming.
- (twittering-http-get-default-sentinel): Ditto.
- (twittering-format-status): Fix indentation.
-
-2009-03-09 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el (twittering-mode): Add keybind in Major mode
- docstring by Alex Schröder <kensanataNOSPAMgmail.com>
-
-2008-08-03 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el (twittering-mode-version): Update to 0.6
- * twittering-mode.el (twittering-friends-timeline-last-update): 新
- 規変数
- (twittering-setftime, twittering-local-strftime)
- (twittering-global-strftime): `twittering-local-strftime'を機能分
- 割
- (twittering-http-get): オプション引数`parameters'を追加、他調整
- (twittering-http-post): 同上の調整
- (twittering-status-to-status-datum): last-updateを更新する処理を追
- 加
- (twittering-friends-timeline, twittering-erase-old-statuses):
- statusのupdate時にsinceをパラメータと指定する処理をサポート
-
-2008-07-21 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el (twittering-http-get, twittering-http-post):
- 改行が1つ多かったので除去
-
-2008-05-11 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el (twittering-format-status): id/user-idのフォー
- マット整形。時間情報にuriを付与。Nicholasのパッチにより全体に
- username情報を付与
- (twittering-status-to-status-datum): username/user-screen-nameにつ
- いて整理
- (twittering-get-status-url): 新規関数(マクロでもいいんだけど...)
-
-2008-05-01 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el : 全体のコメント修正、以下の修正は大部分を
- gan2さんが実施した
- (twittering-mode-version): 新規関数
- (twittering-timer): コメント追加
- (twittering-scroll-mode, twittering-jojo-mode)
- (twittering-icon-mode): Nicholas Riley <njrileyNOSPAMuiuc.edu>さんのパッ
- チ採用、バッファローカル化
- (list-push): 新規マクロ
- (twittering-mode-map): キーバインド変更
- (twittering-mode-hook): フック変数新規作成(以前から利用してたけど
- 定義がなかった)
- (twittering-render-friends-timeline): Nicholas Riley
- <njrileyNOSPAMuiuc.edu>さんのパッチ採用、ステータスの挿入正常化
- (twittering-goto-next-status)
- (twittering-get-next-username-face-pos)
- (twittering-goto-previous-status)
- (twittering-get-previous-username-face-pos)
- (twittering-goto-next-status-of-user)
- (twittering-goto-previous-status-of-user)
- (twittering-get-username-at-pos, twit): 新規関数
-
-2008-02-08 Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-
- * twittering-mode.el : 全体的に整形、Proxy、Safe Password、
- User-Agent、Major mode stringを対応。Version 0.3
- (twittering-mode-version): 暫定のバージョン定数を定義
- (twittering-proxy-use): プロキシ関係設定を導入 from <http://d.hatena.ne.jp/lurdan/20080108/1199775387>
- (twittering-proxy-server): 同上
- (twittering-proxy-port, twittering-proxy-user): 同上
- (twittering-proxy-password): 同上
- (twittering-toggle-proxy): 同上
- (twittering-user-agent-default-function): 同上
- (twittering-user-agent-default-function): デフォルトUser-Agent生成関数
- (twittering-user-agent-function): User-Agent生成関数指定変数を導入
- (twittering-user-agent): 内部でのUser-Agent生成関数
- (twittering-tmp-dir): ユーザー固有のImageTmpDirを生成 from <http://d.hatena.ne.jp/odz/20071021/1192957783>
- (twittering-mode-map): プロキシの有効無効のキーバインド定義
- (twittering-mode-string): メジャーモード文字列を変数定義
- (twittering-mode): メジャーモード開始時に文字列を設定
- (twittering-http-get): プロキシ、User-Agentによる処理を追加
- (twittering-http-post): 同上
- (twittering-get-password): パスワードを動的に確認する関数を定義
-
-2007-10-14 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el : Naoya T. <naoya.tNOSPAMaqua.plala.or.jp>, masa_edw のパッチをとりこむ
- (twittering-url-encode): 使わないので削除
- (twittering-decode-html-entities): patched: 数値エンティティだけでなく,asciiエンティティにも対応.
- (twittering-font-lock-keywords): font-lock-keywordsを削除.text propertyによって設定する.
- (twittering-format-status): patched: statusとformat-strからstatusの表示用文字列を生成.
- (twittering-scroll-mode): patched: 新しいtwitがあったときに,カーソルもスクロールするか固定するかを設定するマイナモード, masa_edwのパッチ
- (twittering-status-format): twitの表示方法をきめるテンプレート文字列
- (twittering-icon-mode): patched: ifをwhenにおかえた.nilを渡されたときはマイナモードのスイッチに振舞を変更
- (twittering-local-strftime): patched: 時間をフォーマット文字列に従い文字列化
- (twittering-mode-init-variables): font-lock-modeは,Emacs21系ではautoloadするために一度呼ぶ必要がある. icon-mode, scroll-modeをマイナモードに登録.
- (twittering-inspect-object): 使わないので削除
- (twittering-http-get-default-sentinel): エラーを追いやすくするため,condition-caseを廃止
- (twittering-status-to-status-datum): 全てのデータを抽出するようコード追加.ユーザ名,URIリンク表示などの処理もここで.
-
-2007-10-13 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el (twittering-font-lock-keywords): ユーザー名のフェイスを適用する規則を修正.アイコン画像を表示したときに,下線が画像にかからないようにした.
- (twittering-render-friends-timeline): ポイントが特定のtwitに対して固定されるようにした(patch from masa_edw)
-
-2007-10-12 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el (twittering-idle-time): つかわないので削除
- (twittering-get-or-generate-buffer): バッファ取得のための関数.存在しないバッファだったら,新たに生成して返す.
- (twittering-buffer): Variable:twittering-bufferを名前に持つバッファを返す関数.このバッファを使う場合は,(twittering-buffer)によって取得する.
- (twittering-http-buffer): twittering-bufferと同じ
- (twittering-wget-buffer): twittering-bufferと同じ
-
-
-2007-10-11 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el (twittering-icon-mode): アイコンを表示するか否かのフラグ
- (twittering-wget-buffer): アイコン画像をwgetで取得するプロセスのバッファ
- (twittering-icon-mode): アイコンの表示/非表示を切り換えるコマンド
- (twittering-tmp-dir): アイコンの画像を保存するディレクトリ
- (twittering-image-stack): ダウンロードすべきアイコン画像のリスト
- (twittering-image-type): 画像の種類を判別する関数
- (twittering-render-friends-timeline): friends timelineを表示する部分を切り出した
-
-2007-10-10 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el: バージョン番号をつけた 0.1.0
-
-2007-10-07 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el (twittering-http-get-default-sentinel): http-bufferを毎回生成-削除するのをやめて,内容をeraseして使い回すようにした.
- (twittering-http-get-default-sentinel):HTTPレスポンスのステータスコードが上手く拾えなかったときの処理を追加
- (twittering-http-get-default-sentinel): カレントバッファか*twittering*のときは,friends-timelineを更新してもポイントの位置が変わらないように修正.
-
-2007-09-24 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el (twittering-status-to-status-datum): URIをクリック可能にする処理を追加
-
-2007-09-23 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el (twittering-uri-face): URI用のフェイス
- (twittering-click): クリック時に実行されるコマンド
- (twittering-enter): EnterかC-mが押されたときに実行されるコマンド
-
-2007-09-19 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el (twittering-mode-syntax-table): "(double quote)を,文字列クオートと認識しないようにsytax-tableを変更.
- (twittering-friends-timeline): friends timelineの取得したデータを保存しておく変数.twittering modeが起動している限り,この変数に取得したstatusを随時追加してゆく.
- (cl): assocrefをinnner defunして,バイトコンパイル時にWarningが出ていた.clパッケージのfletを使うことでWarningが出ないように解決した.
- (twittering-status-to-status-datum): twittering-status-to-lineから名前変更
- (twittering-friends-timeline-data): twittering-friends-timelineから名前変更
- (twittering-status-to-status-datum): idもstatus datumに含めるようにした.
- (twittering-cache-status-datum): status datumをdata-var(デフォルトはtwittering-friends-timeline-data)にキャッシュする関数.すでにあるstatus datumを渡すとnil,新しいstatus datumを渡すとtを返してdata-varに追加する.
- (twittering-http-get-default-sentinel):過去のstatus datumをキャッシュして,バッファに過去のstatusも表示されるようにした.
- (twittering-erase-old-statuses): 21件目以降の古いstatusを消す関数.実際はキャッシュを全部消して,twittering-http-getを呼んでいるだけ.C-c C-eにバインド.
- (twittering-username-face): ユーザ名用のface.(defface <name>)の後に(defvar <name>)で使用可能になった.なぜ?
- (twittering-status-to-status-datum): ユーザ名のテキストにmouse-face属性と,uri属性(ユーザのページのURI)を付加するようにした.
- (twittering-click-username): ユーザ名をクリックするか,C-mを押したときに起動するコマンド.
- (twittering-mode-map): vimライクなキーバインドを追加
- (twittering-mode): twittering-mode-hookでfont-lock-defaultsが設定された後に,font-lock-mode を2回呼んで変更を反映させるようにした.
- (twittering-mode-init-variables): twittering-username-faceの定義をこの関数の中にうつした.
- (twittering-browse-user-page): twittering-click-usernameから名前変更.
- (twittering-update-status-interactive): twittering-update-statusから名前変更.
- (twittering-reply-to-user): ユーザ名上でEnterを押すとこの関数が呼びだされるようにキーバインド変更.ミニバッファに @<ユーザ名> が自動挿入される.
- (twittering-view-user-page): twittering-browse-user-pageから名前変更.C-c C-vにバインド.
- (twittering-update-status-if-not-blank): 引数statusが,空白文字のみか, @<ユーザ名> のみの場合には nil を返し,他の文字も含む場合には POSTしてtを返す関数.
- (twittering-update-status-from-minibuffer): ミニバッファからstatusを更新するための関数.無効な文字(twittering-update-status-if-not-blankで判定)が入力された場合は,有効な文字列が入力されるまでループする.
-
-2007-09-12 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el (twittering-ucs-to-char): Emacs21系では,Mule-UCSがロードされていないと,(decode-char 'ucs HOGE)がnilになり,文字コードを取得できないことがある.そこで,ucs-to-charが使える環境ではucs-to-charを,使えない環境(Emacs22など)ではdecode-charを使うように自動で切り替えるマクロを書いた.
-
-2007-09-10 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el (twittering-refresh-buffer): 使わないので削除
- (twittering-http-post-default-sentinel): condition-case でエラーハンドリングするようにした.
- (twittering-http-get-default-sentinel): *twittering*バッファをread-onlyにした
- (twittering-http-post-default-sentinel): condition-case でエラーハンドリングするコードを追加.
- (twittering-start): 複数のタイマが走らないように,twittering-timerがnilでない=既存のタイマが走っている場合は一旦twittering-stopを呼び出してからタイマをスタートするようにした.
-
-2007-09-09 Y. Hayamizu <haya@haya-laptop-ubuntu>
-
- * twittering-mode.el: リリース
- (case-string): CarbonEmacs (Emacs22)で,case-stringを呼びだすコードよりも前にdefmacroを持ってきたら,警告が出ないという報告.
- (twittering-decode-html-entities): ucs-to-charの使用をやめ,(decode-char 'ucs ...)を使うことに. (reported by masa_edw)
- (twittering-update-status): read-from-minibufferの7番目の引数にtを指定し,input methodをカレントバッファから継承するようにした.
- (twittering-decode-html-entities): string-to-intはobsoleteなので,string-to-numberに変更 (reported by masa_edw)
- (twittering-get-response-header): (setq (get-buffer ...)) となっていたので,(setq buffer (get-buffer ...))に修正. twittering-get-response-bodyも同様
- (twittering-timer-action): twittering-refresh-triggerは既に使っていない変数だったので削除した
- (debug-print): マクロが最初にコンパイルされる時点では,debug-modeが変数として宣言されていないので,debug-modeの判断まで含めたコードを吐くようにした.
- (twittering-http-post-default-sentinel): xml-parse.elのかわりに,xml.el(Emacs標準?)を使うように変更したことに伴い書き換えた
- (twittering-get-response-body): xml-parse.elのかわりに,xml.el(Emacs標準?)を使うように変更したことに伴い書き換えた
- (twittering-xmltree-to-status): xml-parse.elのかわりに,xml.el(Emacs標準?)を使うように変更したことに伴い書き換えた
- (twittering-status-lines): xml-parse.elのかわりに,xml.el(Emacs標準?)を使うように変更したことに伴い書き換えた
- (twittering-status-to-line): xml-parse.elのかわりに,xml.el(Emacs標準?)を使うように変更したことに伴い書き換えた
- (twittering-get-timeline): xml-parse.elのかわりに,xml.el(Emacs標準?)を使うように変更したことに削除
- (twittering-status-lines): xml-parse.elのかわりに,xml.el(Emacs標準?)を使うように変更したことに削除
- (twittering-parse-xml): xml-parse.elのかわりに,xml.el(Emacs標準?)を使うように変更したことに削除
- (twittering-timer-interval): twittering-refresh-intervalから名前変更
- (twittering-inspect-object): 任意のLispオブジェクトを文字列で表現できるユーティリティ関数
- (twittering-timer-action): xml.elにより処理が軽くなったので,一定時間間隔での更新に変更.
- (twittering-xmltree-to-status): Emacs21とEmacs22のxml.elの差異を吸収するコードを追加.Emacs22では,ノードのリストに空の文字列が混入することがあるため,文字列を除去するようにした.
-
+++ /dev/null
-<!-- -*- mode: markdown -*- -->
-
-Installation Guide
-==================
-
-For Windows users
------------------
-
-* Uncompress the archive file, and add a path of a directory
- containing `twittering-mode.el` to your `load-path`.
- * For example, if you uncompressed it under `C:\foo\`, there may be
- a directory `C:\foo\twittering-mode-X.X.X\` which contains
- `twittering-mode.el`. So add the following code to your `.emacs`
-
- (add-to-list 'load-path "C:/foo/twittering-mode-X.X.X")
-
-* Proceed to **Set up your Emacs**
-
-For Linux and other Unix users
-------------------------------
-
-* Uncompress the archive file, and add a path of a directory
- containing `twittering-mode.el` to your `load-path`.
- * For example, if you uncompressed it under `/path/to/foo`, there may be
- a directory `/path/to/foo/twittering-mode-X.X.X/` which contains
- `twittering-mode.el`. So add the following code to your `.emacs`
-
- (add-to-list 'load-path "/path/to/foo/twittering-mode-X.X.X")
-
-* Install cURL, gnutls, or openssl for using SSL connection.
-* Proceed to **Set up your Emacs**
-
-Set up your Emacs
------------------
-
-* Add following code to your `.emacs`:
-
- (require 'twittering-mode)
-
-Run twittering-mode
--------------------
-
-1. Execute `M-x twit` to run twittering-mode.
-2. Open OAuth authorization page with your browser, click "Allow", and
-enter the PIN code.
-3. Your friends' timeline will appear. Enjoy!
+++ /dev/null
-<!-- -*- mode: markdown -*- -->
-
- インストールの手引き
-======================
-
- Windows
----------
-
-* twittering-modeのファイルを展開して現れたディレクトリを`load-path`に
- 追加する。
- * 例: `C:\foo\`というディレクトリの下に展開したとすると、
- `twittering-mode.el`が入っているディレクトリ
- `C:\foo\twittering-mode-X.X.X\`があるはずなので、`.emacs`に次の内容
- を追加する:
-
- (add-to-list 'load-path "C:/foo/twittering-mode-X.X.X")
-
-* **Emacsの設定** へ進む
-
- Linuxやその他Unix環境
------------------------
-
-* twittering-modeのファイルを展開して現れたディレクトリを`load-path`に
- 追加する。
- * 例: `/path/to/foo`というディレクトリの下に展開したとすると、
- `twittering-mode.el`が入っているディレクトリ
- `/path/to/foo/twittering-mode-X.X.X/`があるはずなので、`.emacs`に次の内容
- を追加する:
-
- (add-to-list 'load-path "/path/to/foo/twittering-mode-X.X.X")
-
-* SSL通信を利用するためには、cURL、gnutls、opensslのどれかをインストー
- ルしておく
-* **Emacsの設定** へ進む
-
- Emacsの設定
--------------
-
-* 次のコードを`.emacs`に追加する:
-
- (require 'twittering-mode)
-
- twittering-modeを動かす
--------------------------
-
-1. `M-x twit`を実行
-2. 画面の指示に従いOAuthの認証ページを開き、"Allow"ボタンをクリックして、
-表示されたPINコードをEmacsに入力する
-3. Twitterのタイムラインが表示されるはず!
+++ /dev/null
-
-EMACS ?= emacs
-
-DISTRIB_FILES = twittering-mode.el \
- README README.ja \
- NEWS NEWS.ja \
- INSTALL INSTALL.ja \
- win-curl \
- url-emacs21 \
- emacs21
-
-.PHONY: all check clean update-po release release-upload upload
-
-all:
-
-update-po:
- $(MAKE) -C doc update-po
-
-check:
- ./test/run-test.sh -y
-
-clean :
- rm -f twittering-mode.elc README *.zip *.tar.gz
-
-VERSION = $$(cat VERSION)
-DISTRIB_DIR = twittering-mode-$(VERSION)
-
-README: README.markdown
- cp $< $@
-release: $(DISTRIB_FILES)
- @(! [ -z "$${SF_USERNAME}" ] || (echo "Environmental variable 'SF_USERNAME', which is a username of sf.net, is required."; false))
- @echo -n "wrote NEWS file? [y or n]: "; read ans; [ "$${ans}" = "y" ]
- @echo -n "What is next version number?: " && \
- read version && \
- (if [ "$${version}" != "$$(cat VERSION)" ]; then \
- mv VERSION LAST-VERSION; \
- echo $${version} > VERSION; \
- fi) && \
- ruby misc/vernum-updater.rb \
- --prev-version=$$(cat LAST-VERSION) --next-version=$$(cat VERSION) \
- doc/web/index.text
- ruby misc/vernum-updater.rb \
- --prev-version=HEAD --next-version=$$(cat VERSION) \
- twittering-mode.el NEWS NEWS.ja
- @([ -d $(DISTRIB_DIR) ] && rm -rf $(DISTRIB_DIR)) || true
- mkdir $(DISTRIB_DIR)
- cp -r -t $(DISTRIB_DIR)/ $(DISTRIB_FILES)
- zip -r $(DISTRIB_DIR).zip $(addprefix $(DISTRIB_DIR)/,$(DISTRIB_FILES))
- tar czvf $(DISTRIB_DIR).tar.gz $(addprefix $(DISTRIB_DIR)/,$(DISTRIB_FILES))
- rm -rf $(DISTRIB_DIR)
-
-release-upload: release
- make upload
-
-upload:
- (echo "cd /home/frs/project/t/tw/twmode/"; \
- echo "-rm $(DISTRIB_DIR)/*"; \
- echo "-rmdir $(DISTRIB_DIR)"; \
- echo "mkdir $(DISTRIB_DIR)"; \
- echo "cd $(DISTRIB_DIR)"; \
- echo "put $(DISTRIB_DIR).zip"; \
- echo "put $(DISTRIB_DIR).tar.gz") > upload.bat
- sftp -b upload.bat $${SF_USERNAME},twmodeNOSPAMweb.sourceforge.net
- rm -f upload.bat
-
+++ /dev/null
-
- NEWS -- The history of twittering-mode
-========================================
-
- HEAD: XXXX-XX-XX
-------------------
-
-### Important notice
-
-### Improvements
-
-### Bug fixes
-
- 3.0.0: 2013-04-21
-------------------
-
-### Important notice
-* Obsolete implicit sign string feature.
- The function `twittering-sign-string-function' and the variable
- `twittering-sign-simple-string' are now obsolete. The `edit
- skeleton' feature can be used as an alternative. For example,
- the configuration
- (setq twittering-sign-simple-string "footer")
- is equivalent to the following one;
- (setq twittering-edit-skeleton-footer " [footer]")
- (setq twittering-edit-skeleton 'footer)
-* Obsolete variable `twittering-scroll-mode'
- The variable `twittering-scroll-mode' is obsolete. The current
- version of twittering-mode always behaves as the previous version
- does on scroll-mode. To track the latest tweet, put the cursor on
- the header or footer that is rendered on the latest end.
-* A new key binding for "C-cC-w", future replacement for "C-cD".
- "C-cD" has been bound to `twittering-delete-status`, the function to
- delete a tweet. But the binding violates the Emacs Key Binding
- Conventions. "C-cC-w" is bound to the function. The old binding is
- also valid, but the new one is recommended.
-
-### Improvements
-* Edit skeleton according to the current timeline.
- You can define edit skeletons that refer to the current timeline.
- See the docstring of the variable `twittering-edit-skeleton-alist'.
- In addition, `inherit-hashtags' and `inherit-any', the predefined
- edit skeletons, insert hashtags if the current timeline is a search
- timeline where the query string includes hashtags.
-* Disabling overlay on excessive string.
- In default, `twittering-edit-mode' emphasizes too long strings by
- putting the overlay `twittering-warning-overlay' on characters
- following the 140th character. On some environments, however, some
- input methods seem to interfere the update of the overlay. In such
- case, you may avoid the problems by disabling the update of the
- overlay as follows.
- (setq twittering-disable-overlay-on-too-long-string t)
-* Jump to next/previous URI
- You can go to tne next or previous URI explicitly written in a tweet
- by the command `twittering-goto-next-uri' or
- `twittering-goto-previous-uri'.
- Also, you can use the commands, `twittering-goto-next-thing' and
- `twittering-goto-previous-thing'. With a prefix argument by
- preceding "C-u", they ignore things except URIs explicitly written
- in a tweet.
-* Additional root CA certificates.
- The root CA certificates `VeriSign Class 3 Public Primary CA - G2'
- and `GeoTrust Global CA' are also embedded in `twittering-mode.el'.
- They are used for verifying `api.twitter.com' and
- `search.twitter.com', respectively. The certificate `Equifax Secure
- Certificate Authority', which has been embedded, is now used for
- verifying the server `www.googleapis.com' when shortening a URI.
-* Support for new URL shortening services.
- You can use `migre.me' as URL shortening service by the following.
- (setq twittering-tinyurl-service 'migre.me) ;; for mig.re
-* Support for retweeted_by_user and retweeted_to_user timeline.
- ":retweeted_by_user/USER" and ":retweeted_to_user/USER" are added as
- a new timeline specs. The former consists of retweets posted by the
- user and the latter consists of retweets that will be sent to the
- home timeline of the user.
- After specifying ":retweeted_by_user/" or ":retweeted_to_user/" for
- `twittering-visit-timeline', which is bound to "V" in default, you
- can supplement a username with referring the username history.
-* Counting characters with considering the t.co link wrapper.
- When editing a tweet, the t.co link wrapper will be taken into
- account. The length of wrapped URIs is retrieved with
- help/configuration API periodically. The default period is 1 day.
- You can configure the interval of updating the length by the
- variable `twittering-service-configuration-update-interval'.
-* Ad-hoc support for non-ASCII hashtags.
- Non-ASCII hashtags are decorated and you can visit its timeline by
- `v'. Note that the rule of detecting hashtags may be looser than
- that of the Twitter web UI. Problems have not been found yet, but a
- string considered as a hashtag in twittering-mode may not be treated
- as a hashtag in the Twitter web UI.
-* Rendering the t.co wrapped link as the original URL.
- If a tweet includes a link wrapped by the t.co service, it is
- rendered as the original URL. If `json.el' is unavailable, a link on
- a search timeline is rendered as the wrapped URL. But the link will
- be opened as the wrapped URL when you invoke `twittering-enter'
- (bound to `C-m' in default).
-* Posting a tweet consiting of mentions from pop-up buffer.
- From pop-up buffer, you can post a tweet consisting of
- mentions.
-* Restoring timeline buffers with `revive.el' by HIROSE Yuuji.
- Timeline buffers can be restored with the Emacs LISP program
- `revive.el' written by HIROSE Yuuji. There are two types of
- configuration.
- 1. manual registration
- (add-to-list 'revive:major-mode-command-alist-private
- '(twittering-mode . twittering-revive:twittering))
- (add-to-list 'revive:save-variables-local-private
- '(twittering-mode twittering-timeline-spec-string))
- (require 'revive)
- 2. automatic registration (for revive.el 2.19)
- (require 'revive)
- (twittering-setup-revive)
- Note that `(add-to-list ...)' of the manual configuration must be
- evaluated before loading `revive.el' and `(twittering-setup-revive)'
- of the automatic one must be evaluated after loading `revive.el'.
- Since the Emacs LISP program `windows.el' written by HIROSE Yuuji
- implicitly loads `revive.el' if possible, you should also take care
- of the order of loading `windows.el' and the configuration.
-* New format specifier "%u" for `twittering-retweet-format'.
- "%u" is added as a new format specifier for
- `twittering-retweet-format'. It is replaced with the URL of the
- cited tweet.
-* Skeleton for initializing an organic retweet.
- You can use a skeleton as the variable `twittering-retweet-format'
- for initializing an organic retweet. This means that you can also
- specify the initial cursor position. Strings included in the
- skeleton are converted with the below replacement table and then the
- skeleton is inserted with `skeleton-insert'.
- The replacement table is as follows.
- %s - The screen-name of the cited tweet.
- %t - The text of the cited tweet.
- %u - The URL of the cited tweet.
- %# - The ID of the cited tweet.
- %% - % itself.
- This is equivalent to the rule applied for
- `twittering-retweet-format' as a string.
- Note that it is inserted before the edit skeleton specified by
- `twittering-edit-skeleton' is performed.
-* Tweet type of edit skeleton for an organic retweet.
- The symbol `organic-retweet' is added as a tweet type specifying the
- type of the tweet being edited, which is referred by edit skeleton.
- You can define an edit skeleton that is performed only for organic
- retweets. Note that edit skeletons cannot refer to the tweet being
- retweeted in the current implementation.
-* Support for list names including non-ASCII characters.
-* Display of replied tweets on a search timeline.
- If `json.el' is available, twittering-mode can retrieve an ID which
- a tweet on a search timeline replies to. If so, replied tweets can
- be displayed by `twittering-toggle-show-replied-statuses' bound to
- "r" in default.
-* Header and footer on a timeline buffer.
- On a timeline buffer, the header and footer are rendered. They are
- special field and do not correspond to tweets. If you press the
- enter key (or invoking `twittering-enter') on the header or footer,
- the timeline buffer will be extended by retrieving more tweets
- according to whether the cursor is placed on the latest end or
- oldest one.
- You can track the latest tweet by putting the cursor on the latest
- side of the header and footer.
- You can customize the header and footer strings with the variables
- `twittering-timeline-header' and `twittering-timeline-footer',
- respectively. Their face can also be customized with the variables
- `twittering-timeline-header-face' and
- `twittering-timeline-footer-face'.
-* Support for exclude-if timelines.
- ":exclude-if/FUNC/SPEC" is added as a new timeline spec. The
- timeline equals SPEC, except that it does not include tweets that
- the function FUNC returns non-nil for. FUNC must be a function that
- receives an alist corresponding to a tweet as an argument. A lambda
- expression and a symbol bound to a function are valid as FUNC. But a
- symbol name must not include two special characters, "(" or "/". You
- can specify any timeline spec for SPEC. For example, you can ignore
- tweets including "WORD" from the home timeline by the following
- timeline spec; ":exclude-if/(lambda (tweet) (string-match \"WORD\"
- (cdr (assq 'text tweet))))/:home".
-* Support for merge timelines.
- Merge timelines such as "(SPEC1+SPEC2)" or "(SPEC1+SPEC2+SPEC3)" and
- so on, are added as new timeline specs. The merge timeline consists
- of all tweets in the specified timelines. You can specify any
- timeline spec for constituents. For example, you can see all direct
- messages, which you have sent or received, on a buffer by the
- following timeline spec;
- "(:direct_messages+:direct_messages_sent)".
-* New hook invoked when rendering tweets.
- A new hook variable `twittering-new-tweets-rendered-hook' is
- added. The hook is invoked when new tweets are rendered. It is not
- invoked when rendering tweets that are retrieved formerly. Since the
- existing hook `twittering-new-tweets-hook' is invoked for each
- successful retrieval of tweets, it may be invoked for tweets that
- are not rendered in composite timelines such as exclude-if and merge
- timelines. The new hook works well for composite timelines.
- In the new hook, you can use `twittering-rendered-new-tweets' as a
- list of new tweets. `twittering-rendered-new-tweets-spec' and
- `twittering-rendered-new-tweets-spec-string' can be used as the
- timeline spec and the timeline spec string. For detail, see the
- docstring of the new hook variable.
-* New hook invoked after initializing global variables.
- A new hook variable `twittering-mode-init-hook' is added. The hook
- is invoked after initializing global variables. Unlike
- `twittering-mode-hook', which is invoked every time a buffer is
- generated for twittering-mode, the new hook invoked only once.
-* Description on a pop-up edit buffer.
- The description is rendered on the top of the pop-up edit
- buffer. Which the tweet is a reply, a direct message or an
- independent ordinary tweet is explicitly displayed. You can also
- copy the tweet being replied.
-* Switch of a reply and a normal tweet on a pop-up edit buffer.
- You can toggle whether the tweet being edited will be sent as a
- reply or a normal tweet by invoking `twittering-edit-toggle-reply'
- bound to "C-c C-r" in default.
-* Support for exclude-re timelines.
- ":exclude-re/REGEXP/SPEC" is added as a new timeline spec. The
- timeline equals SPEC, except that it does not include tweets that
- match the regular expression REGEXP. In REGEXP, a slash must be
- escaped with a backslash. For example, tweets including a slash are
- excluded from the timeline corresponding to the Emacs string literal
- ":exclude-re/\\//:home".
-* Iterative retrieval of a series of replies.
- You can trace back a series of replies by a new function
- `twittering-toggle-or-retrieve-replied-statuses' bound to "R" in
- default. The function behaves as follows:
- - If some of tweets in the series of replies pointed by the cursor
- have not been rendered, try to show them as possible. If some of
- them have not been retrieved yet, retrieve the latest one and show
- it.
- - If all tweets in the series of replies pointed by the cursor
- have been rendered, hide them.
- - If the cursor does not point to one of tweets in a series of
- replies, do nothing.
-* Configuration of how to open a window for an edit buffer.
- A new variable `twittering-pop-to-buffer-function' is added. It
- specifies how to open a window for an edit buffer. The default value
- is `twittering-pop-to-buffer-in-bottom-largest-window', which opens
- a window by splitting the largest window on the bottom of the
- current frame. You can also use the function
- `twittering-pop-to-buffer-in-current-window', which splits the
- current window.
-* Support for `single tweet' timelines.
- ":single/ID" is added as a new timeline spec. The timeline consists
- of a tweet specified by ID. You can read a very old tweet by using
- the timeline spec.
-* Single tweet timeline from a URL in a tweet.
- You can visit a `single tweet' timeline from a URL pointing to the
- tweet by invoking `twittering-other-user-timeline' on the URL. The
- function is bound to "v" in default.
-* New command to get tweets before a specific time.
- By using the new command `twittering-get-tweets-before', you can get
- tweets of the current timeline before a specific time.
-* Support for backward retrieval of favorites timeline.
-* Different intervals of retrieving timelines.
- An interval of retrieving each timeline can be configured by the new
- variable `twittering-relative-retrieval-interval-alist'. The alist
- consists of pairs of a regexp and a relative interval. The regexp
- specifies timelines and they are retrieved at intervals that are the
- relative interval times as long as the variable
- `twittering-timer-interval'.
-* Support for the Twitter REST API v1.1.
- The default value of `twittering-service-method' is changed to
- `twitter-api-v1.1'. The configuration means that twittering-mode
- uses the Twitter REST API v1.1. The service method requires SSL
- connection and JSON parser. Note that the former requires cURL with
- OpenSSL, GNU Wget with OpenSSL, OpenSSL or GnuTLS and the latter
- requires `json.el' that is not distributed with Emacs 22 or
- earlier.
- In addition, some timelines are obsolete in the Twitter REST API
- v1.1. The obsolete timeline spec strings follow; ":friends",
- ":replies", ":public", ":retweeted_by_me", ":retweeted_to_me",
- ":retweeted_by_user/USER", ":retweeted_to_user/USER".
-
-### Bug fixes
-* Fix of displaying a message of authorization.
-* Fix of confirmation of available connection methods.
-* Fix of the function for HMAC-SHA1.
- Results from the function `twittering-hmac-sha1' might return
- incorrect digests depending on the current coding system. The
- problem has been fixed.
-* Fix of confusion of a username consisting of digits with a user ID.
- The confusion when retrieving `user_timeline' has been fixed. But
- the confusion when retrieving `favorites' for other users has not
- been fixed yet because the API for `favorites' has no parameters to
- directly specify a screen name not a user ID.
- Thanks to Makoto Fujiwara who reported this problem.
-* Fix of unintentional cursor motion on editing a tweet.
- If the current buffer was not managed by `twittering-mode', the
- cursor of the buffer was moved without intention by calling
- `twittering-update-status-interactive' from the buffer. The bug has
- been fixed.
- Thanks to mofigan who reported this problem.
-* Fix of storing icons on some cases.
- Icons were not correctly saved if `twittering-icon-storage-limit' or
- `twittering-convert-fix-size' was nil. The bug has been fixed.
- Thanks to HufflepuffBR who reported this problem about the former
- variable `twittering-icon-storage-limit'.
-* Fix of unconditional addition of `load-path' on byte-compilation.
- On byte-compilation, the directories `emacs21' and `url-emacs21',
- which are included in the repository of twittering-mode, were
- unconditionally added into `load-path'. Due to this bug, some macros
- were embedded as obsolete definitions for Emacs21 in the result of
- byte-compilation. Some functions in the result cause errors on Emacs
- 22 or later because the obsolete definitions conflict with Emacs
- newer than 21. On Emacs 22 or later, the directories are no longer
- added to `load-path' on byte-compilation. The bug has been fixed.
- Thanks to HKey who has discovered the bug.
-* Fix of the strange motion of the cursor.
- The cursor motion based on logical lines had caused non-intuitive
- behavior by interfering text property attaced to tweets. The problem
- did not appear when the motion was based on display line. The bug
- has been fixed.
- Thanks to lemit who reported the problem.
-* Deletion of a tweet from a buffer after the API is succeeded.
- A tweet is deleted from a buffer after receiving a successful
- response of the `destroy-status' API. If the API ends in failure,
- you can try to delete the status again because the status remains on
- the buffer.
-* Fix of the escape of a query string in a search timeline spec.
-* Fix of errors raised by asynchronous sentinels.
- Previously, an error might be raised from a sentinel when a timeline of
- non-existent user was requested. The bug has been fixed.
-
- 2.0.0: 2011-04-22
-------------------
-
-### Important notice
-
-### Improvements
-
-* Support for storing private information in a file encrypted by master
- password. Once you save the authorized account by using master password,
- you have to input PIN no longer. This is enabled by
- `(setq twittering-use-master-password t)'.
- The private information is stored in `~/.twittering-mode.gpg', which can
- be specified by `twittering-private-info-file'.
- To enable master password, you need GnuPG and an additional Emacs LISP
- program, which is `alpaca.el' or EasyPG (Emacs23 includes EasyPG).
- To use with `alpaca.el', you should use the version 0.13. With other
- versions of `alpaca.el' the current implementation may not work well
- because it deeply depends on internal implementation of `alpaca.el'.
-* Authentication via xAuth.
- You can enable xAuth by "(setq twittering-auth-method 'xauth)".
-* Rejection of invalid PIN code input and strip extra white spaces.
-* Confirmation of process status for avoiding dead-lock.
-* Native retweets on `user', `friends', `mentions' and `public' timelines.
-* Detection of abnormal exit of an invoked process.
- The exit-status on abnormal exit is printed to the buffer "*Messages*".
-* Support for disabling server authentication.
- Server authentication is enabled by default.
- It can be disabled by "(setq twittering-allow-insecure-server-cert t)".
-* Replacement of unknown numeric character references with its alternative.
- The alternative can be specified by "twittering-unicode-replacement-char".
- Its default value is U+FFFD.
-* Addition of the files ".nosearch".
- The files ".nosearch" are added to sub-directories. This makes the sub-
- directories be excluded from recursive registration of "load-path".
-* Suppression of multiple authorization.
- Authorization will be performed only once even if multiple timelines
- are specified as initial timelines.
-* Independence of byte-compiled form from "cl".
- Byte-compiled `twittering-mode.el' does not depend on `cl'.
-* Update of the embedded CA certificate.
- The embedded CA certificate is replaced with `Equifax Secure Certificate
- Authority'.
-* Support for StatusNet.
- You can switch `twittering-mode.el' to StatusNet mode by
- "(setq twittering-service-method 'statusnet)". Note that you cannot
- use one instance of Emacs with `twittering-mode.el' for Twitter and
- StatusNet simultaneously.
- To use StatusNet, you must configure variables of host information.
- For the service on `http://identi.ca/', you may require the below
- configuration.
- (setq twittering-service-method 'statusnet)
- (setq twittering-auth-method 'basic)
- (setq twittering-username "YOUR-ACCOUNT-NAME")
- ;; host
- (setq twittering-api-host "identi.ca")
- (setq twittering-api-search-host "identi.ca")
- (setq twittering-web-host "identi.ca")
- ;; paths for API
- (setq twittering-api-prefix "api/")
- (setq twittering-search-api-method "api/search")
- (setq twittering-web-path-prefix "")
-* Copy a URI in a tweet or a URI pointing to the tweet by "U".
- Thanks to Faried Nawaz.
-* Copy tweets by "C-<mouse-3>".
- Thanks to Faried Nawaz.
-* Support for `wget'.
- The external program `wget' can be used for communicating with Twitter
- as well as `curl'. You can give priority to `wget' by the below
- configuration.
- (setq twittering-connection-type-order '(wget curl native))
-* Display of the current connection method on the mode-line.
- By default, the current connection method is displayed on the mode-line.
- You can disable it by "(setq twittering-display-connection-method nil)".
-* Silent retrieval of icons.
- The default value of `twittering-url-show-status' is changed to nil.
- So, icons are retrieved silently by default.
-* New connection methods, `urllib-http' and `urllib-https'.
- New connection methods are added, which are implemented by using `url'
- library. The library supports HTTP redirection, but it may be slow and
- unstable. This method is not recommended if you can use other methods.
- If you give incorrect account information on BASIC authentication or
- xAuth with this new methods, you will be asked to input account
- information again. This behavior is a function of the url library, but
- twittering-mode cannot use account information given on the second try.
- When you are asked to input it again, cancel it by 'C-g' and do
- 'M-x twit'.
-* Redisplaying tweets with idle timer.
- Twittering-mode waits for Emacs to become idle before it redisplays
- tweets for time and icon image. Tweets are redisplayed each time Emacs
- remains idle for a certain time specified by the variable
- `twittering-timer-interval-for-redisplaying', which is 1 second by
- default.
-* Retrieval of icon images by `curl' and `wget'.
- Icon images can be retrieved by the same connection method as that used
- for retrieving tweets. The priority of methods is similarly determined
- by `twittering-connection-type-order'.
-* Lazy invocation of `convert'.
- The program `convert' for converting the size of icon images is invoked
- after Emacs remains idle a certain time. The delay will prevent Emacs
- from stucking on inputting characters on other buffer. The delay time is
- specified by the new variable `twittering-url-request-sentinel-delay',
- which is 1 second by default.
-* Support for favorites timeline.
- ":favorites" and ":favorites/USER" are added as new timeline specs.
- By using the latter, you can read favorites for other users. You can
- specify a username with completion when you input ":favorites/" for
- `twittering-visit-timeline' bound to "V" in default.
- Note that favorites are rendered in order of time when each tweet is
- posted. This is because it is impossible to retrieve the time when a
- tweet was favorited. At most, 20 favorites can be retrieved. Backward
- retrieval of more previous favorites is not supported yet.
-* Support for new URL shortening services.
- You can use `bit.ly', `goo.gl', `is.gd' or `j.mp' as URL shortening
- service by the following.
- (setq twittering-tinyurl-service 'bit.ly) ;; for bit.ly
- (setq twittering-tinyurl-service 'goo.gl) ;; for goo.gl
- (setq twittering-tinyurl-service 'is.gd) ;; for is.gd
- (setq twittering-tinyurl-service 'j.mp) ;; for j.mp
- To use `bit.ly' or `j.mp', you need to configure `twittering-bitly-login'
- and `twittering-bitly-api-key' according to your account as follows.
- (setq twittering-bitly-login "YOUR-LOGIN-NAME")
- (setq twittering-bitly-api-key "YOUR-API-KEY")
- Thanks to Michael Kohl and Lars Gregori.
-* Change of the format specifiers, "%c", "%C", "%@", for official ReTweet.
- `created_at' for official ReTweet means when the original tweet was
- posted instead of when it was retweeted.
-* Function to report a user as a spammer.
- The function `twittering-block-and-report-as-spammer' is added. By
- invoking the function on a tweet, you can block its author and report
- him or her as a spammer.
-* Function to block a user.
- The function `twittering-block' is added. By invoking the function
- on a tweet, you can block its author.
-* Support for persistent icon storage.
- By "(setq twittering-use-icon-storage t)", you can save retrieved
- and resized icon images into a persistent storage, which is disabled
- in default. On next and later invocation, twittering-mode can
- display icons faster because the storage reduces time required to
- retrieve and resize images.
- In default, recently rendered 500 icons are stored at most. You can
- change the limit by the variable `twittering-icon-storage-limit'. To
- store all icons, configure the variable as nil.
- The default storage file is `~/.twittering-mode-icons.gz'. You can
- change it by changing `twittering-icon-storage-file'. Note that icon
- images in the storage generated on a certain version of Emacs may be
- unavailable on another version of Emacs.
-* New format specifier "%RT{...}".
- For `twittering-status-format', the new format specifier "%RT{...}"
- is added, which is rendered only when the tweet is an official
- ReTweet. In the brace, you can use any format specifiers, which are
- rendered with the information of the retweet itself instead of the
- retweeted original tweet. For example, "%RT{%s}" means who retweeted
- the tweet.
-* Cancel of official ReTweets.
- If an official ReTweet has been posted by yourself, you can cancel
- it by 'C-cD', which is the same way of deleting a tweet.
-* Completion of lists to which a specific user subscribes.
- You can visit a list to which a specific user subscribes by 'C-uL'.
- Thanks to Naohiro Aota.
-* Edit skeleton.
- Edit skeleton is a dynamic template system on posting a tweet. You
- can define an "edit skeleton", which specifies what string is
- automatically inserted as a footer, header or others before editing
- a tweet. `twittering-edit-skeleton-alist' is the alist of edit
- skeletons. For further details, see docstring of
- `twittering-edit-skeleton-alist'.
- The following edit skeletons are pre-defined;
- none: insert nothing,
- footer: insert `twittering-edit-skeleton-footer' as a footer,
- footer-only-normal: insert `twittering-edit-skeleton-footer' as a
- footer only when the tweet being edited is a normal tweet, not a
- reply or direct message,
- inherit-hashtags: insert hashtags extracted from the replied tweet,
- inherit-mentions: insert mentions extracted from the replied tweet,
- inherit-any: insert hashtags and mentions extracted from the replied
- tweet.
- You can switch the current edit skeleton by invoking
- `twittering-switch-edit-skeleton'.
- The footer string, `twittering-edit-skeleton-footer', can be changed
- by invoking `twittering-edit-skeleton-change-footer'.
-* Variable of fallback image format.
- You can change the fallback format of images by changing the
- variable `twittering-fallback-image-format'. The default format is
- XPM. Images which Emacs does not supports are displayed by
- converting them into the fallback format.
- By the following configuration, you may avoid strange behaviors when
- displaying XPM images on NTEmacs. Thanks to Silver Chariot.
- (setq twittering-fallback-image-format 'png)
-
-### Bug fixes
-
-* Support for the url library included in Emacs 23 and later.
-* Fix of options of `curl' for POST with an empty body.
-* Fix of retweeting a retweet.
-* Fix of a race condition on abnormal exit of a process for verification.
-* Fix of replying to tweets displayed as replied tweets.
- Thanks to Naohiro Aota.
-* Fix of rendering the format specifier "%L".
- The specifier "%L" is correctly rendered with a preceding whitespace.
- Thanks to Tom X. Tobin.
-* Fix of repeatedly registering a sentinel for retrieving an image.
-
- 1.0.0: 2010-06-05
-------------------
-
-### Important notice
-
-#### Posting tweets with minibuffer is obsolete now.
-
-There's two way to edit and post tweets in twittering-mode: with
-minibuffer (existing way), and with pop-up buffer (new feature!). You
-can choose it by setting the variable
-`twittering-update-status-function`. Currently its default value is
-the new way, `twittering-update-status-from-pop-up-buffer`. If you
-want to post from minibuffer, set the variable value to
-`twittering-update-status-from-minibuffer`.
-
-The new feature, pop-up buffer, has several advantages over the
-existing way.
-
-* Not conflicting with input methods.
-* Much less risk of posting halfway typed tweets by error.
-* Visual assertion of length of tweets.
-
-### Improvements
-
-* Introduction of a concept 'timeline spec'.
-* Pop-up buffer to edit and post tweets.
-* Auto proxy setup with environment variables (http_proxy, HTTP_PROXY)
-* Support for official ReTweet.
-* Added some format specifiers of tweets.
-* Support for recursive format specifiers such as
- "%FILL{%FACE[bold]{%C{%m/%d}}: %T}".
-* Support for user-defined prefix on filling by "%FILL[prefix]{...}".
-* Displaying image files without temporary files.
-* Support multiple buffers, where their name is derived from timeline spec.
-* Multiple initial timelines by setting a list of timeline spec strings to
- the variable `twittering-initial-timeline-spec-string'.
-* Toggle automatic retrieval of the timeline by pressing 'a'.
-* Improved compatibility with global-font-lock mode.
-* Unread statuses notifier on mode-line (experimental).
-* Switching timeline buffers by pressing 'f' or 'b'.
-* Graphical indicators for SSL and ACTIVE/INACTIVE state on mode-line.
-* Asynchronous retrieval of icon images.
-* Deleting a tweet by inputting 'C-cD'.
-* HTTPS connection using `tls' library working with an external command
- `gnutls' or `openssl' instead of `curl'.
-* Individual proxy configurations for HTTP and HTTPS.
- If `twittering-proxy-server' and `twittering-proxy-port' are non-nil,
- they have priority over the other variables `twittering-http-proxy-*' and
- `twittering-https-proxy-*'. To use individual proxies for HTTP and HTTPS,
- you must keep the prior variables (`twittering-proxy-server' and
- `twittering-proxy-port') nil.
-* Silent retrieval of icon images.
- You can enable silent retrieval by "(setq twittering-url-show-status nil)".
-* Authentication via OAuth.
- It requires a consumer information registered with Twitter and an external
- WWW browser to authorize a request token. Additionally, for SSL, it
- requires an external command `curl' or another command included in the
- variable `tls-program', which may be `openssl' or `gnutls-cli'.
- (Caution: Neither `openssl' nor `gnutls-cli' support SSL via proxy.)
- You can disable SSL for OAuth by "(setq twittering-oauth-use-ssl nil)".
- You can enable OAuth by "(setq twittering-auth-method 'oauth)".
- If `twittering-oauth-invoke-browser' is non-nil, twittering-mode
- automatically opens a browser on authorization.
-
-### Bug fixes
-
-* Avoid SSL certificate error by embedding CA cert in code.
- * twittering-cert-file
- * twittering-ensure-ca-cert
-* Fix URI (percent) encoding (thanks to IMAI Toshiyuki).
- * twittering-url-reserved-p
- * twittering-percent-encode
-* Improved portability.
- * twittering-completing-read
-* And lots of minor fixes
-
-### Thanks to
-
-* Alberto Garcia
-* IMAI Toshiyuki
-
- 0.9.0: 2009-12-29
--------------------
-
-### Improvements
-
-* Moved to GitHub.
-* Brand new web site in English and Japanese.
-* Secure sessions via HTTPS if 'cURL' is available.
-* Lists support.
-* Follow/remove support.
-* Favorite/unfavorite support.
-* Hash tag support.
-* Direct message support.
-* On-the-spot TinyURL-ize(tinyurl or to.ly).
-* On-the-fly tweet length check.
-* ReTweet format string.
-* Remembers visited user names and tweets.
-* Parameterized the number of tweets retrieved at a time.
-* Walk through items(username, URL, etc) by TAB.
-* Image type discriminant with 'file' program if available.
-* More descriptive error messages on minibuffer.
-* Do not discard old timeline data as possible.
-* Suspend by hitting 'q'.
-* Image file resize with 'convert' program(imagemagick) if available.
-* Unit test framework was introduced.
-* Support 'Proxy-connection: Keep-Alive'.
-* Flexible format string function (twittering-format-string).
-* Refactored 'twittering-format-status' by twitterint-format-string.
-* More efficient HTTP response processing.
-
-### Bug fixes
-
-* URL cannot not be opened by mouse-click or Enter.
-* Don't set the original status ID when retweeting.
-* Wrong regexp for searching URL in status text.
-* Username extraction from status text.
-* Update mode-line immediately.
-* Use a temporary buffer for each HTTP session.
-* Use MD5 hash to distinguish image files with the same name.
-* Check whether temp buffers are alive in sentinels before killing them.
-* And some typos.
-
-### Thanks to
-
-* Alberto Garcia
-* Jaemok Jeong
-* Kouhei Sutou
-* Naohiro Aota
-* Satoshi Yatagawa
-* Tadashi MATSUO
-* Thomas Danckaert
-* Tsuyoshi CHO
-* IMAI Toshiyuki
+++ /dev/null
-
- NEWS -- twittering-modeのあゆみ
-=================================
-
- HEAD: XXXX-XX-XX
-------------------
-
-### 重要なお知らせ
-
-### 改良
-
-### バグ修正
-
- 3.0.0: 2013-04-21
-------------------
-
-### 重要なお知らせ
-* 暗黙に署名を付加する機能の廃止
- 関数`twittering-sign-string-function'と変数
- `twittering-sign-simple-string'の機能は廃止されました。同様の機能は
- `edit skeleton'で設定できますので、こちらを使ってください。
- 例えば以前までの設定
- (setq twittering-sign-simple-string "footer")
- は、以下の設定で置き換えられます。
- (setq twittering-edit-skeleton-footer " [footer]")
- (setq twittering-edit-skeleton 'footer)
-* 変数`twittering-scroll-mode'の廃止
- 変数`twittering-scroll-mode'は廃止されました。現在の版は、過去の版で
- scroll-modeが有効であったときのように振舞います。最新のtweetに追従す
- るには、timelineバッファの最新側のヘッダもしくはフッタ上にカーソルを
- 置いてください。
-* "C-cD"の代替として"C-cC-w"を導入
- これまで、"C-cD"がtweet削除用関数'twittering-delete-status'にbindさ
- れていました。しかしこのキーはEmacsのKey Binding Conventionsに則って
- いません。そこでその代替として"C-cC-w"を同関数にbindしました。"C-cD"
- も有効ですが、"C-cC-w"の使用を推奨します。
-
-### 改良
-* 現在のtimelineに応じたedit skeleton
- 現在のtimelineに応じたedit skeletonを定義できるようになりました。
- 詳しくは変数`twittering-edit-skeleton-alist'のdocstringを参照くださ
- い。
- また、定義済みedit skeleton `inherit-hashtags'と`inherit-any'は現在
- のtimelineがハッシュタグを含むようなsearch timelineである場合に、そ
- のハッシュタグを自動で追加するよう変更されています。
-* 超過文字列の強調表示無効化
- 通常、`twittering-edit-mode'では140字を超える部分にoverlay
- `twittering-warning-overlay'を付加して強調表示するようになっています。
- しかし環境によってはinput methodとこのoverlayの更新とが干渉して問題
- を起こす場合があるようです。そのような場合、下記の設定でoverlayの付
- 加を無効化すれば問題を回避できる可能性があります。
- (setq twittering-disable-overlay-on-too-long-string t)
-* tweet中のURI文字列へのジャンプ
- tweet中のURI文字列へジャンプするコマンド`twittering-goto-next-uri'、
- `twittering-goto-previous-uri'が追加されました。
- また、旧来のコマンド`twittering-goto-next-thing'と
- `twittering-goto-previous-thing'にC-uでprefix argumentを与えると
- tweet中のURI文字列だけを対象としてジャンプするようになりました。
-* CA証明書を追加
- 新たにRoot CA証明書`VeriSign Class 3 Public Primary CA - G2'と
- `GeoTrust Global CA'を内蔵しました。これらの証明書はそれぞれ、
- `api.twitter.com'と`search.twitter.com'のサーバ認証で参照されます。
- 以前から内蔵されている証明書`Equifax Secure Certificate Authority'は
- URI短縮に用いる`www.googleapis.com'のサーバ認証でのみ参照されるよう
- になりました。
-* 新たな短縮URL生成サービスに対応
- 新たに`migre.me'に対応しました。下記のような設定で有効にできます。
- (setq twittering-tinyurl-service 'migre.me) ;; for mig.re
-* 指定したユーザ関連のretweetを集めたtimelineに対応
- 新しく":retweeted_by_user/USER", ":retweeted_to_user/USER"の2種類の
- timelineに対応しました。前者は指定したユーザUSERが投稿したretweetを
- 集めたtimelineで、後者は指定したユーザのhome timelineに届くretweetを
- 集めたtimelineです。
- `twittering-visit-timeline'(デフォルトでは"V"にbindされています)で指
- 定する際には":retweeted_by_user/"もしくは":retweeted_to_user/"と入力
- してEnterを入力すると、続けて補完機能付きでユーザ名を入力できます。
-* 文字数カウント時にt.coでの短縮を考慮
- tweetを編集する際に、t.coでのURI変換を考慮した文字数を表示するように
- なりました。変換後の文字数はhelp/configuration APIを通じて定期的に更
- 新されます。デフォルトの更新間隔は1日ですが、変数
- `twittering-service-configuration-update-interval'で変更することもで
- きます。
-* 非ASCII文字を含むハッシュタグへの簡易的な対応
- 非ASCII文字を含むハッシュタグについても、強調表示されるようになり、
- `v'でそのtimelineを開くことができるようになりました。ハッシュタグの
- 検出基準がTwitterのweb UIのそれとは多少異なる点に注意してください。
- 今のところ大きな問題は見つかっていませんが、場合によっては
- twittering-mode上でハッシュタグと見なされる文字列がTwitterのweb UIで
- はハッシュタグとは見なされない恐れはあります。
-* t.coで短縮されたリンクを短縮前のURLで表示
- Twitter公式のt.coサービスで短縮されたリンクが短縮前のURLとして描画さ
- れるようになりました。但し`json.el'が利用不可の場合はsearch timeline
- 上ではt.coで生成されたURLがそのまま描画されます。また、リンク上で
- `twittering-enter'(デフォルトでは`C-m')を実行した場合は短縮URL経由で
- 開かれます
-* mentionのみからなるtweetの投稿
- ポップアップバッファからであれば、mentionのみからなるtweetも投稿でき
- るようになりました。
-* `revive.el'によるtimelineバッファの復元
- HIROSE Yuujiさん作のEmacs LISPプログラム`revive.el'でtimelineバッファ
- を復元できるようになりました。設定方法には下記の2通りがあります。
- 1. 手動登録
- (add-to-list 'revive:major-mode-command-alist-private
- '(twittering-mode . twittering-revive:twittering))
- (add-to-list 'revive:save-variables-local-private
- '(twittering-mode twittering-timeline-spec-string))
- (require 'revive)
- 2. 関数を使っての自動登録 (revive.el 2.19用)
- (require 'revive)
- (twittering-setup-revive)
- 上記設定で、手動登録の`(add-to-list ...)'の部分は`revive.el'をloadす
- る前に評価する必要がある点に注意してください。また逆に自動登録の場合
- は`revive.el'をloadした後で`(twittering-setup-revive)'を評価する必要
- があります。
- また、同じくHIROSE Yuujiさん作のEmacs LISPプログラム`windows.el'は
- `revive.el'を暗黙にloadしますので、`windows.el'をloadするタイミング
- にも注意してください。
-* `twittering-retweet-format'用の新しい書式指定子"%u"
- `twittering-retweet-format'で指定できる書式指定子として"%u"が追加さ
- れました。これは引用されるtweetを指すURLと置き換えられます。
-* skeletonによる非公式ReTweetの初期文字列設定
- 非公式ReTweetを編集する際の初期文字列を指定する変数
- `twittering-retweet-format'にskeletonを指定できるようになりました。
- 文字列に加えて編集開始時のカーソル位置も指定できます。skeletonに含ま
- れる文字列を下記の対応表によって変換してから、関数`skeleton-insert'
- で挿入します。
- 対応表は以下の通りです。
- %s - 引用されるtweetの投稿者のscreen-name
- %t - 引用されるtweetの内容
- %u - 引用されるtweetを指すURL
- %# - 引用されるtweetのID
- %% - %自身
- この表は`twittering-retweet-format'に適用される規則と同じです。
- この変数`twittering-retweet-format'による初期文字列の挿入後に変数
- `twittering-edit-skeleton'で指定されたedit skeletonが適用される点に
- 注意してください。
-* edit skeleton用に非公式ReTweetを示すシンボルを追加
- edit skeletonにおける編集中tweetの種別を表現するシンボルに
- `organic-retweet'が追加されました。非公式ReTweetにのみ適用されるedit
- skeletonを定義できます。但し、現在の実装ではedit skeleton側から非公
- 式ReTweetされようとしているtweetの内容を参照することはできません。
-* 非ASCII文字を含むリスト名に対応
-* search timeline上での返信先tweetの表示
- `json.el'が使用可能な場合には、search timelineにおいても返信先tweet
- のIDが取得できるようになりました。`json.el'が使用可能であれば関数
- `twittering-toggle-show-replied-statuses'(デフォルトでは"r"にbindさ
- れています)を呼び出すことで返信先tweetを表示できます。
-* ヘッダとフッタの表示
- timelineバッファにヘッダとフッタが表示されるようになりました。これら
- はtweetとは独立の特別な行として描画されます。ヘッダやフッタ上でEnter
- キーを押す(もしくは`twittering-enter'を実行する)と、それがtimelineの
- 時系列で最新の側か過去の側かに応じてtweetを取得して描画します。
- また、ヘッダとフッタの内の最新側にカーソルを置いておくと、常にカーソ
- ル行の近くに最新tweetを描画するようにできます。
- ヘッダ、フッタとして表示される文字列は、`twittering-timeline-header'、
- `twittering-timeline-footer'という変数で変更できます。また、表示する
- 際のfaceは`twittering-timeline-header-face'と
- `twittering-timeline-footer-face'で変更できます。
-* exclude-if timelineに対応
- 新しく":exclude-if/FUNC/SPEC"というtimelineに対応しました。この
- timelineはSPECで表されるものとほぼ同じですが、関数FUNCがnon-nilを返
- すようなtweetは除外されている点が異なります。FUNCはひとつのtweetに対
- 応した連想リストをひとつ受け取る関数でなければなりません。FUNCとして
- はλ式もしくは関数に対応するシンボルが指定できます。但しシンボルで指
- 定する場合、名前に"("や"/"を含むものは指定できません。SPECには任意の
- timeline specを指定できます。例えば、home timelineから"WORD"を含む
- tweetを除外したtimelineは下記のtimeline specで指定できます。
- ":exclude-if/(lambda (tweet) (string-match \"WORD\" (cdr (assq 'text
- tweet))))/:home"
-* merge timelineに対応
- 新しく"(SPEC1+SPEC2)"や"(SPEC1+SPEC2+SPEC3)"といった形式のtimelineに
- 対応しました。merge timelineは指定したtimelineのtweetを全て含む
- timelineです。任意のtimeline specを構成要素にできます。例えば、
- "(:direct_messages+:direct_messages_sent)"というtimeline specを使え
- ばこれまでに送ったり受け取ったりしたdirect messageの全てをひとつのバッ
- ファに表示できます。
-* tweet描画時に実行される新しいhookの追加
- 新しいhook変数`twittering-new-tweets-rendered-hook'を追加しました。
- このhookは実際に新しいtweetを描画したときに実行されます。以前に取得
- したtweetを再描画する際には実行されません。既存のhook変数
- `twittering-new-tweets-hook'はtweetの取得に成功するたびに実行される
- ので、exclude-if timelineやmerge timelineのような複合timelineに含ま
- れる実際には描画されないtweetについてもhookを実行します。新しいhook
- は複合timelineについてもうまく動作します。
- hook内では、`twittering-rendered-new-tweets'という変数で描画された
- tweetのリストを参照できます。他にも描画されたtimelineを表すtimeline
- specとtimeline spec文字列を`twittering-rendered-new-tweets-spec'と
- `twittering-rendered-new-tweets-spec-string'という変数で参照できます。
- 詳細は`twittering-new-tweets-rendered-hook'のdocstringを参照してくだ
- さい。
-* 大域変数初期化時に実行される新しいhookの追加
- 新しいhook変数`twittering-mode-init-hook'を追加しました。このhookは
- 大域変数を初期化した後に実行されます。twittering-mode用のbufferを作
- 成するたびに実行される`twittering-mode-hook'とは異なり、新しいhookは
- 一度しか実行されません。
-* 編集バッファ上でのtweet種別の表示
- 編集中のtweetについての情報が編集バッファの先頭に表示されるようにな
- りました。編集中のtweetがreplyなのか、direct messageなのか、あるいは
- 通常のtweetなのかが確認できます。reply先のtweet内容のコピーもできま
- す。
-* 編集中のtweetをreplyとして送るかどうかの切り替え
- 編集中のtweetをreplyとして送るかどうかを編集バッファ上で切り替えられ
- るようになりました。関数`twittering-edit-toggle-reply'(デフォルトでは
- "C-c C-r"にbindされています)を呼ぶたびにreplyとして送るかどうかが切
- り替わります。
-* exclude-re timelineに対応
- 新しく":exclude-re/REGEXP/SPEC"というtimelineに対応しました。この
- timelineはSPECで表されるものとほぼ同じですが、正規表現REGEXPにマッチ
- するようなtweetは除外されている点が異なります。REGEXP内で / を指定す
- る際は \ でエスケープする必要があります。例えば、Emacsの文字列リテラ
- ル":exclude-re/\\//:home"で表されるtimelineでは、 / を含むtweetが除
- 外されています。
-* replyの系列の逐次取得
- 新しい関数`twittering-toggle-or-retrieve-replied-statuses'(デフォル
- トでは"R"にbindされています)を使って、replyを遡って取得できるように
- なりました。この関数の動作は下記の通りです。
- - カーソルがreply、もしくは展開表示されたreply先のいずれかを指してい
- て、そのreplyの系列の一部がまだ表示されていない場合、そのreply系列
- を可能な限り表示します。reply系列内のいくつかのtweetが未取得の場合
- には、その内の最新のものを取得し、表示します。
- - カーソルがreply、もしくは展開表示されたreply先のいずれかを指してい
- て、そのreplyの系列が全て展開表示されている場合、展開表示をとりや
- めます。
- - カーソルがreply系列内のtweetを指していない場合、何もしません。
-* 編集バッファ用を開く方法の設定
- 新たに変数`twittering-pop-to-buffer-function'を追加しました。この変
- 数は編集バッファを開く方法を指定するものです。デフォルトの値は関数
- `twittering-pop-to-buffer-in-bottom-largest-window'となっています。
- この関数は現在のフレーム内で最下段にあるウィンドウの内、面積最大のも
- のを分割することで編集バッファ用のウィンドウを確保します。他にも、関
- 数`twittering-pop-to-buffer-in-current-window'を指定することもできま
- す。この関数は現在のウィンドウを分割してウィンドウを確保します。
-* single tweet timelineに対応
- 新しく":single/ID"というtimelineに対応しました。このtimelineはIDで
- 指定されたtweetのみからなるtimelineです。非常に古いtweet等にアクセス
- するのに利用できます。
-* tweetに含まれるURLからのsingle tweet timeline取得
- 特定のtweetを指すURL上で関数`twittering-other-user-timeline'を呼ぶこ
- とで、そのtweetに対応したsingle tweet timelineを開けるようになりまし
- た。この関数はデフォルトでは"v"にbindされています。
-* 特定日時以前のtweetを取得するコマンドを追加
- 現在のtimelineの、指定した日時以前のtweetを取得できる新しいコマンド
- `twittering-get-tweets-before'が追加されました。
-* favorites timelineで過去のtweetの遡って取得する機能を追加
-* timelineごとに異なる取得間隔
- 新しい変数`twittering-relative-retrieval-interval-alist'で、timeline
- ごとに取得間隔を変更できるようになりました。この変数は正規表現と相対
- 間隔からなる連想リストです。この正規表現にマッチするtimelineは、
- `twittering-timer-interval'を「相対間隔」倍した間隔で更新されるよう
- になります。
-* Twitter REST API v1.1に対応
- 変数`twittering-service-method'の値を`twitter-api-v1.1'に変更しまし
- た。この設定でtwittering-modeはTwitter REST API v1.1を使うようになり
- ます。この場合、SSL接続とJSON解析器が必要です。SSL接続にはcURL with
- OpenSSL, GNU Wget with OpenSSL, OpenSSLとGnuTLSのいずれかが必要で、
- さらにJSON解析器として`json.el'が必要となる点に注意してください。
- Emacs22とそれ以前のEmacsでは`json.el'が同梱されていませんので別途用
- 意する必要があります。
- また、Twitter REST API v1.1ではいくつかのtimelineが廃止されています。
- 廃止されたtimelineに対応するtimeline spec文字列は":friends",
- ":replies", ":public", ":retweeted_by_me", ":retweeted_to_me",
- ":retweeted_by_user/USER", ":retweeted_to_user/USER"です。
-
-### バグ修正
-* 認証成功・失敗についてのメッセージが表示されるよう修正
-* 利用可能な通信方法(connection method)の確認処理の修正
-* HMAC-SHA1の計算を修正
- 以前の`twittering-hmac-sha1'は現在のcoding-systemによっては間違った
- 結果を返す場合がありました。この問題を修正しました。
-* 数字からなるユーザ名(screen_name)とユーザIDの混同を一部修正
- 他ユーザのtimelineを取得する際、数字のみからなるユーザ名を指定すると
- ユーザIDと混同してしまう問題を修正しました。他ユーザの「お気に入り」
- (favorites)を取得する場合にも同様の問題が起こりますが、こちらは修正
- できていません。「お気に入り」を取得するAPIにユーザIDではなくユーザ
- 名を指定するパラメータがないためです。
- Thanks to Makoto Fujiwara who reported this problem.
-* tweet編集バッファを開いた際の意図しないカーソル移動を解消
- `twittering-mode'で管理されていないバッファから
- `twittering-update-status-function'を呼び出して編集バッファを作ると
- 元のバッファでのカーソルが不必要に動かされてしまうバグを解消しました。
- Thanks to mofigan who reported this problem.
-* アイコン保存処理を修正
- `twittering-icon-storage-limit'もしくは`twittering-convert-fix-size'
- がnilの場合に、アイコンが正しく保存できていなかったのを修正しました。
- Thanks to HufflepuffBR who reported this problem about the former
- variable `twittering-icon-storage-limit'.
-* byte-compile時、`load-path'に無条件でパスが追加される問題を解消
- twittering-modeのrepositoryに含まれているディレクトリ`emacs21',
- `url-emacs21'がbyte-compile時に無条件で`load-path'に加えられており、
- byte-compile時にいくつかのマクロがEmacs21用の古い定義として取り込ま
- れていました。古い定義は22以降のEmacs上で使うことができませんので
- byte-compileによって正しく動作しないファイルが生成される状態になって
- いました。そこでbyte-compile時にもEmacs 22以降ではパスが追加されない
- よう変更して、この問題を解消しました。
- Thanks to HKey who has discovered the bug.
-* カーソル移動がおかしくなる問題を解消
- tweetに割り当てたtext propertyが干渉して、twittering-modeのbuffer内
- での論理行単位のカーソル移動がおかしくなっていました。この問題を解消
- しました。
- Thanks to lemit who reported the problem.
-* bufferからtweetを消すのをtweet削除APIが成功した後に変更
- bufferからtweetを消去するタイミングを`destroy-status' APIが成功した
- という応答を受け取った後に変更しました。APIが失敗に終わった場合、
- 対象tweetはbufferに残っているので再度削除を試みることができます。
-* search timeline spec内の検索文字列のエスケープを修正
-* 非同期実行される関数がエラーを起こしていたのを修正
- 存在しないユーザのtimelineを取得しようとすると非同期実行される関数が
- エラーを起こしてしまっていましたので、修正しました。
-
- 2.0.0: 2011-04-22
-------------------
-
-### 重要なお知らせ
-
-### 改良
-
-* OAuth, xAuthで取得した認証済みaccess tokenの暗号化保存に対応
- 認証済みaccess tokenをGnuPGで暗号化して保存することができます。
- tokenを保存しておけば、次回以降の起動時にOAuthのための外部
- ブラウザ起動やPIN入力等の手続きは必要なくなります。代わりに暗号化を
- 解くためのpassphraseを入力してください。
- この機能は"(setq twittering-use-master-password t)"とすれば有効に
- なります(デフォルトでは無効です)。
- 暗号化された秘密情報はデフォルトでは`~/.twittering-mode.gpg'に記録
- されますがこの保存先は変数`twittering-private-info-file'で変更可能
- です。
- この機能を有効にするには外部プログラムGnuPGに加えてEmacs LISPプロ
- グラム`alpaca.el'かEasyPGが必要です。Emacsは23以降であればEasyPGを
- 同梱していますので追加のEmacs LISPプログラムは必要ありません。
- `alpaca.el'はversion 0.13を想定していますので、他のversionでは動作に
- 問題がある恐れがあります。
-* xAuthのサポート
- OAuth認証の他にxAuthによる認証にも対応しました。xAuthによる認証を
- 有効にするには"(setq twittering-auth-method 'xauth)"の設定を追加して
- ください。
-* PINコード入力時に不必要な空白を自動で削除
-* 起動した外部プロセスのstatusを確認してdead-lockを回避
-* `user', `friends', `mentions', `public'でもnative retweetを表示
-* 起動した外部プロセスの異常終了を検出
- 異常終了したプロセスのexit-statusは"*Messages*"バッファで確認できます。
-* HTTPS通信でのサーバ認証の無効化に対応
- サーバ認証はデフォルトでは有効ですが、これを無効化することもできる
- ようになりました。"(setq twittering-allow-insecure-server-cert t)"の
- 設定でHTTPS通信時にもサーバ認証を行わなくなります。
-* 未知の数値文字参照を代替文字で置換
- decodeできない数値文字参照が現れたときにその文字を変数
- `twittering-unicode-replacement-char'で指定された文字に置換して表示
- します。代替文字のデフォルトはU+FFFDです。
-* サブディレクトリに`.nosearch'を追加
- 必要のないサブディレクトリが再帰的に`load-path'に追加されるのを防ぎ
- ます。
-* 初期timelineを複数設定している場合の認証情報入力回数を1回に変更
-* byte-compile後のclライブラリへの依存を解消
-* 内蔵しているCA証明書を更新
- 内蔵しているCA証明書を`Equifax Secure Certificate Authority'で置き
- 換えました。
-* StatusNetモードをサポート
- `twittering-mode.el'をStatusNet用に切り替えられるようになりました。
- "(setq twittering-service-method 'statusnet)"という設定で切り替わ
- ります。TwitterとStatusNetを同時に使うことはできませんので注意して
- ください。
- StatusNet向けに使うにはホスト情報の設定も必要になります。
- `http://identi.ca/'でのサービスの場合、以下のような設定が必要です。
- (setq twittering-service-method 'statusnet)
- (setq twittering-auth-method 'basic)
- (setq twittering-username "YOUR-ACCOUNT-NAME")
- ;; host
- (setq twittering-api-host "identi.ca")
- (setq twittering-api-search-host "identi.ca")
- (setq twittering-web-host "identi.ca")
- ;; paths for API
- (setq twittering-api-prefix "api/")
- (setq twittering-search-api-method "api/search")
- (setq twittering-web-path-prefix "")
-* "U"でtweet中のURIやそのtweet自体へのURIをコピー
- Thanks to Faried Nawaz.
-* "C-<mouse-3>"でtweetをコピー
- Thanks to Faried Nawaz.
-* wgetによるtweet取得に対応
- Twitterサーバとの通信に外部プログラムwgetを使えるようになりました。
- 下記の設定でwgetが優先して使われるようになります。
- (setq twittering-connection-type-order '(wget curl native))
-* 現在の通信方法(connection method)をモードライン上に表示
- デフォルトで現在の通信方法(connection method)がモードライン上に表示
- されます。下記の設定で表示しないようにもできます。
- (setq twittering-display-connection-method nil)
-* アイコン取得時の情報表示をデフォルトで抑制
- `twittering-url-show-status'のデフォルト値がnilに変更されました。
- デフォルトではアイコン取得時の情報は表示されなくなります。
-* urlライブラリによるtweet取得に対応
- 通信方法(connection method)として`urllib-http'と`urllib-https'を追加
- しました。`native'とは異なりHTTP redirectionもサポートしていますが
- 動作は遅く、また不安定になる場合もあるようです。他のmethodが利用できる
- 場合にはそちらを用いることを推奨します。
- `urllib-http',`urllib-https'を用いてのBASIC認証,xAuthで間違ったアカウ
- ント情報を与えるとurlライブラリの機能で再入力を求められますが、再入力
- した情報で通信を続行することはできません。再入力を求められたときはC-g
- でキャンセルし、改めてM-x twitを実行してください。
-* ユーザからの入力待ち状態になってから再描画
- 時刻やアイコン画像の表示のためのtweetの再描画を、Emacsがユーザからの
- 入力待ち状態(idle状態)に入り、その状態が一定時間継続してから行うように
- しました。待ち時間は変数`twittering-timer-interval-for-redisplaying'で
- 指定できます。デフォルトの待ち時間は1秒です。
-* curlやwgetでのアイコン画像取得に対応
- アイコン画像の取得にtweet取得と同じ通信方法(connection method)が使える
- ようになりました。各methodの優先順位はtweet取得と同じく変数
- `twittering-connection-type-order'で決定されます。
-* アイコン画像変更プログラムの遅延呼び出し
- アイコン画像を指定されたサイズに変更するためのプログラム(convert)実行
- をEmacsがユーザからの入力待ち状態(idle状態)になって一定時間が経過して
- から行うようにしました。待ち時間は変数
- `twittering-url-request-sentinel-delay'で指定できます。デフォルトの
- 待ち時間は1秒です。
-* 「お気に入り」に対応
- 「お気に入り」一覧を表示するtimeline specとして":favorites"と
- ":favorites/USER"を追加しました。":favorites/USER"で指定したユーザの
- 「お気に入り」を見ることができます。`twittering-visit-timeline'(デフォ
- ルトでは"V"にbindされています)に対して":favorites/"と入力してEnter
- すると、続いてユーザ名を補完入力できます。「お気に入り」は元々のtweetの
- 投稿時刻の順に表示されるので注意してください。これは「お気に入り」に
- 登録した時刻を取得する方法がないためです。また、取得できる「お気に入
- り」は最大20件です。より過去にさかのぼっての取得は未対応です。
-* 新たにいくつかの短縮URL生成サービスに対応
- 新たに`bit.ly', `goo.gl', `is.gd', `j.mp'に対応しました。下記のような
- 設定で有効にできます。
- (setq twittering-tinyurl-service 'bit.ly) ;; bit.lyの場合
- (setq twittering-tinyurl-service 'goo.gl) ;; goo.glの場合
- (setq twittering-tinyurl-service 'is.gd) ;; is.gdの場合
- (setq twittering-tinyurl-service 'j.mp) ;; j.mpの場合
- `bit.ly'や`j.mp'を使うにはお持ちのアカウントに応じて下記のように
- `twittering-bitly-login'と`twittering-bitly-api-key'を設定しておく必要が
- あります。
- (setq twittering-bitly-login "YOUR-LOGIN-NAME")
- (setq twittering-bitly-api-key "YOUR-API-KEY")
- Thanks to Michael Kohl and Lars Gregori.
-* 公式ReTweetについての書式指定子"%c","%C","%@"の意味を変更
- 公式ReTweetの`created_at'は、retweetした時刻ではなくオリジナルの
- tweetを投稿した時刻を意味するようになりました。
-* spam送信者報告機能
- 関数`twittering-block-and-report-as-spammer'を追加しました。tweet上で
- この関数を呼び出すと、その投稿者をブロックし、さらにspam送信者として
- 報告できます。
-* ブロック機能
- 関数`twittering-block'を追加しました。tweet上でこの関数を呼び出すと、
- その投稿者をブロックできます。
-* アイコン画像保存機能
- "(setq twittering-use-icon-storage t)"とすることで一度取得・サイズ変
- 更したアイコン画像を専用のファイルに保存しておけるようになりました。
- この機能はデフォルトでは無効です。次回以降は専用ファイルに格納された
- 画像が優先的に使われますのでアイコン取得・サイズ変更にかかる時間が省
- けます。
- デフォルトでは直近に描画されたアイコンを最大500個まで保存します。保
- 存されるアイコンの個数は変数`twittering-icon-storage-limit'で変更で
- きます。この変数をnilに設定すると全てのアイコンが保存されます。
- アイコンを保存するファイルはデフォルトでは
- `~/.twittering-mode-icons.gz'ですが`twittering-icon-storage-file'と
- いう変数で変更できます。あるバージョンのEmacsで生成したアイコン保存
- ファイルは別のバージョンでは使えない恐れがあるので注意してください。
-* 新しい書式指定子"%RT{...}"
- `twittering-status-format'で使える書式指定子として"%RT{...}"が追加さ
- れました。これは対象となるtweetが公式RTのときだけ描画されます。括弧
- の中には任意の文字列と書式指定子を入れることができ、括弧内の書式指定
- 子はRTされたtweetではなくそのRT自身の情報を使って描画されます。例え
- ば、"%RT{%s}"はRTしたユーザのscreen_nameとなります。
-* 公式ReTweetのキャンセル
- 自分自身が投稿した公式ReTweetをtweet削除と同じ操作(デフォルトで
- は'C-cD')でキャンセルできるようになりました。
-* あるユーザがフォローしているリストの補完付き選択機能
- 'C-uL'で特定ユーザがフォローしているリストを補完付きで選択し、開ける
- ようになりました。
-* Edit skeleton
- 投稿内容編集開始時に状況に応じて自動的に文字を追加できる仕組みを導入
- しました。edit skeletonはいつ、どのような文字列を先頭に、あるいは末
- 尾に追加するかの規則です。連想リスト`twittering-edit-skeleton-alist'
- に要素を追加することで、新しいedit skeletonを定義できます。edit
- skeletonの定義方法の詳細については`twittering-edit-skeleton-alist'の
- docstringを参照ください。
- デフォルトでは以下のedit skeletonが定義されています。
- none: 何も追加しません。
- footer: `twittering-edit-skeleton-footer'で指定された文字列をフッタ
- として末尾に追加します。
- footer-only-normal: footerと同様ですがreplyやdirect messageを編集す
- る際には追加を行いません。
- inherit-hashtags: 返信先に含まれるハッシュタグを末尾に追加します。
- inherit-mentions: 返信先に含まれるユーザ参照を先頭に追加します。
- inherit-any: 返信先に含まれるハッシュタグやユーザ参照を追加します。
- 関数`twittering-switch-edit-skeleton'で有効なedit skeletonを切り替え
- るにはことができます。
- また、フッタ文字列`twittering-edit-skeleton-footer'の内容は関数
- `twittering-edit-skeleton-change-footer'で変更できます。
-* 代替画像形式を指定する変数
- アイコン画像の形式がEmacsにサポートされていない形式である場合、画像
- をEmacsがサポートする形式に変換してから表示するのですが、その際の変
- 換先の画像形式を指定する変数`twittering-fallback-image-format'を追加
- しました。デフォルトの形式はXPMです。
- 下記のように設定すれば、NTEmacsでXPMを表示する際の不自然な挙動を回避
- できるかもしれません。 Thanks to Silver Chariot.
- (setq twittering-fallback-image-format 'png)
-
-### バグ修正
-
-* Emacs 23以降に同梱されているurlライブラリでも正しく動くよう修正
-* 外部コマンドcURLでbodyが空のPOSTを正しく行えるよう修正
-* Native retweetをさらにretweetできるよう修正
- オリジナルのtweetへのretweet扱いになります。
-* アカウント認証時に発生する可能性のあった競合状態が起こらないよう修正
-* 返信先として表示されているtweetへの返信を正しく扱うよう修正
- `twittering-show-replied-statuses'で返信先として表示されているtweetに
- 対して`twittering-enter'で返信したときに、カーソル下のtweetに対する
- 返信となるよう修正しました。
- Thanks to Naohiro Aota.
-* 書式指定子"%L"の振舞いを修正
- `twittering-status-format'のdocstringの通りに空白が挿入されるように
- なりました。
- Thanks to Tom X. Tobin.
-* アイコン画像取得の際に同一sentinelを複数回登録していたのを修正
-
- 1.0.0: 2010-06-05
-------------------
-
-### 重要なお知らせ
-
-#### ミニバッファからの投稿はサポート廃止予定です
-
-twittering-modeでtweetを投稿するには、これまではミニバッファから入力す
-る方法を採用していましたが、今回新機能としてポップアップバッファから投
-稿できる機能を実装しました。変数 `twittering-update-status-function` を
-設定することによってこの2つの方法を切り替えることができます。今回のリリー
-スでは、新しいポップアップバッファがデフォルトに設定されています。従来
-通りミニバッファから投稿したい場合は、この変数の値を
-twittering-update-status-from-minibuffer に設定してください。
-
-ポップアップバッファによる投稿では、従来の投稿方法に比べて次のような利
-点があります:
-
-* tweet入力時にIME等と干渉しない
-* 入力途中で誤って投稿してしまうミスがおきにくい
-* 入力内容の文字数を表示してくれる
-
-### 改良
-
-* ポップアップバッファを用いたtweetの編集、投稿機能
-* 環境変数 http_proxy, HTTP_PROXY を利用した自動プロキシ設定
-* 公式ReTweetサポート
-* タイムライン表示のフォーマット指定子に新たなものを追加
-* 一時ファイルを生成しない画像ファイル表示方法を採用
-* 'timeline spec'導入による柔軟なタイムライン表示機能
-* 'timeline spec'導入による複数タイムライン・複数バッファ表示のサポート
- * `twittering-initial-timeline-spec-string'を設定することで、初期化時
- に複数のタイムラインを表示させることが可能
-* 自動更新のon/offをサポート(キーボードの'a'で切り替え)
-* global-font-lockモードとの親和性向上
-* モードラインでの未読通知 (experimental)
-* フォーマット指定子 "%FILL{...}" の修正
-* タイムラインの切り替え機能(キーボードの 'f' と 'b' で切り替え)
-* SSLの有効/無効をモードラインの画像で表示
-* アイコン画像の非同期な取得と表示
-* tweetの削除機能('C-cD' で削除)
-* 'gnutls', 'openssl'コマンドを利用したtlsライブラリによるHTTPS通信
-* HTTPとHTTPSに個別のプロキシを設定可能に
-* 画像取得時の出力を抑制
- * .emacs に (setq twittering-url-show-status nil) を追加することで有
- 効にできる
-* OAuth認証対応
-
- 0.9: 2009-12-29
------------------
-
-### 改良
-
-* GitHubへ移動
-* 英語と日本語でWebサイトを開設
-* cURLが利用可能なときはHTTPSを使ってセキュアに通信するように
-* リスト対応
-* フォロー/リムーブ対応
-* お気に入り機能に対応
-* ハッシュタグ対応
-* ダイレクトメッセージ送信に対応
-* URLをその場でTinyURL化する機能
-* 入力文字列の文字数チェック
-* ReTweetの形式を選択可能に
-* 閲覧したユーザー名や、送信したつぶやきの履歴を保存
-* 一度に取得するつぶやきの数をパラメータ化
-* ユーザー名やURLなどの要素をTABキーで移動可能に
-* 'file'コマンドを利用した画像の種類の判別
-* よりわかりやすいエラー出力
-* 取得済みのタイムラインのデータを保持するように
-* サスペンド機能
-* Imagemagickが利用可能なときは画像のリサイズを行うように
-* 単体テストフレームワークの導入
-* 'Proxy-connection: Keep-Alive'への対応
-* 柔軟な文字列フォーマット関数の導入(twittering-format-string)
-* HTTPレスポンス処理の効率改善
-
-### バグ修正
-
-* マウスクリックやEnterキーでURLを開けない問題を修正
-* ReTweetのときはオリジナルIDを設定しないように
-* URL抽出の正規表現を修正
-* ユーザー名抽出の処理を修正
-* モードラインを即時更新するよう修正
-* 各HTTPセッションごとに一時バッファを利用するよう変更
-* MD5ハッシュを利用して同じ名前の画像ファイルの衝突を回避
-* センティネルでバッファをkillする際のエラー処理
-* いくつかの誤字修正
-
-### 感謝
-
-* Alberto Garcia
-* Jaemok Jeong
-* Kouhei Sutou
-* Naohiro Aota
-* Satoshi Yatagawa
-* Tadashi MATSUO
-* Thomas Danckaert
-* Tsuyoshi CHO
-* IMAI Toshiyuki
-
+++ /dev/null
- Twittering-mode: Emacs用Twitterクライアント
-=============================================
-
-Twittering-modeを使うと、EmacsenからTwitterを利用することができます。
-
-- web: http://twmode.sf.net
-- github: http://github.com/hayamiz/twittering-mode
-
- 機能
-------
-
-* Twitterの機能への対応状況:
- * 様々なタイムラインの閲覧
- * フレンドタイムライン
- * 返信
- * ユーザーのタイムライン
- * パブリックタイムライン
- * つぶやきの投稿
- * ダイレクトメッセージ
- * ReTweet
- * ハッシュタグ
- * 署名
- * フォロー/リムーブ
- * お気に入り
-* HTTPプロキシ対応
-* HTTPSによる安全な通信
-
- 動作確認環境
---------------
-
-- GNU Emacs 21 (一部機能制限あり)
-- GNU Emacs 22, 23
-
- 作者と協力者
---------------
-
-- Y. Hayamizu
-- naoya_t
-- Tsuyoshi CHO
-- Alberto Garcia
-- Satoshi Yatagawa
-- 高山智也
-- 松尾(cvmat)
-- 青田(naota)
-- Jaemok Jeong(jmjeong)
-- Thomas Danckaert
-- IMAI Toshiyuki
-
- 参考
-------
-
-- http://www.emacswiki.org/emacs-en/TwitteringMode
+++ /dev/null
- Twittering-mode: a Twitter client for Emacs
-=============================================
-
-Twittering-mode enables you to twit on Emacsen.
-
-- web: http://twmode.sf.net
-- github: http://github.com/hayamiz/twittering-mode
-
- Features
-----------
-
-* Activities on Twitter
- * Viewing various timelines
- * Home timeline
- * Replies
- * User's timeline
- * Public timeline
- * Favorites timeline
- * Retweets timeline
- * Merged timeline
- * Timeline without tweets satisfying a condition
- * Posting tweets
- * Direct message
- * ReTweet
- * Hash tag
- * Signature
- * Following and removing users
- * Marking tweets as favorites
-* HTTP Proxy support
-* Secure connection via HTTPS (cURL, GNU Wget, OpenSSL or GnuTLS is required)
-
- Supported Emacsen
--------------------
-
-- GNU Emacs 21 (some restrictions)
-- GNU Emacs 22, 23, 24
-
- Prerequisites
--------------------
-
-- For SSL connection, one of the followings is required.
- SSL connection is required for the Twitter REST API v1.1.
- - cURL http://curl.haxx.se/
- - GNU Wget http://www.gnu.org/software/wget/
- - OpenSSL http://www.openssl.org/
- - GnuTLS http://www.gnu.org/software/gnutls/
-- For parsing JSON, json.el is required.
- It is distributed with Emacs 23.1 and later.
-- For keeping an OAuth authorized token in a local storage encrypted
- with master password, GnuPG ( http://www.gnupg.org/ ) is required.
- On Emacs 22 and earlier, either EasyPG ( http://epg.sourceforge.jp/ )
- or alpaca.el( http://www.mew.org/~kazu/proj/cipher/ ) is also
- required.
-- For displaying icons in formats that are not supported by Emacs and
- resizing icon images, ImageMagick ( http://www.imagemagick.org/ ) or
- its compatible alternative is required, e.g. GraphicsMagick
- ( http://www.graphicsmagick.org/ ). Note that twittering-mode on
- icon-mode converts retrieved icons into XPM in default. So,
- icon-mode without additional configuration requires, ImageMagick (or
- its alternative).
-- For keeping retrieved icons in a local storage, gzip
- ( http://www.gzip.org/ ) is required.
-
- Quick start
-------------------------
-
-0. Put *twittering-mode.el* in a directory specified by the variable
- `load-path`. Note that the directories *emacs21* and *url-emacs21*
- must be placed at the same directory on Emacs 21. On Windows
- without curl or wget, the directory *win-curl* must be placed
- there. You can add a directory to the variable `load-path` by
- `(add-to-list 'load-path "ADDITIONAL-DIRECTORY")`.
-1. Execute `M-x twit` to run twittering-mode.
-2. Open OAuth authorization page with an external browser, click *Allow*,
- and enter the PIN code in the prompt of Emacs.
-
- If you have introduced the configuration
- `(setq twittering-use-master-password t)`, twittering-mode will
- ask you a master password and it will write the authorized OAuth
- token into *~/.twittering-mode.gpg* (in default) with encryption.
- Once the authorized OAuth token is encrypted, you do not have to
- retrieve a PIN code with an external browser. The master password
- is only required to establish authorized connection to Twitter.
-3. Your home timeline will appear. Basic key bindings are as
- follows.
- - `V`: Open or switch to another timeline by
- [timeline-spec](#timeline-spec).
- - `u` or `C-cC-s`: Post a tweet.
- - `RET`: Post a reply to the pointed tweet or open the pointed URL
- with `browse-url`.
- - `C-c RET`: Post an organic retweet. This is only a tweet citing
- the pointed tweet and not an official/native retweet.
- - `C-uC-c RET`: Post an official/native retweet.
- - `d`: Send a direct message.
- - `C-cC-w`: Delete the pointed tweet.
-4. Add some of the following major configurations to your init file
- if you like.
- - To display icons, add `(setq twittering-icon-mode t)`.
- This may require ImageMagick or its compatible alternative.
- - To resize icons, add `(setq twittering-convert-fix-size SIZE)`.
- The default size is 48 pixels. This requires ImageMagick or its
- compatible alternative.
- - To keep retrieved icons in a local storage, add
- `(setq twittering-use-icon-storage t)`. This requires gzip. The
- icons are saved on *~/.twittering-mode-icons.gz*, which can be
- changed by the variable `twittering-icon-storage-file`.
- - To display tweets in the *reverse* order, add
- `(setq twittering-reverse-mode t)`. With it, the latest tweet
- is rendered the bottom of the buffer.
- - To use a HTTP proxy, add the following configuration.
- <pre><code>
- (setq twittering-proxy-use t)
- (setq twittering-proxy-server "PROXY-HOSTNAME")
- (setq twittering-proxy-port PROXY-PORT-NUMBER)
- </code></pre>
- - To change the number of tweets retrieved at once, add
- `(setq twittering-number-of-tweets-on-retrieval NUMBER)`.
- - To change the interval of retrieving tweets, add
- `(setq twittering-timer-interval SECOND)`. You should be careful
- not to exceed the limitation of number of API calls.
- - To display the number of unread tweets on the mode-line, add
- `(twittering-enable-unread-status-notifier)`.
- - To display the remaining number of API calls, add
- `(setq twittering-display-remaining t)`.
- - To change the format of an organic retweet, configure the
- variable `twittering-retweet-format`. For example, add
- `(setq twittering-retweet-format '(nil _ " %u RT @%s: %t"))`.
- For details, see the docstring of the variable by
- `M-x describe-variable`.
- - To change the timelines automatically opened on starting
- twittering-mode, configure the variable
- `twittering-initial-timeline-spec-string`. For example,
- add the below configuration.
- <pre><code>
- (setq twittering-initial-timeline-spec-string
- '("(:home+@)"
- "(:search/twittering mode/+:search/twmode/)"))
- </code></pre>
- For details, see the docstring of the variable by
- `M-x describe-variable`.
- - To customize the format of tweets, configure the variable
- `twittering-status-format`. For example, add the below
- configuration.
- <pre><code>
- (setq twittering-status-format
- "%FOLD{%RT{%FACE[bold]{RT}}%i%s>>%r @%C{%Y-%m-%d %H:%M:%S} %@{}\n%FOLD[ ]{%T%RT{\nretweeted by %s @%C{%Y-%m-%d %H:%M:%S}}}}")
- </code></pre>
- For details, see the docstring of the variable by
- `M-x describe-variable`.
- - To inherit mentions and hashtags on editing a reply, add
- `(setq twittering-edit-skeleton 'inherit-any)`.
- For details, see the docstring of the variable by
- `M-x describe-variable`.
-
- Enjoy!
-
- Usage
-------------------------
-- Move the cursor.
- - `0`: Go to the beginning of the line.
- - `^`: Go to the beginning of the text on the line.
- - `$`: Go to the end of the line.
- - `G`: Go to the bottom tweet.
- - `H`: Go to the top tweet.
- - `h`: Move the cursor left.
- - `j`: Go to the next tweet.
- - `k`: Go to the previous tweet.
- - `l`: Move the cursor right.
- - `n`: Go to the next tweet by the author of the pointed tweet.
- - `p`: Go to the previous tweet by the author of the pointed tweet.
- - `TAB`: Go to the next thing (link, user name, URL, etc.).
- - `M-TAB` or `<backtab>`: Go to the previous thing (link, user name,
- URL, etc.).
- - `C-v` or `SPC`: Scroll the buffer upward.
- - `M-v` or `<backspace>`: Scroll the buffer downward.
-- Switch a timeline.
- - `L`: Open a list timeline interactively.
- - `V`: Open a timeline by [timeline-spec](#timeline-spec).
- - `b`: Switch to the previous timeline.
- - `f`: Switch to the next timeline.
- - `C-cC-d`: Open the direct messages timeline.
- This is equivalent to `V` with `:direct_messages`.
- - `v`: Open the home timeline of the pointed user.
- - `C-cC-f`: Open the friend timeline.
- This is equivalent to `V` with `:friends`.
- - `C-cC-q`: Open a search timeline.
- This is equivalent to `V` with `:search/QUERY/`.
- - `C-cC-r`: Open the replies timeline.
- This is equivalent to `V` with `:replies`.
- - `C-cC-u`: Open the current user timeline.
- This is equivalent to `V` with `USERNAME`, where *USERNAME* is
- your screen-name.
- - `q`: Close the current buffer.
-- Update/clear the timeline.
- - `g`: Update the current timeline.
- - `C-cC-e`: Erase tweets of the current buffer from memory.
-- Display replied tweets.
- - `r`: Display replied tweets or hide them.
- - `R`: Display replied tweets, retrieve the replied tweet or hide
- them.
-- Post a tweet.
- - `u` or `C-cC-s`: Post a tweet.
- - `RET`: Post a reply to the pointed tweet or open the pointed URL
- with `browse-url`.
- - `C-c RET`: Post an organic retweet. This is only a tweet citing
- the pointed tweet and not an official/native retweet.
- - `C-uC-c RET`: Post an official/native retweet.
- - `d`: Send a direct message.
- - `C-cC-l`: Post a joke message.
-- Delete a tweet.
- - `C-cC-w`: Delete the pointed tweet.
-- View more info.
- - `U`: Push the URL of the pointed link or tweet onto the kill ring.
- - `C-cC-v`: Open the profile of the pointed user with `browse-url`.
- - `<mouse-1>`: Open the pointed URL with `browse-url`.
-- Change the mode of twittering-mode.
- - `a`: Toggle the state of the buffer between active/inactive.
- Twittering-mode does not update an inactive buffer.
- - `i`: Toggle the state of the buffer between with or without icon
- images.
- - `t` or `C-cC-p`: Toggle between with or without a proxy server.
- - `C-cC-t`: Set the current hashtag.
-
-
-<a id="timeline-spec">Timeline spec</a>
-------------------------
-By pressing *V* (`twittering-visit-timeline`) on twittering-mode, you
-can specify a timeline to be opened by *timeline spec*.
-A timeline spec can be used anywhere you have to specify a timeline.
-
-The valid timeline specs follows:
-
-- Basic timeline
- - `:home` : The home timeline.
- - `:mentions` : Tweets mentioning you.
- - `:public` : The public timeline.
- - `USER` : Tweets posted by *USER*.
- - `USER/LISTNAME` :
- The list timeline owned by *USER* and named *LISTNAME*.
-- Direct message
- - `:direct_messages` : Direct messages sent to you.
- - `:direct_messages_sent` : Direct messages that you sent.
-- Favorite
- - `:favorites` : Tweets that you marked as a favorite.
- - `:favorites/USER` : Tweets that *USER* marked as a favorite.
-- Hashtag
- - `#HASHTAG` : Tweets including *#HASHTAG*.
-- Retweet
- - `:retweeted_by_me` : Retweets that you posted.
- - `:retweeted_by_user/USER` : Retweets posted by *USER*.
- - `:retweeted_to_me` : Retweets sent to your home timeline.
- - `:retweeted_to_user/USER` :
- Retweets sent to *USER*'s home timeline.
- - `:retweets_of_me` :
- Your tweets that have been retweeted by others.
-- Single
- - `:single/ID` : A tweet specified by *ID*.
-- Search
- - `:search/QUERY-STRING/` :
- Tweets matching *QUERY-STRING*. In *QUERY-STRING*, */* (slash) and
- *\\* (backslash) must be escaped as *\\/* or *\\\\*, respectively.
-- Alias<br />
- You can define aliases for timeline specs. By defining a short alias
- as a long timeline spec, you can refer it more easily. There are two
- types of alias, *simple* and *functional* as below. Both types are
- defined in the association list bound to the variable
- `twittering-timeline-spec-alias`.
- - `$ALIAS-NAME`
- The timeline spec bound to *ALIAS-NAME* in
- `twittering-timeline-spec-alias`.
- - `$ALIAS-NAME(ARGUMENT)`
- The timeline spec generated by calling the function, which is
- bound to *ALIAS-NAME* in `twittering-timeline-spec-alias`, with
- the argument *ARGUMENT*. The function can be specified as a symbol
- or a lambda expression.
- Functions must receive one string argument.
-
- As an example, consider the following definition of
- `twittering-timeline-spec-alias`.
- <pre><code>
- (setq twittering-timeline-spec-alias
- '(("FRIENDS" . "my-account/friends-list")
- ("related-to" .
- (lambda (username)
- (if username
- (format ":search/to:%s OR from:%s OR @%s/"
- username username username)
- ":home")))
- ("related-to-twitter" . "$related-to(twitter)")))
- </code></pre>
- With this configuration, you can use the below aliases.
- - `$FRIENDS` is equivalent to `my-account/friends-list`.
- - `$related-to` is equivalent to `:home`.
- - `$related-to(twitterapi)` is equivalent to `:search/to:twitterapi OR from:twitterapi OR @twitterapi/`.
- - `$related-to-twitter` is equivalent to `:search/to:twitter OR from:twitter OR @twitter/`.
-
- You can use an alias on definition of other aliases, but an alias
- including a circular-reference is forbidden.
-- Composite timeline spec
- - `(SPEC1+SPEC2)` :
- The timeline generated by merging two timelines, specified by
- *SPEC1* and *SPEC2*.
- - `:exclude-if/FUNC/SPEC` :
- The timeline equals *SPEC*, except that it does not include tweets
- that the function *FUNC* returns non-nil for. *FUNC* must be a
- function that receives an alist corresponding to a tweet as an
- argument. A lambda expression and a symbol bound to a function are
- valid as *FUNC*. But a symbol name must not include two special
- characters, "(" or "/". You can specify any timeline spec for
- *SPEC*. For example, you can ignore tweets including "WORD" from the
- home timeline by the following timeline spec;
- `:exclude-if/(lambda (tweet) (string-match "WORD" (cdr (assq 'text tweet))))/:home`.
- - `:exclude-re/REGEXP/SPEC` :
- The timeline equals *SPEC*, except that it does not include tweets
- that match the regular expression *REGEXP*. In *REGEXP*, a slash
- must be escaped with a backslash. For example, tweets including a
- slash are excluded from the timeline corresponding to the Emacs
- string literal `":exclude-re/\\//:home"`.
-
- Authors & Contributors
-------------------------
-
-- Y. Hayamizu
-- naoya_t
-- Tsuyoshi CHO
-- Alberto Garcia
-- Satoshi Yatagawa
-- 高山智也
-- Tadashi MATSUO (cvmat)
-- 青田(naota)
-- Jaemok Jeong(jmjeong)
-- Thomas Danckaert
-- IMAI Toshiyuki
-
- See also
-----------
-
-- http://www.emacswiki.org/emacs-en/TwitteringMode
+++ /dev/null
-
-== ToDo List ==
-
-- use temporary buffers for http request
-- write more tests
+++ /dev/null
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
-dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
-MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
-dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
-BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
-cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
-MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
-aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
-ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
-IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
-7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
-1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
------END CERTIFICATE-----
+++ /dev/null
------BEGIN CERTIFICATE-----\r
-MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\r
-MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\r
-YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG\r
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg\r
-R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9\r
-9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq\r
-fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv\r
-iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU\r
-1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+\r
-bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW\r
-MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA\r
-ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l\r
-uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn\r
-Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS\r
-tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF\r
-PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un\r
-hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV\r
-5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==\r
------END CERTIFICATE-----\r
+++ /dev/null
------BEGIN CERTIFICATE-----\r
-MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ\r
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh\r
-c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy\r
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp\r
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X\r
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw\r
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg\r
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo\r
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5\r
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB\r
-AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4\r
-pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0\r
-13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID\r
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk\r
-U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i\r
-F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY\r
-oJ2daZH9\r
------END CERTIFICATE-----
\ No newline at end of file
+++ /dev/null
-
-.PHONY: all update-po
-
-all:
-
-update-po:
- $(MAKE) -C web update-po
- $(MAKE) -C manual update-po
-
-
-
+++ /dev/null
-
-.PHONY: all update-po clean
-
-all: twmode/twmode.html
-
-update-po:
-
-twmode/twmode.html: twmode.texinfo
- texi2html --split chapter $<
-
-clean:
- rm -rf twmode
+++ /dev/null
-
-@appendix GNU Free Documentation License
-
-@cindex FDL, GNU Free Documentation License
-@center Version 1.1, March 2000
-
-@display
-Copyright @copyright{} 2000 Free Software Foundation, Inc.
-59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
-
-Everyone is permitted to copy and distribute verbatim copies
-of this license document, but changing it is not allowed.
-@end display
-
-@enumerate 0
-@item
-PREAMBLE
-
-The purpose of this License is to make a manual, textbook, or other
-written document @dfn{free} in the sense of freedom: to assure everyone
-the effective freedom to copy and redistribute it, with or without
-modifying it, either commercially or noncommercially. Secondarily,
-this License preserves for the author and publisher a way to get
-credit for their work, while not being considered responsible for
-modifications made by others.
-
-This License is a kind of ``copyleft'', which means that derivative
-works of the document must themselves be free in the same sense. It
-complements the GNU General Public License, which is a copyleft
-license designed for free software.
-
-We have designed this License in order to use it for manuals for free
-software, because free software needs free documentation: a free
-program should come with manuals providing the same freedoms that the
-software does. But this License is not limited to software manuals;
-it can be used for any textual work, regardless of subject matter or
-whether it is published as a printed book. We recommend this License
-principally for works whose purpose is instruction or reference.
-
-@item
-APPLICABILITY AND DEFINITIONS
-
-This License applies to any manual or other work that contains a
-notice placed by the copyright holder saying it can be distributed
-under the terms of this License. The ``Document'', below, refers to any
-such manual or work. Any member of the public is a licensee, and is
-addressed as ``you''.
-
-A ``Modified Version'' of the Document means any work containing the
-Document or a portion of it, either copied verbatim, or with
-modifications and/or translated into another language.
-
-A ``Secondary Section'' is a named appendix or a front-matter section of
-the Document that deals exclusively with the relationship of the
-publishers or authors of the Document to the Document's overall subject
-(or to related matters) and contains nothing that could fall directly
-within that overall subject. (For example, if the Document is in part a
-textbook of mathematics, a Secondary Section may not explain any
-mathematics.) The relationship could be a matter of historical
-connection with the subject or with related matters, or of legal,
-commercial, philosophical, ethical or political position regarding
-them.
-
-The ``Invariant Sections'' are certain Secondary Sections whose titles
-are designated, as being those of Invariant Sections, in the notice
-that says that the Document is released under this License.
-
-The ``Cover Texts'' are certain short passages of text that are listed,
-as Front-Cover Texts or Back-Cover Texts, in the notice that says that
-the Document is released under this License.
-
-A ``Transparent'' copy of the Document means a machine-readable copy,
-represented in a format whose specification is available to the
-general public, whose contents can be viewed and edited directly and
-straightforwardly with generic text editors or (for images composed of
-pixels) generic paint programs or (for drawings) some widely available
-drawing editor, and that is suitable for input to text formatters or
-for automatic translation to a variety of formats suitable for input
-to text formatters. A copy made in an otherwise Transparent file
-format whose markup has been designed to thwart or discourage
-subsequent modification by readers is not Transparent. A copy that is
-not ``Transparent'' is called ``Opaque''.
-
-Examples of suitable formats for Transparent copies include plain
-@sc{ascii} without markup, Texinfo input format, La@TeX{} input format,
-@acronym{SGML} or @acronym{XML} using a publicly available
-@acronym{DTD}, and standard-conforming simple @acronym{HTML} designed
-for human modification. Opaque formats include PostScript,
-@acronym{PDF}, proprietary formats that can be read and edited only by
-proprietary word processors, @acronym{SGML} or @acronym{XML} for which
-the @acronym{DTD} and/or processing tools are not generally available,
-and the machine-generated @acronym{HTML} produced by some word
-processors for output purposes only.
-
-The ``Title Page'' means, for a printed book, the title page itself,
-plus such following pages as are needed to hold, legibly, the material
-this License requires to appear in the title page. For works in
-formats which do not have any title page as such, ``Title Page'' means
-the text near the most prominent appearance of the work's title,
-preceding the beginning of the body of the text.
-
-@item
-VERBATIM COPYING
-
-You may copy and distribute the Document in any medium, either
-commercially or noncommercially, provided that this License, the
-copyright notices, and the license notice saying this License applies
-to the Document are reproduced in all copies, and that you add no other
-conditions whatsoever to those of this License. You may not use
-technical measures to obstruct or control the reading or further
-copying of the copies you make or distribute. However, you may accept
-compensation in exchange for copies. If you distribute a large enough
-number of copies you must also follow the conditions in section 3.
-
-You may also lend copies, under the same conditions stated above, and
-you may publicly display copies.
-
-@item
-COPYING IN QUANTITY
-
-If you publish printed copies of the Document numbering more than 100,
-and the Document's license notice requires Cover Texts, you must enclose
-the copies in covers that carry, clearly and legibly, all these Cover
-Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
-the back cover. Both covers must also clearly and legibly identify
-you as the publisher of these copies. The front cover must present
-the full title with all words of the title equally prominent and
-visible. You may add other material on the covers in addition.
-Copying with changes limited to the covers, as long as they preserve
-the title of the Document and satisfy these conditions, can be treated
-as verbatim copying in other respects.
-
-If the required texts for either cover are too voluminous to fit
-legibly, you should put the first ones listed (as many as fit
-reasonably) on the actual cover, and continue the rest onto adjacent
-pages.
-
-If you publish or distribute Opaque copies of the Document numbering
-more than 100, you must either include a machine-readable Transparent
-copy along with each Opaque copy, or state in or with each Opaque copy
-a publicly-accessible computer-network location containing a complete
-Transparent copy of the Document, free of added material, which the
-general network-using public has access to download anonymously at no
-charge using public-standard network protocols. If you use the latter
-option, you must take reasonably prudent steps, when you begin
-distribution of Opaque copies in quantity, to ensure that this
-Transparent copy will remain thus accessible at the stated location
-until at least one year after the last time you distribute an Opaque
-copy (directly or through your agents or retailers) of that edition to
-the public.
-
-It is requested, but not required, that you contact the authors of the
-Document well before redistributing any large number of copies, to give
-them a chance to provide you with an updated version of the Document.
-
-@item
-MODIFICATIONS
-
-You may copy and distribute a Modified Version of the Document under
-the conditions of sections 2 and 3 above, provided that you release
-the Modified Version under precisely this License, with the Modified
-Version filling the role of the Document, thus licensing distribution
-and modification of the Modified Version to whoever possesses a copy
-of it. In addition, you must do these things in the Modified Version:
-
-@enumerate A
-@item
-Use in the Title Page (and on the covers, if any) a title distinct
-from that of the Document, and from those of previous versions
-(which should, if there were any, be listed in the History section
-of the Document). You may use the same title as a previous version
-if the original publisher of that version gives permission.
-
-@item
-List on the Title Page, as authors, one or more persons or entities
-responsible for authorship of the modifications in the Modified
-Version, together with at least five of the principal authors of the
-Document (all of its principal authors, if it has less than five).
-
-@item
-State on the Title page the name of the publisher of the
-Modified Version, as the publisher.
-
-@item
-Preserve all the copyright notices of the Document.
-
-@item
-Add an appropriate copyright notice for your modifications
-adjacent to the other copyright notices.
-
-@item
-Include, immediately after the copyright notices, a license notice
-giving the public permission to use the Modified Version under the
-terms of this License, in the form shown in the Addendum below.
-
-@item
-Preserve in that license notice the full lists of Invariant Sections
-and required Cover Texts given in the Document's license notice.
-
-@item
-Include an unaltered copy of this License.
-
-@item
-Preserve the section entitled ``History'', and its title, and add to
-it an item stating at least the title, year, new authors, and
-publisher of the Modified Version as given on the Title Page. If
-there is no section entitled ``History'' in the Document, create one
-stating the title, year, authors, and publisher of the Document as
-given on its Title Page, then add an item describing the Modified
-Version as stated in the previous sentence.
-
-@item
-Preserve the network location, if any, given in the Document for
-public access to a Transparent copy of the Document, and likewise
-the network locations given in the Document for previous versions
-it was based on. These may be placed in the ``History'' section.
-You may omit a network location for a work that was published at
-least four years before the Document itself, or if the original
-publisher of the version it refers to gives permission.
-
-@item
-In any section entitled ``Acknowledgments'' or ``Dedications'',
-preserve the section's title, and preserve in the section all the
-substance and tone of each of the contributor acknowledgments
-and/or dedications given therein.
-
-@item
-Preserve all the Invariant Sections of the Document,
-unaltered in their text and in their titles. Section numbers
-or the equivalent are not considered part of the section titles.
-
-@item
-Delete any section entitled ``Endorsements''. Such a section
-may not be included in the Modified Version.
-
-@item
-Do not retitle any existing section as ``Endorsements''
-or to conflict in title with any Invariant Section.
-@end enumerate
-
-If the Modified Version includes new front-matter sections or
-appendices that qualify as Secondary Sections and contain no material
-copied from the Document, you may at your option designate some or all
-of these sections as invariant. To do this, add their titles to the
-list of Invariant Sections in the Modified Version's license notice.
-These titles must be distinct from any other section titles.
-
-You may add a section entitled ``Endorsements'', provided it contains
-nothing but endorsements of your Modified Version by various
-parties---for example, statements of peer review or that the text has
-been approved by an organization as the authoritative definition of a
-standard.
-
-You may add a passage of up to five words as a Front-Cover Text, and a
-passage of up to 25 words as a Back-Cover Text, to the end of the list
-of Cover Texts in the Modified Version. Only one passage of
-Front-Cover Text and one of Back-Cover Text may be added by (or
-through arrangements made by) any one entity. If the Document already
-includes a cover text for the same cover, previously added by you or
-by arrangement made by the same entity you are acting on behalf of,
-you may not add another; but you may replace the old one, on explicit
-permission from the previous publisher that added the old one.
-
-The author(s) and publisher(s) of the Document do not by this License
-give permission to use their names for publicity for or to assert or
-imply endorsement of any Modified Version.
-
-@item
-COMBINING DOCUMENTS
-
-You may combine the Document with other documents released under this
-License, under the terms defined in section 4 above for modified
-versions, provided that you include in the combination all of the
-Invariant Sections of all of the original documents, unmodified, and
-list them all as Invariant Sections of your combined work in its
-license notice.
-
-The combined work need only contain one copy of this License, and
-multiple identical Invariant Sections may be replaced with a single
-copy. If there are multiple Invariant Sections with the same name but
-different contents, make the title of each such section unique by
-adding at the end of it, in parentheses, the name of the original
-author or publisher of that section if known, or else a unique number.
-Make the same adjustment to the section titles in the list of
-Invariant Sections in the license notice of the combined work.
-
-In the combination, you must combine any sections entitled ``History''
-in the various original documents, forming one section entitled
-``History''; likewise combine any sections entitled ``Acknowledgments'',
-and any sections entitled ``Dedications''. You must delete all sections
-entitled ``Endorsements.''
-
-@item
-COLLECTIONS OF DOCUMENTS
-
-You may make a collection consisting of the Document and other documents
-released under this License, and replace the individual copies of this
-License in the various documents with a single copy that is included in
-the collection, provided that you follow the rules of this License for
-verbatim copying of each of the documents in all other respects.
-
-You may extract a single document from such a collection, and distribute
-it individually under this License, provided you insert a copy of this
-License into the extracted document, and follow this License in all
-other respects regarding verbatim copying of that document.
-
-@item
-AGGREGATION WITH INDEPENDENT WORKS
-
-A compilation of the Document or its derivatives with other separate
-and independent documents or works, in or on a volume of a storage or
-distribution medium, does not as a whole count as a Modified Version
-of the Document, provided no compilation copyright is claimed for the
-compilation. Such a compilation is called an ``aggregate'', and this
-License does not apply to the other self-contained works thus compiled
-with the Document, on account of their being thus compiled, if they
-are not themselves derivative works of the Document.
-
-If the Cover Text requirement of section 3 is applicable to these
-copies of the Document, then if the Document is less than one quarter
-of the entire aggregate, the Document's Cover Texts may be placed on
-covers that surround only the Document within the aggregate.
-Otherwise they must appear on covers around the whole aggregate.
-
-@item
-TRANSLATION
-
-Translation is considered a kind of modification, so you may
-distribute translations of the Document under the terms of section 4.
-Replacing Invariant Sections with translations requires special
-permission from their copyright holders, but you may include
-translations of some or all Invariant Sections in addition to the
-original versions of these Invariant Sections. You may include a
-translation of this License provided that you also include the
-original English version of this License. In case of a disagreement
-between the translation and the original English version of this
-License, the original English version will prevail.
-
-@item
-TERMINATION
-
-You may not copy, modify, sublicense, or distribute the Document except
-as expressly provided for under this License. Any other attempt to
-copy, modify, sublicense or distribute the Document is void, and will
-automatically terminate your rights under this License. However,
-parties who have received copies, or rights, from you under this
-License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-@item
-FUTURE REVISIONS OF THIS LICENSE
-
-The Free Software Foundation may publish new, revised versions
-of the GNU Free Documentation 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. See
-@uref{http://www.gnu.org/copyleft/}.
-
-Each version of the License is given a distinguishing version number.
-If the Document specifies that a particular numbered version of this
-License ``or any later version'' applies to it, you have the option of
-following the terms and conditions either of that specified version or
-of any later version that has been published (not as a draft) by the
-Free Software Foundation. If the Document does not specify a version
-number of this License, you may choose any version ever published (not
-as a draft) by the Free Software Foundation.
-@end enumerate
-
-@page
-@appendixsubsec ADDENDUM: How to use this License for your documents
-
-To use this License in a document you have written, include a copy of
-the License in the document and put the following copyright and
-license notices just after the title page:
-
-@smallexample
-@group
- Copyright (C) @var{year} @var{your name}.
- Permission is granted to copy, distribute and/or modify this document
- under the terms of the GNU Free Documentation License, Version 1.1
- or any later version published by the Free Software Foundation;
- with the Invariant Sections being @var{list their titles}, with the
- Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}.
- A copy of the license is included in the section entitled ``GNU
- Free Documentation License''.
-@end group
-@end smallexample
-
-If you have no Invariant Sections, write ``with no Invariant Sections''
-instead of saying which ones are invariant. If you have no
-Front-Cover Texts, write ``no Front-Cover Texts'' instead of
-``Front-Cover Texts being @var{list}''; likewise for Back-Cover Texts.
-
-If your document contains nontrivial examples of program code, we
-recommend releasing these examples in parallel under your choice of
-free software license, such as the GNU General Public License,
-to permit their use in free software.
-
-@c Local Variables:
-@c ispell-local-pdict: "ispell-dict"
-@c End:
-
+++ /dev/null
-\input texinfo @c -*-texinfo-*-
-@c %**start of header
-@setfilename twmode.info
-@settitle Twittering-mode user's manual
-@c %**end of header
-@copying
-The manual for twittering-mode users..
-
-Copyright @copyright{} 2010 Yuto Hayamizu
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3
-or any later version published by the Free Software Foundation;
-with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
-A copy of the license is included in the section entitled ``GNU
-Free Documentation License''.
-
-A copy of the license is also available from the Free Software
-Foundation Web site at @url{http://www.gnu.org/licenses/fdl.html}.
-
-@end quotation
-
-The document was typeset with
-@uref{http://www.texinfo.org/, GNU Texinfo}.
-
-@end copying
-
-@titlepage
-@title Twittering-mode manual
-@subtitle The manual for twittering-mode lovers.
-@author Yuto Hayamizu <y.hayamizu@@gmail.com>
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@c Output the table of the contents at the beginning.
-@contents
-
-@ifnottex
-@node Top
-@top Twittering-mode manual
-
-@insertcopying
-@end ifnottex
-
-@c Generate the nodes for this menu with `C-c C-u m'.
-@menu
-* Getting started::
-* Introduction::
-* Copying This Manual::
-* Index::
-@end menu
-
-@c Update all node entries with `C-c C-u C-n'.
-@c Insert new nodes with `C-c C-c n'.
-
-@node Getting started
-@chapter Getting started
-
-@section Installation
-
-@itemize @bullet
-@item
-Download the latest twittering-mode from
-@uref{http://twmode.sf.net/,http://twmode.sf.net/}, and expand it.
-@item
-Copy following files and directories to the same directory, which is
-included in your @code{load-path}:
-@itemize @bullet
-@item
-@file{twittering-mode.el}
-@item
-(Windows users only) @file{win-curl/}
-@item
-(Emacs21 or older users only) @file{url-emacs21/}
-@end itemize
-@item
-If you are using GNU Emacs on Windows, you might need following
-libraries in order to display images(png, jpeg, gif):
-@itemize
-@item
-@uref{http://gnuwin32.sourceforge.net/packages/jpeg.htm,GnuWin32 Jpeg}
-@item
-@uref{http://gnuwin32.sourceforge.net/packages/libpng.htm,GnuWin32 LibPng}
-@item
-@uref{http://gnuwin32.sourceforge.net/packages/giflib.htm,GnuWin32 GifLib}
-@item
-Download binaries and copy *.dll files to the directory where
-emacs.exe exists.
-@end itemize
-@end itemize
-
-@section Quick start
-
-Add following code to your @file{.emacs}:
-
-@example
-(add-to-list 'load-path "/path/to/installed/dir") ;; if you need
-(require 'twittering-mode)
-@end example
-
-and execute
-
-@example
-M-x twit
-@end example
-
-Then you are prompted to enter your Twitter username and
-password. After that, your friends timeline will appear in
-@code{*twittering*} buffer.
-
-@subheading Browsing timelines
-
-You can see some kinds of timelines on twittering-mode.
-
-@itemize
-@item
-@code{g}: Reload current timeline
-@item
-@code{C-c C-f}: Friends timeline
-@item
-@code{C-c C-r}: Replies
-@item
-@code{V} and enter @var{USERNAME}: Show @var{USERNAME}'s tweets
-@item
-@code{C-c C-u}: Your tweets
-@item
-@code{C-c C-g}: Public timeline
-@end itemize
-
-Following commands help you move around a timeline.
-
-@itemize
-@item
-@code{j}: next tweet.
-@item
-@code{k}: previous tweet.
-@item
-@code{h}: move to left.
-@item
-@code{l}: move to right.
-@item
-@code{i}: on/off icon-mode
-@item
-@code{TAB}: next interesting things(usernames, links ...)
-@item
-@code{G}: go to the end of the buffer
-@item
-@code{H}: go to the beginning of the buffer
-
-@end itemize
-
-@subheading Posting your tweet
-
-@itemize
-@item
-@code{C-c C-s}: Post tweet from minibuffer.
-@end itemize
-
-@subheading And more settings
-
-Some more settings will make your twittering-mode life better.
-
-@example
-(setq twittering-username "YOURNAME")
-@end example
-
-@node Introduction
-@chapter Introduction
-
-@node What is twittering-mode?
-@section What is twittering-mode?
-
-Twittering-mode is an Emacs major mode for Twitter. You can check
-timelines, tweet, mark posts as favorites and so on with Emacs.
-
-@node Supported platforms
-@subsection Supported platforms
-
-@itemize @bullet
-@item
-GNU Emacs 23
-
-@item
-GNU Emacs 22
-
-@item
-GNU Emacs 21 (some restrictions)
-@end itemize
-
-@node Features
-@subsection Features
-
-@itemize @bullet
-@item
-Feature 1
-@item
-Feature 2
-@item
-Feature 3
-@end itemize
-
-@node Copying This Manual
-@appendix Copying This Manual
-
-@menu
-* GNU Free Documentation License:: License for copying this manual.
-@end menu
-
-@c Get fdl.texi from http://www.gnu.org/licenses/fdl.html
-@include fdl.texi
-
-@node Index
-@unnumbered Index
-
-@printindex cp
-
-@bye
-
-@c twmode.texinfo ends here
+++ /dev/null
-
-AddLanguage ja .ja
-
-LanguagePriority ja en
-
+++ /dev/null
-
-CATALOGS := ja.po
-LANGS := en ja
-MARKDOWN_DOCS := \
- index.text \
- how-to-contribute.text \
- screenshot.text
-
-PUBLISH := ./publish.rb
-RM ?= rm -f
-HTML_DOCS := $(subst .text,.html,$(MARKDOWN_DOCS))
-HTML_ASSETS := style.css images
-
-.PHONY: all clean upload update-po publish
-
-.SUFFIXES: .text .html
-
-all: publish
-
-.text.html: $(PUBLISH) header.rhtml footer.rhtml
- $(PUBLISH) -H header.rhtml -F footer.rhtml \
- -d lang=\"en\" -d langs="\"$(LANGS)\".split" -d file=\"$@\" \
- -o $@ $<
-
-upload: upload.bat
- @(! [ -z "$${SF_USERNAME}" ] || (echo "Environmental variable 'SF_USERNAME', which is a username of sf.net, is required."; false))
- sftp -b $< $${SF_USERNAME},twmodeNOSPAMweb.sourceforge.net
-
-upload.bat: $(HTML_DOCS) Makefile publish
- files=$$(find -name "*.html"; \
- find -name "*.html.??"; \
- find -name ".htaccess"; \
- find -name "*.css"; \
- find -name "*.png"; \
- find -name "*.jpg"); \
- dirs=$$(echo $$files|xargs -n1 dirname|sort|uniq); \
- (echo "cd htdocs"; \
- echo $$dirs | xargs -n 1 echo "-mkdir"; \
- for file in $$files; do echo "put $${file} $${file}"; done) > $@
-
-twmode.pot: $(HTML_DOCS)
- xml2po -k -o $@ $(HTML_DOCS)
- for catalog in $(CATALOGS); do \
- [ -f $$catalog ] || cp $@ $$catalog; \
- done
-
-update-po: twmode.pot Makefile
- for catalog in $(CATALOGS); do \
- xml2po -k -m xhtml -u $$catalog $(HTML_DOCS); \
- done
-
-publish: $(HTML_DOCS) $(CATALOGS)
- for catalog in $(CATALOGS); do \
- lang=$$(echo $$catalog|sed 's/.po$$//'); \
- [ -d $$lang ] || mkdir $$lang; \
- cp -t $$lang -r $(HTML_ASSETS); \
- for text in $(MARKDOWN_DOCS); do \
- html=$$(echo $$text|sed 's/.text$$/.html/'); \
- $(PUBLISH) -H header.rhtml -F footer.rhtml \
- -d lang=\"$$lang\" -d langs="\"$(LANGS)\".split" \
- -d file=\"$$html\" --po-file=$$catalog \
- -o $$lang/$$html $$text; \
- done; \
- done
-
-clean:
- $(RM) *.html *.html upload.bat
- for catalog in $(CATALOGS); do \
- lang=$$(echo $$catalog|sed 's/.po$$//'); \
- $(RM) $$lang/*.html; \
- done
+++ /dev/null
-</div>
-<div style="clear: both;"> </div>
-</div>
-
-<div id="bottom"> </div>
-<div id="footer">
-Designed by <a href="http://www.free-css-templates.com/">Free CSS Templates</a>, Thanks to <a href="http://www.legalhelpers.com/chapter-13-bankruptcy/chapter13.html">Chapter 13 Bankruptcy</a>
-<br />
-<a href="http://www.famfamfam.com/"><img src="images/famfamfam-logo.png" /></a>
-</div>
-</div>
-
-<!-- Piwik -->
-<script type="text/javascript">
-var pkBaseURL = (("https:" == document.location.protocol) ? "https://sourceforge.net/apps/piwik/twmode/" : "http://sourceforge.net/apps/piwik/twmode/");
-document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
-</script><script type="text/javascript">
-piwik_action_name = '';
-piwik_idsite = 1;
-piwik_url = pkBaseURL + "piwik.php";
-piwik_log(piwik_action_name, piwik_idsite, piwik_url);
-</script>
-<object><noscript><p><img src="http://sourceforge.net/apps/piwik/twmode/piwik.php?idsite=1" /></p></noscript></object>
-<!-- End Piwik Tag -->
-
- </body>
-</html>
+++ /dev/null
-<%
-lang_menu_items = langs.map do |l|
- rel_dir = "../#{l}"
- if lang == "en" && l == "en"
- rel_dir = "."
- elsif lang == "en"
- rel_dir = "./#{l}"
- elsif l == "en"
- rel_dir = ".."
- end
- "<a href=\"#{rel_dir}/#{file}\"><img src=\"#{rel_dir}/images/lang-#{l}.png\" /></a>"
- end.join(" ")
-%>
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%=h lang %>" lang="<%=h lang %>">
- <head>
- <title>Twittering-mode</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <link rel="stylesheet" type="text/css" href="style.css" media="screen" />
- </head>
- <body>
-<div id="wrap">
-
-<!--
-<div id="header">
-<h1><a href="#">Twittering-mode</a></h1>
-<h2>A major mode for Twitter.</h2>
-</div>
-<div id="top"> </div>
--->
-
-<div style="width: 100px; float: right; text-align: right; padding-right: 15px;">
-<a href="http://sourceforge.net/projects/twmode"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=288615&type=8" width="80" height="15" /></a>
-</div>
-<div style="width: 500px; float: left; text-align: left; padding-left: 15px;">
-<%= lang_menu_items %>
-</div>
-
-<div id="top"> </div>
-
-<div id="menu">
-<ul>
-<li><a href="./index.html"><img src="./images/logo.png" /></a></li>
-</ul>
-</div>
-
-<div id="content">
-<div class="left">
+++ /dev/null
-# How to contribute to twittering-mode
-
-## Code
-
-Recommended way is to fork on [GitHub](http://github.com/hayamiz/twittering-mode). Visit there and click 'fork' button.
-
-Of course you can clone the git repository in the ordinary way:
-
- git clone git://github.com/hayamiz/twittering-mode.git
-
-### How to create patches
-
-We recommend to follow these steps:
-
-1. Pull the master branch(`hayamiz/master` on [GitHub](http://github.com/hayamiz/twittering-mode)).
-1. Create a **topic branch** and make some modifications.
-1. Before sending a patch, **rebase** the topic branch to the master.
-1. Now it's ready to **post** your patch. Send a [pull request](http://github.com/guides/pull-requests) on [GitHub](http://github.com/hayamiz/twittering-mode) (if you have forked) and write a mail to [twittering-mode ML](http://sourceforge.net/mail/?group_id=288615).
-
-#### Topic branch
-
-(now writing...)
-
-#### Rebasing a topic branch
-
-(now writing...)
-
-#### Posting your patch
-
-(now writing...)
-
-## Communication
-
-All your voices should be sent to [twittering-mode ML](http://sourceforge.net/mail/?group_id=288615).
-
-### Bug reports
-
-If you find some bugs in twittering-mode, please send a mail with detailed information to [twittering-mode ML](http://sourceforge.net/mail/?group_id=288615):
-
-* Platform (Windows, Linux, Mac OS X, ...)
-* Kind of Emacs and its version number (GNU Emacs, XEmacs, Carbon Emacs, ...): you can check it by `(emacs-version)<C-j>` on `*scratch*` buffer.
-* What you *wanted* to do, what you *actually did*, and what *happened*.
-* Any other information you think it's important.
-
-If you have enough time, please try to reproduce the bug in a minimal environment. You can launch Emacs without loading any scripts by `emacs -Q`. This saves our time so much :)
-
-### Feature requests and others
-
-Join [twittering-mode ML](http://sourceforge.net/mail/?group_id=288615) and let's talk!
-
-[« Back to top](./index.html)
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="360"
- height="75"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docname="logo.svg"
- version="1.0"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- gridtolerance="10000"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="1.4"
- inkscape:cx="77.661383"
- inkscape:cy="58.437716"
- inkscape:document-units="px"
- inkscape:current-layer="layer4"
- showgrid="false"
- inkscape:window-width="1280"
- inkscape:window-height="1002"
- inkscape:window-x="1024"
- inkscape:window-y="0" />
- <defs
- id="defs4">
- <inkscape:perspective
- id="perspective10"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 526.18109 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective2857"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 526.18109 : 1"
- sodipodi:type="inkscape:persp3d" />
- <filter
- inkscape:collect="always"
- id="filter5924"
- x="-0.019761876"
- width="1.0395238"
- y="-0.10917721"
- height="1.2183544">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="2.8028142"
- id="feGaussianBlur5926" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter3477"
- x="-0.6"
- width="2.2"
- y="-0.6"
- height="2.2">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="1.6414979"
- id="feGaussianBlur3479" />
- </filter>
- </defs>
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:groupmode="layer"
- inkscape:label="background"
- style="display:inline"
- sodipodi:insensitive="true">
- <rect
- style="fill:#3c90e8;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect2865"
- width="360"
- height="75"
- x="0"
- y="3.9968029e-15" />
- <path
- style="fill:#000000"
- d=""
- id="path2863" />
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer4"
- inkscape:label="glow">
- <path
- sodipodi:type="arc"
- style="fill:#b2ff14;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter3477)"
- id="path3204"
- sodipodi:cx="151.39661"
- sodipodi:cy="7.1303754"
- sodipodi:rx="3.2829957"
- sodipodi:ry="3.2829957"
- d="M 154.6796,7.1303754 A 3.2829957,3.2829957 0 1 1 148.11361,7.1303754 A 3.2829957,3.2829957 0 1 1 154.6796,7.1303754 z"
- transform="matrix(3.048077,0,0,3.048077,-387.43063,-5.8431764)" />
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer2"
- inkscape:label="Logo"
- style="display:inline">
- <g
- style="display:inline"
- id="g4525"
- transform="translate(-5.5725e-2,1.3405102)">
- <path
- id="path4523"
- d="M 19.941037,24.429198 L 12.862601,24.429198 L 12.862601,44.310372 C 12.86259,46.444169 13.601209,48.249687 15.078459,49.726915 L 19.879486,54.527941 L 18.032937,56.37449 L 13.23191,51.635015 C 11.221217,49.665374 10.21587,47.22383 10.215881,44.310372 L 10.215881,9.5337057 L 12.862601,9.5337057 L 12.862601,21.84403 L 19.941037,21.84403 L 19.941037,24.429198"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4521"
- d="M 64.615038,23.75213 L 62.953144,25.414024 C 61.43483,26635026 41.471606,50.629679 41.471628,49.480708 L 41.471628,21.84403 L 44.118348,21.84403 L 44.118348,49.480708 C 44.118326,50.629679 44.528666,51.635026 45.34938,52.496738 C 46.211081,53.31743 47.216417,53.72777 48.36541,53.72777 L 53.781952,53.72777 C 54.971921,53.72777 55.977257,53.31743 56.797982,52.496738 C 57.61863,51.635026 58.028981,50.629679 58.029014,49.480708 L 58.029014,30.892118 C 58.028981,28.060777 59.054838,25.619233 61.106595,23.567475 L 62.768489,21.905582 L 64.615038,23.75213"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4519"
- d="M 78.944089,14.211629 C 78.944078,15.483736 78.472186,16.591665 77.528402,17.535417 C 76.215297,18.848554 75.558739,20.633551 75.55875,22.890408 L 75.55875,56.37449 L 72.973582,56.37449 L 72.973582,22.890408 C 72.973571,20.633551 72.317024,18.848554 71.00393,17.535417 C 70.060134,16.591665 69.588242,15.483736 69.588242,14.211629 C 69.588242,12.898568 70.039614,11.79065 70.942378,10.887841 C 71.886162,9.9441012 72.994091,9.4721981 74.266166,9.4721541 C 75.538229,9.4721981 76.625637,9.9441012 77.528402,10.887841 C 78.472186,11.79065 78.944078,12.898568 78.944089,14.211629"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4517"
- d="M 93.642454,24.429198 L 86.564017,24.429198 L 86.564017,44.310372 C 86.564017,46.444169 87.302626,48.249687 88.779876,49.726915 L 93.580902,54.527941 L 91.734353,56.37449 L 86.933327,51.635015 C 84.922633,49.665374 83.917297,47.22383 83.917297,44.310372 L 83.917297,9.5337057 L 86.564017,9.5337057 L 86.564017,21.84403 L 93.642454,21.84403 L 93.642454,24.429198"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4515"
- d="M 108.34082,24.429198 L 101.26238,24.429198 L 101.26238,44.310372 C 101.26237,46.444169 102.00099,48.249687 103.47824,49.726915 L 108.27927,54.527941 L 106.43272,56.37449 L 101.63169,51.635015 C 99.621002,49.665374 98.615652,47.22383 98.615662,44.310372 L 98.615662,9.5337057 L 101.26238,9.5337057 L 101.26238,21.84403 L 108.34082,21.84403 L 108.34082,24.429198"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4513"
- d="M 132.51814,34.769871 C 132.51812,37.642298 131.51277,40.083842 129.50211,42.094514 L 122.11591,49.419157 L 120.26937,47.572608 L 127.65556,40.186413 C 129.13278,38.709196 129.8714,36.92,21.844063 120.20781,21.84403 L 125.62436,21.84403 C 127.55296,21.844063 129.17382,22.521131 130.48693,23.875234 C 131.84105,25.188371 132.51812,26.809224 132.51814,28.737812 L 132.51814,34.769871"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4511"
- d="M 149.98633,23.690579 L 142.41548,31.261428 C 140.8972,32.779731 140.13807,34.605759 140.13807,36.739522 L 140.13807,56.37449 L 137.49135,56.37449 L 137.49135,36.739522 C 137.49135,33.867139 138.49668,31.425595 140.50738,29.41488 L 148.07823,21.84403 L 149.98633,23.690579"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4509"
- d="M 164.31537,14.211629 C 164.31536,15.483736 163.84347,16.591665 162.89969,17.535417 C 161.58658,18.848554 160.93002,20.633551 160.93003,22.890408 L 160.93003,56.37449 L 158.34487,56.37449 L 158.34487,22.890408 C 158.34486,20.633551 157.68831,18.848554 156.37521,17.535417 C 155.43142,16.591665 154.95953,15.483736 154.95953,14.211629 C 154.95953,12.898568 155.4109,11.79065 156.31366,10.887841 C 157.25745,9.9441012 158.36538,9.4721981 159.63745,9.4721541 C 160.90951,9.4721981 161.99692,9.9441012 162.89969,10.887841 C 163.84347,11.79065 164.31536,12.898568 164.31537,14.211629"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4507"
- d="M 188.49268,47.449505 C 188.49266,50.321921 187.48731,52.763465 185.47665,54.774148 L 183.81476,56.436041 L 181.90666,54.589493 L 183.6301,52.866047 C 185.10732,51.388819 185.84594,49.583302 185.84596,47.449505 L 185.84596,28.737812 C 185.84594,27.547843 185.4356,26.542507 184.61493,25.721782 C 183.79422,24.901123 182.78888,24.490783 181.5989,24.49075 L 176.18236,24.49075 C 175.03338,24.490783 174.02804,24.901123 173.16633,25.721782 C 172.34563,26.542507 171.93529,27.547843 171.93529,28.737812 L 171.93529,56.37449 L 169.28857,56.37449 L 169.28857,28.737812 C 169.28857,26.809224 169.96564,25.188371 171.31978,23.875234 C 172.6739,22.521131 174.29476,21.844063 176.18236,21.84403 L 181.5989,21.84403 C 183.5275,21.844063 185.14836,22.521131 186.46148,23.875234 C 187.81559,25.188371 188.49266,26.809224 188.49268,28.737812 L 188.49268,47.449505"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4505"
- d="M 212.67,56.37449 C 212.66998,59.246895 211.66464,61.688439 209.65398,63.699133 L 202.26778,71.085327 L 221.84403 C 207.70482,21.844063 209.32569,22.521131 210.6388,23.875234 C 211.99292,25.188371 212.66998,26.809224 212.67,28.737812 L 212.67,56.37449"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4503"
- d="M 237.33972,34.215906 L 217.6432,34.215906 L 217.6432,31.569186 L 237.33972,31.569186 L 237.33972,34.215906"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4501"
- d="M 278.07443,47.449505 C 278.07439,50.321921 277.06905,52.763465 275.0584,54.774148 L 273.3965,56.436041 L 271.4884,54.589493 L 273.21185,52.866047 C 274.68905,51.388819 275.42767,49.583302 275.42771,47.449505 L 275.42771,28.737812 C 275.42767,27.547843 275.01732,26.542507 274.19667,25.721782 C 273.37595,24.901123 272.37061,24.490783 271.18064,24.49075 L 265.764bsp;263.42512,21.844063 265.7641,21.84403 L 271.18064,21.84403 C 273.10923,21.844063 274.73008,22.521131 276.04322,23.875234 C 277.39733,25.188371 278.07439,26.809224 278.07443,28.737812 L 278.07443,47.449505"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <g
- transform="matrix(1.0991361,0,0,1.0991361,-189.33997,-644.35655)"
- id="g4499"
- style="fill:#ffffff;fill-opacity:1">
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 447.25282,631.25691 C 447.2528,632.97425 446.6368,634.44891 445.40482,635.68091 C 444.21013,636.91291 442.73547,637.52891 440.98082,637.52891 L 436.05282,637.52891 C 434.33548,637.52891 432.86081,636.91291 431.62882,635.68091 C 430.39681,634.44891 429.78081,632.97425 429.78082,631.25691 L 429.78082,612.38491 C 429.78081,610.63027 430.39681,609.15561 431.62882,607.96091 C 432.86081,606.72894 434.33548,606.11294 436.05282,606.11291 L 440.98082,606.11291 C 442.73547,606.11294 444.21013,606.72894 445.40482,607.96091 C 446.6368,609.15561 447.2528,610.63027 447.25282,612.38491 L 447.25282,631.25691"
- id="path4497" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 444.84482,631.25691 L 444.84482,612.38491 C 444.8448,611.30227 444.47147,610.38761 443.72482,609.64091 C 442.97813,608.89427 442.06347,608.52094 440.98082,608.52091 L 436.05282,608.52091 C 435.00747,608.52094 434.09281,608.89427 433.30882,609.64091 C 432.56214,610.38761 432.18881,611.30227 432.18882,612.38491 L 432.18882,631.25691 C 432.18881,632.30225 432.56214,633.21692 433.30882,634.00091 C 434.09281,634.74758 435.00747,635.12091 436.05282,635.12091 L 440.98082,635.12091 C 442.06347,635.12091 442.97813,634.74758 443.72482,634.00091 C 444.47147,633.21692 444.8448,632.30225 444.84482,631.25691"
- id="path4495" />
- </g>
- <path
- id="path4493"
- d="M 326.42906,49.480708 C 326.42904,51.368299 325.75197,52.989151 324.39785,54.343286 C 323.08473,55.697422 321.46388,56.37449 319.53528,56.37449 L 314.11873,56.37449 C 312.23114,56.37449 310.61028,55.697422 309.25616,54.343286 C 307.90201,52.989151 307.22494,51.368299 307.22495,49.480708 L 307.22495,36.739522 C 307.22494,33.867139 308.23029,31.425595 310.24098,29.41488 L 317.87338,21.782478 L 319.71993,23.629027 L 312.08753,31.261428 C 310.61028,32.738689 309.87166,34.564728 309.87167,36.739522 L 309.87167,49.480708 C 309.87166,50.629679 310.282,51.635026 311.1027,52.496738 C 311.96442,53.31743 312.96975,53.72777 314.11873,53.72777 L 319.53528,53.72777 C 320.72526,53.72777 321.73059,53.31743 322.55131,52.496738 C 323.37198,51.635026 323.78232,50.629679 323.78234,49.480708 L 323.78234,9.4721541 L 326.42906,9.4721541 L 326.42906,49.480708"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path4491"
- d="M 350.60635,34.769871 C 350.60633,37.642298&nbs8299 331.40225,49.480708 L 331.40225,28.737812 C 331.40224,26.809224 332.0793,25.188371 333.43345,23.875234 C 334.78758,22.521131 336.40844,21.844063 338.29603,21.84403 L 343.71257,21.84403 C 345.64117,21.844063 347.26202,22.521131 348.57515,23.875234 C 349.92926,25.188371 350.60633,26.809224 350.60635,28.737812 L 350.60635,34.769871"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- </g>
- <g
- transform="translate(-5.5725e-2,1.3405102)"
- id="g5848"
- style="display:inline;filter:url(#filter5924)">
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 19.941037,24.429198 L 12.862601,24.429198 L 12.862601,44.310372 C 12.86259,46.444169 13.601209,48.249687 15.078459,49.726915 L 19.879486,54.527941 L 18.032937,56.37449 L 13.23191,51.635015 C 11.221217,49.665374 10.21587,47.22383 10.215881,44.310372 L 10.215881,9.5337057 L 12.862601,9.5337057 L 12.862601,21.84403 L 19.941037,21.84403 L 19.941037,24.429198"
- id="path5850" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 64.615038,23.75213 L 62.953144,25.414024 C 61.43483,26.932327 60.675701,28.758355 60.675734,30.892118 L 60.675734,49.480708 C 60.675701,51.368299 59.998633,52.989151 58.64453sp;44.118326,50.629679 44.528666,51.635026 45.34938,52.496738 C 46.211081,53.31743 47.216417,53.72777 48.36541,53.72777 L 53.781952,53.72777 C 54.971921,53.72777 55.977257,53.31743 56.797982,52.496738 C 57.61863,51.635026 58.028981,50.629679 58.029014,49.480708 L 58.029014,30.892118 C 58.028981,28.060777 59.054838,25.619233 61.106595,23.567475 L 62.768489,21.905582 L 64.615038,23.75213"
- id="path5852" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 78.944089,14.211629 C 78.944078,15.483736 78.472186,16.591665 77.528402,17.535417 C 76.215297,18.848554 75.558739,20.633551 75.55875,22.890408 L 75.55875,56.37449 L 72.973582,56.37449 L 72.973582,22.890408 C 72.973571,20.633551 72.317024,18.848554 71.00393,17.535417 C 70.060134,16.591665 69.588242,15.483736 69.588242,14.211629 C 69.588242,12.898568 70.039614,11.79065 70.942378,10.887841 C 71.886162,9.9441012 72.994091,9.4721981 74.266166,9.4721541 C 75.538229,9.4721981 76.625637,9.9441012 77.528402,10.887841 C 78.472186,11.79065 78.944078,12.898568 78.944089,14.211629"
- id="path5854" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 93.642454,24.429198 L 86.564017,24.429198 L 86.564017,44.310372 C 86.564017,46.444169 87.302626,48.249687 88.779876,49.726915 L 93.580902,54.527941 L 91.734353,56.37449 L 86.933327,51.635015 C 84.922633,49.665374 83.917297,47.22383 83.917297,44.310372 L 83.917297,9.5337057 L 86.564017,9.5337057 L 86.564017,21.84403 L 93.642454,21.84403 L 93.642454,24.429198"
- id="path5856" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 108.34082,24.429198 L 101.26238,24.429198 L 101.26238,44.310372 C 101.26237,46.444169 102.00099,48.249687 103.47824,49.726915 L 108.27927,54.527941 L 106.43272,56.37449 L 101.63169,51.635015 C 99.621002,49.665374 98.615652,47.22383 98.615662,44.310372 L 98.615662,9.5337057 L 101.26238,9.5337057 L 101.26238,21.84403 L 108.34082,21.84403 L 108.34082,24.429198"
- id="path5858" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 132.51814,34.769871 C 132.51812,37.642298 131.51277,40.083842 129.50211,42.094514 L 122.11591,49.419157 L 120.26937,47.572608 L 127.65556,40.186413 C 129.13278,38.709196 129.8714,36.903678 129.87142,34.769871 L 129.87142,28.737812 C 129.8714,27.547843 129.46106,26.542507 128.64039,25.721782 C 127.;131.84105,25.188371 132.51812,26.809224 132.51814,28.737812 L 132.51814,34.769871"
- id="path5860" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 149.98633,23.690579 L 142.41548,31.261428 C 140.8972,32.779731 140.13807,34.605759 140.13807,36.739522 L 140.13807,56.37449 L 137.49135,56.37449 L 137.49135,36.739522 C 137.49135,33.867139 138.49668,31.425595 140.50738,29.41488 L 148.07823,21.84403 L 149.98633,23.690579"
- id="path5862" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 164.31537,14.211629 C 164.31536,15.483736 163.84347,16.591665 162.89969,17.535417 C 161.58658,18.848554 160.93002,20.633551 160.93003,22.890408 L 160.93003,56.37449 L 158.34487,56.37449 L 158.34487,22.890408 C 158.34486,20.633551 157.68831,18.848554 156.37521,17.535417 C 155.43142,16.591665 154.95953,15.483736 154.95953,14.211629 C 154.95953,12.898568 155.4109,11.79065 156.31366,10.887841 C 157.25745,9.9441012 158.36538,9.4721981 159.63745,9.4721541 C 160.90951,9.4721981 161.99692,9.9441012 162.89969,10.887841 C 163.84347,11.79065 164.31536,12.898568 164.31537,14.211629"
- id="path5864" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 188.49268,nbsp;C 187.81559,25.188371 188.49266,26.809224 188.49268,28.737812 L 188.49268,47.449505"
- id="path5866" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 212.67,56.37449 C 212.66998,59.246895 211.66464,61.688439 209.65398,63.699133 L 202.26778,71.085327 L 200.42123,69.177227 L 207.80743,61.852584 C 209.28464,60.375345 210.02326,58.549317 210.02329,56.37449 L 210.02329,28.7378.737812 L 212.67,56.37449"
- id="path5868" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 237.33972,34.215906 L 217.6432,34.215906 L 217.6432,31.569186 L 237.33972,31.569186 L 237.33972,34.215906"
- id="path5870" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 278.07443,47.449505 C 278.07439,50.321921 277.06905,52.763465 275.0584,54.774148 L 273.3965,56.436041 L 271.4884,54.589493 L 273.21185,52.866047 C 274.68905,51.388819 275.42767,49.583302 275.42771,47.449505 L 275.42771,28.737812 C 275.42767,27.547843 275.01732,26.542507 274.19667,25.721782 C 273.37595,24.901123 272.37061,24.490783 271.18064,24.49075 L 265.7641,24.49075 C 264.61511,24.490783 263.60977,24.901123 262.74807,25.721782 C 261.92736,26.542507 261.51702,27.547843 261.5nbsp;C 277.39733,25.188371 278.07439,26.809224 278.07443,28.737812 L 278.07443,47.449505"
- id="path5872" />
- <g
- style="fill:#ffffff;fill-opacity:1"
- id="g5874"
- transform="matrix(1.0991361,0,0,1.0991361,-189.33997,-644.35655)">
- <path
- id="path5876"
- d="M 447.25282,631.25691 C 447.2528,632.97425 446.6368,634.44891 445.40482,635.68091 C 444.21013,636.91291 442.73547,637.52891 440.98082,637.52891 L 436.05282,637.52891 C 434.33548,637.52891 432.86081,636.91291 431.62882,635.68091 C 430.39681,634.44891 429.78081,632.97425 429.78082,631.25691 L 429.78082,612.38491 C 429.78081,610.63027 430.39681,609.15561 431.62882,607.96091 C 432.86081,606.72894 434.33548,606.11294 436.05282,606.11291 L 440.98082,606.11291 C 442.73547,606.11294 444.21013,606.72894 445.40482,607.96091 C 446.6368,609.15561 447.2528,610.63027 447.25282,612.38491 L 447.25282,631.25691"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- <path
- id="path5878"
- d="M 444.84482,631.25691 L 444.84482,612.38491 C 444.8448,611.30227 444.47147,610.38761 443.72482,609.64091 C 442.97813,608.89427 442.06347,608.52094 440.98082,608.52091 L 436.05282,608.52091 C 435.00747,608.52094 434.09281,608.89427 433.30882,609.64091 C 432.56214,610.38761 432.18881,611.30227 432.18882,612.38491 L 432.18882,631.25691 C 432.18881,632.30225 432.56214,633.21692 433.30882,634.00091 C 434.09281,634.74758 435.00747,635.12091 436.05282,635.12091 L 440.98082,635.12091 C 442.06347,635.12091 442.97813,634.74758 443.72482,634.00091 C 444.47147,633.21692 444.8448,632.30225 444.84482,631.25691"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" />
- </g>
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 326.42906,49.480708 C 326.42904,51.368299 325.75197,52.989151 324.39785,54.343286 C 323.08473,55.697422 321.46388,56.37449 319.53528,56.37449 L 314.11873,56.37449 C 312.23114,56.37449 310.61028,55.697422 309.25616,54.343286 C 307.90201,52.989151 307.22494,51.368299 307.22495,49.480708 L 307.22495,36.739522 C 307.22494,33.867139 308.23029,31.425595 310.24098,29.41488 L 317.87338,21.782478 L 319.71993,23.629027 L 312.08753,31.261428 C 310.61028,32.738689 309.87166,34.564728 309.87167,36.739522 L 309.87167,49.480708 C 309.87166,50.629679 310.282,51.635026 311.1027,52.496738 C 311.96442,53.31743 312.96975,53.72777 314.11873,53.72777 L 319.53528,53.72777 C 320.72526,53.72777 321.73059,53.31743 322.55131,52.496738 C 323.37198,51.635026 323.78232,50.629679 323.78234,49.480708 L 323.78234,9.4721541 L 326.42906,9.4721541 L 326.42906,49.480708"
- id="path5880" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- d="M 350.60635,34.769871 C 350.60633,37.642298 349.60098,40.083842 347.59032,42.094514 L 340.20413,49.419157 L 338.35758,47.572608 L 345.74377,40.186413 C 347.28758,22.521131 336.40844,21.844063 338.29603,21.84403 L 343.71257,21.84403 C 345.64117,21.844063 347.26202,22.521131 348.57515,23.875234 C 349.92926,25.188371 350.60633,26.809224 350.60635,28.737812 L 350.60635,34.769871"
- id="path5882" />
- </g>
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer3"
- inkscape:label="text"
- style="display:none">
- <text
- id="text2383"
- y="186.61864"
- x="125.66487"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- xml:space="preserve"><tspan
- style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:SkinnyAL;-inkscape-font-specification:SkinnyAL"
- y="186.61864"
- x="125.66487"
- id="tspan2385"
- sodipodi:role="line">twittering-mode</tspan></text>
- </g>
-</svg>
+++ /dev/null
-<!-- -*- mode: markdown -*- -->
-
-<!-- # Twittering-mode -->
-
-Twittering-mode is an Emacs major mode for Twitter. You can check
-timelines, tweet, mark posts as favorites and so on with Emacs.
-
-[](http://www.twitter.com/twmode)
-
-## Screenshot
-
-
-
-and [more](./screenshot.html)
-
-## Download
-
-* Latest release (2013/5/7): [twittering-mode-3.0.0](http://sourceforge.net/projects/twmode/files/)
-* Development version: [GitHub repository](http://github.com/hayamiz/twittering-mode/)
-
-See the [history](http://github.com/hayamiz/twittering-mode/commits/master/twittering-mode.el).
-
-## Documentation
-For the latest release, see [README.markdown](http://github.com/hayamiz/twittering-mode/blob/3.0.x/README.markdown).
-For the development version, see [README.markdown](http://github.com/hayamiz/twittering-mode/blob/master/README.markdown).
-
-## Getting involved
-
-See [how to contribute](./how-to-contribute.html) for detailed information.
-
-### Mailing lists
-
-Join [twittering-mode ML](http://sourceforge.net/mail/?group_id=288615).
-
-### Repository
-
-You can clone the git repository:
-
- git clone git://github.com/hayamiz/twittering-mode.git
-
-Or fork on [GitHub](http://github.com/hayamiz/twittering-mode)
-
-## See also
-
-* [EmacsWiki: TwitteringMode](http://www.emacswiki.org/emacs/TwitteringMode)
+++ /dev/null
-msgid ""
-msgstr ""
-"Project-Id-Version: twittering-mode HEAD\n"
-"POT-Creation-Date: 2013-05-07 00:26+0900\n"
-"PO-Revision-Date: 2009-12-29 22:18+0900\n"
-"Last-Translator: Tadashi Matsuo <tadNOSPAMmymail.twin.jp>\n"
-"Language-Team: Japanese\n"
-"Language: ja\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: index.html:7(title) how-to-contribute.html:7(title)
-#: screenshot.html:7(title)
-msgid "Twittering-mode"
-msgstr "Twittering-mode"
-
-#: index.html:43(p)
-msgid ""
-"Twittering-mode is an Emacs major mode for Twitter. You can check timelines, "
-"tweet, mark posts as favorites and so on with Emacs."
-msgstr ""
-"twittering-modeは、EmacsでTwitterをするためのメジャーモードです。タイムライン"
-"のチェック、投稿、お気に入りなど様々なTwitterの機能をEmacsから使うことができ"
-"ます。"
-
-#: index.html:48(h2)
-msgid "Screenshot"
-msgstr "スクリーンショット"
-
-#: index.html:52(p)
-msgid "and <a href=\"./screenshot.html\">more</a>"
-msgstr "and <a href=\"./screenshot.html\">more</a>"
-
-#: index.html:54(h2)
-msgid "Download"
-msgstr "ダウンロード"
-
-#: index.html:57(li)
-msgid ""
-"Latest release (2013/5/7): <a href=\"http://sourceforge.net/projects/twmode/"
-"files/\">twittering-mode-3.0.0</a>"
-msgstr ""
-"最新のリリース (2013/5/7): <a href=\"http://sourceforge.net/projects/twmode/"
-"files/\">twittering-mode-3.0.0</a>"
-
-#: index.html:58(li)
-msgid ""
-"Development version: <a href=\"http://github.com/hayamiz/twittering-mode/"
-"\">GitHub repository</a>"
-msgstr ""
-"開発版: <a href=\"http://github.com/hayamiz/twittering-mode/\">GitHubレポジト"
-"リ</a>"
-
-#: index.html:61(p)
-msgid ""
-"See the <a href=\"http://github.com/hayamiz/twittering-mode/commits/master/"
-"twittering-mode.el\">history</a>."
-msgstr ""
-"twittering-modeの<a href=\"http://github.com/hayamiz/twittering-mode/commits/"
-"master/twittering-mode.el\">更新履歴</a>"
-
-#: index.html:63(h2)
-msgid "Documentation"
-msgstr "ドキュメント"
-
-#: index.html:65(p)
-msgid ""
-"For the latest release, see <a href=\"http://github.com/hayamiz/twittering-"
-"mode/blob/3.0.x/README.markdown\">README.markdown</a>. For the development "
-"version, see <a href=\"http://github.com/hayamiz/twittering-mode/blob/master/"
-"README.markdown\">README.markdown</a>."
-msgstr ""
-"最新のリリースについては<a href=\"http://github.com/hayamiz/twittering-"
-"mode/blob/3.0.x/README.markdown\">README.markdown</a>を、開発版については"
-"<a href=\"http://github.com/hayamiz/twittering-mode/blob/master/README.mark"
-"down\">README.markdown</a>を参照してください。"
-
-#: index.html:68(h2)
-msgid "Getting involved"
-msgstr "twittering-modeの開発に参加する"
-
-#: index.html:70(p)
-msgid ""
-"See <a href=\"./how-to-contribute.html\">how to contribute</a> for detailed "
-"information."
-msgstr ""
-"詳しくは<a href=\"./how-to-contribute.html\">Twittering-modeの開発へ参加</a>"
-"をご覧ください。"
-
-#: index.html:72(h3)
-msgid "Mailing lists"
-msgstr "メーリングリスト"
-
-#: index.html:74(p)
-msgid ""
-"Join <a href=\"http://sourceforge.net/mail/?group_id=288615\">twittering-"
-"mode ML</a>."
-msgstr ""
-"是非<a href=\"http://sourceforge.net/mail/?group_id=288615\">twittering-mode "
-"ML</a>を購読してください。"
-
-#: index.html:76(h3)
-msgid "Repository"
-msgstr "レポジトリ"
-
-#: index.html:78(p)
-msgid "You can clone the git repository:"
-msgstr "次のコマンドを実行することで、gitレポジトリをcloneできます:"
-
-#: index.html:80(code) how-to-contribute.html:47(code)
-msgid "git clone git://github.com/hayamiz/twittering-mode.git"
-msgstr "git clone git://github.com/hayamiz/twittering-mode.git"
-
-#: index.html:83(p)
-msgid ""
-"Or fork on <a href=\"http://github.com/hayamiz/twittering-mode\">GitHub</a>"
-msgstr ""
-"また、<a href=\"http://github.com/hayamiz/twittering-mode\">GitHub</a>でfork"
-"することもできます。"
-
-#: index.html:85(h2)
-msgid "See also"
-msgstr "See also"
-
-#: index.html:88(a)
-msgid "EmacsWiki: TwitteringMode"
-msgstr "EmacsWiki: TwitteringMode"
-
-#: index.html:95(a) how-to-contribute.html:100(a) screenshot.html:76(a)
-msgid "Free CSS Templates"
-msgstr "Free CSS Templates"
-
-#: index.html:95(a) how-to-contribute.html:100(a) screenshot.html:76(a)
-msgid "Chapter 13 Bankruptcy"
-msgstr "Chapter 13 Bankruptcy"
-
-#: index.html:94(div) how-to-contribute.html:99(div) screenshot.html:75(div)
-msgid ""
-"Designed by <placeholder-1/>, Thanks to <placeholder-2/>\n"
-"<br/>\n"
-"<a href=\"http://www.famfamfam.com/\"><img src=\"images/famfamfam-logo.png\"/"
-"></a>"
-msgstr ""
-"Designed by <placeholder-1></placeholder-1>, Thanks to <placeholder-2></"
-"placeholder-2>\n"
-"<br />\n"
-"<a href=\"http://www.famfamfam.com/\"><img src=\"images/famfamfam-logo.png"
-"\" /></a>"
-
-#. Piwik
-#: index.html:102(script) how-to-contribute.html:107(script)
-#: screenshot.html:83(script)
-msgid ""
-"var pkBaseURL = ((\"https:\" == document.location.protocol) ? \"https://"
-"sourceforge.net/apps/piwik/twmode/\" : \"http://sourceforge.net/apps/piwik/"
-"twmode/\"); document.write(unescape(\"%3Cscript src='\" + pkBaseURL + "
-"\"piwik.js' type='text/javascript'%3E%3C/script%3E\"));"
-msgstr ""
-
-#: index.html:105(script) how-to-contribute.html:110(script)
-#: screenshot.html:86(script)
-msgid ""
-"piwik_action_name = ''; piwik_idsite = 1; piwik_url = pkBaseURL + \"piwik.php"
-"\"; piwik_log(piwik_action_name, piwik_idsite, piwik_url);"
-msgstr ""
-
-#: how-to-contribute.html:39(h1)
-msgid "How to contribute to twittering-mode"
-msgstr "twittering-modeの開発に参加する"
-
-#: how-to-contribute.html:41(h2)
-msgid "Code"
-msgstr "Code"
-
-#: how-to-contribute.html:43(p)
-msgid ""
-"Recommended way is to fork on <a href=\"http://github.com/hayamiz/twittering-"
-"mode\">GitHub</a>. Visit there and click 'fork' button."
-msgstr ""
-"<a href=\"http://github.com/hayamiz/twittering-mode\">GitHub</a>でレポジトリ"
-"をforkするのが一番おすすめの方法です。<a href=\"http://github.com/hayamiz/"
-"twittering-mode\">GitHub:twittering-mode</a>を開いて、'fork'ボタンをクリック"
-"してください。"
-
-#: how-to-contribute.html:45(p)
-msgid "Of course you can clone the git repository in the ordinary way:"
-msgstr ""
-"もちろん、次のコマンドを実行してgitのレポジトリを直接cloneしても構いません。"
-
-#: how-to-contribute.html:50(h3)
-msgid "How to create patches"
-msgstr "パッチの作り方"
-
-#: how-to-contribute.html:52(p)
-msgid "We recommend to follow these steps:"
-msgstr "次のような手順でパッチを作る慣例となっています:"
-
-#: how-to-contribute.html:55(li)
-msgid ""
-"Pull the master branch(<code>hayamiz/master</code> on <a href=\"http://"
-"github.com/hayamiz/twittering-mode\">GitHub</a>)."
-msgstr ""
-"マスターブランチ(<a href=\"http://github.com/hayamiz/twittering-mode"
-"\">GitHub</a>レポジトリの<code>hayamiz/master</code>)を取得する"
-
-#: how-to-contribute.html:56(li)
-msgid "Create a <strong>topic branch</strong> and make some modifications."
-msgstr "<strong>トピックブランチ</strong>を作成して、そこに変更を加える"
-
-#: how-to-contribute.html:57(li)
-msgid ""
-"Before sending a patch, <strong>rebase</strong> the topic branch to the "
-"master."
-msgstr ""
-"パッチを投稿する前に、トピックブランチをマスターブランチに<strong>rebase</"
-"strong>する"
-
-#: how-to-contribute.html:58(li)
-msgid ""
-"Now it's ready to <strong>post</strong> your patch. Send a <a href=\"http://"
-"github.com/guides/pull-requests\">pull request</a> on <a href=\"http://"
-"github.com/hayamiz/twittering-mode\">GitHub</a> (if you have forked) and "
-"write a mail to <a href=\"http://sourceforge.net/mail/?"
-"group_id=288615\">twittering-mode ML</a>."
-msgstr ""
-"以上で<strong>パッチを投稿する</strong>準備は完了です。(GitHubでforkした人は)"
-"<a href=\"http://github.com/guides/pull-requests\">pull request</a>を送って、"
-"<a href=\"http://sourceforge.net/mail/?group_id=288615\">メーリングリスト</a>"
-"へ投稿しましょう"
-
-#: how-to-contribute.html:61(h4)
-msgid "Topic branch"
-msgstr "トピックブランチ"
-
-#: how-to-contribute.html:63(p) how-to-contribute.html:67(p)
-#: how-to-contribute.html:71(p)
-msgid "(now writing...)"
-msgstr "(準備中...)"
-
-#: how-to-contribute.html:65(h4)
-msgid "Rebasing a topic branch"
-msgstr "トピックブランチをrebaseする"
-
-#: how-to-contribute.html:69(h4)
-msgid "Posting your patch"
-msgstr "パッチを投稿する"
-
-#: how-to-contribute.html:73(h2)
-msgid "Communication"
-msgstr "バグ報告、その他意見など"
-
-#: how-to-contribute.html:75(p)
-msgid ""
-"All your voices should be sent to <a href=\"http://sourceforge.net/mail/?"
-"group_id=288615\">twittering-mode ML</a>."
-msgstr ""
-"バグ報告を始めとして、機能追加や意見、感想などは<a href=\"http://sourceforge."
-"net/mail/?group_id=288615\">twittering-modeのメーリングリスト</a>へ投稿してく"
-"ださい。"
-
-#: how-to-contribute.html:77(h3)
-msgid "Bug reports"
-msgstr "バグ報告"
-
-#: how-to-contribute.html:79(p)
-msgid ""
-"If you find some bugs in twittering-mode, please send a mail with detailed "
-"information to <a href=\"http://sourceforge.net/mail/?"
-"group_id=288615\">twittering-mode ML</a>:"
-msgstr ""
-"もしtwittering-modeにバグを発見したら、<a href=\"http://sourceforge.net/"
-"mail/?group_id=288615\">メーリングリスト</a>に次に示すような情報を添えて投稿"
-"してください:"
-
-#: how-to-contribute.html:82(li)
-msgid "Platform (Windows, Linux, Mac OS X, ...)"
-msgstr "動作環境(Windows, Linux, Mac OS X, ...)"
-
-#: how-to-contribute.html:83(li)
-msgid ""
-"Kind of Emacs and its version number (GNU Emacs, XEmacs, Carbon Emacs, ...): "
-"you can check it by <code>(emacs-version)<C-j></code> on "
-"<code>*scratch*</code> buffer."
-msgstr ""
-"Emacsの種類とバージョン番号 (GNU Emacs, XEmacs, Carbon Emacs, ...): "
-"<code>*scratch*</code>バッファで<code>(emacs-version)<C-j></code>とタイ"
-"プすれば確認できます。"
-
-#: how-to-contribute.html:84(li)
-msgid ""
-"What you <em>wanted</em> to do, what you <em>actually did</em>, and what "
-"<em>happened</em>."
-msgstr ""
-"<em>何がしたかった</em>のか、<em>実際に行った操作</em>、<em>実際に発生した現"
-"象</em>"
-
-#: how-to-contribute.html:85(li)
-msgid "Any other information you think it's important."
-msgstr "その他重要であると思われる情報"
-
-#: how-to-contribute.html:88(p)
-msgid ""
-"If you have enough time, please try to reproduce the bug in a minimal "
-"environment. You can launch Emacs without loading any scripts by <code>emacs "
-"-Q</code>. This saves our time so much :)"
-msgstr ""
-"もし可能であれば、最小の環境でバグを再現してみてください。<code>emacs -Q</"
-"code>でEmacsを起動すれば、.emacsなどの起動スクリプトを一切読み込みません。こ"
-"の環境でバグが再現するかどうかを事前に試してもらえると、バグの原因をつきとめ"
-"やすくなります。"
-
-#: how-to-contribute.html:90(h3)
-msgid "Feature requests and others"
-msgstr "機能追加の要望や、その他の意見"
-
-#: how-to-contribute.html:92(p)
-msgid ""
-"Join <a href=\"http://sourceforge.net/mail/?group_id=288615\">twittering-"
-"mode ML</a> and let's talk!"
-msgstr ""
-"<a href=\"http://sourceforge.net/mail/?group_id=288615\">twittering-mode の"
-"メーリングリスト</a>を購読して投稿してください。"
-
-#: how-to-contribute.html:94(a) screenshot.html:70(a)
-msgid "« Back to top"
-msgstr "« トップへ戻る"
-
-#: screenshot.html:39(h1)
-msgid "Screenshots"
-msgstr "スクリーンショット"
-
-#: screenshot.html:41(h2)
-msgid "Timeline"
-msgstr "タイムライン"
-
-#: screenshot.html:43(h3)
-msgid "Friends timeline"
-msgstr "フレンズタイムライン"
-
-#: screenshot.html:45(h4)
-msgid "Without icons"
-msgstr "アイコン非表示モード"
-
-#: screenshot.html:49(h4)
-msgid "With icons"
-msgstr "アイコン表示モード"
-
-#: screenshot.html:53(h3) screenshot.html:61(li)
-msgid "User's timeline"
-msgstr "ユーザータイムライン"
-
-#: screenshot.html:57(h3)
-msgid "Supported timelines"
-msgstr "表示できるタイムライン"
-
-#: screenshot.html:60(li)
-msgid "Home timeline"
-msgstr "ホームタイムライン"
-
-#: screenshot.html:62(li)
-msgid "Mentions"
-msgstr "Mentions"
-
-#: screenshot.html:63(li)
-msgid "Lists"
-msgstr "リスト"
-
-#: screenshot.html:64(li)
-msgid "Direct messages"
-msgstr "ダイレクトメッセージ"
-
-#: screenshot.html:65(li)
-msgid "Search timeline"
-msgstr "検索タイムライン"
-
-#: screenshot.html:66(li)
-msgid "Favorites"
-msgstr "お気に入り"
-
-#: screenshot.html:67(li)
-msgid "Public timeline"
-msgstr "パブリックタイムライン"
-
-#~ msgid ""
-#~ "Currently there's no stable release, but it does <strong>not</strong> "
-#~ "mean twittering-mode is unstable for practical usage."
-#~ msgstr ""
-#~ "現在のところ、安定版リリースはありませんが、開発版でも十分実用的に使用でき"
-#~ "ます。"
-
-#~ msgid ""
-#~ "<a href=\"http://github.com/hayamiz/twittering-mode/raw/master/twittering-"
-#~ "mode.el\">twittering-mode.el</a> (development version)"
-#~ msgstr ""
-#~ "<a href=\"http://github.com/hayamiz/twittering-mode/raw/master/twittering-"
-#~ "mode.el\">twittering-mode.el</a> (開発版)"
-
-#, fuzzy
-#~ msgid "Twittering-mode screenshot"
-#~ msgstr "twittering-modeスクリーンショット"
-
-#~ msgid "twittering-mode.el"
-#~ msgstr "twittering-mode.el"
-
-#~ msgid "Contribute"
-#~ msgstr "プロジェクトに参加"
-
-#~ msgid ""
-#~ "See <a href=\"#\">Developer's guideline</a>(will be available soon) for "
-#~ "more information."
-#~ msgstr ""
-#~ "詳しい情報については<a href=\"#\">開発の手引き</a>(準備中)を参照してくださ"
-#~ "い。"
-
-#~ msgid "Japanese"
-#~ msgstr "日本語"
-
-#, fuzzy
-#~ msgid ""
-#~ "Languages: <a href=\"index.html.ja\"><img src=\"./images/lang-ja.png\" "
-#~ "alt=\"Japanese\" /></a>"
-#~ msgstr ""
-#~ "Other languages: <a href=\"index.html\"><img src=\"./images/lang-en.png\" "
-#~ "alt=\"English\" /></a>"
-
-#~ msgid "Other languages:"
-#~ msgstr "Other languages:"
-
-#~ msgid "English"
-#~ msgstr "英語"
-
-#~ msgid "GitHub"
-#~ msgstr "GitHub"
-
-#~ msgid "Or fork on <placeholder-1></placeholder-1>"
-#~ msgstr "または<placeholder-1></placeholder-1>でforkしてください。"
-
-#~ msgid "translator-credits"
-#~ msgstr "translator-credits"
-
-#~ msgid "GitHub repository"
-#~ msgstr "GitHubレポジトリ"
+++ /dev/null
-#!/usr/bin/env ruby
-# -*- coding: utf-8 -*-
-
-require 'optparse'
-require 'tempfile'
-require 'erb'
-#require 'rubygems'
-require 'bluecloth'
-
-$web_dir = File.dirname(__FILE__)
-
-$default_header = <<EOS
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
- <head>
- <title>html document</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- </head>
- <body>
-EOS
-
-$default_footer = <<EOS
- </body>
-</html>
-EOS
-
-def header(options)
- b = binding
- eval("include ERB::Util", b)
- options[:data].each do |data|
- eval(data, b)
- end
- erb = if options[:header]
- ERB.new(File.open(options[:header]).read)
- else
- ERB.new($default_header)
- end
- erb.result(b)
-end
-
-def footer(options)
- b = binding
- options[:data].each do |data|
- eval(data, b)
- end
- erb = if options[:footer]
- ERB.new(File.open(options[:footer]).read)
- else
- ERB.new($default_footer)
- end
- erb.result(b)
-end
-
-def parse_option(argv)
- opt = OptionParser.new
- opt.banner = "Usage: #{$0} [options] MARKDOWN-FILE"
-
- options = Hash.new
- options[:po_file] = nil
- opt.on('-p', '--po-file=FILE',
- "\n\t\tTranslate with FILE by gettext") do |v|
-
- unless File.exist?(v)
- $stderr.puts("No such po file: #{v}")
- $stderr.puts()
- puts opt.help()
- exit(1)
- end
- options[:po_file] = v
-
- unless system("which xml2po 1> /dev/null 2>/dev/null")
- $stderr.puts("'xml2po' command is required.")
- $stderr.puts()
- $stderr.puts("If you are using Debian or Ubuntu,\n'xml2po' can be installed by the following command:\n apt-get install gnome-doc-utils")
- exit(1)
- end
- end
-
- options[:output] = nil
- opt.on('-o FILE', '--output=FILE',
- "\n\t\tPrint resulting text into FILE") do |file|
- options[:output] = file
- end
-
- options[:header] = nil
- opt.on('-H', '--header=FILE',
- "\n\t\tHeader ERB template. Define parameters by --data option") do |file|
- unless File.exist?(file)
- $stderr.puts("No such file: #{file}")
- $stderr.puts()
- puts opt.help()
- exit(1)
- end
- options[:header] = file
- end
-
- options[:footer] = nil
- opt.on('-F', '--footer=FILE',
- "\n\t\tFooter ERB template. Define parameters by --data option") do |file|
- unless File.exist?(file)
- $stderr.puts("No such file: #{file}")
- $stderr.puts()
- puts opt.help()
- exit(1)
- end
- options[:footer] = file
- end
-
- options[:data] = Array.new
- opt.on('-d', '--data=NAME=VALUE',
- "\n\t\tBind VALUE(any ruby expression) to NAME when rendering HTML.") do |data|
- if data =~ /([^=])=(.+)/
- options[:data] << data
- end
- end
-
- opt.parse!(argv)
-
- options
-end
-
-def main(argv)
- textfile = nil
- output = nil
-
- options = parse_option(argv)
-
- argv.each do |arg|
- next unless File.exist?(arg)
- textfile = File.open(arg)
-
- if options[:output]
- output = File.open(options[:output], "w")
- else
- output = $stdout
- end
- break
- end
-
- unless textfile
- textfile = $stdin
- output = $stdout
- end
-
- tempfile = Tempfile.new("twmode-publish")
-
- html_body = BlueCloth.new(textfile.read).to_html
- tempfile.puts(header(options) + html_body + footer(options))
- tempfile.fsync()
-
- translated_str = nil
- if options[:po_file]
- translated_str = `xml2po -k -m xhtml -p #{options[:po_file]} -o /dev/stdout #{tempfile.path}`
- else
- translated_str = File.open(tempfile.path).read
- end
-
- translated_str = translated_str.gsub(/\A\s*<\?xml\s*version="1\.0"\s*encoding="utf-8"\s*\?>/, '')
-
- output.puts(translated_str)
-
- true
-end
-
-if __FILE__ == $0
- exit(main(ARGV))
-end
+++ /dev/null
-
-# Screenshots
-
-## Timeline
-
-### Friends timeline
-
-#### Without icons
-
-
-
-#### With icons
-
-
-### User's timeline
-
-
-
-### Supported timelines
-
-- Home timeline
-- User's timeline
-- Mentions
-- Lists
-- Direct messages
-- Search timeline
-- Favorites
-- Public timeline
-
-[« Back to top](./index.html)
-
+++ /dev/null
-* {
- padding: 0;
- margin: 0;
-}
-
-body {
-background: #555;
-font-family: Verdana, Arial, Helvetica, sans-serif;
-font-size: 12pt;
-line-height: 13pt;
-color: #333333;;
-}
-
-li {
-margin-left: 20pt;
-padding: 2pt 3pt 2pt 3pt;
-}
-
-p {
-margin: 3pt;
-padding: 3pt;
-}
-
-img { border: none; }
-a { color: #3E92EA; }
-a:hover { text-decoration: none; color : #000; }
-
-#wrap {
-margin: 40px auto 0 auto;
-width: 800px;
-}
-
-#header {
-padding-bottom:10px;
-}
-#header h1 {
-font-size: 28pt;
-font-weight: 100;
-letter-spacing: -1pt;
-padding: 12px 0 5px 10px;
-}
-#header h1 a {
-color: #fff;
-text-decoration: none;
-}
-#header h1 a:hover {
-color: #fff;
-text-decoration: none;
-}
-#header h2 {
-color: #ccc;
-font-size: 15pt;
-font-weight: 100;
-padding: 0 0 0 11px;
-letter-spacing: -1pt;
-line-height: 18pt;
-}
-
-#menu {
-height: 75px;
-line-height: 75px;
-background: #222 url(images/menu.png) repeat-y;
-}
-#menu ul {
-padding-left: 10px;
-list-style-type: none;
-}
-#menu ul li {
-display: block;
-float: left;
-padding: 0;
-marging: 0;
-}
-#menu ul li a {
-color: #eee;
-padding: 0 10px;
-text-decoration: none;
-font-weight: 600;
-}
-#menu ul li a:hover {
-color: #fff;
-text-decoration: underline;
-}
-
-#content {
-background: #555 url(images/content.jpg) repeat-y;
-padding: 10px 30px;
-}
-
-.left {
-/* width: 568px; */
-float: left;
-text-align: justify;
-}
-.left h1 {
-font-size: 24pt;
-line-height: 32pt;
-letter-spacing: -2pt;
-padding : 10px 0 15px 0;
-}
-.left h2 {
-color: #FF4800;
-font-size: 22pt;
-line-height: 22pt;
-letter-spacing: -2pt;
-font-weight: 100;
-padding : 10px 0 15px 0;
-}
-
-.left h3 {
-text-decoration: underline;
-line-height: 22pt;
-margin: 0 0 5pt 0;
-padding : 10pt 0 15pt 0;
-}
-
-.left h4 {
-line-height: 20pt;
-border-left: 10px solid gray;
-padding-left: 5px;
-margin: 10pt 0 15pt 0;
-
-}
-
-.left ul {
-padding: 10px 0 10px 0;
-}
-
-.left ol {
-padding: 10px 0 10px 0;
-}
-
-.left pre {
-margin: 10px;
-padding: 10px;
-border: 1px solid gray;
-border-left: none;
-border-right: none;
-background: AliceBlue;
-}
-
-.left code {
-border: 1px solid lightgray;
-background: wheat;
-}
-
-.left pre code {
-border: none;
-background: none;
-}
-
-.right {
-width: 150px;
-float: right;
-padding: 10px;
-border-left: 1px solid #bbb;
-font-size: 12px;
-}
-.right ul {
-list-style-type: none;
-padding: 5px 10px 10px 10px;
-}
-.right h2 {
-height: 30px;
-font-size: 12px;
-color: #666;
-line-height: 30px;
-}
-.right a { text-decoration: none }
-
-#top {
-background: #555 url(images/top.jpg) no-repeat;
-padding: 5px 0;
-clear: both;
-}
-#bottom {
-background: #555 url(images/bottom.jpg) no-repeat;
-padding: 10px 0;
-}
-
-#footer {
-text-align: center;
-color: #eee;
-font-size: 11px;
-padding: 0 0 10px 0;
-}
-
-.footnote {
-font-size: 10pt;
-}
\ No newline at end of file
+++ /dev/null
-;;; hex-util.el --- Functions to encode/decode hexadecimal string.
-
-;; Copyright (C) 1999, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-
-;; Author: Shuhei KOBAYASHI <shuheiNOSPAMaqua.ocn.ne.jp>
-;; Keywords: data
-
-;; This file is part of FLIM (Faithful Library about Internet Message).
-
-;; 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 3, 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; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(eval-when-compile
- (defmacro hex-char-to-num (chr)
- `(let ((chr ,chr))
- (cond
- ((and (<= ?a chr)(<= chr ?f)) (+ (- chr ?a) 10))
- ((and (<= ?A chr)(<= chr ?F)) (+ (- chr ?A) 10))
- ((and (<= ?0 chr)(<= chr ?9)) (- chr ?0))
- (t (error "Invalid hexadecimal digit `%c'" chr)))))
- (defmacro num-to-hex-char (num)
- `(aref "0123456789abcdef" ,num)))
-
-(defun decode-hex-string (string)
- "Decode hexadecimal STRING to octet string."
- (let* ((len (length string))
- (dst (make-string (/ len 2) 0))
- (idx 0)(pos 0))
- (while (< pos len)
- ;; logior and lsh are not byte-coded.
- ;; (aset dst idx (logior (lsh (hex-char-to-num (aref string pos)) 4)
- ;; (hex-char-to-num (aref string (1+ pos)))))
- (aset dst idx (+ (* (hex-char-to-num (aref string pos)) 16)
- (hex-char-to-num (aref string (1+ pos)))))
- (setq idx (1+ idx)
- pos (+ 2 pos)))
- dst))
-
-(defun encode-hex-string (string)
- "Encode octet STRING to hexadecimal string."
- (let* ((len (length string))
- (dst (make-string (* len 2) 0))
- (idx 0)(pos 0))
- (while (< pos len)
- ;; logand and lsh are not byte-coded.
- ;; (aset dst idx (num-to-hex-char (logand (lsh (aref string pos) -4) 15)))
- (aset dst idx (num-to-hex-char (/ (aref string pos) 16)))
- (setq idx (1+ idx))
- ;; (aset dst idx (num-to-hex-char (logand (aref string pos) 15)))
- (aset dst idx (num-to-hex-char (% (aref string pos) 16)))
- (setq idx (1+ idx)
- pos (1+ pos)))
- dst))
-
-(provide 'hex-util)
-
-;; arch-tag: fe8aaa79-6c86-400e-813f-5a8cc4cb3859
-;;; hex-util.el ends here
+++ /dev/null
-;;; sha1.el --- SHA1 Secure Hash Algorithm in Emacs-Lisp
-
-;; Copyright (C) 1999, 2001, 2002, 2003, 2004,
-;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-
-;; Author: Shuhei KOBAYASHI <shuheiNOSPAMaqua.ocn.ne.jp>
-;; Keywords: SHA1, FIPS 180-1
-
-;; This file is part of FLIM (Faithful Library about Internet Message).
-
-;; 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 3, 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; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; This program is implemented from the definition of SHA-1 in FIPS PUB
-;; 180-1 (Federal Information Processing Standards Publication 180-1),
-;; "Announcing the Standard for SECURE HASH STANDARD".
-;; <URL:http://www.itl.nist.gov/div897/pubs/fip180-1.htm>
-;; (EXCEPTION; two optimizations taken from GnuPG/cipher/sha1.c)
-;;
-;; Test cases from FIPS PUB 180-1.
-;;
-;; (sha1 "abc")
-;; => a9993e364706816aba3e25717850c26c9cd0d89d
-;;
-;; (sha1 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
-;; => 84983e441c3bd26ebaae4aa1f95129e5e54670f1
-;;
-;; (sha1 (make-string 1000000 ?a))
-;; => 34aa973cd4c4daa4f61eeb2bdbad27316534016f
-;;
-;; BUGS:
-;; * It is assumed that length of input string is less than 2^29 bytes.
-;; * It is caller's responsibility to make string (or region) unibyte.
-;;
-;; TODO:
-;; * Rewrite from scratch!
-;; This version is much faster than Keiichi Suzuki's another sha1.el,
-;; but it is too dirty.
-
-;;; Code:
-
-(require 'hex-util)
-
-;;;
-;;; external SHA1 function.
-;;;
-
-(defgroup sha1 nil
- "Elisp interface for SHA1 hash computation."
- :version "22.1"
- :group 'extensions)
-
-(defcustom sha1-maximum-internal-length 500
- "*Maximum length of message to use Lisp version of SHA1 function.
-If message is longer than this, `sha1-program' is used instead.
-
-If this variable is set to 0, use external program only.
-If this variable is set to nil, use internal function only."
- :type 'integer
- :group 'sha1)
-
-(defcustom sha1-program '("sha1sum")
- "*Name of program to compute SHA1.
-It must be a string \(program name\) or list of strings \(name and its args\)."
- :type '(repeat string)
- :group 'sha1)
-
-(defcustom sha1-use-external (condition-case ()
- (executable-find (car sha1-program))
- (error))
- "*Use external SHA1 program.
-If this variable is set to nil, use internal function only."
- :type 'boolean
- :group 'sha1)
-
-(defun sha1-string-external (string &optional binary)
- (let (prog args digest default-enable-multibyte-characters)
- (if (consp sha1-program)
- (setq prog (car sha1-program)
- args (cdr sha1-program))
- (setq prog sha1-program
- args nil))
- (with-temp-buffer
- (insert string)
- (apply (function call-process-region)
- (point-min)(point-max)
- prog t t nil args)
- ;; SHA1 is 40 bytes long in hexadecimal form.
- (setq digest (buffer-substring (point-min)(+ (point-min) 40))))
- (if binary
- (decode-hex-string digest)
- digest)))
-
-(defun sha1-region-external (beg end &optional binary)
- (sha1-string-external (buffer-substring-no-properties beg end) binary))
-
-;;;
-;;; internal SHA1 function.
-;;;
-
-(eval-when-compile
- ;; optional second arg of string-to-number is new in v20.
- (defconst sha1-K0-high 23170) ; (string-to-number "5A82" 16)
- (defconst sha1-K0-low 31129) ; (string-to-number "7999" 16)
- (defconst sha1-K1-high 28377) ; (string-to-number "6ED9" 16)
- (defconst sha1-K1-low 60321) ; (string-to-number "EBA1" 16)
- (defconst sha1-K2-high 36635) ; (string-to-number "8F1B" 16)
- (defconst sha1-K2-low 48348) ; (string-to-number "BCDC" 16)
- (defconst sha1-K3-high 51810) ; (string-to-number "CA62" 16)
- (defconst sha1-K3-low 49622) ; (string-to-number "C1D6" 16)
-
- ;; original definition of sha1-F0.
- ;; (defmacro sha1-F0 (B C D)
- ;; (` (logior (logand (, B) (, C))
- ;; (logand (lognot (, B)) (, D)))))
- ;; a little optimization from GnuPG/cipher/sha1.c.
- (defmacro sha1-F0 (B C D)
- `(logxor ,D (logand ,B (logxor ,C ,D))))
- (defmacro sha1-F1 (B C D)
- `(logxor ,B ,C ,D))
- ;; original definition of sha1-F2.
- ;; (defmacro sha1-F2 (B C D)
- ;; (` (logior (logand (, B) (, C))
- ;; (logand (, B) (, D))
- ;; (logand (, C) (, D)))))
- ;; a little optimization from GnuPG/cipher/sha1.c.
- (defmacro sha1-F2 (B C D)
- `(logior (logand ,B ,C)
- (logand ,D (logior ,B ,C))))
- (defmacro sha1-F3 (B C D)
- `(logxor ,B ,C ,D))
-
- (defmacro sha1-S1 (W-high W-low)
- `(let ((W-high ,W-high)
- (W-low ,W-low))
- (setq S1W-high (+ (% (* W-high 2) 65536)
- (/ W-low ,(/ 65536 2))))
- (setq S1W-low (+ (/ W-high ,(/ 65536 2))
- (% (* W-low 2) 65536)))))
- (defmacro sha1-S5 (A-high A-low)
- `(progn
- (setq S5A-high (+ (% (* ,A-high 32) 65536)
- (/ ,A-low ,(/ 65536 32))))
- (setq S5A-low (+ (/ ,A-high ,(/ 65536 32))
- (% (* ,A-low 32) 65536)))))
- (defmacro sha1-S30 (B-high B-low)
- `(progn
- (setq S30B-high (+ (/ ,B-high 4)
- (* (% ,B-low 4) ,(/ 65536 4))))
- (setq S30B-low (+ (/ ,B-low 4)
- (* (% ,B-high 4) ,(/ 65536 4))))))
-
- (defmacro sha1-OP (round)
- `(progn
- (sha1-S5 sha1-A-high sha1-A-low)
- (sha1-S30 sha1-B-high sha1-B-low)
- (setq sha1-A-low (+ (,(intern (format "sha1-F%d" round))
- sha1-B-low sha1-C-low sha1-D-low)
- sha1-E-low
- ,(symbol-value
- (intern (format "sha1-K%d-low" round)))
- (aref block-low idx)
- (progn
- (setq sha1-E-low sha1-D-low)
- (setq sha1-D-low sha1-C-low)
- (setq sha1-C-low S30B-low)
- (setq sha1-B-low sha1-A-low)
- S5A-low)))
- (setq carry (/ sha1-A-low 65536))
- (setq sha1-A-low (% sha1-A-low 65536))
- (setq sha1-A-high (% (+ (,(intern (format "sha1-F%d" round))
- sha1-B-high sha1-C-high sha1-D-high)
- sha1-E-high
- ,(symbol-value
- (intern (format "sha1-K%d-high" round)))
- (aref block-high idx)
- (progn
- (setq sha1-E-high sha1-D-high)
- (setq sha1-D-high sha1-C-high)
- (setq sha1-C-high S30B-high)
- (setq sha1-B-high sha1-A-high)
- S5A-high)
- carry)
- 65536))))
-
- (defmacro sha1-add-to-H (H X)
- `(progn
- (setq ,(intern (format "sha1-%s-low" H))
- (+ ,(intern (format "sha1-%s-low" H))
- ,(intern (format "sha1-%s-low" X))))
- (setq carry (/ ,(intern (format "sha1-%s-low" H)) 65536))
- (setq ,(intern (format "sha1-%s-low" H))
- (% ,(intern (format "sha1-%s-low" H)) 65536))
- (setq ,(intern (format "sha1-%s-high" H))
- (% (+ ,(intern (format "sha1-%s-high" H))
- ,(intern (format "sha1-%s-high" X))
- carry)
- 65536))))
- )
-
-;;; buffers (H0 H1 H2 H3 H4).
-(defvar sha1-H0-high)
-(defvar sha1-H0-low)
-(defvar sha1-H1-high)
-(defvar sha1-H1-low)
-(defvar sha1-H2-high)
-(defvar sha1-H2-low)
-(defvar sha1-H3-high)
-(defvar sha1-H3-low)
-(defvar sha1-H4-high)
-(defvar sha1-H4-low)
-
-(defun sha1-block (block-high block-low)
- (let (;; step (c) --- initialize buffers (A B C D E).
- (sha1-A-high sha1-H0-high) (sha1-A-low sha1-H0-low)
- (sha1-B-high sha1-H1-high) (sha1-B-low sha1-H1-low)
- (sha1-C-high sha1-H2-high) (sha1-C-low sha1-H2-low)
- (sha1-D-high sha1-H3-high) (sha1-D-low sha1-H3-low)
- (sha1-E-high sha1-H4-high) (sha1-E-low sha1-H4-low)
- (idx 16))
- ;; step (b).
- (let (;; temporary variables used in sha1-S1 macro.
- S1W-high S1W-low)
- (while (< idx 80)
- (sha1-S1 (logxor (aref block-high (- idx 3))
- (aref block-high (- idx 8))
- (aref block-high (- idx 14))
- (aref block-high (- idx 16)))
- (logxor (aref block-low (- idx 3))
- (aref block-low (- idx 8))
- (aref block-low (- idx 14))
- (aref block-low (- idx 16))))
- (aset block-high idx S1W-high)
- (aset block-low idx S1W-low)
- (setq idx (1+ idx))))
- ;; step (d).
- (setq idx 0)
- (let (;; temporary variables used in sha1-OP macro.
- S5A-high S5A-low S30B-high S30B-low carry)
- (while (< idx 20) (sha1-OP 0) (setq idx (1+ idx)))
- (while (< idx 40) (sha1-OP 1) (setq idx (1+ idx)))
- (while (< idx 60) (sha1-OP 2) (setq idx (1+ idx)))
- (while (< idx 80) (sha1-OP 3) (setq idx (1+ idx))))
- ;; step (e).
- (let (;; temporary variables used in sha1-add-to-H macro.
- carry)
- (sha1-add-to-H H0 A)
- (sha1-add-to-H H1 B)
- (sha1-add-to-H H2 C)
- (sha1-add-to-H H3 D)
- (sha1-add-to-H H4 E))))
-
-(defun sha1-binary (string)
- "Return the SHA1 of STRING in binary form."
- (let (;; prepare buffers for a block. byte-length of block is 64.
- ;; input block is split into two vectors.
- ;;
- ;; input block: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ...
- ;; block-high: +-0-+ +-1-+ +-2-+ +-3-+
- ;; block-low: +-0-+ +-1-+ +-2-+ +-3-+
- ;;
- ;; length of each vector is 80, and elements of each vector are
- ;; 16bit integers. elements 0x10-0x4F of each vector are
- ;; assigned later in `sha1-block'.
- (block-high (eval-when-compile (make-vector 80 nil)))
- (block-low (eval-when-compile (make-vector 80 nil))))
- (unwind-protect
- (let* (;; byte-length of input string.
- (len (length string))
- (lim (* (/ len 64) 64))
- (rem (% len 4))
- (idx 0)(pos 0))
- ;; initialize buffers (H0 H1 H2 H3 H4).
- (setq sha1-H0-high 26437 ; (string-to-number "6745" 16)
- sha1-H0-low 8961 ; (string-to-number "2301" 16)
- sha1-H1-high 61389 ; (string-to-number "EFCD" 16)
- sha1-H1-low 43913 ; (string-to-number "AB89" 16)
- sha1-H2-high 39098 ; (string-to-number "98BA" 16)
- sha1-H2-low 56574 ; (string-to-number "DCFE" 16)
- sha1-H3-high 4146 ; (string-to-number "1032" 16)
- sha1-H3-low 21622 ; (string-to-number "5476" 16)
- sha1-H4-high 50130 ; (string-to-number "C3D2" 16)
- sha1-H4-low 57840) ; (string-to-number "E1F0" 16)
- ;; loop for each 64 bytes block.
- (while (< pos lim)
- ;; step (a).
- (setq idx 0)
- (while (< idx 16)
- (aset block-high idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (aset block-low idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (setq idx (1+ idx)))
- (sha1-block block-high block-low))
- ;; last block.
- (if (prog1
- (< (- len lim) 56)
- (setq lim (- len rem))
- (setq idx 0)
- (while (< pos lim)
- (aset block-high idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (aset block-low idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (setq idx (1+ idx)))
- ;; this is the last (at most) 32bit word.
- (cond
- ((= rem 3)
- (aset block-high idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (aset block-low idx (+ (* (aref string pos) 256)
- 128)))
- ((= rem 2)
- (aset block-high idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (aset block-low idx 32768))
- ((= rem 1)
- (aset block-high idx (+ (* (aref string pos) 256)
- 128))
- (aset block-low idx 0))
- (t ;; (= rem 0)
- (aset block-high idx 32768)
- (aset block-low idx 0)))
- (setq idx (1+ idx))
- (while (< idx 16)
- (aset block-high idx 0)
- (aset block-low idx 0)
- (setq idx (1+ idx))))
- ;; last block has enough room to write the length of string.
- (progn
- ;; write bit length of string to last 4 bytes of the block.
- (aset block-low 15 (* (% len 8192) 8))
- (setq len (/ len 8192))
- (aset block-high 15 (% len 65536))
- ;; XXX: It is not practical to compute SHA1 of
- ;; such a huge message on emacs.
- ;; (setq len (/ len 65536)) ; for 64bit emacs.
- ;; (aset block-low 14 (% len 65536))
- ;; (aset block-high 14 (/ len 65536))
- (sha1-block block-high block-low))
- ;; need one more block.
- (sha1-block block-high block-low)
- (fillarray block-high 0)
- (fillarray block-low 0)
- ;; write bit length of string to last 4 bytes of the block.
- (aset block-low 15 (* (% len 8192) 8))
- (setq len (/ len 8192))
- (aset block-high 15 (% len 65536))
- ;; XXX: It is not practical to compute SHA1 of
- ;; such a huge message on emacs.
- ;; (setq len (/ len 65536)) ; for 64bit emacs.
- ;; (aset block-low 14 (% len 65536))
- ;; (aset block-high 14 (/ len 65536))
- (sha1-block block-high block-low))
- ;; make output string (in binary form).
- (let ((result (make-string 20 0)))
- (aset result 0 (/ sha1-H0-high 256))
- (aset result 1 (% sha1-H0-high 256))
- (aset result 2 (/ sha1-H0-low 256))
- (aset result 3 (% sha1-H0-low 256))
- (aset result 4 (/ sha1-H1-high 256))
- (aset result 5 (% sha1-H1-high 256))
- (aset result 6 (/ sha1-H1-low 256))
- (aset result 7 (% sha1-H1-low 256))
- (aset result 8 (/ sha1-H2-high 256))
- (aset result 9 (% sha1-H2-high 256))
- (aset result 10 (/ sha1-H2-low 256))
- (aset result 11 (% sha1-H2-low 256))
- (aset result 12 (/ sha1-H3-high 256))
- (aset result 13 (% sha1-H3-high 256))
- (aset result 14 (/ sha1-H3-low 256))
- (aset result 15 (% sha1-H3-low 256))
- (aset result 16 (/ sha1-H4-high 256))
- (aset result 17 (% sha1-H4-high 256))
- (aset result 18 (/ sha1-H4-low 256))
- (aset result 19 (% sha1-H4-low 256))
- result))
- ;; do not leave a copy of input string.
- (fillarray block-high nil)
- (fillarray block-low nil))))
-
-(defun sha1-string-internal (string &optional binary)
- (if binary
- (sha1-binary string)
- (encode-hex-string (sha1-binary string))))
-
-(defun sha1-region-internal (beg end &optional binary)
- (sha1-string-internal (buffer-substring-no-properties beg end) binary))
-
-;;;
-;;; application interface.
-;;;
-
-(defun sha1-region (beg end &optional binary)
- (if (and sha1-use-external
- sha1-maximum-internal-length
- (> (abs (- end beg)) sha1-maximum-internal-length))
- (sha1-region-external beg end binary)
- (sha1-region-internal beg end binary)))
-
-(defun sha1-string (string &optional binary)
- (if (and sha1-use-external
- sha1-maximum-internal-length
- (> (length string) sha1-maximum-internal-length))
- (sha1-string-external string binary)
- (sha1-string-internal string binary)))
-
-;;;###autoload
-(defun sha1 (object &optional beg end binary)
- "Return the SHA1 (Secure Hash Algorithm) of an object.
-OBJECT is either a string or a buffer.
-Optional arguments BEG and END denote buffer positions for computing the
-hash of a portion of OBJECT.
-If BINARY is non-nil, return a string in binary form."
- (if (stringp object)
- (sha1-string object binary)
- (with-current-buffer object
- (sha1-region (or beg (point-min)) (or end (point-max)) binary))))
-
-(provide 'sha1)
-
-;; arch-tag: c0f9abd0-ffc1-4557-aac6-ece7f2d4c901
-;;; sha1.el ends here
+++ /dev/null
-;;; tls.el --- TLS/SSL support via wrapper around GnuTLS
-
-;; Copyright (C) 1996, 1997, 1998, 1999, 2002, 2003, 2004,
-;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-
-;; Author: Simon Josefsson <simonNOSPAMjosefsson.org>
-;; Keywords: comm, tls, gnutls, ssl
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs 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 3, or (at your option)
-;; any later version.
-
-;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; This package implements a simple wrapper around "gnutls-cli" to
-;; make Emacs support TLS/SSL.
-;;
-;; Usage is the same as `open-network-stream', i.e.:
-;;
-;; (setq tmp (open-tls-stream "test" (current-buffer) "news.mozilla.org" 563))
-;; ...
-;; #<process test>
-;; (process-send-string tmp "mode reader\n")
-;; 200 secnews.netscape.com Netscape-Collabra/3.52 03615 NNRP ready ...
-;; nil
-;; (process-send-string tmp "quit\n")
-;; 205
-;; nil
-
-;; To use this package as a replacement for ssl.el by William M. Perry
-;; <wmperryNOSPAMcs.indiana.edu>, you need to evaluate the following:
-;;
-;; (defalias 'open-ssl-stream 'open-tls-stream)
-
-;;; Code:
-
-(eval-and-compile
- (autoload 'format-spec "format-spec")
- (autoload 'format-spec-make "format-spec"))
-
-(defgroup tls nil
- "Transport Layer Security (TLS) parameters."
- :group 'comm)
-
-(defcustom tls-end-of-info
- (concat
- "\\("
- ;; `openssl s_client' regexp. See ssl/ssl_txt.c lines 219-220.
- ;; According to apps/s_client.c line 1515 `---' is always the last
- ;; line that is printed by s_client before the real data.
- "^ Verify return code: .+\n---\n\\|"
- ;; `gnutls' regexp. See src/cli.c lines 721-.
- "^- Simple Client Mode:\n"
- "\\(\n\\|" ; ignore blank lines
- ;; According to GnuTLS v2.1.5 src/cli.c lines 640-650 and 705-715
- ;; in `main' the handshake will start after this message. If the
- ;; handshake fails, the programs will abort.
- "^\\*\\*\\* Starting TLS handshake\n\\)*"
- "\\)")
- "Regexp matching end of TLS client informational messages.
-Client data stream begins after the last character matched by
-this. The default matches `openssl s_client' (version 0.9.8c)
-and `gnutls-cli' (version 2.0.1) output."
- :version "22.2"
- :type 'regexp
- :group 'tls)
-
-(defcustom tls-program '("gnutls-cli -p %p %h"
- "gnutls-cli -p %p %h --protocols ssl3"
- "openssl s_client -connect %h:%p -no_ssl2")
- "List of strings containing commands to start TLS stream to a host.
-Each entry in the list is tried until a connection is successful.
-%h is replaced with server hostname, %p with port to connect to.
-The program should read input on stdin and write output to
-stdout. Also see `tls-success' for what the program should output
-after successful negotiation."
- :type '(repeat string)
- :version "22.1"
- :group 'tls)
-
-(defcustom tls-process-connection-type nil
- "*Value for `process-connection-type' to use when starting TLS process."
- :version "22.1"
- :type 'boolean
- :group 'tls)
-
-(defcustom tls-success "- Handshake was completed\\|SSL handshake has read "
- "*Regular expression indicating completed TLS handshakes.
-The default is what GNUTLS's \"gnutls-cli\" or OpenSSL's
-\"openssl s_client\" outputs."
- :version "22.1"
- :type 'regexp
- :group 'tls)
-
-(defcustom tls-certtool-program (executable-find "certtool")
- "Name of GnuTLS certtool.
-Used by `tls-certificate-information'."
- :version "22.1"
- :type 'string
- :group 'tls)
-
-(defun tls-certificate-information (der)
- "Parse X.509 certificate in DER format into an assoc list."
- (let ((certificate (concat "-----BEGIN CERTIFICATE-----\n"
- (base64-encode-string der)
- "\n-----END CERTIFICATE-----\n"))
- (exit-code 0))
- (with-current-buffer (get-buffer-create " *certtool*")
- (erase-buffer)
- (insert certificate)
- (setq exit-code (condition-case ()
- (call-process-region (point-min) (point-max)
- tls-certtool-program
- t (list (current-buffer) nil) t
- "--certificate-info")
- (error -1)))
- (if (/= exit-code 0)
- nil
- (let ((vals nil))
- (goto-char (point-min))
- (while (re-search-forward "^\\([^:]+\\): \\(.*\\)" nil t)
- (push (cons (match-string 1) (match-string 2)) vals))
- (nreverse vals))))))
-
-(defun open-tls-stream (name buffer host port)
- "Open a TLS connection for a port to a host.
-Returns a subprocess-object to represent the connection.
-Input and output work as for subprocesses; `delete-process' closes it.
-Args are NAME BUFFER HOST PORT.
-NAME is name for process. It is modified if necessary to make it unique.
-BUFFER is the buffer (or buffer-name) to associate with the process.
- Process output goes at end of that buffer, unless you specify
- an output stream or filter function to handle the output.
- BUFFER may be also nil, meaning that this process is not associated
- with any buffer
-Third arg is name of the host to connect to, or its IP address.
-Fourth arg PORT is an integer specifying a port to connect to."
- (let ((cmds tls-program)
- (use-temp-buffer (null buffer))
- process cmd done)
- (if use-temp-buffer
- (setq buffer (generate-new-buffer " TLS")))
- (with-current-buffer buffer
- (message "Opening TLS connection to `%s'..." host)
- (while (and (not done) (setq cmd (pop cmds)))
- (message "Opening TLS connection with `%s'..." cmd)
- (let ((process-connection-type tls-process-connection-type)
- response)
- (setq process (start-process
- name buffer shell-file-name shell-command-switch
- (format-spec
- cmd
- (format-spec-make
- ?h host
- ?p (if (integerp port)
- (int-to-string port)
- port)))))
- (while (and process
- (memq (process-status process) '(open run))
- (progn
- (goto-char (point-min))
- (not (setq done (re-search-forward tls-success nil t)))))
- (unless (accept-process-output process 1)
- (sit-for 1)))
- (message "Opening TLS connection with `%s'...%s" cmd
- (if done "done" "failed"))
- (if (not done)
- (delete-process process)
- ;; advance point to after all informational messages that
- ;; `openssl s_client' and `gnutls' print
- (let ((start-of-data nil))
- (while
- (not (setq start-of-data
- ;; the string matching `tls-end-of-info'
- ;; might come in separate chunks from
- ;; `accept-process-output', so start the
- ;; search where `tls-success' ended
- (save-excursion
- (if (re-search-forward tls-end-of-info nil t)
- (match-end 0)))))
- (accept-process-output process 1))
- (if start-of-data
- ;; move point to start of client data
- (goto-char start-of-data)))
- (setq done process))))
- (message "Opening TLS connection to `%s'...%s"
- host (if done "done" "failed")))
- (when use-temp-buffer
- (if done (set-process-buffer process nil))
- (kill-buffer buffer))
- done))
-
-(provide 'tls)
-
-;;; arch-tag: 5596d1c4-facc-4bc4-94a9-9863b928d7ac
-;;; tls.el ends here
+++ /dev/null
-<!-- -*- mode: markdown -*- -->
-
-# What to do on a release
-
-- Add new version number to `/NEWS` and `/NEWS.ja` and describe updates.
-- `make release` to update version numbers and create tarballs.
- - Fix the new version number based on the rule above and update `/VERSION`.
- - Update version numbers in source code(`/twittering-mode.el`).
- - Update version numbers on web pages(`/doc/web/index.text`).
- - Change the version number in `/VERSION` to next (expected) version number.
-- Make a tag `v<VERSION>`
-- Upload new source files to souceforge.net
-- Publish web pages(`cd doc/web; make upload`).
-- Release announce on MLs.
-- Release announce on freshmeat.net.
-- Release announce on Twitter.
+++ /dev/null
-#!/usr/bin/env ruby
-
-require 'net/http'
-require 'net/https'
-require 'optparse'
-require 'uri'
-
-def verbose_printer(verbosity)
- if verbosity
- pid = Process.pid
- Proc.new do |msg|
- $stderr.puts "[#{pid}]: #{msg}"
- end
- else
- Proc.new do |a|
- end
- end
-end
-
-def parse_option(argv)
- parser = OptionParser.new
- opt = Hash.new
-
- print_help = Proc.new do |msg, *args|
- exits = if args.size > 0
- args.shift
- else
- true
- end
- if msg
- puts msg
- puts
- end
- puts "Usage: #{$0} [OPTIONS] HOSTNAME"
- puts parser.help
-
- if exits
- exit(1)
- end
- end
-
- parser.on('-h') do
- print_help.call(nil)
- end
-
- # TODO: should be rewrite in cURL style option
- opt[:verbose] = nil
- parser.on('-v', '--verbose',
- "\n\t\tverbose") do
- opt[:verbose] = true
- end
-
- opt[:headers] = Hash.new
- parser.on('-H', '--header HEADER',
- "\n\t\tadditional HTTP header field." +
- "\n\t\tuse like -h \"User-Agent: Ruby\"") do |header|
- unless header =~ /^([-A-Za-z]+):\s*(.+)$/
- print_help.call("Invalid HTTP header format: #{header}")
- end
- opt[:headers][$~[1]] = $~[2]
- end
-
- opt[:method] = 'GET'
- parser.on('-m', '--method METHOD',
- "\n\t\tHTTP request method"+
- " (GET and POST are supported)") do |method|
- unless method =~ /\A(GET|POST)\Z/
- print_help.call("Not such HTTP method: #{method}")
- end
- opt[:method] = method
- end
-
- opt[:path] = '/'
- parser.on('-P', '--path PATH',
- "\n\t\tHTTP request path (default: \"/\")") do |path|
- opt[:path] = path
- end
-
- opt[:encode] = nil
- parser.on('-e', '--encode',
- "\n\t\tpercent encode HTTP request path (default: no)") do
- opt[:encode] = true
- end
-
- opt[:ssl] = nil
- parser.on('-s', '--ssl', "\n\t\tuse SSL (default: no)") do
- opt[:ssl] = true
- end
-
- opt[:port] = nil
- parser.on('-p', '--port PORT',
- "\n\t\tdestination port number" +
- " (default: 80 on non-SSL, 443 on SSL)") do |port|
- opt[:port] = port.to_i
- puts "port: #{opt[:port]}"
- end
-
- opt[:ssl_cert] = nil
- parser.on('-c', '--cert PATH',
- "\n\t\tCA certificate file(*.pem)" +
- " for verifying certificates") do |path|
- unless File.exist?(path)
- print_help.call("No such file: #{path}")
- end
- opt[:ssl_cert] = path
- end
-
- parser.parse!(argv)
-
- if argv.size == 0
- print_help.call('HOSTNAME required')
- end
- opt[:host] = argv.first
- if !opt[:port]
- opt[:port] = if opt[:ssl]
- 443
- else
- 80
- end
- end
- opt[:path] = URI.encode(opt[:path]) if opt[:encode]
-
- opt
-end
-
-def print_header_string(res)
- print "HTTP/#{res.http_version} #{res.code} #{res.message}"
- res.canonical_each do |name,value|
- print("\r\n#{name}: #{value}")
- end
-end
-
-def main(argv)
- Net::HTTP.version_1_2
- opt = parse_option(argv)
- vprint = verbose_printer(opt[:verbose])
-
- http = Net::HTTP.new(opt[:host], opt[:port])
- if opt[:ssl]
- http.use_ssl = true
- vprint.call("SSL enabled")
- if opt[:ssl_cert]
- http.ca_file = opt[:ssl_cert]
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
- http.verify_depth = 5
- end
- end
-
- res = nil
- begin
- http.start do |client|
- res = case opt[:method]
- when /GET/
- client.get(opt[:path], opt[:headers])
- when /POST/
- client.post(opt[:path], opt[:headers])
- end
- end
- end
-
- if res
- print_header_string(res)
- print "\r\n\r\n"
- print res.body
- $stdout.flush
- else
- $stderr.puts "error"
- end
-end
-
-if __FILE__ == $0
- main(ARGV.dup)
-end
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="96"
- height="96"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docname="twitter-icon.svg"
- version="1.0"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- inkscape:export-filename="/home/haya/repos/twittering-mode/misc/twitter-icon.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- gridtolerance="10000"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="1.4"
- inkscape:cx="28.460376"
- inkscape:cy="58.794859"
- inkscape:document-units="px"
- inkscape:current-layer="layer2"
- showgrid="false"
- inkscape:window-width="1024"
- inkscape:window-height="722"
- inkscape:window-x="0"
- inkscape:window-y="25" />
- <defs
- id="defs4">
- <inkscape:perspective
- id="perspective10"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 526.18109 : 1"
- sodipodi:type="inkscape:persp3d" />
- <inkscape:perspective
- id="perspective2857"
- inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
- inkscape:vp_z="744.09448 : 526.18109 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_x="0 : 526.18109 : 1"
- sodipodi:type="inkscape:persp3d" />
- <filter
- inkscape:collect="always"
- id="filter5924"
- x="-0.019761875"
- width="1.0395238"
- y="-0.10917721"
- height="1.2183543">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="2.8028142"
- id="feGaussianBlur5926" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter3781"
- x="-0.32089513"
- width="1.6417903"
- y="-0.39418649"
- height="1.788373">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="8.1491487"
- id="feGaussianBlur3783" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4143"
- x="-0.13009262"
- width="1.2601852"
- y="-0.15980533"
- height="1.3196107">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="3.3037089"
- id="feGaussianBlur4145" />
- </filter>
- <filter
- inkscape:collect="always"
- id="filter4623"
- x="-0.081529018"
- width="1.163058"
- y="-0.19361144"
- height="1.3872229">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="2.8770179"
- id="feGaussianBlur4625" />
- </filter>
- </defs>
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:groupmode="layer"
- inkscape:label="background"
- style="display:inline"
- sodipodi:insensitive="true">
- <rect
- style="fill:#3c90e8;fill-opacity:1;stroke:none;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect2865"
- width="96"
- height="96"
- x="0"
- y="3.5527137e-15" />
- <path
- style="fill:#000000"
- d=""
- id="path2863" />
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer2"
- inkscape:label="tw">
- <g
- id="g4154"
- transform="translate(-0.5050724,0)">
- <text
- xml:space="preserve"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
- x="17.83165"
- y="51.593716"
- id="text2458"><tspan
- sodipodi:role="line"
- id="tspan2460"
- x="17.83165"
- y="51.593716"
- style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:7;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:SkinnyAL;-inkscape-font-specification:SkinnyAL">tw</tspan></text>
- <text
- id="text3753"
- y="51.593716"
- x="17.83165"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;filter:url(#filter4143);font-family:Bitstream Vera Sans"
- xml:space="preserve"><tspan
- style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:7;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:SkinnyAL;-inkscape-font-specification:SkinnyAL"
- y="51.593716"
- x="17.83165"
- id="tspan3755"
- sodipodi:role="line">tw</tspan></text>
- </g>
- <g
- style="display:inline"
- id="g4627"
- transform="translate(9.7040827e-2,-0.4677026)">
- <g
- transform="translate(0,8)"
- id="g4197"
- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4623)">
- <path
- id="path4199"
- d="M 33.494214,76.760929 C 33.494187,78.94218 32.73075,80.79624 31.203903,82.323111 L 29.941891,83.585118 L 28.492925,82.182888 L 29.801671,80.874139 C 30.923428,79.752357 31.484325,78.381288 31.484343,76.760929 L 31.484343,62.551657 C 31.484325,61.648018 31.172712,60.884582 30.54953,60.261346 C 29.926286,59.638157 29.162858,59.32655&nbs.89257,59.51349 C 20.952015,58.048963 22.369834,57.316687 24.146009,57.316661 L 28.25922,57.316661 C 29.723746,57.316687 30.954584,57.830838 31.951753,58.859115 C 32.980034,59.856281 33.494187,61.087126 33.494214,62.551657 L 33.494214,76.760929"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans" />
- <g
- transform="matrix(0.8346612,0,0,0.8346612,-89.916048,11.50044)"
- id="g4201"
- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.99045467;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.99045467;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
- d="M 170.83422,80.035999 C 170.8342,81.753337 170.2182,83.228002 168.98622,84.459999 C 167.79153,85.691999 166.31687,86.307999 164.56222,86.307999 L 159.63422,86.307999 C 157.91688,86.307999 156.44221,85.691999 155.21022,84.459999 C 153.97821,83.228002 153.36221,81.753337 153.36222,80.035999 L 153.36222,61.163999 C 153.36221,59.409359 153.97821,57.934694 155.21022,56.739999 C 156.44221,55.508029 157.91688,54.89203 159.63422,54.891999 L 164.56222,54.891999 C 166.31687,54.89203 167.79153,55.508029 168.98622,56.739999 C 170.2182,57.934694 170.8342,59.409359 170.83422,61.163999 L 170.83422,80.035999"
- id="path4203" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5.99045467;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
- d="M 168.42622,80.035999 L 168.42622,61.163999 C 168.4262,60.081358 168.05286,59.166692 167.30622,58.419999 C 166.55953,57.673361 165.64487,57.300028 164.56222,57.299999 L 159.63422,57.299999 C 158.58887,57.300028 157.67421,57.673361 156.89022,58.419999 C 156.14354,59.166692 155.77021,60.081358 155.77022,61.163999 L 155.77022,80.035999 C 155.77021,81.081337 156.14354,81.996003 156.89022,82.779999 C 157.67421,83.526668 158.58887,83.900001 159.63422,83.899999 L 164.56222,83.899999 C 165.64487,83.900001 166.55953,83.526668 167.30622,82.779999 C 168.05286,81.996003 168.4262,81.081337 168.42622,80.035999"
- id="path4205" />
- </g>
- <path
- id="path4207"
- d="M 71.851083,78.303382 C 71.851065,79.736778 71.336912,80.967623 70.308631,81.995923 C 69.311471,83.024226 68.080624,83.538377 66.616089,83.538377 L 62.502878,83.538377 C 61.069481,83.538377 59.838633,83.024226 58.810335,81.995923 C 57.782028,80.967623 57.267875,79.736778 57.267883,78.303382 L 57.267883,68.62799 C 57.267875,66.446759 58.031311,64.5927 59.558194,63.065808 L 65.354076,57.26992 L 66.756308,58.672152 L 60.960426,64.468039 C 59.838633,65.589841 59.277737,66.97649 59.277746,68.62799 L 59.277746,78.303382 C 59.277737,79.175886 59.589341,79.939322 60.212567,80.593692 C 60.866932,81.216908 61.630368,81.528514 62.502878,81.528514 L 66.616089,81.528514 C 67.519736,81.528514 68.283164,81.216908 68.906399,80.593692 C 69.52959,79.939322 69.841203,79.175886 69.841221,78.303382 L 69.841221,47.921715 L 71.851083,47.921715 L 71.851083,78.303382"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans" />
- <path
- id="path4209"
- d="M 91.029521,67.132277 C 91.029503,69.313539 90.266057,71.167598 88.73921,72.694459 L 83.130282,78.256641 L 81.72805,76.85441 L 87.336978,71.245487 C 88.458744,70.123716 89.019641,68.752647 89.01965,67.132277 L 89.01965,62.551657 C 89.019641,61.648018 88.708028,60.884582 88.084828,60.261346 C 87.461602,59.638157 86.698165,59.3503,61.087126 91.029521,62.551657 L 91.029521,67.132277"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans" />
- </g>
- <g
- transform="translate(0,8)"
- style="fill:#ffffff;fill-opacity:1"
- id="g4189">
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
- d="M 33.494214,76.760929 C 33.494187,78.94218 32.73075,80.79624 31.203903,82.323111 L 29.941891,83.585118 L 28.492925,82.182888 L 29.801671,80.874139 C 30.923428,79.752357 31.484325,78.381288 31.484343,76.760929 L 31.484343,62.551657 C 31.484325,61.648018 31.172712,60.884582 30.54953,60.261346 C 29.926286,59.638157 29.162858,59.32655 28.25922,59.326526 L 24.146009,59.326526 C 23.273482,59.32655 22.51061 L 28.25922,57.316661 C 29.723746,57.316687 30.954584,57.830838 31.951753,58.859115 C 32.980034,59.856281 33.494187,61.087126 33.494214,62.551657 L 33.494214,76.760929"
- id="path4169" />
- <g
- style="fill:#ffffff;fill-opacity:1"
- id="g4171"
- transform="matrix(0.8346612,0,0,0.8346612,-89.916048,11.50044)">
- <path
- id="path4167"
- d="M 170.83422,80.035999 C 170.8342,81.753337 170.2182,83.228002 168.98622,84.459999 C 167.79153,85.691999 166.31687,86.307999 164.56222,86.307999 L 159.63422,86.307999 C 157.91688,86.307999 156.44221,85.691999 155.21022,84.459999 C 153.97821,83.228002 153.36221,81.753337 153.36222,80.035999 L 153.36222,61.163999 C 153.36221,59.409359 153.97821,57.934694 155.21022,56.739999 C 156.44221,55.508029 157.91688,54.89203 159.63422,54.891999 L 164.56222,54.891999 C 166.31687,54.89203 167.79153,55.508029 168.98622,56.739999 C 170.2182,57.934694 170.8342,59.409359 170.83422,61.163999 L 170.83422,80.035999"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans" />
- <path
- id="path4165"
- d="M 168.42622,80.035999 L 168.42622,61.163999 C 168.4262,60.081358 168.05286,59.166692 167.30622,58.419999 C 166.55953,57.673361 165.64487,57.300028 164.56222,57.299999 L 159.63422,57.299999 C 158.58887,57.300028 157.67421,57.673361 156.89022,58.419999 C 156.14354,59.166692 155.77021,60.081358 155.77022,61.163999 L 155.77022,80.035999 C 155.77021,81.081337 156.14354,81.996003 156.89022,82.779999 C 157.67421,83.526668 158.58887,83.900001 159.63422,83.899999 L 164.56222,83.899999 C 165.64487,83.900001 166.55953,83.526668 167.30622,82.779999 C 168.05286,81.996003 168.4262,81.081337 168.42622,80.035999"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans" />
- </g>
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
- d="M 71.851083,78.303382 C 71.851065,79.736778 71.336912,80.967623 70.308631,81.995923 C 69.311471,83.024226 68.080624,83.538377 66.616089,83.538377 L 62.502878,83.538377 C 61.069481,83.538377 59.838633,83.024226 58.810335,81.995923 C 57.782028,80.967623 57.267875,79.736778 57.267883,78.303382 L 57.267883,68.62799 C 57.267875,66.446759 58.031311,64.5927 59.558194,63.065808 L 65.354076,57.26992 L 66.756308,58.672152 L 60.960426,64.468039 C 59.838633,65.589841 59.277737,66.97649 59.277746,68.62799 L 59.277746,78.303382 C 59.277737,79.175886 59.589341,79.939322 60.212567,80.593692 C 60.866932,81.216908 61.630368,81.528514 62.502878,81.528514 L 66.616089,81.528514 C 67.519736,81.528514 68.283164,81.216908 68.906399,80.593692 C 69.52959,79.939322 69.841203,79.175886 69.841221,78.303382 L 69.841221,47.921715 L 71.851083,47.921715 L 71.851083,78.303382"
- id="path4163" />
- <path
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;font-family:Bitstream Vera Sans"
- d="M 91.029521,67.132277 C 91.029503,69.313539 90.266057,71.167598 88.73921,72.694459 L 83.130282,78.256641 L 81.72805,76.85441 L 87.336978,71.245487 C 88.458744,70.123716 89.019641,68.752647 89.01965,67.132277 L 89.01965,62.551657 C 89.019641,61.648018 88.708028,60.884582 88.084828,60.261346 C 87.461602,59.638157 86.698165,59.32655 85.794527,59.326526 L 81.681307,59.326526 C 80.808798,59.32655 80.045361,59.638157 79.390996,60.261346 C 78.76777,60.884582 78.456166,61.648018 78.456175,62.551657 L 78.456175,78.303382 C 78.456166,79.175886 78.76777,79.939322 79.390996,80.593692 C 80.045361,81.216908 80.808798,81.528514 81.681307,81.528514 L 89.01965,81.528514 L 89.01965,83.538377 L 81.681307,83.538377 C 80.24791,83.538377 79.017062,83.024226 77.988764,81.995923 C 76.960457,80.967623 76.446304,79.736778 76.446312,78.303382 L 76.446312,62.551657 C 76.446304,61.087126 76.960457,59.856281 77.988764,58.859115 C 79.017062,57.830838 80.24791,57.316687 81.681307,57.316661 L 85.794527,57.316661 C 87.259062,57.316687 88.4899,57.830838 89.48706,58.859115 C 90.51535,59.856281 91.029503,61.087126 91.029521,62.551657 L 91.029521,67.132277"
- id="text2462" />
- </g>
- </g>
- </g>
- <g
- inkscape:groupmode="layer"
- id="layer3"
- inkscape:label="text"
- style="display:none">
- <text
- id="text2383"
- y="186.61864"
- x="125.66487"
- style="font-size:36px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
- xml:space="preserve"><tspan
- style="font-size:56px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:SkinnyAL;-inkscape-font-specification:SkinnyAL"
- y="186.61864"
- x="125.66487"
- id="tspan2385"
- sodipodi:role="line">twittering-mode</tspan></text>
- </g>
-</svg>
+++ /dev/null
-#!/usr/bin/env ruby
-
-require 'optparse'
-require 'tempfile'
-require 'pathname'
-require 'fileutils'
-
-def y_or_n_p(msg)
- answer = nil
-
- while answer == nil
- print "#{msg} [yes or no]: "
- $stdout.flush
- ans = $stdin.readline.strip
- case ans
- when /yes/
- answer = true
- break
- when /no/
- answer = false
- break
- else
- puts "Please type 'yes' or 'no'."
- puts
- end
- end
-
- answer
-end
-
-class FileContext
- def initialize(lines, cur_line_idx,
- match_col_start, match_col_end, rplstr)
- @lines = lines
- @cur_line_idx = cur_line_idx
- @match_col_start = match_col_start
- @match_col_end = match_col_end
- @rplstr = rplstr
- end
-
- def inspect
- cur_line = @lines[@cur_line_idx][1].dup
- len = @match_col_end - @match_col_start
- rplstr = "\033[1m\033[4m" + cur_line[@match_col_start, len] + "\033[0m"
- cur_line[@match_col_start, len] = rplstr
- lines = @lines.dup
- lines[@cur_line_idx] = [@lines[@cur_line_idx][0], cur_line]
-
- lineno_width = lines[lines.size - 1][0].to_s.size
- lines.map{|line| sprintf("%#{lineno_width}d: %s", line[0], line[1])}.join.rstrip
- end
-
- def line
- @lines[@cur_line_idx][1]
- end
-
- def lineno
- @lines[@cur_line_idx][0]
- end
-
- def replaced_line
- cur_line = @lines[@cur_line_idx][1].dup
- len = @match_col_end - @match_col_start
- cur_line[@match_col_start, len] = @rplstr
- cur_line
- end
-end
-
-class FileReplacer
- def initialize(file, opt)
- @infile = File.open(file, "r")
- @outfile = Tempfile.new("fileupdater")
- @opt = opt
-
- @lineno = 1
- # current line is the first element of after_buffer
- @before_buffer = []
- @after_buffer = []
- (@opt[:context] + 1).times do
- self.fetch_line(true)
- end
- end
-
- def replace!()
- while @after_buffer.size > 0
- pos = 0
- cur_line_str = @after_buffer.first[1]
- while @opt[:regexp].match(cur_line_str[pos..(cur_line_str.size)])
- context = FileContext.new(@before_buffer + @after_buffer,
- @before_buffer.size,
- pos + $~.begin(0),
- pos + $~.end(0), @opt[:replace])
- rpl = yield(context) || cur_line_str
- if rpl != cur_line_str
- @after_buffer[0][1] = rpl
- end
- pos = $~.begin(0) + 1
- end
- @outfile.print(@after_buffer.first[1])
-
- self.fetch_line
- end
-
- @infile.close
- @outfile.close
- FileUtils.copy(@outfile.path, @infile.path)
- end
-
- def fetch_line(beginning_of_file = false)
- eof_reached = false
- line = nil
- begin
- line = @infile.readline
- rescue EOFError => e
- eof_reached = true
- end
-
- if line
- @after_buffer.push([@lineno, line])
- @lineno += 1
- end
-
- if ! beginning_of_file &&
- (eof_reached || @after_buffer.size > @opt[:context] + 1)
- @before_buffer.push(@after_buffer.shift)
- @before_buffer.shift if @before_buffer.size > @opt[:context]
- end
-
- @after_buffer.first
- end
-end
-
-def update(file, opt)
- base = Pathname.pwd
- path = Pathname.new(file).realpath.to_s
- replacer = FileReplacer.new(file,
- :regexp => Regexp.compile(Regexp.quote(opt[:prev_version])),
- :replace => opt[:next_version],
- :context => opt[:context])
- replacer.replace! do |context|
- puts "==== file: #{Pathname.new(path).relative_path_from(base).to_s} ===="
- puts context.inspect
- puts
- puts "\033[34m\033[1mbefore\033[0m: #{context.line}"
- puts "\033[31m\033[1mafter\033[0m : #{context.replaced_line}"
- puts
- if y_or_n_p("Update this line?")
- context.replaced_line
- else
- context.line
- end
- end
-rescue Errno::ENOENT => e
- nil
-end
-
-def parse_args(argv)
- parser = OptionParser.new
- opt = Hash.new
- print_help = Proc.new do |msg|
- puts msg
- puts
- puts parser.help
- exit
- end
-
- opt[:context] = 3
- parser.on('-C', '--context=NUM',
- "\n\t\tPrint NUM lines around matching lines."+
- " Default value is #{opt[:context]}") do |num|
- opt[:context] = num.to_i
- opt[:context] = 3 if opt[:context] < 3
- end
-
- parser.on('-p', '--prev-version=NUM',
- "\n\t\tPrevious version number.") do |prev|
- opt[:prev_version] = prev
- end
-
- parser.on('-n', '--next-version=NUM',
- "\n\t\tNext version number.") do |next_|
- opt[:next_version] = next_
- end
-
- parser.parse!(argv)
-
- unless opt[:prev_version]
- print_help.call("Previous version number must be specified")
- end
-
- unless opt[:next_version]
- print_help.call("Next version number must be specified")
- end
-
- opt
-end
-
-def main(argv)
- opt = parse_args(argv)
-
- argv.each do |file|
- update(file, opt)
- end
-end
-
-if __FILE__ == $0
- main(ARGV.dup)
-end
+++ /dev/null
-;;; test.el --- Unit test framework for Emacs lisp program
-;; Copyright (C) 2008 by Wang Liang
-
-;; Author: Wang Liang <netcasperNOSPAMgmail.com>
-
-;; test.el is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; test.el 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 GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Download
-;; Latest version is at http://www.wanglianghome.org/svn/test/test.el
-;; You can check out with subversion.
-;; $ svn co http://www.wanglianghome.org/svn/test/
-
-;;; Screenshot
-;; http://www.wanglianghome.org/images/test.png
-
-;;; Usage
-
-;; Overview
-;; This unit test framework is developed for testing operations on a buffer.
-;; But it definitely can be used to test operations unrelated to buffers.
-;;
-;; For example, I write `my-buffer-substring'. I also have a file and if it
-;; is loaded into a buffer and run (my-buffer-substring 10 22) on that buffer,
-;; it must return "hello, world". To test it, I can write a test case with
-;; this framework,
-;;
-;; (defun my-buffer-substring-setup ()
-;; (insert-file-contents "my-file"))
-;;
-;; (defcase my-buffer-substring-test nil 'my-buffer-substring-setup
-;; (test-assert-string-equal (my-buffer-substring 10 22) "hello, world"))
-;;
-;; And then run it by invoking
-;; `M-x test-run-one-case MY-BUFFER-SUBSTRING-TEST'.
-;;
-;; http://www.wanglianghome.org/svn/test/example.el is an example of usage.
-
-;; To use this framework, add the following lines to your .emacs file
-;; (add-to-list 'load-path "/path/to/test/")
-;; (require 'test)
-
-;; Write test cases
-;; Test case is written with `defcase' macro. For example,
-;;
-;; (defcase my-code-test nil nil
-;; (test-assert-ok (my-fun)))
-;;
-;; This test case includes one assertion but no tags and no setup code.
-;; It checks return value of `my-fun'. If it's `nil', case fails.
-;; Otherwise, case passes. You can add more assertions into one case.
-;;
-;; Besides `test-assert-ok', `test-assert-key' is used to assert that a key
-;; is bound to a function in a mode-map. For example,
-;; (test-assert-key example-mode-map (kbd "C-c C-c") 'example-function)
-;;
-;; Assertion for binary comparison or prediction is much more flexible.
-;; You can use `test-assert-CMP' if `CMP', either provided by Emacs or
-;; written by you, accepts more than two parameters. All those assertions
-;; fallback to `test-assert-binary-relation' function so that I do not need
-;; to write them as many as possible. Since `test-assert-binary-relation'
-;; only considers first two parameters, others are ignored.
-;;
-;; You can develop your own assertions by using "test-assert-extended-" as
-;; function name prefix. For example You develop `test-assert-extended->'
-;; to compare many numbers since `test-assert->' only compares two. Inside
-;; your own assertion function, you should use `assert' from `cl' package to
-;; do real job.
-;;
-;; Test cases can be grouped with tags so that you can run them with one
-;; command. To add tags to the previous test case,
-;;
-;; (defcase my-code-test (my-lib-suite my-lib-sublib-suite) nil
-;; (test-assert-ok (my-fun)))
-;;
-;; All test cases are run in a temporary buffer. You can setup buffer
-;; content by providing `setup' code. For example,
-;;
-;; (defun my-lib-setup ()
-;; (insert-file-contents "my-input-filename")
-;; (my-mode))
-;;
-;; (defcase my-code-test (my-lib my-lib-sublib) 'my-lib-setup
-;; (test-assert-ok (my-fun)))
-;;
-;; You probably want to add a common tag to all your test case for a specific
-;; package, and add a common setup code too. So you can write your own macro
-;; to make it easy to develop test cases. For example,
-;;
-;; (defmacro defmylibcase (case-name tags &rest body)
-;; `(defcase ,case-name ,(append '(my-lib-suite) tags) 'my-lib-setup
-;; ,@body))
-;;
-;; And then,
-;;
-;; (defmylibcase my-code-test-2 (my-lib-sublib-suite)
-;; (test-assert-ok (my-fun)))
-;;
-
-;; Run test cases
-;; `M-x test-run-one-case CASE' runs one test case.
-;; `M-x test-run-all-cases' runs all test cases stored in `test-cases'.
-;; `M-x test-run-one-tag TAG' runs all test cases grouped by TAG.
-;; `(test-run-tags TAGS)' runs all test cases grouped by one of TAGS.
-;;
-;; Test result, including detail error message and summary, is shown in
-;; buffer `*test-result*'.
-;; Every test case has a summary line to show how many cases pass and how
-;; many cases fail. There are also a summary line to show total number of
-;; pass and failure for all commands except `test-run-one-case'.
-;; Error message is helpful. If assertion fails, `test-assert-ok' prints
-;; evaluated form, `test-assert-binary-relation' prints what is got and why
-;; it failed.
-
-;;; Code
-
-(require 'cl)
-
-(defconst test-version "0.9"
- "test version")
-
-(defun test-version ()
- "Show test version."
- (interactive)
- (message "test version %s" test-version))
-
-(defvar test-cases (make-hash-table)
- "All case in all tags")
-
-(defvar test-tags (make-hash-table)
- "All tags from all test cases")
-
-(defvar test-special-assertion-functions '(test-assert-ok test-assert-key)
- "Assertion functions must not fallback to `test-assert-binary-relation'.")
-
-(defun test-completing-read (prompt choices dummy require-match)
- "Use iswitchb completion functionality."
- (let ((iswitchb-make-buflist-hook
- (lambda ()
- (setq iswitchb-temp-buflist choices))))
- (iswitchb-read-buffer prompt nil require-match)))
-
-(defvar test-completing-read-function
- (if (fboundp 'iswitchb-read-buffer) 'test-completing-read 'completing-read))
-
-(defvar test-assert-method-prefix "test-assert-"
- "Prefix of test-assert methods.")
-
-(defvar test-assert-extended-prefix "test-assert-extended-"
- "Prefix of user-extended test-assert methods.")
-
-(defun test-assert-p (test)
- "Return non-nil if TEST is an assertion."
- (let ((method-name (symbol-name (car test))))
- (string-equal test-assert-method-prefix
- (substring method-name
- 0
- (min (length test-assert-method-prefix)
- (length method-name))))))
-
-(defun test-special-assert-p (test)
- "Return non-nil if TEST is `test-assert-ok' or user-extended assertion."
- (or (memq (car test) test-special-assertion-functions)
- (let ((method-name (symbol-name (car test))))
- (string-equal test-assert-extended-prefix
- (substring method-name
- 0
- (min (length test-assert-extended-prefix)
- (length method-name)))))))
-
-(defun test-report-error (test error)
- "Print form TEST and error message from ERROR."
- (princ "# ")
- (prin1 test)
- (princ "\n")
- (let* ((msg (error-message-string error))
- (from-here (string-equal
- "# " (substring msg 0 5))))
- (unless from-here
- (princ "# "))
- (princ msg)
- (unless from-here)
- (princ "\n"))
- (princ "# \n"))
-
-(defun test-gensym (&optional prefix)
- "Generate uninterned symbol.
-If PREFIX is non-nil, use it as prefix. Otherwise, use \"--test--\"."
- (gensym (or prefix "--test--")))
-
-(defun test-transform-body (body fail succ err &optional not-toplevel)
- "This function transforms the BODY, which is a body of defcase,
-recursively to alternate `test-assert-*' to apropriate
-expressions"
- (if (not (listp body))
- body
- (mapcar
- (lambda (arg)
- (cond ((not (listp arg))
- arg)
- ((not (test-assert-p arg))
- (let ((arg (cond
- ((listp arg)
- (test-transform-body arg fail succ err t))
- (t arg))))
- (if not-toplevel
- arg
- `(condition-case ,err
- ;; do not count as success
- ,arg
- (error (incf ,fail) ; but count as failure
- (test-report-error ',arg ,err))))))
- ((test-special-assert-p arg)
- `(condition-case ,err
- (progn
- ,arg
- (incf ,succ))
- (error (incf ,fail)
- (test-report-error ',arg ,err))))
- (t
- `(condition-case ,err
- (progn
- (test-assert-binary-relation
- ;; function to test binary relation
- ',(intern
- (substring
- (symbol-name (car arg))
- (length test-assert-method-prefix)))
- ;; parameters to above function
- ,@(cdr arg))
- (incf ,succ))
- (error (incf ,fail)
- (test-report-error ',arg ,err))))))
- body)))
-
-(defmacro defcase (case-name tags setup &rest body)
- "Define test case which includes one or multiple assertions."
- (let ((tag (test-gensym))
- (tag-cases (test-gensym))
- (fail (test-gensym))
- (succ (test-gensym))
- (err (test-gensym)))
- `(progn
- (assert (and (listp ',tags)
- (or (null ',tags)
- (every 'symbolp ',tags)))
- ;; `show-args' can not be `t' since `assert' will
- ;; evaluate EVERY parameter of `and'. This breaks
- ;; short-circuit effect of `and'.
- nil
- "Tags must be nil or a list of symbols.")
- ;; Associate case with every tag, and push tags into hash table.
- (dolist (,tag ',tags)
- (when ,tag
- (let ((,tag-cases (gethash ,tag test-tags '())))
- (add-to-list ',tag-cases ',case-name)
- (puthash ,tag ,tag-cases test-tags))))
- ;; Push function, which runs test case and returns `(pass-count
- ;; fail-count)', into hash table.
- (puthash ',case-name
- (lambda ()
- (let ((,fail 0)
- (,succ 0))
- (with-temp-buffer
- (when ,setup
- (funcall ,setup))
- ;; transform `body' of macro during expansion time.
- ,@(test-transform-body body fail succ err)
- ;; summarize
- (princ (format "%s: %d pass, %d fail."
- (symbol-name ',case-name)
- ,succ ,fail))
- (princ "\n"))
- ;; return value
- (list ,succ ,fail)))
- test-cases))))
-
-(defun test-princ-current-time ()
- "Print start time to run test cases."
- (princ "# ")
- (princ (current-time-string))
- (princ "\n"))
-
-(defmacro test-report (&rest body)
- "Show test report in buffer `*test-result*'."
- `(progn
- (with-output-to-temp-buffer "*test-result*"
- (test-princ-current-time)
- ,@body)
- (with-current-buffer "*test-result*"
- (test-result-mode))))
-
-(defun test-run (cases)
- "Run test cases in CASES."
- (dolist (case-name (test-args-to-list cases))
- (funcall (gethash case-name test-cases))))
-
-(defvar test-last-summary nil)
-(defun test-run-and-summarize (cases)
- "Run test cases in CASES and print summary."
- (let ((total-succ 0)
- (total-fail 0))
- (dolist (case-name (test-args-to-list cases))
- (let ((summary (funcall (gethash case-name test-cases))))
- (incf total-succ (car summary))
- (incf total-fail (cadr summary))))
- (setq test-last-summary
- `((succ . ,total-succ) (fail . ,total-fail)))
- (princ "# ")
- (princ (format "Total: %d pass, %d fail." total-succ total-fail))))
-
-(defun test-args-to-list (args)
- "Make sure ARGS is a list."
- (if (listp args)
- args
- (list args)))
-
-(defun test-find-all-cases (tags)
- "Return all test cases grouped by TAGS.
-This function guarantees that no duplicated cases in return value."
- (let ((tag-list (test-args-to-list tags))
- (cases '()))
- (dolist (tag tag-list)
- (dolist (test-case (gethash tag test-tags))
- (add-to-list 'cases test-case)))
- cases))
-
-(defun test-maphashkey (fn hashtable)
- "Call FN on each key of hash table HASHTABLE and return a list of result."
- (let ((keys '()))
- (maphash (lambda (key value)
- (add-to-list 'keys (funcall fn key)))
- hashtable)
- keys))
-
-(defun test-find-all-case-names (&optional tag)
- "Return all case names, or name of cases grouped by TAG if TAG is non-nil, as a list."
- (if tag
- (mapcar 'symbol-name (test-find-all-cases tag))
- (test-maphashkey 'symbol-name test-cases)))
-
-(defun test-find-all-tag-names ()
- "Return all tag names as a list."
- (test-maphashkey 'symbol-name test-tags))
-
-(defun test-completing-read-one (prompt choice)
- "Read a string and return a symbol whose name is the string being read."
- ;; Better to read a tag symbol directly.
- (intern (funcall test-completing-read-function prompt choice nil t)))
-
-(defun test-completing-read-one-tag ()
- "Read a tag name and return corresponding tag symbol."
- (test-completing-read-one "Tag: " (test-find-all-tag-names)))
-
-(defun test-completing-read-one-case (&optional tag)
- "Read a case name and return corresponding case symbol. If TAG is non-nil, only cases grouped by it is allowed."
- (test-completing-read-one "Case name: " (test-find-all-case-names tag)))
-
-(defun test-run-one-tag (tag-name)
- "Run test cases grouped by tag TAG-NAME."
- (interactive (list (test-completing-read-one-tag)))
- (test-report (princ "# Tag: ") (princ tag-name) (princ "\n")
- (test-run-and-summarize (test-find-all-cases tag-name))))
-
-(defun test-run-tags (&rest tags)
- "Run all test cases grouped by TAGS."
- (test-report (princ "# Tags: ")
- (princ (mapconcat 'symbol-name tags " "))
- (princ "\n")
- (test-run-and-summarize (test-find-all-cases tags))))
-
-(defun test-run-one-case (case-name)
- "Run one test case whose name is CASE-NAME."
- (interactive (list (test-completing-read-one-case)))
- (test-report (test-run case-name)))
-
-(defun test-run-all-cases ()
- "Run all test cases saved in TEST-CASES."
- (interactive)
- (test-report (test-run-and-summarize (test-maphashkey 'identity test-cases))))
-
-(defmacro test-motion-target (&rest body)
- "Return position after motion."
- `(progn
- ,@body
- (point)))
-
-;;; Special assertions
-(defun test-assert-ok (form)
- "Assert that FORM returns non-nil."
- (assert form nil
- (with-output-to-string
- (princ "# not ok: ")
- (prin1 form))))
-
-(defun test-assert-key (mode-map kbd function)
- "Assert that KBD is binding to FUNCTION in MODE-MAP."
- (let ((got (lookup-key mode-map kbd)))
- (assert (eq got function)
- t
- (with-output-to-string
- (princ "# got: ")
- (prin1 got)
- (princ "\n")
- (princ "# not bound to: ")
- (prin1 function)))))
-
-;;; Assertion for binary comparison or prediction.
-(defun test-assert-binary-relation (fn got expected)
- "Fallback function to assert all binary relation between GOT and EXPECTED with FN."
- (assert (funcall fn got expected)
- t
- (with-output-to-string
- (princ "# got: ")
- (prin1 got)
- (princ "\n")
- (princ "# not ")
- (prin1 fn)
- (princ ": ")
- (prin1 expected))))
-
-;;; `test-result-mode'
-
-(defvar test-result-font-lock-keywords
- `(("^\\(# got: \\)\\(.*\\)$"
- (1 font-lock-preprocessor-face) (2 font-lock-warning-face))
- ("^\\(# not ok: \\)\\(.*\\)$"
- (1 font-lock-preprocessor-face) (2 font-lock-warning-face))
- ("^\\(# .*?: \\)\\(.*\\)$"
- (1 font-lock-preprocessor-face) (2 font-lock-type-face))
- ;; be careful about the order
- ("^# .*$" . font-lock-preprocessor-face)
- ("^\\(.*\\): \\([0-9]+\\) pass, \\([0-9]+\\) fail.$"
- (1 font-lock-function-name-face) (2 font-lock-type-face) (3 font-lock-warning-face)))
- "Font lock for `test-result-mode'.")
-
-(defconst test-result-font-lock-defaults
- '(test-result-font-lock-keywords t nil nil nil (font-lock-multiline . nil)))
-
-(define-derived-mode test-result-mode nil "Test-Result"
- (set (make-local-variable 'font-lock-defaults) test-result-font-lock-defaults))
-
-(provide 'test)
+++ /dev/null
-
-(defvar twittering-test-dir nil)
-
-(when load-file-name
- (setq twittering-test-dir (file-name-directory load-file-name))
- (add-to-list 'load-path twittering-test-dir))
-
-(require 'twittering-mode (expand-file-name "../twittering-mode.el"
- twittering-test-dir))
-(require 'test (expand-file-name "../test.el"
- twittering-test-dir))
-
-(defun get-fixture (name)
- (when (symbolp name)
- (setq name (symbol-name name)))
- (let ((fixture-path (expand-file-name
- (concat name ".el")
- (expand-file-name "fixture" twittering-test-dir))))
- (if (file-exists-p fixture-path)
- (with-temp-buffer
- (insert-file-contents fixture-path)
- (beginning-of-buffer)
- (read (current-buffer)))
- nil)))
-
-(defmacro with-network (&rest body)
- `(when (getenv "NETWORK")
- ,@body))
-
-(defun twittering-run-test ()
- (interactive)
-
- (dolist (file-name (directory-files twittering-test-dir))
- (when (string-match "^test-" file-name)
- (let ((file-name (expand-file-name file-name twittering-test-dir)))
- (load file-name))))
-
- (test-run-all-cases)
-
- (let* ((fail-count (cdr (assoc 'fail test-last-summary)))
- (exit-status (if (eq 0 fail-count) 0 1)))
- (save-excursion
- (set-buffer "*test-result*")
- (end-of-buffer)
- (search-backward-regexp "" nil t)
- (beginning-of-buffer)
- (while (search-forward-regexp "\\b\\([0-9]+\\) pass\\b" nil t)
- (replace-match
- (concat "\033[1m\033[32m" (match-string 0) "\033[0m")))
-
- (beginning-of-buffer)
- (while (search-forward-regexp "\\b\\([0-9]+\\) fail\\b" nil t)
- (let ((pass (string-equal "0" (match-string 1))))
- (replace-match
- (concat "\033[1m\033[31m" (match-string 0) "\033[0m"))
- (beginning-of-line)
- (when (search-forward-regexp "^\\([^:#]+\\):" nil t)
- (replace-match
- (concat (if pass
- "\033[1m\033[32m"
- "\033[1m\033[31m")
- (match-string 1)
- "\033[0m")
- nil nil nil 1))
- ))
- (princ (buffer-string)))
- (terpri)
- (when noninteractive
- (kill-emacs exit-status))
- ))
-
-(twittering-run-test)
+++ /dev/null
-(((id . "6480639448")
- (text . "Help protect and support Free Software and the GNU Project by joining the Free Software Foundation! http://www.fsf.org/join?referrer=7019")
- (source . "web")
- (created-at 19230 62217)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "GNU project")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "6068719152")
- (text . "Worg's a collaboratively-edited site about org-mode that uses org-mode and git as the backend. Cool! http://bit.ly/5dfq90
- (via @learnemacs)")
- (source . "Tweetie")
- (created-at 19213 57955)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "5430846002")
- (text . "Happy 3 years of Planet Emacsen! http://planet.emacsen.org/")
- (source . "web")
- (created-at 19185 61918)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "5395447473")
- (text . "@ibread yes, by people letting me know they want to be added to it.")
- (source . "web")
- (created-at 19184 23723)
- (truncated . nil)
- (in-reply-to-status-id . "5387945498")
- (in-reply-to-screen-name . "ibread")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "5388319142")
- (text . "Want M-x customize to display real variable names? Set `custom-unlispify-tag-names' and `custom-unlispify-menu-entries' to nil.")
- (source . "web")
- (created-at 19184 731)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "5386633091")
- (text . "@ibread done.")
- (source . "web")
- (created-at 19183 57365)
- (truncated . nil)
- (in-reply-to-status-id . "5382204189")
- (in-reply-to-screen-name . "ibread")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "5376421165")
- (text . "Use Emacs? 日本語で話せますか? Let's make http://twitter.com/emacs/japanese the authoritative list of Japanese-language Emacs users on twitter!")
- (source . "web")
- (created-at 19183 27786)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "5272344132")
- (text . "Do you hang out in @freenode's #emacs channel? Let me know and I'll add you to http://twitter.com/emacs/irc")
- (source . "web")
- (created-at 19178 8958)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "5082433713")
- (text . "Want to find all foos in your bar-mode buffers? Use ibuffer! M-x ibuffer RET * M bar-mode RET O foo RET
- (via @kensanata asking in #emacs)")
- (source . "web")
- (created-at 19168 59548)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "4904187220")
- (text . "@serverhorror no, but I'm all for it.")
- (source . "Tweetie")
- (created-at 19159 52264)
- (truncated . nil)
- (in-reply-to-status-id . "4848149430")
- (in-reply-to-screen-name . "serverhorror")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "4297523005")
- (text . "Collaborative editing in Emacs that works with Gobby: http://rudel.sourceforge.net/
- (via @technomancy) Looks great! Can't wait to try it.")
- (source . "web")
- (created-at 19129 13348)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "4049776133")
- (text . "Using Emacs to develop web applications? Try using Luke Gorrie's http://tr.im/http_twiddle to interactively write/edit/test HTTP requests.")
- (source . "web")
- (created-at 19121 59554)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "3946747696")
- (text . "@gabrielsaldana ‘gnus-secondary-select-methods’ is your friend.")
- (source . "Tweetie")
- (created-at 19116 22686)
- (truncated . nil)
- (in-reply-to-status-id . "3946440115")
- (in-reply-to-screen-name . "gabrielsaldana")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "2923425504")
- (text . "GNU Emacs 23.1 has been released! Share and Enjoy!")
- (source . "Echofon")
- (created-at 19057 5382)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "2896622068")
- (text . "Steve Yegge's js2-mode
- (which is fabulous BTW) now bundled with @emacs: http://bit.ly/4cLzac")
- (source . "web")
- (created-at 19055 24997)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "2745124537")
- (text . "Correction: Emacs 23.1 will be released in nine days, on Wednesday the 29th.")
- (source . "web")
- (created-at 19044 54957)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "2743146093")
- (text . "Barring unforeseen issues, Emacs 23.1 will be released in two days, on Wednesday the 22nd: http://article.gmane.org/gmane.emacs.devel/112846")
- (source . "web")
- (created-at 19044 47475)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "2617217996")
- (text . "@gabrielsaldana: I build from trunk with --with-ns. The various pre-compiled distributions all seem to include weird changes to my defaults.")
- (source . "web")
- (created-at 19035 28055)
- (truncated . nil)
- (in-reply-to-status-id . "2616864784")
- (in-reply-to-screen-name . "gabrielsaldana")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil))
-
- ((id . "2473438293")
- (text . "Edit XHTML5 documents in nxml-mode with on-the-fly validation: http://bit.ly/lYnEg
-
- (by @hober)")
- (source . "web")
- (created-at 19023 46920)
- (truncated . nil)
- (in-reply-to-status-id . "")
- (in-reply-to-screen-name . "")
- (user-id . "9492852")
- (user-name . "emacs")
- (user-screen-name . "emacs")
- (user-location . "")
- (user-description . "Emacs is the extensible self-documenting text editor.")
- (user-profile-image-url . "http://a1.twimg.com/profile_images/33497412/emacs_normal.gif")
- (user-url . "http://www.gnu.org/software/emacs/")
- (user-protected . nil)))
+++ /dev/null
-#!/bin/bash
-
-emacsen="emacs emacs23 emacs22 emacs21"
-
-continue_on_error=
-if [ $# -gt 0 ]; then
- continue_on_error="yes"
-fi
-exit_status=0
-
-for emacs in $(echo ${emacsen}); do
- if ! which $emacs 1> /dev/null 2> /dev/null; then
- echo "No such executable found: ${emacs}: skipped."
- continue
- fi
- $emacs -q --no-site-file --batch --load $(dirname $0)/el-test-runner.el
- exit_status=$?
- if [ $exit_status != 0 ]; then
- echo "Test failed on $(${emacs} --version | head -n 1)"
- if [ -z "${continue_on_error}" ]; then
- exit 1
- else
- echo "sleep 5 secs..."
- sleep 5
- fi
- fi
-done
-
-exit $exit_status
+++ /dev/null
-#!/usr/bin/env ruby
-
-require 'optparse'
-require 'webrick'
-require 'webrick/httpproxy'
-require 'singleton'
-
-class TwitterAPI
- include Singleton
-
- attr_accessor :res
- attr_accessor :req
-
- def self.call(req, res)
- uri = req.request_uri
- format = File.extname(uri.path)
- format = "xml" if format == ""
- format = format.gsub(/^\./, '')
- endpoint = uri.path.gsub(/\.[a-z]+$/, '').gsub(/^\//, '')
- params = Hash.new
- (uri.query || "").split("&").each do |param|
- if param =~ /([^=]+)=(.+)/
- params[$~[1]] = $~[2]
- params[$~[1].to_sym] = $~[2]
- else
- raise ArgumentError.new("Invalid query string: #{param}")
- end
- end
-
- tw = self.instance
- tw.res = res
- tw.req = req
- tw.send(endpoint.gsub(/\//, '_'), format, params)
- end
-
- def statuses_public_timeline(format, params)
- @res.body = "URI: #{@req.request_uri.to_s}, format: #{format}, params: #{params.inspect}"
- end
-end
-
-def parse_options(argv)
- parser = OptionParser.new
- opt = Hash.new
-
- print_help = Proc.new do |msg|
- $stderr.puts msg
- puts
- puts parser.help
- exit 1
- end
-
- opt[:port] = 80
- parser.on('-p', '--port=PORT',
- "\n\t\tPort number to be used.") do |port|
- opt[:port] = port.to_i
- if opt[:port] == 0
- print_help.call("Invalid port number: #{port}")
- end
- end
-
- opt[:proxy] = false
- parser.on('-P', '--proxy',
- "\n\t\tRun as a proxy server if this option is specified.") do
- opt[:proxy] = true
- end
-
- parser.parse!(argv)
-
- opt
-end
-
-def main(argv)
- opt = parse_options(argv)
-
- server = WEBrick::HTTPServer.new({:Port => opt[:port],
- :BindAddress => "127.0.0.1"})
- server.mount_proc("/") do |req, res|
- TwitterAPI.call(req, res)
- end
-
- Signal.trap('INT') do
- server.shutdown
- end
-
- server.start
-end
-
-if __FILE__ == $0
- main(ARGV.dup)
-end
+++ /dev/null
-;;; -*- coding: utf-8 -*-
-
-(when (and (> 22 emacs-major-version)
- (require 'url-methods nil t))
- ;; `twittering-make-http-request-from-uri', which is called for the format
- ;; specifier "%i", requires `url-generic-parse-url'. But the function for
- ;; Emacs 21, which is distributed with twittering-mode, does not work
- ;; correctly until calling `url-scheme-get-property'.
- (url-scheme-get-property "http" 'name)
- (url-scheme-get-property "https" 'name))
-
-(defcase test-version nil nil
- (test-assert-string-match "^twittering-mode-v\\([0-9]+\\(\\.[0-9]+\\)*\\|HEAD\\)"
- (twittering-mode-version)))
-
-(defcase test-assocref nil nil
- (test-assert-eq 'bar (assocref 'foo '((baz . qux) (foo . bar))))
- (test-assert-eq nil (assocref 'quxx '((baz . qux) (foo . bar)))))
-
-(defmacro test-setup-proxy(bindings)
- `(let ,(append '((process-environment nil)
- (twittering-proxy-use t)
- (twittering-proxy-server nil)
- (twittering-proxy-port nil)
- (twittering-http-proxy-server nil)
- (twittering-http-proxy-port nil)
- (twittering-https-proxy-server nil)
- (twittering-https-proxy-port nil))
- bindings)
- (twittering-setup-proxy)))
-
-(defcase test-proxy nil nil
- (test-assert-ok
- (test-setup-proxy
- ((twittering-proxy-server "proxy.example.com")
- (twittering-proxy-port 8080))))
- (test-assert-ok
- (test-setup-proxy
- ((twittering-proxy-server "proxy.example.com")
- (twittering-proxy-port "8080"))))
-
- (test-assert-ok
- (test-setup-proxy
- ((twittering-http-proxy-server "proxy.example.com")
- (twittering-http-proxy-port 8080))))
- (test-assert-ok
- (test-setup-proxy
- ((twittering-http-proxy-server "proxy.example.com")
- (twittering-http-proxy-port "8080"))))
-
- (test-assert-ok
- (test-setup-proxy
- ((twittering-https-proxy-server "proxy.example.com")
- (twittering-https-proxy-port 8080))))
- (test-assert-ok
- (test-setup-proxy
- ((twittering-https-proxy-server "proxy.example.com")
- (twittering-https-proxy-port "8080"))))
-
- (test-assert-equal
- (let ((twittering-proxy-use nil)
- (process-environment nil)
- (twittering-https-proxy-server "proxy.example.com")
- (twittering-https-proxy-port 8080))
- (twittering-toggle-proxy)
- (list twittering-proxy-use
- (progn
- (twittering-toggle-proxy)
- twittering-proxy-use)))
- '(t nil))
-
- ;; The test of configuration via an environment variable should be
- ;; performed last because it changes global variables of the url library
- ;; in an irreversible manner.
- (test-assert-ok
- (test-setup-proxy
- ((process-environment
- '("http_proxy=http://proxy1.example.com:8080/"))))))
-
-(defcase test-user-agent nil nil
- (test-assert-string-equal (format "Emacs/%d.%d Twittering-mode/%s"
- emacs-major-version
- emacs-minor-version
- twittering-mode-version)
- (twittering-user-agent))
- (setq twittering-user-agent-function
- (lambda () "foo user agent"))
- (test-assert-string-equal "foo user agent"
- (twittering-user-agent))
- )
-
-(defcase test-icon-mode nil nil
- (setq twittering-icon-mode nil)
- (twittering-icon-mode)
- (test-assert-ok twittering-icon-mode)
- (twittering-icon-mode)
- (test-assert-ok (not twittering-icon-mode))
- (twittering-icon-mode nil)
- (test-assert-ok twittering-icon-mode)
- (twittering-icon-mode t)
- (test-assert-ok twittering-icon-mode)
- (twittering-icon-mode -1)
- (test-assert-ok (not twittering-icon-mode))
- (twittering-icon-mode 1)
- (test-assert-ok twittering-icon-mode)
- )
-
-(defcase test-percent-encode nil nil
- (test-assert-string-equal "Rinko"
- (twittering-percent-encode "Rinko"))
- (test-assert-string-equal "%25"
- (twittering-percent-encode "%"))
- (test-assert-string-equal "love%20plus"
- (twittering-percent-encode "love plus"))
- (test-assert-string-equal "%0A"
- (twittering-percent-encode "\n")))
-
-(with-network
- (when (require 'url nil t)
- (defcase tinyurl nil nil
- (test-assert-string-equal "http://tinyurl.com/3xsrg5"
- (twittering-tinyurl-get "http://example.com/example"))
- )))
-
-(defcase case-string nil nil
- (test-assert-string-equal "Kobayakawa"
- (case-string "Rinko"
- (("Rinko") "Kobayakawa")
- (t "unknown")))
-
- (test-assert-string-equal "unknown"
- (case-string "Manaka"
- (("Rinko") "Kobayakawa")
- (t "unknown")))
-
- (test-assert-string-equal "Kobayakawa"
- (case-string "Rinko"
- (("Manaka") "Takane")
- (("Rinko") "Kobayakawa")
- (("Nene") "Anegasaki")
- (t nil)))
-
- (test-assert-string-equal "Amphibian"
- (case-string "Frog"
- (("Rabbit") "Mammal")
- (("Salamandar" "Frog") "Amphibian")
- (t nil)))
- )
-
-(defcase format-string nil nil
- (test-assert-string-equal ""
- (twittering-format-string "" "" nil))
-
- (test-assert-string-equal "Hello world"
- (twittering-format-string "Hello world" "" nil))
-
- (test-assert-string-equal "RT: twittering-mode now (via @twmode)"
- (twittering-format-string "RT: %t (via @%s)" "%"
- '(("t" . "twittering-mode now")
- ("s" . "twmode"))))
-
- (test-assert-string-equal "RT: %t (via @twmode)"
- (twittering-format-string "RT: %t (via @%s)" "%"
- '(("t" . "%t")
- ("s" . "twmode"))))
-
- (test-assert-string-equal "new\nline"
- (twittering-format-string "new~%line" "~"
- '(("%" . "\n"))))
- )
-
-(defun test-restore-timeline-spec(spec-str spec normalized-spec)
- (let ((spec-from-str
- (twittering-string-to-timeline-spec spec-str)))
- (list
- (equal (twittering-string-to-timeline-spec
- (twittering-timeline-spec-to-string spec))
- normalized-spec)
- (equal normalized-spec spec-from-str))))
-
-(defun test-exclude-if-function (status)
- (string-match "test" (cdr (assq 'text status))))
-
-(defcase timeline-spec nil nil
- (test-assert-equal
- (test-restore-timeline-spec
- "(user+(user/mylist+(@))+:exclude-re/WORD/(USER2+:mentions))"
- '(merge (user "user")
- (merge (list "user" "mylist")
- (merge (replies)))
- (exclude-re "WORD" (merge (user "USER2")
- (mentions))))
- '(merge (user "user")
- (list "user" "mylist")
- (replies)
- (exclude-re "WORD" (merge (user "USER2")
- (mentions)))))
- '(t t))
- (test-assert-equal
- (test-restore-timeline-spec
- "(user-A+~+((user-B))+(:exclude-re/R+/user-C+(:exclude-re/R3\\//USER-D+:public)))"
- '(merge (user "user-A")
- (home)
- (merge (user "user-B")
- (exclude-re "R+" (user "user-C")))
- (exclude-re "R3/" (user "USER-D"))
- (public))
- '(merge (user "user-A")
- (home)
- (user "user-B")
- (exclude-re "R+" (user "user-C"))
- (exclude-re "R3/" (user "USER-D"))
- (public)))
- '(t t))
-
- ;; Duplicates in a merge timeline are removed.
- (test-assert-equal
- (test-restore-timeline-spec
- "(ABC+user/mylist+user/mylist+ABC)"
- '(merge (user "ABC") (list "user" "mylist"))
- '(merge (user "ABC") (list "user" "mylist")))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ":search/ABC/"
- '(search "ABC")
- '(search "ABC"))
- '(t t))
- (test-assert-equal
- (test-restore-timeline-spec
- ":search/AB\\\\C\\/aaa\\\\/"
- '(search "AB\\C/aaa\\")
- '(search "AB\\C/aaa\\"))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ":exclude-if/test-exclude-if-function/:home"
- '(exclude-if test-exclude-if-function (home))
- '(exclude-if test-exclude-if-function (home)))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ":exclude-if/(lambda (x) t)/:home"
- '(exclude-if (lambda (x) t) (home))
- '(exclude-if (lambda (x) t) (home)))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ":exclude-if/(lambda (tweet) (string-match \"test\\\\.\" (cdr (assq 'text tweet))))/@"
- '(exclude-if (lambda (tweet)
- (string-match "test\\." (cdr (assq 'text tweet))))
- (replies))
- '(exclude-if (lambda (tweet)
- (string-match "test\\." (cdr (assq 'text tweet))))
- (replies)))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ":exclude-if/(lambda (tweet) (string-match \"\\\\\\\\\" (cdr (assq 'text tweet))))/:exclude-if/(lambda (tw) (assq 'retweeting-id tw))/user/mylist"
- '(exclude-if (lambda (tweet)
- (string-match "\\\\" (cdr (assq 'text tweet))))
- (exclude-if (lambda (tw) (assq 'retweeting-id tw))
- (list "user" "mylist")))
- '(exclude-if (lambda (tweet)
- (string-match "\\\\" (cdr (assq 'text tweet))))
- (exclude-if (lambda (tw) (assq 'retweeting-id tw))
- (list "user" "mylist"))))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ":exclude-re/ABC/user"
- '(exclude-re "ABC" (user "user"))
- '(exclude-re "ABC" (user "user")))
- '(t t))
- (test-assert-equal
- (test-restore-timeline-spec
- ":exclude-re/ABC/user/mylist"
- '(exclude-re "ABC" (list "user" "mylist"))
- '(exclude-re "ABC" (list "user" "mylist")))
- '(t t))
- (test-assert-equal
- (test-restore-timeline-spec
- ":exclude-re/ABC\\\\/user/mylist"
- '(exclude-re "ABC\\\\" (list "user" "mylist"))
- '(exclude-re "ABC\\\\" (list "user" "mylist")))
- '(t t))
- (test-assert-equal
- (test-restore-timeline-spec
- ":exclude-re/ABC\\/\\(word\\|123\\)/user"
- '(exclude-re "ABC/\\(word\\|123\\)" (user "user"))
- '(exclude-re "ABC/\\(word\\|123\\)" (user "user")))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ":retweeted_by_me" '(retweeted_by_me) '(retweeted_by_me))
- '(t t))
- (test-assert-equal
- (test-restore-timeline-spec
- ":retweeted_to_me" '(retweeted_to_me) '(retweeted_to_me))
- '(t t))
- (test-assert-equal
- (test-restore-timeline-spec
- ":retweets_of_me" '(retweets_of_me) '(retweets_of_me))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ":favorites" '(favorites) '(favorites))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ":favorites/USER" '(favorites "USER") '(favorites "USER"))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- "#tag" '(search "#tag") '(search "#tag"))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ;; "リスト" consists of U+256A, U+2539 and U+2548.
- ;; They should be supported by raw Emacs21.
- "USER/non-ASCIIリスト"
- '(list "USER" "non-ASCIIリスト")
- '(list "USER" "non-ASCIIリスト"))
- '(t t))
-
- (test-assert-equal
- (test-restore-timeline-spec
- ;; An example from
- ;; https://dev.twitter.com/docs/api/1/get/statuses/home_timeline ,
- ;; which is posted by cindy li.
- ":single/18700887835"
- '(single "18700887835")
- '(single "18700887835"))
- '(t t))
- )
-
-(defcase timeline-spec-dependence nil nil
- ;; Duplicates in a merge timeline are removed.
- (test-assert-equal
- (let ((spec (twittering-string-to-timeline-spec "(:home+@+(@+:home))")))
- (twittering-get-primary-base-timeline-specs spec))
- '((home) (replies)))
-
- (test-assert-equal
- (let ((spec (twittering-string-to-timeline-spec
- "(:home+@+:exclude-if/(lambda (x) t)/(@+:home+USER))")))
- (twittering-get-primary-base-timeline-specs spec))
- '((home) (replies) (user "USER")))
- )
-
-(defun format-status (status format-str)
- (twittering-update-status-format format-str)
- (twittering-format-status status))
-
-(lexical-let ((status (car (get-fixture 'timeline-data))))
- (defcase test-format-status nil nil
- (test-assert-string-equal "hello world"
- (format-status status "hello world"))
- (test-assert-string-equal "%"
- (format-status status "%%"))
-
-
-
- (test-assert-string-equal "something like emacs"
- (format-status status "something like %s"))
-
- (test-assert-string-equal "We love emacs!"
- (format-status status "We love %S!"))
-
- (test-assert-string-equal
- ""
- (let ((twittering-icon-mode nil))
- (format-status status "%i")))
- (test-assert-string-equal
- " "
- (let ((twittering-icon-mode t)
- (window-system t))
- (format-status status "%i")))
-
- (test-assert-string-equal
- "Emacs is the extensible self-documenting text editor."
- (format-status status "%d"))
-
- (test-assert-string-equal "GNU project"
- (format-status status "%l"))
- (test-assert-string-equal " [GNU project]"
- (format-status status "%L"))
- (setcdr (assoc 'user-location status) "")
- (test-assert-string-equal ""
- (format-status status "%l"))
- (test-assert-string-equal ""
- (format-status status "%L"))
-
- (setcdr (assoc 'in-reply-to-screen-name status) "hoge")
- (setcdr (assoc 'in-reply-to-status-id status) "123456")
- (test-assert-string-equal " in reply to hoge"
- (format-status status "%r"))
- (setcdr (assoc 'in-reply-to-screen-name status) "foo")
- (setcdr (assoc 'in-reply-to-status-id status) "")
- (test-assert-string-equal ""
- (format-status status "%r"))
- (setcdr (assoc 'in-reply-to-screen-name status) "")
- (setcdr (assoc 'in-reply-to-status-id status) "654321")
- (test-assert-string-equal ""
- (format-status status "%r"))
- (setcdr (assoc 'in-reply-to-screen-name status) "")
- (setcdr (assoc 'in-reply-to-status-id status) "")
- (test-assert-string-equal ""
- (format-status status "%r"))
-
- (test-assert-string-equal "http://www.gnu.org/software/emacs/"
- (format-status status "%u"))
-
- (test-assert-string-equal "9492852"
- (format-status status "%j"))
-
- (test-assert-string-equal ""
- (format-status status "%p"))
- (setcdr (assoc 'user-protected status) t)
- (test-assert-string-equal "[x]"
- (format-status status "%p"))
- (setcdr (assoc 'user-protected status) nil)
- (test-assert-string-equal ""
- (format-status status "%p"))
-
- (test-assert-string-equal
- "created at Wed Dec 09 00:44:57 +0000 2009"
- (let ((tz (current-time-zone)))
- (set-time-zone-rule t)
- (prog1
- (format-status status "created at %c")
- (set-time-zone-rule (cddr tz)))))
-
- (test-assert-string-equal
- "created at 2009/12/09 09:44:57"
- (let ((tz (current-time-zone)))
- (set-time-zone-rule "JST-9")
- (prog1
- (format-status status "created at %C{%Y/%m/%d %H:%M:%S}")
- (set-time-zone-rule (cddr tz)))))
-
- ;; (test-assert-string-equal "09:44 午前 12月 09, 2009"
- ;; (format-status status "%@"))
-
- (test-assert-string-equal "Help protect and support Free Software and the GNU Project by joining the Free Software Foundation! http://www.fsf.org/join?referrer=7019"
- (format-status status "%T"))
-
- (setcdr (assoc 'truncated status) nil)
- (test-assert-string-equal ""
- (format-status status "%'"))
- (setcdr (assoc 'truncated status) t)
- (test-assert-string-equal "..."
- (format-status status "%'"))
- (setcdr (assoc 'truncated status) nil)
-
- (test-assert-string-equal "web"
- (format-status status "%f"))
-
- (test-assert-string-equal "6480639448"
- (format-status status "%#"))
-
- (test-assert-string-equal
- " emacs, :
- Help protect and support Free Software and the GNU Project by joining the Free Software Foundation! http://www.fsf.org/join?referrer=7019 // from web"
- (let ((twittering-icon-mode nil))
- (format-status status "%i %s, :\n %T // from %f%L%r")))
- (test-assert-string-equal
- " emacs, :
- Help protect and support Free Software and the GNU Project by joining the Free Software Foundation! http://www.fsf.org/join?referrer=7019 // from web"
- (let ((twittering-icon-mode t)
- (window-system t))
- (format-status status "%i %s, :\n %T // from %f%L%r")))
-
- (test-assert-string-equal
- "
- Help protect and support Free Software and the GNU Project by joining the
- Free Software Foundation! http://www.fsf.org/join?referrer=7019 // from web"
- (let ((twittering-fill-column 80))
- (format-status status "\n%FILL[ ]{%T // from %f%L%r}")))
-
- (test-assert-string-equal
- "
- Help protect and support Free Software and the GNU Project by joining the
- Free Software Foundation! http://www.fsf.org/join?referrer=7019 // from web"
- (let ((twittering-fill-column 80))
- (format-status status "\n%FOLD[ ]{%T // from %f%L%r}")))
-
- (test-assert-string-equal
- "
- Edit XHTML5 documents in nxml-mode with on-the-fly validation:
- http://bit.ly/lYnEg (by @hober) // from web"
- (let ((twittering-fill-column 80)
- (oldest-status (car (last (get-fixture 'timeline-data)))))
- (format-status oldest-status "\n%FILL[ ]{%T // from %f%L%r}")))
-
- (test-assert-string-equal
- (if (> 22 emacs-major-version)
- ;; `fill-region' on Emacs21 does not keep white spaces and
- ;; tabs adjacent to hard newlines.
- "
---Edit XHTML5 documents in nxml-mode with on-the-fly validation:
---http://bit.ly/lYnEg
---
--- (by @hober) // from web"
- "
---Edit XHTML5 documents in nxml-mode with on-the-fly validation:
---http://bit.ly/lYnEg
---
--- (by @hober) // from web")
- (let ((twittering-fill-column 80)
- (oldest-status (car (last (get-fixture 'timeline-data)))))
- (format-status oldest-status "\n%FOLD[--]{%T // from %f%L%r}")))
- ))
-
-(defcase test-find-curl-program nil nil
- (test-assert-string-match "curl" (twittering-find-curl-program))
- (with-temp-buffer
- (when (twittering-find-curl-program)
- (test-assert-eq 0
- (call-process (twittering-find-curl-program)
- nil (current-buffer) nil
- "--help")))))
-
-(with-network
- (defcase test-ensure-ca-cert nil nil
- (when (twittering-find-curl-program)
- (test-assert-eq 0
- (with-temp-buffer
- (call-process (twittering-find-curl-program)
- nil (current-buffer) nil
- "--cacert"
- (twittering-ensure-ca-cert)
- "https://twitter.com/"))))))
-
-(defcase test-status-not-blank-p nil nil
- (test-assert-ok (not (twittering-status-not-blank-p "")))
- (test-assert-ok (not (twittering-status-not-blank-p "\n")))
- (test-assert-ok (not (twittering-status-not-blank-p "@foo")))
- (test-assert-ok (not (twittering-status-not-blank-p "@bar ")))
- (test-assert-ok (twittering-status-not-blank-p "hello"))
- (test-assert-ok (twittering-status-not-blank-p "@baz hello"))
- (test-assert-ok (twittering-status-not-blank-p "@baz\n\nhello"))
- (test-assert-ok (twittering-status-not-blank-p "\nhello"))
- (test-assert-ok (twittering-status-not-blank-p "hello\n"))
- (test-assert-ok (twittering-status-not-blank-p "@foo hello @bar"))
- (test-assert-ok (twittering-status-not-blank-p "hello @foo"))
- )
-
-(defcase test-hmac-sha1 nil nil
- ;; The following tests are copied from RFC 2202.
- (test-assert-string-equal
- (let* ((v (make-list 20 ?\x0b))
- (key (cond
- ((fboundp 'unibyte-string) (apply 'unibyte-string v))
- (t (concat v))))
- (data "Hi There"))
- (mapconcat (lambda (c) (format "%02x" c))
- (twittering-hmac-sha1 key data)
- ""))
- "b617318655057264e28bc0b6fb378c8ef146be00")
-
- (test-assert-string-equal
- (let* ((key "Jefe")
- (data "what do ya want for nothing?"))
- (mapconcat (lambda (c) (format "%02x" c))
- (twittering-hmac-sha1 key data)
- ""))
- "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79")
-
- (test-assert-string-equal
- (let* ((key-v (make-list 20 ?\xaa))
- (key (cond
- ((fboundp 'unibyte-string) (apply 'unibyte-string key-v))
- (t (concat key-v))))
- (data-v (make-list 50 ?\xdd))
- (data (cond
- ((fboundp 'unibyte-string) (apply 'unibyte-string data-v))
- (t (concat data-v)))))
- (mapconcat (lambda (c) (format "%02x" c))
- (twittering-hmac-sha1 key data)
- ""))
- "125d7342b9ac11cd91a39af48aa17b4f63f175d3")
- )
-
-(defun verify-hmac-of-long-data(coding-system)
- (or (not (coding-system-p coding-system))
- (let ((coding-system-for-read coding-system)
- (coding-system-for-write coding-system))
- (let* ((key "key")
- (data (make-string 64 ?a))
- (result
- (mapcar
- (lambda (pair)
- (let ((n (car pair))
- (expected (cdr pair)))
- (string=
- (mapconcat (lambda (c) (format "%02x" c))
- (twittering-hmac-sha1 key (make-string n ?a))
- "")
- expected)))
- '((64 . "804f18b0143cc2677eeda7b5f60f6984fc32d094")
- (128 . "2ff5eea1596f3a41fbb5e1ff02b17a50a229c177")
- (256 . "ce7f0d472740f975b137052e05955b4ca7ec9a58")
- (512 . "9dce54d150cbf817a8d979bd6a371eaf4643ac40")
- (1024 . "53e18d494844a645cd8ac0757873460696b0c9df")
- (2048 . "0fabada271421b303434131195e67c006d3fc3d7")
- (4095 . "ef35e91ef97d811cfecfe83071045c31de4e4e61")
- (8193 . "cefba76fb9ad5a665887a875ed7bc42ec9f00919")
- (16383 . "c6ba93118262ab9426760909fa4981558bdc10e5")
- (32767 . "442813d73d237fb45fca6c05360c43db877744f6")))))
- (if (equal result '(t t t t t t t t t t))
- t
- result)))))
-
-(defcase test-hmac-sha1-long nil nil
- (test-assert-eq (verify-hmac-of-long-data 'iso-safe) t)
- (test-assert-eq (verify-hmac-of-long-data 'iso-safe-unix) t)
- (test-assert-eq (verify-hmac-of-long-data 'iso-safe-dos) t)
- (test-assert-eq (verify-hmac-of-long-data 'iso-safe-mac) t)
- (test-assert-eq (verify-hmac-of-long-data 'utf-8) t)
- (test-assert-eq (verify-hmac-of-long-data 'utf-8-unix) t)
- (test-assert-eq (verify-hmac-of-long-data 'utf-8-dos) t)
- (test-assert-eq (verify-hmac-of-long-data 'utf-8-mac) t)
- (test-assert-eq (verify-hmac-of-long-data 'utf-16) t)
- (test-assert-eq (verify-hmac-of-long-data 'utf-16-unix) t)
- (test-assert-eq (verify-hmac-of-long-data 'utf-16-dos) t)
- (test-assert-eq (verify-hmac-of-long-data 'utf-16-mac) t)
- (test-assert-eq (verify-hmac-of-long-data 'iso-latin-1) t)
- (test-assert-eq (verify-hmac-of-long-data 'iso-latin-1-unix) t)
- (test-assert-eq (verify-hmac-of-long-data 'iso-latin-1-dos) t)
- (test-assert-eq (verify-hmac-of-long-data 'iso-latin-1-mac) t)
- )
-
-(defun verify-hmac-with-short-internal-length (coding-system)
- (or (not (coding-system-p coding-system))
- (not (boundp 'sha1-maximum-internal-length))
- (let* ((coding-system-for-read coding-system)
- (coding-system-for-write coding-system)
- (max-internal-length-list '(1 10 50 100 500 1000))
- (result
- (mapcar
- (lambda (n)
- (let ((sha1-maximum-internal-length n)
- (key "Jefe")
- (data "what do ya want for nothing?")
- (expected "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"))
- (string= (mapconcat (lambda (c) (format "%02x" c))
- (twittering-hmac-sha1 key data)
- "")
- expected)))
- max-internal-length-list)))
- (if (equal result (make-list (length max-internal-length-list) t))
- t
- result))))
-
-(defcase test-hmac-sha1-with-short-internal-length nil nil
- (test-assert-eq (verify-hmac-with-short-internal-length 'iso-safe) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'iso-safe) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'iso-safe-unix) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'iso-safe-dos) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'iso-safe-mac) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'utf-8) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'utf-8-unix) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'utf-8-dos) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'utf-8-mac) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'utf-16) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'utf-16-unix) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'utf-16-dos) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'utf-16-mac) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'iso-latin-1) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'iso-latin-1-unix) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'iso-latin-1-dos) t)
- (test-assert-eq (verify-hmac-with-short-internal-length 'iso-latin-1-mac) t)
- )
-
-(defcase test-oauth nil nil
- ;; "Authenticating Requests | dev.twitter.com"
- ;; http://dev.twitter.com/pages/auth
- (setq sample-consumer-key "GDdmIQH6jhtmLUypg82g")
- (setq sample-consumer-secret "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98")
-
- ;; Acquiring a request token
- ;; http://dev.twitter.com/pages/auth#request-token
- (test-assert-string-equal
- (let* ((oauth-params
- `(("oauth_nonce" . "QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk")
- ("oauth_callback" . ,(twittering-oauth-url-encode "http://localhost:3005/the_dance/process_callback?service_provider_id=11"))
- ("oauth_signature_method" . "HMAC-SHA1")
- ("oauth_timestamp" . "1272323042")
- ("oauth_consumer_key" . ,sample-consumer-key)
- ("oauth_version" . "1.0")))
- (url "https://api.twitter.com/oauth/request_token"))
- (twittering-oauth-auth-str-request-token
- url nil sample-consumer-key sample-consumer-secret oauth-params))
- "OAuth oauth_nonce=\"QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk\",oauth_callback=\"http%3A%2F%2Flocalhost%3A3005%2Fthe_dance%2Fprocess_callback%3Fservice_provider_id%3D11\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1272323042\",oauth_consumer_key=\"GDdmIQH6jhtmLUypg82g\",oauth_version=\"1.0\",oauth_signature=\"8wUi7m5HFQy76nowoCThusfgB%2BQ%3D\"")
-
- ;; response
- (test-assert-equal
- (let ((response-str "oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA&oauth_callback_confirmed=true"))
- (twittering-oauth-make-response-alist response-str))
- '(("oauth_token" . "8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc")
- ("oauth_token_secret"
- . "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA")
- ("oauth_callback_confirmed" . "true")))
-
- ;; Sending the user to authorization
- ;; http://dev.twitter.com/pages/auth#authorization
- ;; response (when using callback)
- (test-assert-equal
- (let ((response-str "oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_verifier=pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY"))
- (twittering-oauth-make-response-alist response-str))
- '(("oauth_token" . "8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc")
- ("oauth_verifier"
- . "pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY")))
-
- ;; Exchanging a request token for an access token
- ;; http://dev.twitter.com/pages/auth#access-token
- (test-assert-string-equal
- (let* ((request-token "8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc")
- (request-token-secret "x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA")
- (verifier "pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY")
- (oauth-params
- `(("oauth_nonce" . "9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8")
- ("oauth_signature_method" . "HMAC-SHA1")
- ("oauth_timestamp" . "1272323047")
- ("oauth_consumer_key" . ,sample-consumer-key)
- ("oauth_token" . ,request-token)
- ("oauth_verifier" . ,verifier)
- ("oauth_version" . "1.0")))
- (url "https://api.twitter.com/oauth/access_token"))
- (twittering-oauth-auth-str-exchange-token
- url nil
- sample-consumer-key sample-consumer-secret
- request-token request-token-secret verifier oauth-params))
- "OAuth oauth_nonce=\"9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1272323047\",oauth_consumer_key=\"GDdmIQH6jhtmLUypg82g\",oauth_token=\"8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc\",oauth_verifier=\"pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY\",oauth_version=\"1.0\",oauth_signature=\"PUw%2FdHA4fnlJYM6RhXk5IU%2F0fCc%3D\"")
-
- ;; response
- (test-assert-equal
- (let ((response-str "oauth_token=819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw&oauth_token_secret=J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA&user_id=819797&screen_name=episod"))
- (twittering-oauth-make-response-alist response-str))
- '(("oauth_token"
- . "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw")
- ("oauth_token_secret"
- . "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA")
- ("user_id" . "819797")
- ("screen_name" . "episod")))
-
- ;; Making a resource request on a user's behalf
- ;; http://dev.twitter.com/pages/auth#auth-request
- (test-assert-string-equal
- (let* ((access-token "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw")
- (access-token-secret "J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA")
- (oauth-params
- `(("oauth_nonce" . "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y")
- ("oauth_signature_method" . "HMAC-SHA1")
- ("oauth_timestamp" . "1272325550")
- ("oauth_consumer_key" . ,sample-consumer-key)
- ("oauth_token" . ,access-token)
- ("oauth_version" . "1.0")))
- (url "http://api.twitter.com/1/statuses/update.json")
- (encoded-query-parameters
- `((,(twittering-percent-encode "status")
- . ,(twittering-percent-encode
- "setting up my twitter 私のさえずりを設定する")))))
- (twittering-oauth-auth-str-access
- "POST" url encoded-query-parameters
- sample-consumer-key sample-consumer-secret
- access-token access-token-secret
- oauth-params))
- "OAuth oauth_nonce=\"oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1272325550\",oauth_consumer_key=\"GDdmIQH6jhtmLUypg82g\",oauth_token=\"819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw\",oauth_version=\"1.0\",oauth_signature=\"yOahq5m0YjDDjfjxHaXEsW9D%2BX0%3D\"")
- )
-
-(defun find-least-unsupported-code-point (from to)
- (let ((n from)
- (c nil))
- (while (and (<= n to)
- (decode-char 'ucs n))
- (setq n (1+ n)))
- (when (<= n to)
- n)))
-
-(defun encode-char-for-json (code-point)
- ;; According to RFC4627 http://www.ietf.org/rfc/rfc4627 ,
- ;; characters in the Basic Multilingual Plane (U+0000
- ;; through U+FFFF) are escaped as
- ;; "a six-character sequence: a reverse solidus, followed
- ;; by the lowercase letter u, followed by four hexadecimal
- ;; digits that encode the character's code point."
- ;; "To escape an extended character that is not in the Basic
- ;; Multilingual Plane, the character is represented as a
- ;; twelve-character sequence, encoding the UTF-16 surrogate
- ;; pair."
- (cond
- ((< code-point #xFFFF)
- (format "\\u%04X" code-point))
- (t
- ;; a character not in the Basic Multilingual Plane
- (let* ((c (decode-char 'ucs unsupported-code-point))
- (str (encode-coding-char c 'utf-16be)))
- (apply 'format "\\u%02X%02X\\u%02X%02X"
- (string-to-list str))))))
-
-(defun test-read-json-with-unsupported-code-point ()
- (let ((unsupported-code-point
- (or (find-least-unsupported-code-point #x0000 #xD7FF)
- (find-least-unsupported-code-point #xE000 #x10FFFF))))
- (cond
- ((null unsupported-code-point)
- t)
- (t
- (let* ((str (encode-char-for-json unsupported-code-point))
- (quoted-str (concat "\"" str "\""))
- (result (with-temp-buffer
- (insert quoted-str)
- (goto-char (point-min))
- (condition-case err
- (twittering-json-read)
- (error
- nil)))))
- (if (and result
- (stringp result)
- (string= result
- (string twittering-unicode-replacement-char)))
- t
- (format "failed to decode %s!" quoted-str)))))))
-
-(when (require 'json nil t)
- (defcase test-json-read nil nil
- (test-assert-eq t (test-read-json-with-unsupported-code-point))))
-
-(defun test-read-xml-with-unsupported-code-point ()
- (let ((unsupported-code-point
- (or (find-least-unsupported-code-point #x0000 #xD7FF)
- (find-least-unsupported-code-point #xE000 #x10FFFF))))
- (cond
- ((null unsupported-code-point)
- t)
- (t
- (let* ((xml-template
- ;; example from http://www.w3.org/TR/xhtml1/#strict
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
-<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
-<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
- <head>
- <title>test</title>
- </head>
- <body>
- <p>%s</p>
- </body>
-</html>")
- (encoded-str (format "&#%d;" unsupported-code-point))
- (xml-str (format xml-template encoded-str))
- (replacement-str
- (string twittering-unicode-replacement-char))
- (result
- (with-temp-buffer
- (insert xml-str)
- (condition-case err
- (let* ((xml
- (twittering-xml-parse-region (point-min)
- (point-max)))
- (str
- (elt (assq 'p (assq 'body (assq 'html xml))) 2)))
- (if (< emacs-major-version 22)
- ;; On Emacs 21, `xml-parse-region' does not resolve
- ;; numeric character references.
- (twittering-decode-entities-after-parsing-xml str)
- str))
- (error
- nil))))
- (expected-result replacement-str))
- (cond
- ((null result)
- (format "failed to decode %s with an error" encoded-str))
- ((equal result expected-result)
- t)
- (t
- (format "failed to decode %s without errors" encoded-str))))))))
-
-(when (require 'xml nil t)
- (defcase test-xml-parse nil nil
- (test-assert-eq t (test-read-xml-with-unsupported-code-point))))
+++ /dev/null
-;;; twittering-mode.el --- Major mode for Twitter
-
-;; Copyright (C) 2007, 2009, 2010 Yuto Hayamizu.
-;; 2008 Tsuyoshi CHO
-
-;; Author: Y. Hayamizu <y.hayamizuNOSPAMgmail.com>
-;; Tsuyoshi CHO <Tsuyoshi.CHO+developNOSPAMGmail.com>
-;; Alberto Garcia <agarciaNOSPAMigalia.com>
-;; Created: Sep 4, 2007
-;; Version: HEAD
-;; Identity: $Id$
-;; Keywords: twitter web
-;; URL: http://twmode.sf.net/
-
-;; This file is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; This file 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 GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; twittering-mode.el is a major mode for Twitter.
-;; You can check friends timeline, and update your status on Emacs.
-
-;;; Feature Request:
-
-;; URL : http://twitter.com/d00dle/statuses/577876082
-;; * Status Input from Popup buffer and C-cC-c to POST.
-;; URL : http://code.nanigac.com/source/view/419
-;; * update status for region
-
-;;; Code:
-
-(eval-when-compile (require 'cl))
-(require 'xml)
-
-(eval-and-compile
- ;; On byte-compilation, Emacs21 requires loading the libraries
- ;; distributed with twittering-mode.el for macros defined in them.
- (when (> 22 emacs-major-version)
- (setq load-path
- (append (mapcar (lambda (dir)
- (expand-file-name
- dir
- (if load-file-name
- (or (file-name-directory load-file-name)
- ".")
- ".")))
- '("url-emacs21" "emacs21"))
- load-path))))
-
-(when (> 22 emacs-major-version)
- (and (require 'un-define nil t)
- ;; the explicitly require 'unicode to update a workaround with
- ;; navi2ch. see a comment of `twittering-ucs-to-char' for more
- ;; details.
- (require 'unicode nil t))
- (defadvice url-scheme-register-proxy (around twittering-fix-process-env (scheme) activate)
- (let ((process-environment
- (apply 'append
- (let ((env-var (concat scheme "_proxy")))
- (mapcar
- (lambda (str)
- (if (string-match
- (concat "^\\("
- (regexp-opt (list (upcase env-var)
- (downcase env-var)))
- "\\)=$")
- str)
- nil
- (list str)))
- process-environment)))))
- ad-do-it)))
-(require 'url)
-
-(defconst twittering-mode-version "HEAD")
-(defconst twittering-mode-identity "$Id$")
-(defvar twittering-api-host "api.twitter.com")
-(defvar twittering-api-search-host "search.twitter.com")
-(defvar twittering-web-host "twitter.com")
-(defvar twittering-oauth-request-token-url-without-scheme
- "://api.twitter.com/oauth/request_token")
-(defvar twittering-oauth-authorization-url-base-without-scheme
- "://api.twitter.com/oauth/authorize?oauth_token=")
-(defvar twittering-oauth-access-token-url-without-scheme
- "://api.twitter.com/oauth/access_token")
-
-(defun twittering-mode-version ()
- "Display a message for twittering-mode version."
- (interactive)
- (let ((version-string
- (format "twittering-mode-v%s" twittering-mode-version)))
- (if (interactive-p)
- (message "%s" version-string)
- version-string)))
-
-(defvar twittering-auth-method 'oauth
- "*Authentication method for `twittering-mode'.
-The symbol `basic' means Basic Authentication. The symbol `oauth' means
-OAuth Authentication. The symbol `xauth' means xAuth Authentication.
-OAuth Authentication requires `twittering-oauth-consumer-key' and
-`twittering-oauth-consumer-secret'. Additionally, it requires an external
-command `curl' or another command included in `tls-program', which may be
-`openssl' or `gnutls-cli', for SSL.")
-
-(defvar twittering-account-authorization nil
- "State of account authorization for `twittering-username' and
-`twittering-password'. The value is one of the following symbols:
-nil -- The account have not been authorized yet.
-queried -- The authorization has been queried, but not finished yet.
-authorized -- The account has been authorized.")
-
-(defvar twittering-oauth-use-ssl t
- "*Whether to use SSL on authentication via OAuth. Twitter requires SSL
-on authorization via OAuth.")
-(defvar twittering-oauth-invoke-browser nil
- "*Whether to invoke a browser on authorization of access key automatically.")
-
-(defvar twittering-oauth-consumer-key nil)
-(defvar twittering-oauth-consumer-secret nil)
-(defvar twittering-oauth-access-token-alist nil)
-
-(defconst twittering-max-number-of-tweets-on-retrieval 200
- "The maximum number of `twittering-number-of-tweets-on-retrieval'.")
-
-(defvar twittering-number-of-tweets-on-retrieval 20
- "*The number of tweets which will be retrieved in one request.
-The upper limit is `twittering-max-number-of-tweets-on-retrieval'.")
-
-(defvar twittering-tinyurl-service 'tinyurl
- "*The service to shorten URI.
-This must be one of key symbols of `twittering-tinyurl-services-map'.
-To use 'bit.ly or 'j.mp, you have to configure `twittering-bitly-login' and
-`twittering-bitly-api-key'.")
-
-(defvar twittering-tinyurl-services-map
- '((bit.ly twittering-make-http-request-for-bitly
- (lambda (service reply)
- (if (string-match "\n\\'" reply)
- (substring reply 0 (match-beginning 0))
- reply)))
- (goo.gl
- (lambda (service longurl)
- (twittering-make-http-request-from-uri
- "POST" '(("Content-Type" . "application/json"))
- "https://www.googleapis.com/urlshortener/v1/url"
- (concat "{\"longUrl\": \"" longurl "\"}")))
- (lambda (service reply)
- (when (string-match "\"id\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\""
- reply)
- (match-string 1 reply))))
- (is.gd . "http://is.gd/create.php?format=simple&url=")
- (j.mp twittering-make-http-request-for-bitly
- (lambda (service reply)
- (if (string-match "\n\\'" reply)
- (substring reply 0 (match-beginning 0))
- reply)))
- (migre.me . "http://migre.me/api.txt?url=")
- (tinyurl . "http://tinyurl.com/api-create.php?url=")
- (toly
- (lambda (service longurl)
- (twittering-make-http-request-from-uri
- "POST" nil
- "http://to.ly/api.php"
- (concat "longurl=" (twittering-percent-encode longurl))))))
- "Alist of URL shortening services.
-The key is a symbol specifying the service.
-The value is a string or a list consisting of two elements at most.
-
-If the value is a string, `(concat THE-FIRST-ELEMENT longurl)' is used as the
-URL invoking the service.
-If the value is a list, it is interpreted as follows.
-The first element specifies how to make a HTTP request for shortening a URL.
-If the first element is a string, `(concat THE-FIRST-ELEMENT longurl)' is
-used as the URL invoking the service.
-If the first element is a function, it is called as `(funcall THE-FIRST-ELEMENT
-service-symbol longurl)' to obtain a HTTP request alist for invoking the
-service, which must be generated by `twittering-make-http-request'.
-
-The second element specifies how to post-process a HTTP reply by the HTTP
-request.
-If the second element is nil, the reply is directly used as a shortened URL.
-If the second element is a function, it is called as `(funcall
-THE-SECOND-ELEMENT service-symbol HTTP-reply-string)' and its result is used
-as a shortened URL.")
-
-(defvar twittering-bitly-login nil
- "*The login name for URL shortening service bit.ly and j.mp.")
-(defvar twittering-bitly-api-key nil
- "*The API key for URL shortening service bit.ly and j.mp.")
-
-(defvar twittering-mode-map (make-sparse-keymap))
-(defvar twittering-mode-menu-on-uri-map (make-sparse-keymap "Twittering Mode"))
-(defvar twittering-mode-on-uri-map (make-sparse-keymap))
-
-(defvar twittering-tweet-history nil)
-(defvar twittering-user-history nil)
-(defvar twittering-timeline-history nil)
-(defvar twittering-hashtag-history nil)
-(defvar twittering-search-history nil)
-
-(defvar twittering-current-hashtag nil
- "A hash tag string currently set. You can set it by calling
-`twittering-set-current-hashtag'.")
-
-(defvar twittering-timer nil
- "Timer object for timeline refreshing will be stored here.
-DO NOT SET VALUE MANUALLY.")
-
-(defvar twittering-timer-interval 90
- "The interval of auto reloading. You should use 60 or more
-seconds for this variable because the number of API call is
-limited by the hour.")
-
-(defvar twittering-timer-for-redisplaying nil
- "Timer object for timeline redisplay statuses will be stored here.
-DO NOT SET VALUE MANUALLY.")
-
-(defvar twittering-timer-interval-for-redisplaying 5.0
- "The interval of auto redisplaying statuses.
-Each time Emacs remains idle for the interval, twittering-mode updates parts
-requiring to be redrawn.")
-
-(defvar twittering-username nil
- "*An username of your Twitter account.")
-
-(defvar twittering-password nil
- "*A password of your Twitter account. Leave it blank is the
-recommended way because writing a password in .emacs file is so
-dangerous.")
-
-(defvar twittering-initial-timeline-spec-string ":home"
- "*An initial timeline spec string or a list of timeline spec strings.
-This specifies one or more initial timeline spec strings, which are
-automatically visited when invoking `twittering-mode' or `twit'.
-
-If it is a string, it specifies a timeline spec string.
-If it is a list of strings, it specifies multiple timeline spec strings.")
-
-(defvar twittering-timeline-spec nil
- "The timeline spec for the current buffer.")
-(defvar twittering-timeline-spec-string ""
- "The timeline spec string for the current buffer.")
-
-(defvar twittering-timeline-spec-alias nil
- "*Alist for aliases of timeline spec.
-Each element is (NAME . SPEC-STRING), where NAME is a string and
-SPEC-STRING is a string or a function that returns a timeline spec string.
-
-The alias can be referred as \"$NAME\" or \"$NAME(ARG)\" in timeline spec
-string. If SPEC-STRING is a string, ARG is simply ignored.
-If SPEC-STRING is a function, it is called with a string argument.
-For the style \"$NAME\", the function is called with nil.
-For the style \"$NAME(ARG)\", the function is called with a string ARG.
-
-For example, if you specify
- `((\"FRIENDS\" . \"my-account/friends-list\")
- (\"related-to\" .
- ,(lambda (username)
- (if username
- (format \":search/to:%s OR from:%s OR @%s/\"
- username username username)
- \":home\")))),
-then you can use \"$FRIENDS\" and \"$related-to(USER)\" as
-\"my-account/friends-list\" and \":search/to:USER OR from:USER OR @USER/\",
-respectively.")
-
-(defvar twittering-current-timeline-spec-string nil
- "The current timeline spec string. This variable should not be referred
-directly. Use `twittering-current-timeline-spec-string' or
-`twittering-current-timeline-spec'.")
-(defvar twittering-list-index-retrieved nil)
-
-(defvar twittering-process-info-alist nil
- "Alist of active process and timeline spec retrieved by the process.")
-
-(defvar twittering-server-info-alist nil
- "Alist of server information.")
-
-(defvar twittering-api-limit-info-alist '()
- "Alist of an API identifier and an alist representing rate limit for the API.")
-
-(defvar twittering-timeline-spec-to-api-table '()
- "Alist of a timeline spec and an API identifier for retrieving the timeline.")
-
-
-(defvar twittering-mode-init-hook nil
- "*Hook run after initializing global variables for `twittering-mode'.")
-(defvar twittering-mode-hook nil
- "*Hook run every time a buffer is initialized as a twittering-mode buffer.")
-
-(defvar twittering-cookie-alist nil
- "Alist for stroing cookies for each account.
-This variable stores an alist.
-A key of the alist is a string that is a screen name of an account.
-A value of the alist is a cookie alist which corresponds to a list of
-a pair of a cookie name and value.")
-
-(defvar twittering-new-tweets-count 0
- "Number of new tweets when `twittering-new-tweets-hook' is run.")
-(defvar twittering-new-tweets-spec nil
- "Timeline spec, which new tweets belong to, when
-`twittering-new-tweets-hook' is run.")
-(defvar twittering-new-tweets-statuses nil
- "New tweet status messages, when
-`twittering-new-tweets-hook' is run.")
-
-(defvar twittering-new-tweets-hook nil
- "*Hook run when new tweets are received.
-
-You can read `twittering-new-tweets-count' or `twittering-new-tweets-spec'
-to get the number of new tweets received when this hook is run.")
-
-(defvar twittering-rendered-new-tweets-spec nil
- "A timeline spec of newly rendered tweets.
-This variable is bound when invoking hooks registered with
-`twittering-new-tweets-rendered-hook'.")
-
-(defvar twittering-rendered-new-tweets-spec-string nil
- "A timeline spec string of newly rendered tweets.
-This variable is bound when invoking hooks registered with
-`twittering-new-tweets-rendered-hook'.")
-
-(defvar twittering-rendered-new-tweets nil
- "A list of newly rendered tweets.
-Hooks registered with `twittering-new-tweets-rendered-hook' can use this
-variable as a list of rendered tweets. Each tweet is represented as an alist.
-You can refer to a property of a tweet alist as
- (cdr (assq PROPERTY-SYMBOL TWEET-ALIST)).
-Valid symbols are following; id, text, user-name, user-screen-name, user-id,
- source, source-uri.
-In the list, tweets are placed in order of time. The car of the list is the
-latest one, and the last is the oldest one.")
-
-(defvar twittering-new-tweets-rendered-hook nil
- "*Hook run when new tweets are rendered.
-When the registered functions are called, the current buffer is the buffer
-that the new tweets are just rendered on.
-The functions can refer to the timeline spec and timeline spec string as
-`twittering-rendered-new-tweets-spec' and
-`twittering-rendered-new-tweets-spec-string', repectively.
-Hooks can also use the local variable `twittering-rendered-new-tweets' as a
-list of rendered tweets.
-For the detail of the representation of tweets, see the variable
-`twittering-rendered-new-tweets'.")
-
-(defvar twittering-active-mode nil
- "Non-nil if new statuses should be retrieved periodically.
-Do not modify this variable directly. Use `twittering-activate-buffer',
-`twittering-deactivate-buffer', `twittering-toggle-activate-buffer' or
-`twittering-set-active-flag-for-buffer'.")
-
-(defvar twittering-jojo-mode nil)
-(defvar twittering-reverse-mode nil
- "*Non-nil means tweets are aligned in reverse order of `http://twitter.com/'.")
-(defvar twittering-display-remaining nil
- "*If non-nil, display remaining of rate limit on the mode-line.")
-(defvar twittering-display-connection-method t
- "*If non-nil, display the current connection method on the mode-line.")
-(defvar twittering-status-format "%i %s, %@:\n%FILL[ ]{%T // from %f%L%r%R}\n "
- "Format string for rendering statuses.
-Ex. \"%i %s, %@:\\n%FILL{ %T // from %f%L%r%R}\n \"
-
-Items:
- %s - screen_name
- %S - name
- %i - profile_image
- %d - description
- %l - location
- %L - \" [location]\"
- %r - \" sent to user\" (use on direct_messages{,_sent})
- %r - \" in reply to user\" (use on other standard timeline)
- %R - \" (retweeted by user)\"
- %RT{...} - strings rendered only when the tweet is a retweet.
- The braced strings are rendered with the information of the
- retweet itself instead of that of the retweeted original tweet.
- For example, %s for a retweet means who posted the original
- tweet, but %RT{%s} means who retweeted it.
- %u - url
- %j - user.id
- %p - protected?
- %c - created_at (raw UTC string)
- %C{time-format-str} - created_at (formatted with time-format-str)
- %@ - X seconds ago
- %T - raw text
- %t - text filled as one paragraph
- %' - truncated
- %FACE[face-name]{...} - strings decorated with the specified face.
- %FILL[prefix]{...} - strings filled as a paragraph. The prefix is optional.
- You can use any other specifiers in braces.
- %FOLD[prefix]{...} - strings folded within the frame width.
- The prefix is optional. This keeps newlines and does not
- squeeze a series of white spaces.
- You can use any other specifiers in braces.
- %f - source
- %# - id
-")
-
-(defvar twittering-retweet-format '(nil _ " RT: %t (via @%s)")
- "*A format string or a skeleton for retweet.
-If the value is a string, it means a format string for generating an initial
-string of a retweet. The format string is converted with the below replacement
-table. And then, the cursor is placed on the next of the initial string.
-It is equivalent to the skeleton '(nil STRING _).
-Note that this string is inserted before the edit skeleton specified by
-`twittering-edit-skeleton' is performed.
-
-If the value is a list, it is treated as a skeleton used with
-`skeleton-insert'. The strings included in the list are converted with the
-following replacement table. And then, the list with converted strings is
-inserted by `skeleton-insert'.
-Note that this skeleton is performed before the edit skeleton specified by
-`twittering-edit-skeleton' is performed.
-
-Replacement table:
- %s - The screen-name of the cited tweet.
- %t - The text of the cited tweet.
- %u - The URL of the cited tweet.
- %# - The ID of the cited tweet.
- %% - % itself.")
-
-(defvar twittering-fill-column nil
- "*The fill-column used for \"%FILL{...}\" in `twittering-status-format'.
-If nil, the fill-column is automatically calculated.")
-
-(defvar twittering-show-replied-tweets t
- "*The number of replied tweets which will be showed in one tweet.
-
-If the value is not a number and is non-nil, show all replied tweets
-which is already fetched.
-If the value is nil, doesn't show replied tweets.")
-
-(defvar twittering-default-show-replied-tweets nil
- "*The number of default replied tweets which will be showed in one tweet.
-This value will be used only when showing new tweets.
-
-See `twittering-show-replied-tweets' for more details.")
-
-(defvar twittering-disable-overlay-on-too-long-string nil
- "*If non-nil, disable overlay on too long string on edit buffer.
-
-If nil, `twittering-edit-mode' puts an overlay `twittering-warning-overlay' on
-characters following the 140th character.
-
-On some environments, some input methods seem to interfere the update of the
-overlay. In such case, you may avoid the problems by setting this variable to
-non-nil.")
-
-(defvar twittering-use-show-minibuffer-length t
- "*Show current length of minibuffer if this variable is non-nil.
-
-We suggest that you should set to nil to disable the showing function
-when it conflict with your input method (such as AquaSKK, etc.)")
-
-(defvar twittering-notify-successful-http-get t)
-
-(defvar twittering-use-ssl t
- "Use SSL connection if this variable is non-nil.
-
-SSL connections use 'curl' command as a backend.")
-(defvar twittering-allow-insecure-server-cert nil
- "*If non-nil, twittering-mode allows insecure server certificates.")
-
-(defvar twittering-curl-program nil
- "Cache a result of `twittering-find-curl-program'.
-DO NOT SET VALUE MANUALLY.")
-(defvar twittering-curl-program-https-capability nil
- "Cache a result of `twittering-start-http-session-curl-https-p'.
-DO NOT SET VALUE MANUALLY.")
-
-(defvar twittering-wget-program nil
- "Cache a result of `twittering-find-wget-program'.
-DO NOT SET VALUE MANUALLY.")
-
-(defvar twittering-tls-program nil
- "*List of strings containing commands to start TLS stream to a host.
-Each entry in the list is tried until a connection is successful.
-%h is replaced with server hostname, %p with port to connect to.
-Also see `tls-program'.
-If nil, this is initialized with a list of valied entries extracted from
-`tls-program'.")
-
-(defvar twittering-connection-type-order
- '(curl wget urllib-http native urllib-https))
- "*A list of connection methods in the preferred order."
-
-(defvar twittering-connection-type-table
- '((native (check . t)
- (https . twittering-start-http-session-native-tls-p)
- (send-http-request . twittering-send-http-request-native)
- (pre-process-buffer . twittering-pre-process-buffer-native))
- (curl (check . twittering-start-http-session-curl-p)
- (https . twittering-start-http-session-curl-https-p)
- (send-http-request . twittering-send-http-request-curl)
- (pre-process-buffer . twittering-pre-process-buffer-curl))
- (wget (check . twittering-start-http-session-wget-p)
- (https . t)
- (send-http-request . twittering-send-http-request-wget)
- (pre-process-buffer . twittering-pre-process-buffer-wget))
- (urllib-http
- (display-name . "urllib")
- (check . twittering-start-http-session-urllib-p)
- (https . nil)
- (send-http-request . twittering-send-http-request-urllib)
- (pre-process-buffer . twittering-pre-process-buffer-urllib))
- (urllib-https
- (display-name . "urllib")
- (check . twittering-start-http-session-urllib-p)
- (https . twittering-start-http-session-urllib-https-p)
- (send-http-request . twittering-send-http-request-urllib)
- (pre-process-buffer . twittering-pre-process-buffer-urllib)))
- "A list of alist of connection methods.")
-
-(defvar twittering-format-status-function-source ""
- "The status format string that has generated the current
-`twittering-format-status-function'.")
-(defvar twittering-format-status-function nil
- "The formating function generated from `twittering-format-status-function-source'.")
-(defvar twittering-format-status-function-without-compile nil
- "The formating function generated from `twittering-format-status-function-source',
-which is a lambda expression without being compiled.")
-
-(defvar twittering-timeline-data-table (make-hash-table :test 'equal))
-
-(defvar twittering-username-face 'twittering-username-face)
-(defvar twittering-uri-face 'twittering-uri-face)
-
-(defvar twittering-use-native-retweet nil
- "Post retweets using native retweets if this variable is non-nil.")
-
-(defvar twittering-update-status-function
- 'twittering-update-status-from-pop-up-buffer
- "The function used to posting a tweet. It takes 5 arguments,
-INIT-STR, REPLY-TO-ID, USERNAME, TWEET-TYPE, CURRENT-SPEC.
-The first argument INIT-STR is nil or an initial text to be edited.
-REPLY-TO-ID and USERNAME are an ID and a user-screen-name of a tweet to
-which you are going to reply. If the tweet is not a reply, they are nil.
-TWEET-TYPE is a symbol specifying a type of a tweet being edited. It must
-be one of 'direct-message, 'normal, 'organic-retweet and 'reply.
-CURRENT-SPEC means on which timeline the function is called.
-
-Twittering-mode provides two functions for updating status:
-* `twittering-update-status-from-minibuffer': edit tweets in minibuffer
-* `twittering-update-status-from-pop-up-buffer': edit tweets in pop-up buffer")
-
-(defvar twittering-request-confirmation-on-posting nil
- "*If *non-nil*, confirmation will be requested on posting a tweet edited in
-pop-up buffer.")
-
-(defvar twittering-use-master-password nil
- "*Wheter to store private information encrypted with a master password.")
-(defvar twittering-private-info-file
- (expand-file-name "~/.twittering-mode.gpg")
- "*File for storing encrypted private information when
-`twittering-use-master-password' is non-nil.")
-(defvar twittering-private-info-file-loaded nil
- "Whether the private info file has been loaded or not.")
-(defvar twittering-variables-stored-with-encryption
- '(twittering-oauth-access-token-alist))
-
-(defvar twittering-api-prefix "1/")
-(defvar twittering-search-api-method "search")
-(defvar twittering-web-path-prefix "")
-
-(defvar twittering-service-method 'twitter-api-v1.1
- "*Service method for `twittering-mode'.
-The symbol `twitter' means Twitter Service. The symbol `statusnet' means
-StatusNet Service.")
-
-(defvar twittering-service-method-table
- '((twitter (status-url . twittering-get-status-url-twitter)
- (search-url . twittering-get-search-url-twitter))
- (twitter-api-v1.1
- (status-url . twittering-get-status-url-twitter)
- (search-url . twittering-get-search-url-twitter))
- (statusnet (status-url . twittering-get-status-url-statusnet)
- (search-url . twittering-get-search-url-statusnet)))
- "A list of alist of service methods.")
-
-(defvar twittering-timeline-header-face 'twittering-timeline-header-face
- "*Face for the header on `twittering-mode'.
-The face is used for rendering `twittering-timeline-header'.")
-(defvar twittering-timeline-footer-face 'twittering-timeline-footer-face
- "*Face for the footer on `twittering-mode'.
-The face is used for rendering `twittering-timeline-footer'.")
-(defvar twittering-timeline-header "-- Press Enter here to update --\n"
- "*Timeline header string on `twittering-mode'.
-The string is rendered on the beginning of a `twittering-mode' buffer.
-Its face is specified by `twittering-timeline-header-face'.")
-(defvar twittering-timeline-footer "-- Press Enter here to update --"
- "*Timeline footer string on `twittering-mode'.
-The string is rendered on the end of a `twittering-mode' buffer.
-Its face is specified by `twittering-timeline-footer-face'.")
-
-(defvar twittering-pop-to-buffer-function
- 'twittering-pop-to-buffer-in-bottom-largest-window
- "*Function being invoked by `twittering-pop-to-buffer'.
-It will receive an argument, the buffer being selected.
-For example, the following functions can be used; `pop-to-buffer',
-`twittering-pop-to-buffer-simple',
-`twittering-pop-to-buffer-in-current-window',
-`twittering-pop-to-buffer-in-largest-window', and
-`twittering-pop-to-buffer-in-bottom-largest-window'.")
-
-(defvar twittering-relative-retrieval-interval-alist
- '(("\\`:direct.*\\'" 4)
- (":home" ":mentions" 1)
- (t 1))
- "*An alist of relative intervals of retrieving timelines.
-Each element looks like (TIMELINE-SPEC-REGEXP RELATIVE-INTERVAL).
-
-TIMELINE-SPEC-REGEXP must be t or a regexp string specifying primary
-timeline specs.
-If TIMELINE-SPEC-REGEXP is t, it matches all timelines.
-RELATIVE-INTERVAL must be zero or a positive integer specifying relative
-interval of retrieving timelines that match TIMELINE-SPEC-REGEXP.
-
-An interval for a timeline is determined as follows;
-1. Find the first element where TIMELINE-SPEC-REGEXP matches the
- timeline or TIMELINE-SPEC-REGEXP is t.
- If no elements are found, the interval is `twittering-timer-interval'.
-2. Check the RELATIVE-INTERVAL of the element.
- If RELATIVE-INTERVAL is a positive integer, the interval is
- RELATIVE-INTERVAL times as long as `twittering-timer-interval'.
-
- If RELATIVE-INTERVAL is zero, the interval is infinity.
- The timeline is not retrieved automatically.")
-
-(defvar twittering-relative-retrieval-count-alist '()
- "An alist for counting retrieval of primary timelines.")
-
-;;;;
-;;;; Macro and small utility function
-;;;;
-
-(defun assocref (item alist)
- (cdr (assoc item alist)))
-
-(defmacro list-push (value listvar)
- `(setq ,listvar (cons ,value ,listvar)))
-
-(defmacro case-string (str &rest clauses)
- `(cond
- ,@(mapcar
- (lambda (clause)
- (let ((keylist (car clause))
- (body (cdr clause)))
- `(,(if (listp keylist)
- `(or ,@(mapcar (lambda (key) `(string-equal ,str ,key))
- keylist))
- 't)
- ,@body)))
- clauses)))
-
-(defmacro twittering-wait-while (timeout interval condition &optional form &rest timeout-forms)
- "Wait while CONDITION returns non-nil until TIMEOUT seconds passes.
-
-The form CONDITION is repeatedly evaluated for every INTERVAL seconds
-until CONDITION returns nil or TIMEOUT seconds passes unless TIMEOUT is nil.
-If TIMEOUT is nil, there is no time limit.
-
-If CONDITION returns nil, evaluate the form FORM and return its value.
-If TIMEOUT seconds passes, evaluate the forms TIMEOUT-FORMS and return
-the value of the last form in TIMEOUT-FORMS."
- `(lexical-let (,@(when timeout `((timeout ,timeout)))
- (interval ,interval)
- (current 0.0))
- (while (and ,@(when timeout '((< current timeout)))
- ,condition)
- (sit-for interval)
- (setq current (+ current interval)))
- ,(when (or form timeout-forms)
- (if (null timeout)
- form
- `(if (< current timeout)
- ,form
- ,@timeout-forms)))))
-
-
-(defun twittering-extract-matched-substring-all (regexp str)
- (let ((pos 0)
- (result nil))
- (while (string-match regexp str pos)
- (setq result (cons (match-string 1 str) result))
- (setq pos (match-end 0)))
- (reverse result)))
-
-(defun twittering-process-alive-p (proc)
- "Return non-nil if PROC is alive."
- (not (memq (process-status proc) '(nil closed exit failed signal))))
-
-(defun twittering-start-process-with-sentinel (name buffer program args sentinel)
- "Start a program in a subprocess with a sentinel.
-
-This function is the same as `start-process' except that SENTINEL must
-be invoked when the process is successfully started."
- (let ((proc (apply 'start-process name buffer program args)))
- (when (and proc (functionp sentinel))
- (if (twittering-process-alive-p proc)
- (set-process-sentinel proc sentinel)
- ;; Ensure that the sentinel is invoked if a subprocess is
- ;; successfully started.
- (funcall sentinel proc "finished")))
- proc))
-
-(defun twittering-parse-time-string (str &optional round-up)
- "Parse the time-string STR into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).
-This function is the same as `parse-time-string' except to complement the
-lacked parameters with the current time.
-If ROUND-UP is nil, complement the lacked parameters with the oldest ones.
-If ROUND-UP is non-nil, complement the lacked parameters with the latest ones.
-For example, (twittering-parse-time-string \"2012-04-20\")
-returns (0 0 0 20 4 2012 nil nil 32400).
-And (twittering-parse-time-string \"2012-04-20\" t)
-returns (59 59 23 20 4 2012 nil nil 32400).
-The values are identical to those of `decode-time', but any values that are
-unknown are returned as nil."
- (let* ((parsed (parse-time-string str))
- (current (decode-time (current-time)))
- (replacement-alist
- `((SEC . ,(if round-up
- 59
- 0))
- (MIN . ,(if round-up
- 59
- 0))
- (HOUR . ,(if round-up
- 23
- 0))
- (DAY . nil)
- (MON . nil)
- (YEAR . nil)
- (DOW . nil)
- (DST . nil)
- (TZ . nil)))
- (sym-list (mapcar 'car replacement-alist))
- (result nil))
- (while (and parsed current sym-list)
- (let* ((sym (car sym-list))
- (v (or (car parsed)
- (cdr (assq sym replacement-alist))
- ;; If `sym' is not 'DOW and it is bound to nil
- ;; in `replacement-alist', use `current'.
- (unless (eq sym 'DOW)
- (car current)))))
- (setq result (cons v result)))
- (setq parsed (cdr parsed))
- (setq current (cdr current))
- (setq sym-list (cdr sym-list)))
- (reverse result)))
-
-;;;;
-;;;; Utility for portability
-;;;;
-
-(defun twittering-remove-duplicates (list)
- "Return a copy of LIST with all duplicate elements removed.
-This is non-destructive version of `delete-dups' which is not
-defined in Emacs21."
- (if (fboundp 'delete-dups)
- (delete-dups (copy-sequence list))
- (let ((rest list)
- (result nil))
- (while rest
- (unless (member (car rest) result)
- (setq result (cons (car rest) result)))
- (setq rest (cdr rest)))
- (nreverse result))))
-
-(defun twittering-completing-read (prompt collection &optional predicate require-match initial-input hist def inherit-input-method)
- "Read a string in the minibuffer, with completion.
-This is a modified version of `completing-read' and accepts candidates
-as a list of a string on Emacs21."
- ;; completing-read() of Emacs21 does not accepts candidates as
- ;; a list. Candidates must be given as an alist.
- (let* ((collection (twittering-remove-duplicates collection))
- (collection
- (if (and (> 22 emacs-major-version)
- (listp collection)
- (stringp (car collection)))
- (mapcar (lambda (x) (cons x nil)) collection)
- collection)))
- (completing-read prompt collection predicate require-match
- initial-input hist def inherit-input-method)))
-
-(defun twittering-add-to-history (history-var elt &optional maxelt keep-all)
- (if (functionp 'add-to-history)
- (add-to-history history-var elt maxelt keep-all)
- (let* ((added (cons elt
- (if (and (not keep-all)
- (boundp 'history-delete-duplicates)
- history-delete-duplicates)
- (delete elt (symbol-value history-var))
- (symbol-value history-var))))
- (maxelt (or maxelt history-length))
- (len (length added)))
- (set history-var
- (if (<= len maxelt)
- added
- (butlast added (- len maxelt)))))))
-
-(if (fboundp 'assoc-string)
- (defalias 'twittering-assoc-string 'assoc-string)
- (defun twittering-assoc-string (key list &optional case-fold)
- "Like `assoc' but specifically for strings (and symbols).
-This returns the first element of LIST whose car matches the string or
-symbol KEY, or nil if no match exists. When performing the
-comparison, symbols are first converted to strings, and unibyte
-strings to multibyte. If the optional arg CASE-FOLD is non-nil, case
-is ignored.
-
-Unlike `assoc', KEY can also match an entry in LIST consisting of a
-single string, rather than a cons cell whose car is a string.
-
-This is reimplemented version of `assoc-string' which is not
-defined in Emacs21."
- (let* ((key (if (stringp key)
- key
- (symbol-name key)))
- (regexp (concat "\\`" key "\\'"))
- (rest list)
- (result nil)
- (case-fold-search case-fold))
- (while (not (null rest))
- (let* ((current (car rest))
- (current-key
- (if (listp current)
- (car current)
- current))
- (current-key
- (if (stringp current-key)
- current-key
- (symbol-name current-key))))
- (if (string-match key current-key)
- (setq result current
- rest nil)
- (setq rest (cdr rest)))))
- result)))
-
-;;;;
-;;;; Debug mode
-;;;;
-
-(defvar twittering-debug-mode nil)
-(defvar twittering-debug-buffer "*debug*")
-
-(defun twittering-get-or-generate-buffer (buffer)
- (if (bufferp buffer)
- (if (buffer-live-p buffer)
- buffer
- (generate-new-buffer (buffer-name buffer)))
- (if (stringp buffer)
- (or (get-buffer buffer)
- (generate-new-buffer buffer)))))
-
-(defun twittering-debug-buffer ()
- (twittering-get-or-generate-buffer twittering-debug-buffer))
-
-(defmacro debug-print (obj)
- (let ((obsym (gensym)))
- `(let ((,obsym ,obj))
- (if twittering-debug-mode
- (with-current-buffer (twittering-debug-buffer)
- (insert "[debug] " (prin1-to-string ,obsym))
- (newline)
- ,obsym)
- ,obsym))))
-
-(defun debug-printf (fmt &rest args)
- (when twittering-debug-mode
- (with-current-buffer (twittering-debug-buffer)
- (insert "[debug] " (apply 'format fmt args))
- (newline))))
-
-(defun twittering-debug-mode ()
- (interactive)
- (setq twittering-debug-mode
- (not twittering-debug-mode))
- (message (if twittering-debug-mode "debug mode:on" "debug mode:off")))
-
-;;;;
-;;;; Proxy setting / functions
-;;;;
-
-(defvar twittering-proxy-use nil)
-(defvar twittering-proxy-server nil
- "*Proxy server for `twittering-mode'.
-If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.
-
-To use individual proxies for HTTP and HTTPS, both `twittering-proxy-server'
-and `twittering-proxy-port' must be nil.")
-(defvar twittering-proxy-port nil
- "*Port number for `twittering-mode'.
-If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.
-
-To use individual proxies for HTTP and HTTPS, both `twittering-proxy-server'
-and `twittering-proxy-port' must be nil.")
-(defvar twittering-proxy-keep-alive nil)
-(defvar twittering-proxy-user nil
- "*Username for `twittering-proxy-server'.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-(defvar twittering-proxy-password nil
- "*Password for `twittering-proxy-server'.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-
-(defvar twittering-http-proxy-server nil
- "*HTTP proxy server for `twittering-mode'.
-If nil, it is initialized on entering `twittering-mode'.
-The port number is specified by `twittering-http-proxy-port'.
-For HTTPS connection, the proxy specified by `twittering-https-proxy-server'
-and `twittering-https-proxy-port' is used.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-(defvar twittering-http-proxy-port nil
- "*Port number of a HTTP proxy server for `twittering-mode'.
-If nil, it is initialized on entering `twittering-mode'.
-The server is specified by `twittering-http-proxy-server'.
-For HTTPS connection, the proxy specified by `twittering-https-proxy-server'
-and `twittering-https-proxy-port' is used.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-(defvar twittering-http-proxy-keep-alive nil
- "*If non-nil, the Keep-alive is enabled. This is experimental.")
-(defvar twittering-http-proxy-user nil
- "*Username for `twittering-http-proxy-server'.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-(defvar twittering-http-proxy-password nil
- "*Password for `twittering-http-proxy-server'.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-
-(defvar twittering-https-proxy-server nil
- "*HTTPS proxy server for `twittering-mode'.
-If nil, it is initialized on entering `twittering-mode'.
-The port number is specified by `twittering-https-proxy-port'.
-For HTTP connection, the proxy specified by `twittering-http-proxy-server'
-and `twittering-http-proxy-port' is used.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-(defvar twittering-https-proxy-port nil
- "*Port number of a HTTPS proxy server for `twittering-mode'.
-If nil, it is initialized on entering `twittering-mode'.
-The server is specified by `twittering-https-proxy-server'.
-For HTTP connection, the proxy specified by `twittering-http-proxy-server'
-and `twittering-http-proxy-port' is used.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-(defvar twittering-https-proxy-keep-alive nil
- "*If non-nil, the Keep-alive is enabled. This is experimental.")
-(defvar twittering-https-proxy-user nil
- "*Username for `twittering-https-proxy-server'.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-(defvar twittering-https-proxy-password nil
- "*Password for `twittering-https-proxy-server'.
-
-NOTE: If both `twittering-proxy-server' and `twittering-proxy-port' are
-non-nil, the variables `twittering-proxy-*' have priority over other
-variables `twittering-http-proxy-*' or `twittering-https-proxy-*'
-regardless of HTTP or HTTPS.")
-
-(defun twittering-normalize-proxy-vars ()
- "Normalize the type of `twittering-http-proxy-port' and
-`twittering-https-proxy-port'."
- (mapc (lambda (sym)
- (let ((value (symbol-value sym)))
- (cond
- ((null value)
- nil)
- ((integerp value)
- nil)
- ((stringp value)
- (set sym (string-to-number value)))
- (t
- (set sym nil)))))
- '(twittering-proxy-port
- twittering-http-proxy-port
- twittering-https-proxy-port)))
-
-(defun twittering-proxy-info (scheme &optional item)
- "Return an alist for proxy configuration registered for SCHEME.
-SCHEME must be a string \"http\", \"https\" or a symbol 'http or 'https.
-The server name is a string and the port number is an integer."
- (twittering-normalize-proxy-vars)
- (let ((scheme (if (symbolp scheme)
- (symbol-name scheme)
- scheme))
- (info-list
- `((("http" "https")
- . ((server . ,twittering-proxy-server)
- (port . ,twittering-proxy-port)
- (keep-alive . ,twittering-proxy-keep-alive)
- (user . ,twittering-proxy-user)
- (password . ,twittering-proxy-password)))
- (("http")
- . ((server . ,twittering-http-proxy-server)
- (port . ,twittering-http-proxy-port)
- (keep-alive . ,twittering-http-proxy-keep-alive)
- (user . ,twittering-http-proxy-user)
- (password . ,twittering-http-proxy-password)))
- (("https")
- . ((server . ,twittering-https-proxy-server)
- (port . ,twittering-https-proxy-port)
- (keep-alive . ,twittering-https-proxy-keep-alive)
- (user . ,twittering-https-proxy-user)
- (password . ,twittering-https-proxy-password))))))
- (let ((info
- (car (remove nil
- (mapcar
- (lambda (entry)
- (when (member scheme (car entry))
- (let ((info (cdr entry)))
- (when (and (cdr (assq 'server info))
- (cdr (assq 'port info)))
- info))))
- info-list)))))
- (if item
- (cdr (assq item info))
- info))))
-
-(defun twittering-url-proxy-services ()
- "Return the current proxy configuration for `twittering-mode' in the format
-of `url-proxy-services'."
- (remove nil (mapcar
- (lambda (scheme)
- (let ((server (twittering-proxy-info scheme 'server))
- (port (twittering-proxy-info scheme 'port)))
- (when (and server port)
- `(,scheme . ,(format "%s:%s" server port)))))
- '("http" "https"))))
-
-(defun twittering-find-proxy (scheme)
- "Find proxy server and its port from the environmental variables and return
-a cons pair of them.
-SCHEME must be \"http\" or \"https\"."
- (cond
- ((require 'url-methods nil t)
- (url-scheme-register-proxy scheme)
- (let* ((proxy-service (assoc scheme url-proxy-services))
- (proxy (if proxy-service (cdr proxy-service) nil)))
- (if (and proxy
- (string-match "^\\([^:]+\\):\\([0-9]+\\)$" proxy))
- (let ((host (match-string 1 proxy))
- (port (string-to-number (match-string 2 proxy))))
- (cons host port))
- nil)))
- (t
- (let* ((env-var (concat scheme "_proxy"))
- (env-proxy (or (getenv (upcase env-var))
- (getenv (downcase env-var))))
- (default-port (if (string= "https" scheme) "443" "80")))
- (if (and env-proxy
- (string-match
- "^\\(https?://\\)?\\([^:/]+\\)\\(:\\([0-9]+\\)\\)?/?$"
- env-proxy))
- (let* ((host (match-string 2 env-proxy))
- (port-str (or (match-string 4 env-proxy) default-port))
- (port (string-to-number port-str)))
- (cons host port))
- nil)))))
-
-(defun twittering-setup-proxy ()
- (when (require 'url-methods nil t)
- ;; If `url-scheme-registry' is not initialized,
- ;; `url-proxy-services' will be reset by calling
- ;; `url-insert-file-contents' or `url-retrieve-synchronously', etc.
- ;; To avoid it, initialize `url-scheme-registry' by calling
- ;; `url-scheme-get-property' before calling such functions.
- (url-scheme-get-property "http" 'name)
- (url-scheme-get-property "https" 'name))
- (unless (and twittering-http-proxy-server
- twittering-http-proxy-port)
- (let ((info (twittering-find-proxy "http")))
- (setq twittering-http-proxy-server (car-safe info))
- (setq twittering-http-proxy-port (cdr-safe info))))
- (unless (and twittering-https-proxy-server
- twittering-https-proxy-port)
- (let ((info (twittering-find-proxy "https")))
- (setq twittering-https-proxy-server (car-safe info))
- (setq twittering-https-proxy-port (cdr-safe info))))
- (if (and twittering-proxy-use
- (null (twittering-proxy-info "http"))
- (null (twittering-proxy-info "https")))
- (progn
- (message "Disabling proxy due to lack of configuration.")
- (setq twittering-proxy-use nil))
- t))
-
-(defun twittering-toggle-proxy ()
- (interactive)
- (setq twittering-proxy-use
- (not twittering-proxy-use))
- (if (twittering-setup-proxy)
- (message (if twittering-proxy-use "Use Proxy:on" "Use Proxy:off")))
- (twittering-update-mode-line))
-
-;;;;
-;;;; Functions for URL library
-;;;;
-
-(defvar twittering-url-show-status nil
- "*Whether to show a running total of bytes transferred.")
-
-;;;;
-;;;; CA certificate
-;;;;
-
-(defvar twittering-cert-file nil
- "The full-path of the file including the certificates authorizing
-servers on SSL.")
-
-(defconst twittering-ca-cert-list
- '(;; Equifax Secure Certificate Authority
- ;; subject= /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
- ;; SHA1 Fingerprint=D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A
- ;; Retrieved from: https://www.geotrust.com/resources/root-certificates/index.html
- ;; URL: https://www.geotrust.com/resources/root_certificates/certificates/Equifax_Secure_Certificate_Authority.cer
- ;; for www.googleapis.com
- "-----BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
-dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
-MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
-dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
-BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
-cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
-MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
-aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
-ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
-IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
-7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
-1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
------END CERTIFICATE-----
-"
- ;; VeriSign Class 3 Public Primary CA - G2
- ;; subject= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority - G2/OU=(c) 1998 VeriSign, Inc. - For authorized use only/OU=VeriSign Trust Network
- ;; SHA1 Fingerprint=85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F
- ;; Retrieved from: https://www.verisign.com/support/roots.html
- ;; URL: https://www.verisign.com/repository/roots/root-certificates/PCA-3G2.pem
- ;; for api.twitter.com
- "-----BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
-pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
-13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
-U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
-F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
-oJ2daZH9
------END CERTIFICATE-----
-"
- ;; GeoTrust Global CA
- ;; subject= /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
- ;; SHA1 Fingerprint=DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12
- ;; Retrieved from: https://www.geotrust.com/resources/root-certificates/index.html
- ;; URL: https://www.geotrust.com/resources/root_certificates/certificates/GeoTrust_Global_CA.cer
- ;; for search.twitter.com
- "-----BEGIN CERTIFICATE-----
-MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
-MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
-YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
-R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
-9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
-fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
-iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
-1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
-bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
-MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
-ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
-uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
-Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
-tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
-PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
-hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
-5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
------END CERTIFICATE-----
-"))
-
-(defun twittering-delete-ca-cert ()
- (when (and twittering-cert-file
- (file-exists-p twittering-cert-file))
- (delete-file twittering-cert-file))
- (setq twittering-cert-file nil))
-
-(defun twittering-ensure-ca-cert ()
- "Return a full-path of the file including CA certificates.
-
-If it does not exist, create it. The directory includes root certificates
-in \"hash format\". In detail, see verify(1SSL)."
- (unless twittering-cert-file
- (let ((coding-system-for-write 'iso-safe)
- (file (make-temp-file "twmode-cacert")))
- (with-temp-file file
- (apply 'insert twittering-ca-cert-list))
- (setq twittering-cert-file file)
- (add-hook 'kill-emacs-hook 'twittering-delete-ca-cert)))
- twittering-cert-file)
-
-;;;;
-;;;; User agent
-;;;;
-
-(defvar twittering-user-agent-function 'twittering-user-agent-default-function)
-
-(defun twittering-user-agent-default-function ()
- "Twittering mode default User-Agent function."
- (format "Emacs/%d.%d Twittering-mode/%s"
- emacs-major-version emacs-minor-version
- twittering-mode-version))
-
-(defun twittering-user-agent ()
- "Return User-Agent header string."
- (funcall twittering-user-agent-function))
-
-;;;;
-;;;; Basic HTTP functions (general)
-;;;;
-
-(defun twittering-percent-encode (str &optional coding-system)
- "Encode STR according to Percent-Encoding defined in RFC 3986."
- (twittering-oauth-url-encode str coding-system))
-
-(defun twittering-lookup-connection-type (use-ssl &optional order table)
- "Return available entry extracted fron connection type table.
-TABLE is connection type table, which is an alist of type symbol and its
-item alist, such as
- '((native (check . t)
- (https . twittering-start-http-session-native-tls-p)
- (start . twittering-start-http-session-native))
- (curl (check . twittering-start-http-session-curl-p)
- (https . twittering-start-http-session-curl-https-p)
- (start . twittering-start-http-session-curl))) .
-ORDER means the priority order of type symbols.
-If USE-SSL is nil, the item `https' is ignored.
-When the type `curl' has priority and is available for the above table,
-the function returns
- '((check . twittering-start-http-session-curl-p)
- (https . twittering-start-http-session-curl-https-p)
- (start . twittering-start-http-session-curl)) ."
- (let ((rest (or order twittering-connection-type-order))
- (table (or table twittering-connection-type-table))
- (result nil))
- (while (and rest (null result))
- (let* ((candidate (car rest))
- (entry (cons `(symbol . ,candidate)
- (cdr (assq candidate table))))
- (entry (if (assq 'display-name entry)
- entry
- (cons `(display-name . ,(symbol-name candidate))
- entry)))
- (validate (lambda (item)
- (let ((v (cdr (assq item entry))))
- (or (null v) (eq t v) (functionp v)))))
- (confirm (lambda (item)
- (let ((v (cdr (assq item entry))))
- (cond
- ((null v) nil)
- ((eq t v) t)
- ((functionp v) (funcall v)))))))
- (if (and (funcall validate 'check)
- (or (not use-ssl) (funcall validate 'https)))
- (cond
- ((and (funcall confirm 'check)
- (or (not use-ssl) (funcall confirm 'https)))
- (setq rest nil)
- (setq result entry))
- (t
- (setq rest (cdr rest))))
- (message "The configuration for conncetion type `%s' is invalid."
- candidate)
- (setq rest nil))))
- result))
-
-(defun twittering-get-connection-method-name (use-ssl)
- "Return a name of the preferred connection method.
-If USE-SSL is non-nil, return a connection method for HTTPS.
-If USE-SSL is nil, return a connection method for HTTP."
- (cdr (assq 'display-name (twittering-lookup-connection-type use-ssl))))
-
-(defun twittering-lookup-http-start-function (&optional order table)
- "Decide a connection method from currently available methods."
- (let ((entry
- (twittering-lookup-connection-type twittering-use-ssl order table)))
- (cdr (assq 'send-http-request entry))))
-
-(defun twittering-ensure-connection-method (&optional order table)
- "Ensure a connection method with a compromise.
-Return nil if no connection methods are available with a compromise."
- (let* ((use-ssl (or twittering-use-ssl twittering-oauth-use-ssl))
- (entry (twittering-lookup-connection-type use-ssl order table)))
- (cond
- (entry
- t)
- ((and (null entry) use-ssl
- (yes-or-no-p "HTTPS(SSL) is unavailable. Use HTTP instead? "))
- ;; Fall back on connection without SSL.
- (setq twittering-use-ssl nil)
- (setq twittering-oauth-use-ssl nil)
- (twittering-update-mode-line)
- (twittering-ensure-connection-method order table))
- (t
- (message "No connection methods are available.")
- nil))))
-
-(defun twittering-make-http-request (method header-list host port path query-parameters post-body use-ssl)
- "Returns an alist specifying a HTTP request.
-METHOD specifies HTTP method. It must be \"GET\" or \"POST\".
-HEADER-LIST is a list of (field-name . field-value) specifying HTTP header
-fields. The fields \"Host\", \"User-Agent\" and \"Content-Length\" are
-automatically filled if necessary.
-HOST specifies the host.
-PORT specifies the port. This must be an integer.
-PATH specifies the absolute path in URI (without query string).
-QUERY-PARAMTERS is a string or an alist.
-If QUERY-PARAMTERS is a string, it is treated as an encoded query string.
-If QUERY-PARAMTERS is an alist, it represents a list of cons pairs of
-string, (query-key . query-value).
-POST-BODY specifies the post body sent when METHOD equals to \"POST\".
-If POST-BODY is nil, no body is posted.
-If USE-SSL is non-nil, the request is performed with SSL.
-
-The result alist includes the following keys, where a key is a symbol.
- method: HTTP method such as \"GET\" or \"POST\".
- scheme: the scheme name. \"http\" or \"https\".
- host: the host to which the request is sent.
- port: the port to which the request is sent (integer).
- path: the absolute path string. Note that it does not include query string.
- query-string: the query string.
- encoded-query-alist: the alist consisting of pairs of encoded query-name and
- encoded query-value.
- uri: the URI. It includes the query string.
- uri-without-query: the URI without the query string.
- header-list: an alist specifying pairs of a parameter and its value in HTTP
- header field.
- post-body: the entity that will be posted."
- (let* ((scheme (if use-ssl "https" "http"))
- (default-port (if use-ssl 443 80))
- (port (if port port default-port))
- (query-string
- (cond
- ((stringp query-parameters)
- query-parameters)
- ((consp query-parameters)
- (mapconcat (lambda (pair)
- (cond
- ((stringp pair)
- (twittering-percent-encode pair))
- ((consp pair)
- (format
- "%s=%s"
- (twittering-percent-encode (car pair))
- (twittering-percent-encode (cdr pair))))
- (t
- nil)))
- query-parameters
- "&"))
- (t
- nil)))
- (encoded-query-alist
- (cond
- ((stringp query-parameters)
- ;; Query name and its value must be already encoded.
- (mapcar (lambda (str)
- (if (string-match "=" str)
- (let ((key (substring str 0 (match-beginning 0)))
- (value (substring str (match-end 0))))
- `(,key . ,value))
- `(,str . nil)))
- (split-string query-parameters "&")))
- ((consp query-parameters)
- (mapcar (lambda (pair)
- (cond
- ((stringp pair)
- (cons (twittering-percent-encode pair) nil))
- ((consp pair)
- (cons (twittering-percent-encode (car pair))
- (twittering-percent-encode (cdr pair))))
- (t
- nil)))
- query-parameters))
- (t
- nil)))
- (uri-without-query
- (concat scheme "://"
- host
- (when (and port (not (= port default-port)))
- (format ":%d" port))
- path))
- (uri
- (if query-string
- (concat uri-without-query "?" query-string)
- uri-without-query))
- (header-list
- `(,@(when (and (string= method "POST")
- (not (assoc "Content-Length" header-list)))
- `(("Content-Length" . ,(format "%d" (length post-body)))))
- ,@(unless (assoc "Host" header-list)
- `(("Host" . ,host)))
- ,@(unless (assoc "User-Agent" header-list)
- `(("User-Agent" . ,(twittering-user-agent))))
- ,@header-list)))
- (cond
- ((not (member method '("POST" "GET")))
- (error "Unknown HTTP method: %s" method)
- nil)
- ((not (string-match "^/" path))
- (error "Invalid HTTP path: %s" path)
- nil)
- (t
- `((method . ,method)
- (scheme . ,scheme)
- (host . ,host)
- (port . ,port)
- (path . ,path)
- (query-string . ,query-string)
- (encoded-query-alist . ,encoded-query-alist)
- (uri . ,uri)
- (uri-without-query . ,uri-without-query)
- (header-list . ,header-list)
- (post-body . ,post-body))))))
-
-(defun twittering-make-http-request-from-uri (method header-list uri &optional post-body)
- "Returns an alist specifying a HTTP request.
-The result alist has the same form as an alist generated by
-`twittering-make-http-request'.
-
-METHOD specifies HTTP method. It must be \"GET\" or \"POST\".
-HEADER-LIST is a list of (field-name . field-value) specifying HTTP header
-fields. The fields \"Host\" and \"User-Agent\" are automatically filled
-if necessary.
-URI specifies the URI including query string.
-POST-BODY specifies the post body sent when METHOD equals to \"POST\".
-If POST-BODY is nil, no body is posted."
- (let* ((parts-alist
- (let ((parsed-url (url-generic-parse-url uri)))
- ;; This is required for the difference of url library
- ;; distributed with Emacs 22 and 23.
- (cond
- ((and (fboundp 'url-p) (url-p parsed-url))
- ;; Emacs 23 and later.
- `((scheme . ,(url-type parsed-url))
- (host . ,(url-host parsed-url))
- (port . ,(url-portspec parsed-url))
- (path . ,(url-filename parsed-url))))
- ((vectorp parsed-url)
- ;; Emacs 22.
- `((scheme . ,(aref parsed-url 0))
- (host . ,(aref parsed-url 3))
- (port . ,(aref parsed-url 4))
- (path . ,(aref parsed-url 5))))
- (t
- nil))))
- (path (let ((path (cdr (assq 'path parts-alist))))
- (if (string-match "\\`\\(.*\\)\\?" path)
- (match-string 1 path)
- path)))
- (query-string (let ((path (cdr (assq 'path parts-alist))))
- (if (string-match "\\?\\(.*\\)\\'" path)
- (match-string 1 path)
- nil))))
- (twittering-make-http-request method header-list
- (cdr (assq 'host parts-alist))
- (cdr (assq 'port parts-alist))
- path
- query-string
- post-body
- (string= "https"
- (cdr (assq 'scheme parts-alist))))))
-
-(defun twittering-make-connection-info (request &optional additional order table)
- "Make an alist specifying the information of connection for REQUEST.
-REQUEST must be an alist that has the same keys as that generated by
-`twittering-make-http-request'.
-
-ADDITIONAL is appended to the tail of the result alist.
-Following ADDITIONAL, an entry in TABLE is also appended to the result alist,
-where `twittering-lookup-connection-type' determines the entry according to
-the priority order ORDER.
-If ORDER is nil, `twittering-connection-type-order' is used in place of ORDER.
-If TABLE is nil, `twittering-connection-type-table' is used in place of TABLE.
-
-The parameter symbols are following:
- use-ssl: whether SSL is enabled or not.
- allow-insecure-server-cert: non-nil if an insecure server certificate is
- allowed on SSL.
- cacert-file-fullpath: the full-path of a file including the certificates
- authorizing a server certificate on SSL. The file must be in PEM format.
- use-proxy: non-nil if using a proxy.
- proxy-server: a proxy server or nil.
- proxy-port: a port for connecting the proxy (integer) or nil.
- proxy-user: a username for connecting the proxy or nil.
- proxy-password: a password for connecting the proxy or nil.
- request: an alist specifying a HTTP request."
- (let* ((order (or order twittering-connection-type-order))
- (table (or table twittering-connection-type-table))
- (scheme (cdr (assq 'scheme request)))
- (use-ssl (string= "https" scheme))
- (entry (twittering-lookup-connection-type use-ssl order table)))
- `((use-ssl . ,use-ssl)
- (allow-insecure-server-cert
- . ,twittering-allow-insecure-server-cert)
- (cacert-file-fullpath
- . ,(when use-ssl (twittering-ensure-ca-cert)))
- (use-proxy . ,twittering-proxy-use)
- ,@(when twittering-proxy-use
- `((proxy-server . ,(twittering-proxy-info scheme 'server))
- (proxy-port . ,(twittering-proxy-info scheme 'port))
- (proxy-user . ,(twittering-proxy-info scheme 'user))
- (proxy-password . ,(twittering-proxy-info scheme 'password))))
- (request . ,request)
- ,@additional
- ,@entry)))
-
-(defun twittering-get-response-header (buffer)
- "Extract HTTP response header from HTTP response.
-BUFFER may be a buffer or the name of an existing buffer which contains the HTTP response."
- (with-current-buffer buffer
- (save-excursion
- (goto-char (point-min))
- (if (search-forward-regexp "\r?\n\r?\n" nil t)
- (prog1
- (buffer-substring (point-min) (match-end 0))
- (when twittering-debug-mode
- (debug-printf "connection-info=%s\n" connection-info)
- (debug-print "HTTP response header:\n--BEGIN\n")
- (debug-print (buffer-substring (point-min) (match-end 0)))
- (debug-print "--END\n")))
- nil))))
-
-(defun twittering-make-header-info-alist (header-str)
- "Make HTTP header alist from HEADER-STR.
-The alist consists of pairs of field-name and field-value, such as
-'((\"Content-Type\" . \"application/xml\; charset=utf-8\")
- (\"Content-Length\" . \"2075\"))."
- (let* ((lines (split-string header-str "\r?\n"))
- (status-line (car lines))
- (header-lines (cdr lines)))
- (when (string-match
- "^\\(HTTP/1\.[01]\\) \\([0-9][0-9][0-9]\\) \\(.*\\)$"
- status-line)
- (append `((status-line . ,status-line)
- (http-version . ,(match-string 1 status-line))
- (status-code . ,(match-string 2 status-line))
- (reason-phrase . ,(match-string 3 status-line)))
- (remove nil
- (mapcar
- (lambda (line)
- (when (string-match "^\\([^: ]*\\): *\\(.*\\)$" line)
- (cons (match-string 1 line) (match-string 2 line))))
- header-lines))))))
-
-(defun twittering-get-content-subtype-symbol-from-header-info (header-info)
- "Return a symbol corresponding to the subtype of content-type."
- (let* ((content-type
- ;; According to RFC2616, field name of a HTTP header is
- ;; case-insensitive.
- (car
- (remove
- nil
- (mapcar (lambda (entry)
- (when (and (stringp (car entry))
- (let ((case-fold-search t))
- (string-match "\\`content-type\\'"
- (car entry))))
- (cdr entry)))
- header-info))))
- (subtype (when (and (stringp content-type)
- (string-match "\\` *[^/]*/\\([^ ;]*\\)"
- content-type))
- (downcase (match-string 1 content-type))))
- (symbol-alist
- '(("json" . json)
- ("atom+xml" . atom)
- ("xml" . xml))))
- (cdr (assoc subtype symbol-alist))))
-
-(defun twittering-decode-response-body (header-info)
- "Decode the current buffer according to the content-type in HEADER-INFO."
- (let* ((content-type
- ;; According to RFC2616, field name of a HTTP header is
- ;; case-insensitive.
- (car
- (remove
- nil
- (mapcar (lambda (entry)
- (when (and (stringp (car entry))
- (let ((case-fold-search t))
- (string-match "\\`content-type\\'"
- (car entry))))
- (cdr entry)))
- header-info))))
- (parameters (when (stringp content-type)
- (cdr (split-string content-type ";"))))
- (regexp "^[[:space:]]*charset=utf-8[[:space:]]*$")
- (encoded-with-utf-8
- (let ((case-fold-search t))
- (remove nil
- (mapcar (lambda (entry)
- (string-match regexp entry))
- parameters)))))
- (when encoded-with-utf-8
- (decode-coding-region (point-min) (point-max) 'utf-8))))
-
-(defun twittering-send-http-request-internal (request additional-info sentinel &optional order table)
- "Open a connection and return a subprocess object for the connection.
-REQUEST must be an alist that has the same keys as that generated by
-`twittering-make-http-request'.
-SENTINEL is called as a function when the process changes state.
-It gets three arguments: the process, a string describing the change, and
-the connection-info, which is generated by `twittering-make-connection-info'
-and also includes an alist ADDITIONAL-INFO.
-
-How to perform the request is selected from TABLE according to the priority
-order ORDER. ORDER and TABLE are directly sent to
-`twittering-make-connection-info'.
-If ORDER is nil, `twittering-connection-type-order' is used in place of ORDER.
-If TABLE is nil, `twittering-connection-type-table' is used in place of TABLE.
-"
- (let* ((order (or order twittering-connection-type-order))
- (table (or table twittering-connection-type-table))
- (connection-info
- (twittering-make-connection-info request additional-info
- order table))
- (func (cdr (assq 'send-http-request connection-info)))
- (temp-buffer (generate-new-buffer "*twmode-http-buffer*"))
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (cond
- ((and func (functionp func))
- (funcall func "*twmode-generic*" temp-buffer
- connection-info
- (when (and sentinel (functionp sentinel))
- (lexical-let ((sentinel sentinel)
- (connection-info connection-info))
- (lambda (proc status)
- (apply sentinel proc status connection-info nil))))))
- (t
- (error "No valid connection method is found")
- nil))))
-
-(defun twittering-send-http-request (request additional-info func &optional clean-up-func)
- "Send a HTTP request and return a subprocess object for the connection.
-REQUEST must be an alist that has the same keys as that generated by
-`twittering-make-http-request'.
-
-FUNC is called when a HTTP response has been received without errors.
-It is called with the current buffer containing the HTTP response (without
-HTTP headers). FUNC is called with four arguments: the process, a symbol
-describing the status of the process, a connection-info generated by
-`twittering-make-connection-info', and a header-info generated by
-`twittering-get-response-header' and `twittering-make-header-info-alist'.
-The connection-info also includes an alist ADDITIONAL-INFO.
-If FUNC returns non-nil and `twittering-buffer-related-p' is non-nil, the
-returned value is displayed as a message.
-And also, if FUNC returns a string and it matches the regular expression
-\"^\\\\(Failuare\\\\|Response\\\\): \", the returned value is displayed
-as a message.
-
-CLEAN-UP-FUNC is called whenever the sentinel of the subprocess for the
-connection is called (as `set-process-sentinel').
-It is called with three arguments: the process, a symbol describing the status
-of the proess, and a connection-info generated by
-`twittering-make-connection-info'.
-They are the same as arguments for FUNC.
-When a HTTP response has been received, FUNC is called in advance of
-CLEAN-UP-FUNC. CLEAN-UP-FUNC can overwrite the message displayed by FUNC.
-
-If the subprocess has exited, the buffer bound to it is automatically killed
-after calling CLEAN-UP-FUNC.
-
-The method to perform the request is determined from
-`twittering-connection-type-table' according to the priority order
-`twittering-connection-type-order'."
- (lexical-let ((func func)
- (clean-up-func clean-up-func))
- (twittering-send-http-request-internal
- request additional-info
- (lambda (proc status-str connection-info)
- (let ((status (cond
- ((string= status-str "urllib-finished") 'exit)
- ((processp proc) (process-status proc))
- (t nil)))
- (buffer (process-buffer proc))
- (exit-status (cond
- ((string= status-str "urllib-finished") 0)
- ((processp proc) (process-exit-status proc))
- (t 1)))
- (command (process-command proc))
- (pre-process-func
- (cdr (assq 'pre-process-buffer connection-info)))
- (mes nil))
- (unwind-protect
- (setq mes
- (cond
- ((null status)
- (format "Failure: process %s does not exist" proc))
- ((or (memq status '(run stop open listen connect))
- (not (memq status '(exit signal closed failed))))
- ;; If the process is running, FUNC is not called.
- nil)
- ((and command
- (not (= 0 exit-status)))
- ;; If the process abnormally exited,
- (format "Failure: %s exited abnormally (exit-status=%s)"
- (car command) exit-status))
- ((not (buffer-live-p buffer))
- (format "Failure: the buffer for %s is already killed"
- proc))
- (t
- (when (functionp pre-process-func)
- ;; Pre-process buffer.
- (funcall pre-process-func proc buffer connection-info))
- (let* ((header (twittering-get-response-header buffer))
- (header-info
- (and header
- (twittering-make-header-info-alist header))))
- (with-current-buffer buffer
- (goto-char (point-min))
- (when (search-forward-regexp "\r?\n\r?\n" nil t)
- ;; delete HTTP headers.
- (delete-region (point-min) (match-end 0)))
- ;; It may be necessary to decode the contents of
- ;; the buffer by UTF-8 because
- ;; `twittering-http-application-headers' specifies
- ;; utf-8 as one of acceptable charset.
- ;; For the present, only UTF-8 is taken into account.
- (twittering-decode-response-body header-info)
- (apply func proc status connection-info
- header-info nil))))))
- ;; unwind-forms
- (setq mes
- (cond
- ((null mes)
- nil)
- ((string-match "^\\(Failure\\|Response\\): " mes)
- (let* ((request (cdr (assq 'request connection-info)))
- (method (cdr (assq 'method request)))
- (uri (cdr (assq 'uri request))))
- (concat mes " for " method " " uri)))
- ((twittering-buffer-related-p)
- mes)))
- (when mes
- ;; CLEAN-UP-FUNC can overwrite a message from the return value
- ;; of FUNC.
- (message "%s" mes))
- (when (functionp clean-up-func)
- (funcall clean-up-func proc status connection-info))
- (when (and (memq status '(exit signal closed failed))
- (buffer-live-p buffer)
- (not twittering-debug-mode))
- (kill-buffer buffer))))))))
-
-;;;;
-;;;; Basic HTTP functions with tls and Emacs builtins.
-;;;;
-
-(eval-when-compile (require 'tls nil t))
-(defun twittering-start-http-session-native-tls-p ()
- (when (and (not twittering-proxy-use)
- (require 'tls nil t))
- (unless twittering-tls-program
- (let ((programs
- (remove nil
- (mapcar (lambda (cmd)
- (when (string-match "\\`\\([^ ]+\\) " cmd)
- (when (executable-find (match-string 1 cmd))
- cmd)))
- tls-program))))
- (setq twittering-tls-program
- (if twittering-allow-insecure-server-cert
- (mapcar
- (lambda (str)
- (cond
- ((string-match "^\\([^ ]*/\\)?openssl s_client " str)
- (concat (match-string 0 str) "-verify 0 "
- (substring str (match-end 0))))
- ((string-match "^\\([^ ]*/\\)?gnutls-cli " str)
- (concat (match-string 0 str) "--insecure "
- (substring str (match-end 0))))
- (t
- str)))
- programs)
- programs))))
- (not (null twittering-tls-program))))
-
-;; TODO: proxy
-(defun twittering-send-http-request-native (name buffer connection-info sentinel)
- (let* ((request (cdr (assq 'request connection-info)))
- (uri (cdr (assq 'uri connection-info)))
- (method (cdr (assq 'method request)))
- (scheme (cdr (assq 'scheme request)))
- (host (cdr (assq 'host request)))
- (port (cdr (assq 'port request)))
- (path (cdr (assq 'path request)))
- (query-string (cdr (assq 'query-string request)))
- (post-body (cdr (assq 'post-body request)))
- (use-proxy (cdr (assq 'use-proxy connection-info)))
- (proxy-server (cdr (assq 'proxy-server connection-info)))
- (proxy-port (cdr (assq 'proxy-port connection-info)))
- (proxy-user (cdr (assq 'proxy-user connection-info)))
- (proxy-password (cdr (assq 'proxy-password connection-info)))
- (proxy-credentials
- (when (and proxy-user proxy-password)
- (concat "Basic "
- (base64-encode-string
- (concat proxy-user ":" proxy-password)))))
- (header-list
- (let ((original-header-list (cdr (assq 'header-list request))))
- (if proxy-credentials
- (cons
- `("Proxy-Authorization" ,proxy-credentials)
- original-header-list)
- original-header-list)))
- (use-ssl (cdr (assq 'use-ssl connection-info)))
- (allow-insecure-server-cert
- (cdr (assq 'allow-insecure-server-cert connection-info)))
- (connect-host (or proxy-server host))
- (connect-port (or proxy-port port))
- (request-str
- (format "%s %s HTTP/1.1\r\n%s\r\n\r\n%s\r\n"
- method
- (if use-proxy
- ;; As described in 5.1.2 of RFC2616, the
- ;; absolute URI is required here if the connection
- ;; uses a proxy.
- uri
- (concat path
- (when query-string
- (concat "?" query-string))))
- (mapconcat (lambda (pair)
- (format "%s: %s" (car pair) (cdr pair)))
- header-list "\r\n")
- (or post-body "")))
- (coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- (tls-program twittering-tls-program)
- (proc
- (funcall (if use-ssl
- 'open-tls-stream
- 'open-network-stream)
- "network-connection-process"
- nil connect-host connect-port)))
- (when proc
- (set-process-buffer proc buffer)
- (when (functionp sentinel)
- (if (twittering-process-alive-p proc)
- (set-process-sentinel proc sentinel)
- (funcall sentinel proc "finished")))
- (process-send-string proc request-str)
- proc)))
-
-(defun twittering-pre-process-buffer-native (proc buffer connection-info)
- (let ((use-ssl (cdr (assq 'use-ssl connection-info)))
- (args (process-command proc)))
- (cond
- ((and use-ssl args
- (car
- (remove nil
- (mapcar (lambda (cmd)
- (string-match "^\\(.*/\\)?gnutls-cli\\b" cmd))
- args))))
- (with-current-buffer buffer
- (save-excursion
- (goto-char (point-max))
- (when (search-backward-regexp
- "- Peer has closed the GNUTLS connection\r?\n\\'")
- (let ((beg (match-beginning 0))
- (end (match-end 0)))
- (delete-region beg end))))))
- ((and use-ssl args
- (car
- (remove nil
- (mapcar
- (lambda (cmd)
- (string-match "^\\(.*/\\)?openssl s_client\\b" cmd))
- args))))
- (with-current-buffer buffer
- (save-excursion
- (goto-char (point-max))
- (when (search-backward-regexp "closed\r?\n\\'")
- (let ((beg (match-beginning 0))
- (end (match-end 0)))
- (delete-region beg end))))))
- (t
- nil))))
-
-;;;;
-;;;; Basic HTTP functions with curl
-;;;;
-
-(defun twittering-find-curl-program ()
- "Returns an appropriate `curl' program pathname or nil if not found."
- (or (executable-find "curl")
- (let ((windows-p (memq system-type '(windows-nt cygwin)))
- (curl.exe
- (expand-file-name
- "curl.exe"
- (expand-file-name
- "win-curl"
- (file-name-directory (symbol-file 'twit))))))
- (and windows-p
- (file-exists-p curl.exe) curl.exe))))
-
-(defun twittering-start-http-session-curl-p ()
- "Return t if curl was installed, otherwise nil."
- (unless twittering-curl-program
- (setq twittering-curl-program (twittering-find-curl-program)))
- (not (null twittering-curl-program)))
-
-(defun twittering-start-http-session-curl-https-p ()
- "Return t if curl was installed and the curl support HTTPS, otherwise nil."
- (when (twittering-start-http-session-curl-p)
- (unless twittering-curl-program-https-capability
- (with-temp-buffer
- (let ((coding-system-for-read 'iso-safe)
- (coding-system-for-write 'iso-safe)
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (call-process twittering-curl-program
- nil (current-buffer) nil
- "--version")
- (goto-char (point-min))
- (setq twittering-curl-program-https-capability
- (if (search-forward-regexp "^Protocols: .*https" nil t)
- 'capable
- 'incapable)))))
- (eq twittering-curl-program-https-capability 'capable)))
-
-(defun twittering-send-http-request-curl (name buffer connection-info sentinel)
- (let* ((request (cdr (assq 'request connection-info)))
- (method (cdr (assq 'method request)))
- (uri (cdr (assq 'uri request)))
- (header-list (cdr (assq 'header-list request)))
- (post-body (cdr (assq 'post-body request)))
- (use-proxy (cdr (assq 'use-proxy connection-info)))
- (proxy-server (cdr (assq 'proxy-server connection-info)))
- (proxy-port (cdr (assq 'proxy-port connection-info)))
- (proxy-user (cdr (assq 'proxy-user connection-info)))
- (proxy-password (cdr (assq 'proxy-password connection-info)))
- (use-ssl (cdr (assq 'use-ssl connection-info)))
- (allow-insecure-server-cert
- (cdr (assq 'allow-insecure-server-cert connection-info)))
- (cacert-file-fullpath
- (cdr (assq 'cacert-file-fullpath connection-info)))
- (cacert-file-base-directory
- (when cacert-file-fullpath
- (file-name-directory cacert-file-fullpath)))
- (cacert-file-body
- (when cacert-file-fullpath
- (file-name-nondirectory cacert-file-fullpath)))
- (header-list
- `(,@header-list
- ;; Make `curl' remove the HTTP header field "Expect" for
- ;; avoiding '417 Expectation Failed' HTTP response error.
- ;; The header field is automatically added for a HTTP request
- ;; exceeding 1024 byte. See
- ;; http://d.hatena.ne.jp/imait/20091228/1262004813 and
- ;; http://www.escafrace.co.jp/blog/09/10/16/1008
- ("Expect" . "")))
- (curl-args
- `("--include" "--silent" "--compressed"
- ,@(apply 'append
- (mapcar
- (lambda (pair)
- ;; Do not overwrite internal headers `curl' would use.
- ;; Thanks to William Xu.
- ;; "cURL - How To Use"
- ;; http://curl.haxx.se/docs/manpage.html
- (unless (string= (car pair) "Host")
- `("-H" ,(format "%s: %s" (car pair) (cdr pair)))))
- header-list))
- ,@(when use-ssl `("--cacert" ,cacert-file-body))
- ,@(when (and use-ssl allow-insecure-server-cert)
- `("--insecure"))
- ,@(when (and use-proxy proxy-server proxy-port)
- (append
- `("-x" ,(format "%s:%s" proxy-server proxy-port))
- (when (and proxy-user proxy-password)
- `("-U" ,(format "%s:%s" proxy-user proxy-password)))))
- ,@(when (string= "POST" method)
- `("-d" ,(or post-body "")))
- ,uri))
- (coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- (default-directory
- ;; If `use-ssl' is non-nil, the `curl' process
- ;; is executed at the same directory as the temporary cert file.
- ;; Without changing directory, `curl' misses the cert file if
- ;; you use Emacs on Cygwin because the path on Emacs differs
- ;; from Windows.
- ;; With changing directory, `curl' on Windows can find the cert
- ;; file if you use Emacs on Cygwin.
- (if use-ssl
- cacert-file-base-directory
- default-directory)))
- (twittering-start-process-with-sentinel name buffer
- twittering-curl-program
- curl-args sentinel)))
-
-(defun twittering-pre-process-buffer-curl (proc buffer connection-info)
- (let ((use-ssl (cdr (assq 'use-ssl connection-info)))
- (use-proxy (cdr (assq 'use-proxy connection-info))))
- (when (and use-ssl use-proxy)
- ;; When using SSL via a proxy with CONNECT method,
- ;; omit a successful HTTP response and headers if they seem to be
- ;; sent from the proxy.
- (with-current-buffer buffer
- (save-excursion
- (goto-char (point-min))
- (let ((first-regexp
- ;; successful HTTP response
- "\\`HTTP/1\.[01] 2[0-9][0-9] .*?\r?\n")
- (next-regexp
- ;; following HTTP response
- "^\\(\r?\n\\)HTTP/1\.[01] [0-9][0-9][0-9] .*?\r?\n"))
- (when (and (search-forward-regexp first-regexp nil t)
- (search-forward-regexp next-regexp nil t))
- (let ((beg (point-min))
- (end (match-end 1)))
- (delete-region beg end)))))))))
-
-;;;;
-;;;; Basic HTTP functions with wget
-;;;;
-
-(defun twittering-find-wget-program ()
- "Returns an appropriate `wget' program pathname or nil if not found."
- (executable-find "wget"))
-
-(defun twittering-start-http-session-wget-p ()
- "Return t if `wget' was installed, otherwise nil."
- (unless twittering-wget-program
- (setq twittering-wget-program (twittering-find-wget-program)))
- (not (null twittering-wget-program)))
-
-(defun twittering-send-http-request-wget (name buffer connection-info sentinel)
- (let* ((request (cdr (assq 'request connection-info)))
- (method (cdr (assq 'method request)))
- (scheme (cdr (assq 'scheme request)))
- (uri (cdr (assq 'uri request)))
- (header-list (cdr (assq 'header-list request)))
- (post-body (cdr (assq 'post-body request)))
- (use-proxy (cdr (assq 'use-proxy connection-info)))
- (proxy-server (cdr (assq 'proxy-server connection-info)))
- (proxy-port (cdr (assq 'proxy-port connection-info)))
- (proxy-user (cdr (assq 'proxy-user connection-info)))
- (proxy-password (cdr (assq 'proxy-password connection-info)))
- (use-ssl (cdr (assq 'use-ssl connection-info)))
- (allow-insecure-server-cert
- (cdr (assq 'allow-insecure-server-cert connection-info)))
- (cacert-file-fullpath
- (cdr (assq 'cacert-file-fullpath connection-info)))
- (cacert-file-base-directory
- (when cacert-file-fullpath
- (file-name-directory cacert-file-fullpath)))
- (cacert-file-body
- (when cacert-file-fullpath
- (file-name-nondirectory cacert-file-fullpath)))
- (args
- `("--save-headers"
- "--quiet"
- "--output-document=-"
- ,@(remove nil
- (mapcar
- (lambda (pair)
- (unless (string= (car pair) "Host")
- (format "--header=%s: %s" (car pair) (cdr pair))))
- header-list))
- ,@(when use-ssl
- `(,(format "--ca-certificate=%s" cacert-file-body)))
- ,@(when (and use-ssl allow-insecure-server-cert)
- `("--no-check-certificate"))
- ,@(cond
- ((not use-proxy)
- '("--no-proxy"))
- ((and use-proxy proxy-server proxy-port
- proxy-user proxy-password)
- `(,(format "--proxy-user=%s" proxy-user)
- ,(format "--proxy-password=%s" proxy-password)))
- (t
- nil))
- ,@(when (string= "POST" method)
- `(,(concat "--post-data=" (or post-body ""))))
- ,uri))
- (coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- (default-directory
- ;; If `use-ssl' is non-nil, the `wget' process
- ;; is executed at the same directory as the temporary cert file.
- ;; Without changing directory, `wget' misses the cert file if
- ;; you use Emacs on Cygwin because the path on Emacs differs
- ;; from Windows.
- ;; With changing directory, `wget' on Windows can find the cert
- ;; file if you use Emacs on Cygwin.
- (if use-ssl
- cacert-file-base-directory
- default-directory))
- (process-environment
- `(,@(when (and use-proxy proxy-server proxy-port)
- `(,(format "%s_proxy=%s://%s:%s/" scheme
- scheme proxy-server proxy-port)))
- ,@process-environment)))
- (twittering-start-process-with-sentinel name buffer
- twittering-wget-program args
- sentinel)))
-
-(defun twittering-pre-process-buffer-wget (proc buffer connection-info)
- (with-current-buffer buffer
- (save-excursion
- (goto-char (point-min))
- (when (search-forward-regexp "\\`[^\n]*?\r\r\n" (point-max) t)
- ;; When `wget.exe' writes HTTP response in text mode,
- ;; CRLF may be converted into CRCRLF.
- (goto-char (point-min))
- (while (search-forward "\r\n" nil t)
- (replace-match "\n" nil t)))
- (goto-char (point-max))
- (when (search-backward-regexp "\nProcess [^\n]* finished\n\\'"
- (point-min) t)
- (replace-match "" nil t))
- )))
-
-;;;;
-;;;; Basic HTTP functions with url library
-;;;;
-
-(defun twittering-start-http-session-urllib-p ()
- "Return t if url library is available, otherwise nil."
- (require 'url nil t))
-
-(defun twittering-start-http-session-urllib-https-p ()
- "Return t if url library can be used for HTTPS, otherwise nil."
- (and (not twittering-proxy-use)
- (require 'url nil t)
- (cond
- ((<= 22 emacs-major-version)
- ;; On Emacs22 and later, `url' requires `tls'.
- (twittering-start-http-session-native-tls-p))
- ((require 'ssl nil t)
- ;; On Emacs21, `url' requires `ssl'.
- t)
- ((or (and (fboundp 'open-ssl-stream)
- ;; Since `url-gw' (required by `url') defines autoload of
- ;; `open-ssl-stream' from "ssl",
- ;; (fboundp 'open-ssl-stream) will be non-nil even if
- ;; "ssl" cannot be loaded and `open-ssl-stream' is
- ;; unavailable.
- ;; Here, the availability is confirmed by `documentation'.
- (documentation 'open-ssl-stream))
- ;; On Emacs21, `url' requires `ssl' in order to use
- ;; `open-ssl-stream', which is included in `ssl.el'.
- ;; Even if `ssl' cannot be loaded, `open-tls-stream' can be
- ;; used as an alternative of the function.
- (and (twittering-start-http-session-native-tls-p)
- (defalias 'open-ssl-stream 'open-tls-stream)))
- (provide 'ssl)
- t)
- (t
- nil))))
-
-(defun twittering-send-http-request-urllib (name buffer connection-info sentinel)
- (let* ((request (cdr (assq 'request connection-info)))
- (method (cdr (assq 'method request)))
- (scheme (cdr (assq 'scheme request)))
- (uri (cdr (assq 'uri request)))
- (header-list (cdr (assq 'header-list request)))
- (post-body (cdr (assq 'post-body request)))
- (use-proxy (cdr (assq 'use-proxy connection-info)))
- (proxy-server (cdr (assq 'proxy-server connection-info)))
- (proxy-port (cdr (assq 'proxy-port connection-info)))
- (proxy-user (cdr (assq 'proxy-user connection-info)))
- (proxy-password (cdr (assq 'proxy-password connection-info)))
- (proxy-credentials
- (when (and proxy-user proxy-password)
- (concat "Basic "
- (base64-encode-string
- (concat proxy-user ":" proxy-password)))))
- (coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- (url-proxy-services
- (when use-proxy
- `((,scheme . ,(format "%s:%s" proxy-server proxy-port)))))
- (url-request-method method)
- (url-request-extra-headers
- ;; Remove some headers that should be configured by url library.
- ;; They may break redirections by url library because
- ;; `url-request-extra-headers' overwrites the new headers
- ;; that are adapted to redirected connection.
- (apply 'append
- (mapcar (lambda (pair)
- (if (member (car pair)
- '("Host" "Content-Length"))
- nil
- `(,pair)))
- (if proxy-credentials
- (cons
- `("Proxy-Authorization" ,proxy-credentials)
- header-list)
- header-list))))
- (url-request-data post-body)
- (url-show-status twittering-url-show-status)
- (url-http-attempt-keepalives nil)
- (tls-program twittering-tls-program)
- (coding-system-for-read 'binary)
- (coding-system-for-write 'binary))
- (lexical-let ((sentinel sentinel)
- (buffer buffer))
- (let ((result-buffer
- (url-retrieve
- uri
- (lambda (&rest args)
- (let ((proc url-http-process)
- (url-buffer (current-buffer))
- (status-str
- (if (and (< emacs-major-version 22)
- (boundp 'url-http-end-of-headers)
- url-http-end-of-headers)
- "urllib-finished"
- "finished")))
- ;; Callback may be called multiple times.
- ;; (as filter and sentinel?)
- (unless (local-variable-if-set-p 'twittering-retrieved)
- (set (make-local-variable 'twittering-retrieved)
- 'not-completed)
- (with-current-buffer buffer
- (set-buffer-multibyte nil)
- (insert-buffer-substring url-buffer))
- (set-process-buffer proc buffer)
- (unwind-protect
- (apply sentinel proc status-str nil)
- (set-process-buffer proc url-buffer)
- (if (eq twittering-retrieved 'exited)
- (url-mark-buffer-as-dead url-buffer)
- (setq twittering-retrieved 'completed))))
- (when (memq (process-status proc)
- '(nil closed exit failed signal))
- ;; Mark `url-buffer' as dead when the process exited
- ;; and `sentinel' is completed.
- ;; If this `lambda' is evaluated via a filter, the
- ;; process may exit before it is finished to evaluate
- ;; `(apply sentinel ...)'. In the case, `buffer' should
- ;; not be killed. It should be killed after the
- ;; evaluation of `sentinel'.
- (if (eq twittering-retrieved 'completed)
- (url-mark-buffer-as-dead url-buffer)
- (setq twittering-retrieved 'exited))))))))
- (when (buffer-live-p result-buffer)
- (with-current-buffer result-buffer
- (set (make-local-variable 'url-show-status)
- twittering-url-show-status)
- ;; Make `url-http-attempt-keepalives' buffer-local
- ;; in order to send the current value of the variable
- ;; to the sentinel invoked for HTTP redirection,
- (make-local-variable 'url-http-attempt-keepalives))
- (get-buffer-process result-buffer))))))
-
-(defun twittering-pre-process-buffer-urllib (proc buffer connection-info)
- (with-current-buffer buffer
- (save-excursion
- (goto-char (point-max))
- (cond
- ((search-backward-regexp
- "- Peer has closed the GNUTLS connection\r?\n\\'"
- nil t)
- (let ((beg (match-beginning 0))
- (end (match-end 0)))
- (delete-region beg end)))
- ((search-backward-regexp "closed\r?\n\\'" nil t)
- (let ((beg (match-beginning 0))
- (end (match-end 0)))
- (delete-region beg end)))
- (t nil)))))
-
-;;;;
-;;;; HTTP functions for twitter-like serivce
-;;;;
-
-(defun twittering-http-application-headers (&optional method headers)
- "Return an assoc list of HTTP headers for twittering-mode."
- (unless method
- (setq method "GET"))
-
- (let ((headers headers))
- (push (cons "User-Agent" (twittering-user-agent)) headers)
- (when (string= "GET" method)
- (push (cons "Accept"
- (concat
- "text/xml"
- ",application/xml"
- ",application/xhtml+xml"
- ",application/html;q=0.9"
- ",text/plain;q=0.8"
- ",image/png,*/*;q=0.5"))
- headers)
- (push (cons "Accept-Charset" "utf-8;q=0.7,*;q=0.7")
- headers))
- (when (string= "POST" method)
- (push (cons "Content-Type" "text/plain") headers))
- headers
- ))
-
-(defun twittering-add-application-header-to-http-request (request account-info)
- "Make a new HTTP request based on REQUEST with the authorization header.
-The authorization header is generated from ACCOUNT-INFO.
-ACCOUNT-INFO must be an alist that includes the following keys;
- \"screen_name\" and \"password\" if `twittering-auth-method' is 'basic,
- \"screen_name\", \"oauth_token\" and \"oauth_token_secret\" if
- `twittering-auth-method' is 'oauth or 'xauth."
- (let* ((method (cdr (assq 'method request)))
- (auth-str
- (cond
- ((eq twittering-auth-method 'basic)
- (twittering-make-basic-authentication-string account-info))
- ((memq twittering-auth-method '(oauth xauth))
- (twittering-make-oauth-authentication-string account-info request))
- (t
- nil)))
- (cookie-str (twittering-make-cookie-string request account-info))
- (application-headers
- `(,@(twittering-http-application-headers method)
- ("Authorization" . ,auth-str)
- ,@(when cookie-str
- `(("Cookie" . ,cookie-str))))))
- (mapcar (lambda (entry)
- (if (eq (car entry) 'header-list)
- `(header-list
- . ,(append (cdr entry) application-headers))
- entry))
- request)))
-
-(defun twittering-get-error-message (header-info connection-info &optional buffer)
- "Return an error message generated from the arguments.
-HEADER-INFO must be an alist generated by `twittering-get-response-header'.
-CONNECTION-INFO must be an alist generated by
-`twittering-make-connection-info'. It may include some additional information
-which is added by `twittering-send-http-request'.
-BUFFER must be nil or a HTTP response body, which includes error messages from
-the server when the HTTP status code equals to 400 or 403.
-If BUFFER is nil, the current buffer is used instead."
- (let ((buffer (or buffer (current-buffer)))
- (status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info)))
- (format
- (twittering-get-content-subtype-symbol-from-header-info header-info)))
- (cond
- ((and (buffer-live-p buffer)
- (member status-code '("400" "401" "403" "404")))
- ;; Twitter returns an error message as a HTTP response body if
- ;; HTTP status is "400 Bad Request" or "403 Forbidden".
- ;; See "HTTP Response Codes and Errors | dev.twitter.com"
- ;; http://dev.twitter.com/pages/responses_errors .
- ;;
- ;; However, Twitter seems to return an error message even when
- ;; the HTTP status is "401 Unauthorized" or "404 Not Found".
- (let* ((error-mes
- (cond
- ((eq format 'xml)
- (let ((xmltree
- (with-current-buffer buffer
- (twittering-xml-parse-region (point-min)
- (point-max)))))
- (car (cddr (assq 'error (or (assq 'errors xmltree)
- (assq 'hash xmltree)))))))
- ((eq format 'json)
- (let ((json-object (with-current-buffer buffer
- (twittering-json-read))))
- (cdr (assq 'error json-object))))
- (t
- ;; ATOM is not supported.
- nil))))
- (if error-mes
- (format "%s (%s)" status-line error-mes)
- status-line)))
- (t
- status-line))))
-
-(defun twittering-http-get (account-info-alist host method &optional parameters format additional-info sentinel clean-up-sentinel)
- "Send a HTTP GET request with application headers.
-ACCOUNT-INFO-ALIST is an alist used by
-`twittering-add-application-header-to-http-request'.
-The alist made by `((account-info . ,ACCOUNT-INFO-ALIST) ,@ADDITIONAL-INFO)'
-is used as the argument `additional-info' of `twittering-send-http-request'.
-HOST is hostname of remote side, api.twitter.com (or search.twitter.com).
-METHOD must be one of Twitter API method classes
- (statuses, users or direct_messages).
-PARAMETERS is alist of URI parameters.
- ex) ((\"mode\" . \"view\") (\"page\" . \"6\")) => <URI>?mode=view&page=6
-FORMAT is a response data format (\"xml\", \"atom\", \"json\")"
- (let* ((format (or format "xml"))
- (sentinel
- (lexical-let ((sentinel (or sentinel
- 'twittering-http-get-default-sentinel)))
- (lambda (proc status connection-info header-info)
- (twittering-update-server-info connection-info header-info)
- (apply sentinel proc status connection-info header-info nil))))
- (path (concat "/" method "." format))
- (headers nil)
- (port nil)
- (post-body "")
- (request
- (twittering-add-application-header-to-http-request
- (twittering-make-http-request "GET" headers host port path
- parameters post-body
- twittering-use-ssl)
- account-info-alist))
- (additional-info
- `((account-info . ,account-info-alist)
- ,@additional-info)))
- (twittering-send-http-request request additional-info
- sentinel clean-up-sentinel)))
-
-(defun twittering-http-get-default-sentinel (proc status connection-info header-info)
- (let ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info)))
- (format
- (twittering-get-content-subtype-symbol-from-header-info header-info)))
- (case-string
- status-code
- (("200")
- (debug-printf "connection-info=%s" connection-info)
- (let* ((spec (cdr (assq 'timeline-spec connection-info)))
- (spec-string (cdr (assq 'timeline-spec-string connection-info)))
- (service-method (cdr (assq 'service-method connection-info)))
- (statuses
- (cond
- ((eq format 'json)
- (let ((json-array (twittering-json-read)))
- (cond
- ((null json-array)
- nil)
- ((eq (car spec) 'search)
- (cond
- ((memq service-method '(twitter statusnet))
- (mapcar 'twittering-json-object-to-a-status-on-search
- (cdr (assq 'results json-array))))
- ((eq service-method 'twitter-api-v1.1)
- (mapcar 'twittering-json-object-to-a-status
- (cdr (assq 'statuses json-array))))))
- ((twittering-timeline-spec-is-direct-messages-p spec)
- (mapcar
- 'twittering-json-object-to-a-status-on-direct-messages
- json-array))
- (t
- (mapcar 'twittering-json-object-to-a-status
- json-array)))))
- ((eq format 'xml)
- (let ((xmltree
- (twittering-xml-parse-region (point-min) (point-max))))
- (when xmltree
- (twittering-xmltree-to-status xmltree))))
- ((eq format 'atom)
- (let ((xmltree
- (twittering-xml-parse-region (point-min) (point-max))))
- (when xmltree
- (twittering-atom-xmltree-to-status xmltree))))
- (t
- nil)))
- (rendered-tweets nil))
- (let ((updated-timeline-info
- (twittering-add-statuses-to-timeline-data statuses spec))
- (buffer (twittering-get-buffer-from-spec spec)))
- ;; FIXME: We should retrieve un-retrieved statuses until
- ;; statuses is nil. twitter server returns nil as
- ;; xmltree with HTTP status-code is "200" when we
- ;; retrieved all un-retrieved statuses.
- (if twittering-notify-successful-http-get
- (if updated-timeline-info
- (concat
- (format "Fetching %s. Success. " spec-string)
- (mapconcat
- (lambda (info)
- (let ((spec-string (nth 0 info))
- (num (nth 1 info)))
- (format "%s: +%d" spec-string num)))
- updated-timeline-info
- ", "))
- (format "Fetching %s. Success. (No new tweets)"
- spec-string))
- nil))))
- (("404")
- ;; The requested resource does not exist.
- (let ((spec (cdr (assq 'timeline-spec connection-info)))
- (spec-string (cdr (assq 'timeline-spec-string connection-info))))
- ;; Remove specs related to the invalid spec from history.
- (mapc
- (lambda (buffer)
- (let ((other-spec (twittering-get-timeline-spec-for-buffer buffer))
- (other-spec-string
- (twittering-get-timeline-spec-string-for-buffer buffer)))
- (when (twittering-timeline-spec-depending-on-p other-spec spec)
- (twittering-remove-timeline-spec-string-from-history
- other-spec-string))))
- (twittering-get-buffer-list)))
- (format "Response: %s"
- (twittering-get-error-message header-info connection-info)))
- (t
- (format "Response: %s"
- (twittering-get-error-message header-info connection-info))))))
-
-(defun twittering-retrieve-single-tweet-sentinel (proc status connection-info header-info)
- (let ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info)))
- (format
- (twittering-get-content-subtype-symbol-from-header-info header-info)))
- (case-string
- status-code
- (("200" "403" "404")
- (debug-printf "connection-info=%s" connection-info)
- (let* ((id (cdr (assq 'id connection-info)))
- (user-screen-name (cdr (assq 'user-screen-name connection-info)))
- (status
- (cond
- ((string= status-code "403")
- ;; Forbidden. Maybe a protected tweet?
- (twittering-make-alist-of-forbidden-tweet id
- user-screen-name))
- ((string= status-code "404")
- ;; The requested resource does not exist.
- (twittering-make-alist-of-non-existent-tweet id
- user-screen-name))
- ((eq format 'json)
- (let ((json-object (twittering-json-read)))
- (twittering-json-object-to-a-status json-object)))
- ((eq format 'xml)
- (let ((xmltree
- (twittering-xml-parse-region (point-min) (point-max))))
- (when xmltree
- (car
- (twittering-xmltree-to-status
- `((statuses nil ,@xmltree)))))))
- (t
- nil))))
- (when status
- (twittering-add-statuses-to-timeline-data `(,status) '(:single))
- (let ((buffer (cdr (assq 'buffer connection-info)))
- (spec (cdr (assq 'timeline-spec connection-info)))
- (prop
- (cdr (assq 'property-to-be-redisplayed connection-info))))
- (cond
- ((null prop)
- ;; The process has been invoked via `twittering-call-api' with
- ;; the command `retrieve-timeline', not the command
- ;; `retrieve-single-tweet' for rendering a replied tweet.
- ;; No special property that specifies regions being re-rendered
- ;; is given.
- (let ((new-statuses `(,status))
- (buffer (twittering-get-buffer-from-spec spec)))
- (when (and new-statuses buffer)
- (twittering-render-timeline buffer new-statuses t))))
- ((and buffer prop (buffer-live-p buffer))
- (twittering-redisplay-status-on-each-buffer buffer prop)
- (with-current-buffer buffer
- (save-excursion
- (let ((buffer-read-only nil))
- (lexical-let ((prop prop))
- (twittering-for-each-property-region
- prop
- (lambda (beg end value)
- ;; Remove the property required no longer.
- (remove-text-properties beg end `(,prop nil))
- (goto-char beg)
- (twittering-render-replied-statuses)))))))))))
- (cond
- ((string= status-code "403")
- (format "You are not authorized to see this tweet (ID %s)." id))
- ((string= status-code "404")
- (format "The tweet with ID %s does not exist." id))
- (twittering-notify-successful-http-get
- (format "Fetching %s. Success." id))
- (t
- nil))))
- (t
- (format "Response: %s"
- (twittering-get-error-message header-info connection-info))))))
-
-(defmacro twittering-http-get-list-sentinel-base (what)
- `(let ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info)))
- (format
- (twittering-get-content-subtype-symbol-from-header-info header-info))
- (indexes nil)
- (mes nil))
- (case-string
- status-code
- (("200")
- (cond
- ((eq format 'xml)
- (let ((xmltree (twittering-xml-parse-region (point-min) (point-max))))
- (when xmltree
- (setq indexes
- (mapcar
- (lambda (c-node)
- (caddr (assq ,what c-node)))
- (remove nil
- (mapcar
- (lambda (node)
- (and (consp node) (eq 'list (car node))
- node))
- (cdr-safe
- (assq 'lists (assq 'lists_list xmltree))))
- ))
- ))))
- ((eq format 'json)
- (let* ((json-object (twittering-json-read))
- (json-list
- (cond
- ((arrayp json-object)
- ;; GET lists/list in the Twitter REST API v1.1 returns
- ;; an array.
- json-object)
- (t
- ;; GET lists/subscriptions in the Twitter REST API v1.1
- ;; returns an alist.
- (cdr (assq 'lists json-object))))))
- (when json-object
- (setq indexes
- (mapcar (lambda (entry)
- (cdr (assq ,what entry)))
- json-list)))))
- (t
- (error "Format \"%s\" is not supported" format)
- nil)))
- (t
- (setq mes (format "Response: %s"
- (twittering-get-error-message header-info
- connection-info)))))
- (setq twittering-list-index-retrieved
- (or indexes
- mes
- "")) ;; set "" explicitly if user does not have a list.
- mes))
-
-(defun twittering-http-get-list-index-sentinel (proc status connection-info header-info)
- (twittering-http-get-list-sentinel-base 'slug))
-
-(defun twittering-http-get-list-subscriptions-sentinel (proc status connection-info header-info)
- (let ((result (twittering-http-get-list-sentinel-base 'full_name)))
- (when (listp twittering-list-index-retrieved)
- (setq twittering-list-index-retrieved
- (mapcar (lambda (str)
- (and (string-match "\\`@\\(.*\\)\\'" str)
- (match-string 1 str)))
- twittering-list-index-retrieved)))
- result))
-
-(defun twittering-http-post (account-info-alist host method &optional parameters format additional-info sentinel clean-up-sentinel)
- "Send HTTP POST request to api.twitter.com (or search.twitter.com)
-ACCOUNT-INFO-ALIST is an alist used by
-`twittering-add-application-header-to-http-request'.
-The alist made by `((account-info . ,ACCOUNT-INFO-ALIST) ,@ADDITIONAL-INFO)'
-is used as the argument `additional-info' of `twittering-send-http-request'.
-HOST is hostname of remote side, api.twitter.com (or search.twitter.com).
-METHOD must be one of Twitter API method classes
- (statuses, users or direct_messages).
-PARAMETERS is alist of URI parameters.
- ex) ((\"mode\" . \"view\") (\"page\" . \"6\")) => <URI>?mode=view&page=6
-FORMAT is a response data format (\"xml\", \"atom\", \"json\")"
- (let* ((format (or format "xml"))
- (sentinel
- (lexical-let ((sentinel (or sentinel
- 'twittering-http-post-default-sentinel)))
- (lambda (proc status connection-info header-info)
- (twittering-update-server-info connection-info header-info)
- (apply sentinel proc status connection-info header-info nil))))
- (path (concat "/" method "." format))
- (headers nil)
- (port nil)
- (post-body "")
- (request
- (twittering-add-application-header-to-http-request
- (twittering-make-http-request "POST" headers host port path
- parameters post-body
- twittering-use-ssl)
- account-info-alist))
- (additional-info `((account-info . ,account-info-alist)
- ,@additional-info)))
- (twittering-send-http-request request additional-info
- sentinel clean-up-sentinel)))
-
-(defun twittering-http-post-default-sentinel (proc status connection-info header-info)
- (let ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info))))
- (case-string
- status-code
- (("200")
- "Success: Post.")
- (t
- (format "Response: %s"
- (twittering-get-error-message header-info connection-info))))))
-
-(defun twittering-http-post-destroy-status-sentinel (proc status connection-info header-info)
- "A sentinel for deleting a status invoked via `twittering-call-api'."
- (let ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info)))
- (format
- (twittering-get-content-subtype-symbol-from-header-info header-info)))
- (case-string
- status-code
- (("200")
- (let* ((params
- (cond
- ((eq format 'xml)
- (let ((xml
- (twittering-xml-parse-region (point-min) (point-max))))
- `((id . ,(elt (assq 'id (assq 'status xml)) 2))
- (text . ,(elt (assq 'text (assq 'status xml)) 2)))))
- ((eq format 'json)
- (let ((json-object (twittering-json-read)))
- `((id . ,(cdr (assq 'id_str json-object)))
- (text . ,(cdr (assq 'text json-object))))))
- (t
- (error "Format \"%s\" is not supported" format)
- nil)))
- (id (cdr (assq 'id params)))
- (text (cdr (assq 'text params))))
- (cond
- (id
- (twittering-delete-status-from-data-table id)
- (format "Deleting \"%s\". Success." text))
- (t
- "Failure: the response for deletion could not be parsed."))))
- (t
- (format "Response: %s"
- (twittering-get-error-message header-info connection-info))))))
-
-;;;;
-;;;; OAuth
-;;;;
-
-(defun twittering-oauth-url-encode (str &optional coding-system)
- "Encode string according to Percent-Encoding defined in RFC 3986."
- (let ((coding-system (or (when (and coding-system
- (coding-system-p coding-system))
- coding-system)
- 'utf-8)))
- (mapconcat
- (lambda (c)
- (cond
- ((or (and (<= ?A c) (<= c ?Z))
- (and (<= ?a c) (<= c ?z))
- (and (<= ?0 c) (<= c ?9))
- (eq ?. c)
- (eq ?- c)
- (eq ?_ c)
- (eq ?~ c))
- (char-to-string c))
- (t (format "%%%02X" c))))
- (encode-coding-string str coding-system)
- "")))
-
-(defun twittering-oauth-unhex (c)
- (cond
- ((and (<= ?0 c) (<= c ?9))
- (- c ?0))
- ((and (<= ?A c) (<= c ?F))
- (+ 10 (- c ?A)))
- ((and (<= ?a c) (<= c ?f))
- (+ 10 (- c ?a)))
- ))
-
-(defun twittering-oauth-url-decode (str &optional coding-system)
- (let* ((coding-system (or (when (and coding-system
- (coding-system-p coding-system))
- coding-system)
- 'utf-8))
- (substr-list (split-string str "%"))
- (head (car substr-list))
- (tail (cdr substr-list)))
- (decode-coding-string
- (concat
- head
- (mapconcat
- (lambda (substr)
- (if (string-match "\\`\\([0-9a-fA-F]\\)\\([0-9a-fA-F]\\)\\(.*\\)\\'"
- substr)
- (let* ((c1 (string-to-char (match-string 1 substr)))
- (c0 (string-to-char (match-string 2 substr)))
- (tail (match-string 3 substr))
- (ch (+ (* 16 (twittering-oauth-unhex c1))
- (twittering-oauth-unhex c0))))
- (concat (char-to-string ch) tail))
- substr))
- tail
- ""))
- coding-system)))
-
-(defun twittering-oauth-make-signature-base-string (method base-url parameters)
- ;; "OAuth Core 1.0a"
- ;; http://oauth.net/core/1.0a/#anchor13
- (let* ((sorted-parameters (copy-sequence parameters))
- (sorted-parameters
- (sort sorted-parameters
- (lambda (entry1 entry2)
- (string< (car entry1) (car entry2))))))
- (concat
- method
- "&"
- (twittering-oauth-url-encode base-url)
- "&"
- (mapconcat
- (lambda (entry)
- (let ((key (car entry))
- (value (cdr entry)))
- (concat (twittering-oauth-url-encode key)
- "%3D"
- (twittering-oauth-url-encode value))))
- sorted-parameters
- "%26"))))
-
-(defun twittering-oauth-make-random-string (len)
- (let* ((table
- (concat
- "0123456789"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"))
- (n (length table))
- (l 0)
- (result (make-string len ?0)))
- (while (< l len)
- (aset result l (aref table (random n)))
- (setq l (1+ l)))
- result))
-
-(defun twittering-sha1 (&rest args)
- "Return the SHA1 (Secure Hash Algorithm) of an object.
-
-This is equivalent to the function `sha1' except that
-`coding-system-for-read' and `coding-system-for-write' are bound to the
-symbol `binary'.
-
-The function `sha1' uses an external program for large object. However,
-the coding system for transferring data from/to the program is not fixed,
-at least in the implementation distributed with GNU Emacs 21.4.1, 22.2.1
-and 23.2.1.
-Therefore, the result from the function `sha1' may depend on the current
-coding system.
-
-This function avoid the dependency by binding `coding-system-for-read' and
-`coding-system-for-write' to the symbol `binary'."
- (require 'sha1)
- (let ((coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (apply 'sha1 args)))
-
-;;;
-;;; The below function is derived from `hmac-sha1' retrieved
-;;; from http://www.emacswiki.org/emacs/HmacShaOne.
-;;;
-(defun twittering-hmac-sha1 (key message)
- "Return an HMAC-SHA1 authentication code for KEY and MESSAGE.
-
-KEY and MESSAGE must be unibyte strings. The result is a unibyte
-string. Use the function `encode-hex-string' or the function
-`base64-encode-string' to produce human-readable output.
-
-See URL:<http://en.wikipedia.org/wiki/HMAC> for more information
-on the HMAC-SHA1 algorithm.
-
-The Emacs multibyte representation actually uses a series of
-8-bit values under the hood, so we could have allowed multibyte
-strings as arguments. However, internal 8-bit values don't
-correspond to any external representation \(at least for major
-version 22). This makes multibyte strings useless for generating
-hashes.
-
-Instead, callers must explicitly pick and use an encoding for
-their multibyte data. Most callers will want to use UTF-8
-encoding, which we can generate as follows:
-
- (let ((unibyte-key (encode-coding-string key 'utf-8 t))
- (unibyte-value (encode-coding-string value 'utf-8 t)))
- (twittering-hmac-sha1 unibyte-key unibyte-value))
-
-For keys and values that are already unibyte, the
-`encode-coding-string' calls just return the same string."
-;;; Return an HMAC-SHA1 authentication code for KEY and MESSAGE.
-;;;
-;;; KEY and MESSAGE must be unibyte strings. The result is a unibyte
-;;; string. Use the function `encode-hex-string' or the function
-;;; `base64-encode-string' to produce human-readable output.
-;;;
-;;; See URL:<http://en.wikipedia.org/wiki/HMAC> for more information
-;;; on the HMAC-SHA1 algorithm.
-;;;
-;;; The Emacs multibyte representation actually uses a series of
-;;; 8-bit values under the hood, so we could have allowed multibyte
-;;; strings as arguments. However, internal 8-bit values don't
-;;; correspond to any external representation \(at least for major
-;;; version 22). This makes multibyte strings useless for generating
-;;; hashes.
-;;;
-;;; Instead, callers must explicitly pick and use an encoding for
-;;; their multibyte data. Most callers will want to use UTF-8
-;;; encoding, which we can generate as follows:
-;;;
-;;; (let ((unibyte-key (encode-coding-string key 'utf-8 t))
-;;; (unibyte-value (encode-coding-string value 'utf-8 t)))
-;;; (hmac-sha1 unibyte-key unibyte-value))
-;;;
-;;; For keys and values that are already unibyte, the
-;;; `encode-coding-string' calls just return the same string.
-;;;
-;;; Author: Derek Upham - sand (at) blarg.net
-;;;
-;;; Copyright: This code is in the public domain.
- (require 'sha1)
- (when (multibyte-string-p key)
- (error "key must be unibyte"))
- (when (multibyte-string-p message)
- (error "message must be unibyte"))
-
- ;; The key block is always exactly the block size of the hash
- ;; algorithm. If the key is too small, we pad it with zeroes (or
- ;; instead, we initialize the key block with zeroes and copy the
- ;; key onto the nulls). If the key is too large, we run it
- ;; through the hash algorithm and use the hashed value (strange
- ;; but true).
-
- (let ((+hmac-sha1-block-size-bytes+ 64)) ; SHA-1 uses 512-bit blocks
- (when (< +hmac-sha1-block-size-bytes+ (length key))
- (setq key (twittering-sha1 key nil nil t)))
-
- (let ((key-block (make-vector +hmac-sha1-block-size-bytes+ 0)))
- (dotimes (i (length key))
- (aset key-block i (aref key i)))
-
- (let ((opad (make-vector +hmac-sha1-block-size-bytes+ #x5c))
- (ipad (make-vector +hmac-sha1-block-size-bytes+ #x36)))
-
- (dotimes (i +hmac-sha1-block-size-bytes+)
- (aset ipad i (logxor (aref ipad i) (aref key-block i)))
- (aset opad i (logxor (aref opad i) (aref key-block i))))
-
- (when (fboundp 'unibyte-string)
- ;; `concat' of Emacs23 (and later?) generates a multi-byte
- ;; string from a vector of characters with eight bit.
- ;; Since `opad' and `ipad' must be unibyte, we have to
- ;; convert them by using `unibyte-string'.
- ;; We cannot use `string-as-unibyte' here because it encodes
- ;; bytes with the manner of UTF-8.
- (setq opad (apply 'unibyte-string (mapcar 'identity opad)))
- (setq ipad (apply 'unibyte-string (mapcar 'identity ipad))))
-
- (twittering-sha1 (concat opad
- (twittering-sha1 (concat ipad message)
- nil nil t))
- nil nil t)))))
-
-(defun twittering-oauth-auth-str (method base-url query-parameters oauth-parameters key)
- "Generate the value for HTTP Authorization header on OAuth.
-QUERY-PARAMETERS is an alist for query parameters, where name and value
-must be encoded into the same as they will be sent."
- (let* ((parameters (append query-parameters oauth-parameters))
- (base-string
- (twittering-oauth-make-signature-base-string method base-url parameters))
- (key (if (multibyte-string-p key)
- (string-make-unibyte key)
- key))
- (base-string (if (multibyte-string-p base-string)
- (string-make-unibyte base-string)
- base-string))
- (signature
- (base64-encode-string (twittering-hmac-sha1 key base-string))))
- (concat
- "OAuth "
- (mapconcat
- (lambda (entry)
- (concat (car entry) "=\"" (cdr entry) "\""))
- oauth-parameters
- ",")
- ",oauth_signature=\"" (twittering-oauth-url-encode signature) "\"")))
-
-(defun twittering-oauth-auth-str-request-token (url query-parameters consumer-key consumer-secret &optional oauth-parameters)
- (let ((key (concat consumer-secret "&"))
- (oauth-params
- (or oauth-parameters
- `(("oauth_nonce" . ,(twittering-oauth-make-random-string 43))
- ("oauth_callback" . "oob")
- ("oauth_signature_method" . "HMAC-SHA1")
- ("oauth_timestamp" . ,(format-time-string "%s"))
- ("oauth_consumer_key" . ,consumer-key)
- ("oauth_version" . "1.0")))))
- (twittering-oauth-auth-str "POST" url query-parameters oauth-params key)))
-
-(defun twittering-oauth-auth-str-exchange-token (url query-parameters consumer-key consumer-secret request-token request-token-secret verifier &optional oauth-parameters)
- (let ((key (concat consumer-secret "&" request-token-secret))
- (oauth-params
- (or oauth-parameters
- `(("oauth_consumer_key" . ,consumer-key)
- ("oauth_nonce" . ,(twittering-oauth-make-random-string 43))
- ("oauth_signature_method" . "HMAC-SHA1")
- ("oauth_timestamp" . ,(format-time-string "%s"))
- ("oauth_version" . "1.0")
- ("oauth_token" . ,request-token)
- ("oauth_verifier" . ,verifier)))))
- (twittering-oauth-auth-str "POST" url query-parameters oauth-params key)))
-
-(defun twittering-oauth-auth-str-access (method url query-parameters consumer-key consumer-secret access-token access-token-secret &optional oauth-parameters)
- "Generate a string for Authorization in HTTP header on OAuth.
-METHOD means HTTP method such as \"GET\", \"POST\", etc. URL means a simple
-URL without port number and query parameters.
-QUERY-PARAMETERS means an alist of query parameters such as
-'((\"status\" . \"test%20tweet\")
- (\"in_reply_to_status_id\" . \"12345678\")),
-where name and value must be encoded into the same as they will be sent.
-CONSUMER-KEY and CONSUMER-SECRET specifies the consumer.
-ACCESS-TOKEN and ACCESS-TOKEN-SECRET must be authorized before calling this
-function."
- (let ((key (concat consumer-secret "&" access-token-secret))
- (oauth-params
- (or oauth-parameters
- `(("oauth_consumer_key" . ,consumer-key)
- ("oauth_nonce" . ,(twittering-oauth-make-random-string 43))
- ("oauth_signature_method" . "HMAC-SHA1")
- ("oauth_timestamp" . ,(format-time-string "%s"))
- ("oauth_version" . "1.0")
- ("oauth_token" . ,access-token)))))
- (twittering-oauth-auth-str method url query-parameters oauth-params key)))
-
-;; "Using xAuth | dev.twitter.com"
-;; http://dev.twitter.com/pages/xauth
-(defun twittering-xauth-auth-str-access-token (url query-parameters consumer-key consumer-secret username password &optional oauth-parameters)
- (let ((key (concat consumer-secret "&"))
- (oauth-params
- (or oauth-parameters
- `(("oauth_nonce" . ,(twittering-oauth-make-random-string 43))
- ("oauth_signature_method" . "HMAC-SHA1")
- ("oauth_timestamp" . ,(format-time-string "%s"))
- ("oauth_consumer_key" . ,consumer-key)
- ("oauth_version" . "1.0"))))
- (query-params
- (append query-parameters
- `(("x_auth_mode" . "client_auth")
- ("x_auth_password"
- . ,(twittering-oauth-url-encode password))
- ("x_auth_username"
- . ,(twittering-oauth-url-encode username))))))
- (twittering-oauth-auth-str "POST" url query-params oauth-params key)))
-
-;; "OAuth Core 1.0a"
-;; http://oauth.net/core/1.0a/#response_parameters
-(defun twittering-oauth-make-response-alist (str)
- (mapcar
- (lambda (entry)
- (let* ((pair (split-string entry "="))
- (name-entry (car pair))
- (value-entry (cadr pair))
- (name (and name-entry (twittering-oauth-url-decode name-entry)))
- (value (and value-entry
- (twittering-oauth-url-decode value-entry))))
- `(,name . ,value)))
- (split-string str "&")))
-
-(defun twittering-oauth-get-response-alist (buffer)
- (with-current-buffer buffer
- (goto-char (point-min))
- (when (search-forward-regexp
- "\\`\\(\\(HTTP/1\.[01]\\) \\([0-9][0-9][0-9]\\) \\(.*?\\)\\)\r?\n"
- nil t)
- (let ((status-line (match-string 1))
- (http-version (match-string 2))
- (status-code (match-string 3))
- (reason-phrase (match-string 4)))
- (cond
- ((not (string-match "2[0-9][0-9]" status-code))
- (message "Response: %s" status-line)
- nil)
- ((search-forward-regexp "\r?\n\r?\n" nil t)
- (let ((beg (match-end 0))
- (end (point-max)))
- (twittering-oauth-make-response-alist (buffer-substring beg end))))
- (t
- (message "Response: %s" status-line)
- nil))))))
-
-(defun twittering-oauth-get-token-alist-url (url auth-str post-body)
- (let* ((url-request-method "POST")
- (url-request-extra-headers
- `(("Authorization" . ,auth-str)
- ("Accept-Charset" . "us-ascii")
- ("Content-Type" . "application/x-www-form-urlencoded")
- ("Content-Length" . ,(format "%d" (length post-body)))))
- (url-request-data post-body)
- (coding-system-for-read 'utf-8-unix))
- (lexical-let ((result 'queried))
- (let ((buffer
- (url-retrieve
- url
- (lambda (&rest args)
- (let* ((status (if (< 21 emacs-major-version)
- (car args)
- nil))
- (callback-args (if (< 21 emacs-major-version)
- (cdr args)
- args))
- (response-buffer (current-buffer)))
- (setq result
- (twittering-oauth-get-response-alist response-buffer))
- )))))
- (while (eq result 'queried)
- (sit-for 0.1))
- (unless twittering-debug-mode
- (kill-buffer buffer))
- result))))
-
-(defun twittering-oauth-get-token-alist (url auth-str &optional post-body)
- (let ((request
- (twittering-make-http-request-from-uri
- "POST"
- `(("Authorization" . ,auth-str)
- ("Accept-Charset" . "us-ascii")
- ("Content-Type" . "application/x-www-form-urlencoded"))
- url post-body)))
- (lexical-let ((result 'queried))
- (let ((proc
- (twittering-send-http-request
- request nil
- (lambda (proc status connection-info header-info)
- (let ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info))))
- (case-string
- status-code
- (("200")
- (when twittering-debug-mode
- (let ((buffer (current-buffer)))
- (with-current-buffer (twittering-debug-buffer)
- (insert-buffer-substring buffer))))
- (setq result
- (twittering-oauth-make-response-alist
- (buffer-string)))
- nil)
- (t
- (setq result nil)
- (format "Response: %s" status-line)))))
- (lambda (proc status connection-info)
- (when (and (not (twittering-process-alive-p proc))
- (eq result 'queried))
- (setq result nil))))))
- (twittering-wait-while nil 0.1
- (and (eq result 'queried)
- (twittering-process-alive-p proc)))
- (when (and (eq result 'queried)
- (not (twittering-process-alive-p proc)))
- ;; If the process has been dead, wait a moment because
- ;; Emacs may be in the middle of evaluating the sentinel.
- (twittering-wait-while 10 0.1
- (eq result 'queried)
- nil
- (setq result nil)))
- result))))
-
-(defun twittering-oauth-get-request-token (url consumer-key consumer-secret)
- (let ((auth-str
- (twittering-oauth-auth-str-request-token
- url nil consumer-key consumer-secret)))
- (twittering-oauth-get-token-alist url auth-str)))
-
-(defun twittering-oauth-exchange-request-token (url consumer-key consumer-secret request-token request-token-secret verifier)
- (let ((auth-str
- (twittering-oauth-auth-str-exchange-token
- url nil
- consumer-key consumer-secret
- request-token request-token-secret verifier)))
- (twittering-oauth-get-token-alist url auth-str)))
-
-(defun twittering-oauth-get-access-token (request-token-url authorize-url-func access-token-url consumer-key consumer-secret consumer-name)
- "Return an alist of authorized access token.
-The function retrieves a request token from the site specified by
-REQUEST-TOKEN-URL. Then, The function asks a WWW browser to authorize the
-token by calling `browse-url'. The URL for authorization is calculated by
-calling AUTHORIZE-URL-FUNC with the request token as an argument.
-AUTHORIZE-URL-FUNC is called as `(funcal AUTHORIZE-URL-FUNC request-token)',
-where the request-token is a string.
-After calling `browse-url', the function waits for user to input the PIN code
-that is displayed in the browser. The request token is authorized by the
-PIN code, and then it is exchanged for the access token on the site
-specified by ACCESS-TOKEN-URL.
-CONSUMER-KEY and CONSUMER-SECRET specify the consumer.
-CONSUMER-NAME is displayed at the guide of authorization.
-
-The access token is returned as a list of a cons pair of name and value
-like following:
- ((\"oauth_token\"
- . \"819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw\")
- (\"oauth_token_secret\"
- . \"J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA\")
- (\"user_id\" . \"819797\")
- (\"screen_name\" . \"episod\"))
-."
- (let* ((request-token-alist
- (twittering-oauth-get-request-token
- request-token-url consumer-key consumer-secret))
- (request-token (cdr (assoc "oauth_token" request-token-alist)))
- (request-token-secret
- (cdr (assoc "oauth_token_secret" request-token-alist)))
- (authorize-url (funcall authorize-url-func request-token))
- (str
- (concat
- (propertize "Authorization via OAuth\n" 'face 'bold)
- "\n"
- "1.Allow access by " consumer-name " on the below site.\n"
- "\n "
- (propertize authorize-url 'url authorize-url 'face 'bold)
- "\n"
- "\n"
- (when twittering-oauth-invoke-browser
- (concat
- " Emacs invokes your browser by the function `browse-url'.\n"
- " If the site is not opened automatically, you have to open\n"
- " the site manually.\n"
- "\n"))
- "2.After allowing access, the site will display the PIN code."
- "\n"
- " Input the PIN code "
- (propertize "at the below minibuffer." 'face 'bold))))
- (cond
- (request-token-alist
- (with-temp-buffer
- (switch-to-buffer (current-buffer))
- (let* ((str-height (length (split-string str "\n")))
- (height (max 0 (- (/ (- (window-text-height) 1) 2)
- (/ str-height 2)))))
- (insert (make-string height ?\n) str)
- (if twittering-oauth-invoke-browser
- (browse-url authorize-url)
- (when (y-or-n-p "Open authorization URL with browser? (using `browse-url')")
- (browse-url authorize-url)))
- (let* ((pin
- (block pin-input-block
- (while t
- (let ((pin-input (read-string "Input PIN code: ")))
- (when (string-match "^\\s-*\\([0-9]+\\)\\s-*$" pin-input)
- (return-from pin-input-block
- (match-string 1 pin-input)))))))
- (verifier pin))
- (twittering-oauth-exchange-request-token
- access-token-url
- consumer-key consumer-secret
- request-token request-token-secret verifier)))))
- (t
- (error "Failed to retrieve a request token")
- nil))))
-
-(defun twittering-xauth-get-access-token (access-token-url consumer-key consumer-secret username password)
- (let ((auth-str
- (twittering-xauth-auth-str-access-token
- access-token-url nil consumer-key consumer-secret
- username password))
- (post-body
- (mapconcat (lambda (pair)
- (format "%s=%s" (car pair)
- (twittering-oauth-url-encode (cdr pair))))
- `(("x_auth_mode" . "client_auth")
- ("x_auth_password" . ,password)
- ("x_auth_username" . ,username))
- "&")))
- (twittering-oauth-get-token-alist access-token-url auth-str post-body)))
-
-;;;;
-;;;; Private storage
-;;;;
-
-(defun twittering-private-info-loaded-p ()
- twittering-private-info-file-loaded)
-
-(defun twittering-load-private-info ()
- (let* ((file twittering-private-info-file)
- (decrypted-str (twittering-read-from-encrypted-file file))
- (loaded-alist
- (when decrypted-str
- (condition-case nil
- (read decrypted-str)
- (error
- nil)))))
- (when loaded-alist
- (remove
- nil
- (mapcar
- (lambda (pair)
- (when (consp pair)
- (let ((sym (car pair))
- (value (cdr pair)))
- (cond
- ((memq sym twittering-variables-stored-with-encryption)
- (set sym value)
- sym)
- (t
- nil)))))
- loaded-alist)))))
-
-(defun twittering-load-private-info-with-guide ()
- (let ((str (concat
- "Loading authorized access token for OAuth from\n"
- (format "%s.\n" twittering-private-info-file)
- "\n"
- (propertize "Please input the master password.\n" 'face 'bold)
- "\n"
- "To cancel it, you may need to press C-g multiple times.\n"
- )))
- (with-temp-buffer
- (switch-to-buffer (current-buffer))
- (let* ((str-height (length (split-string str "\n")))
- (height (max 0 (- (/ (- (window-text-height) 1) 2)
- (/ str-height 2)))))
- (insert (make-string height ?\n) str)
- (set-buffer-modified-p nil)
- (twittering-load-private-info)))))
-
-(defun twittering-save-private-info ()
- (let* ((obj (mapcar (lambda (sym)
- `(,sym . ,(symbol-value sym)))
- twittering-variables-stored-with-encryption))
- (str (with-output-to-string (pp obj)))
- (file twittering-private-info-file))
- (when (twittering-write-and-encrypt file str)
- (set-file-modes file #o600)
- (setq twittering-private-info-file-loaded t))))
-
-(defun twittering-save-private-info-with-guide ()
- (let ((str (concat
- "Saving authorized access token for OAuth to "
- (format "%s.\n" twittering-private-info-file)
- "\n"
- (propertize "Please input a master password twice."
- 'face 'bold))))
- (with-temp-buffer
- (switch-to-buffer (current-buffer))
- (let* ((str-height (length (split-string str "\n")))
- (height (max 0 (- (/ (- (window-text-height) 1) 2)
- (/ str-height 2)))))
- (insert (make-string height ?\n) str)
- (set-buffer-modified-p nil)
- (twittering-save-private-info)))))
-
-(defun twittering-capable-of-encryption-p ()
- (and (or (require 'epa nil t) (require 'alpaca nil t))
- (executable-find "gpg")))
-
-(eval-when-compile
- (require 'epa nil t)
- (require 'alpaca nil t))
-(defun twittering-read-from-encrypted-file (file)
- "Decrypt contents from FILE and return them.
-Read encrypted contents from FILE and return the decrypted contents.
-This function requires `epa' or `alpaca' library."
- (cond
- ((not (file-readable-p file))
- (error "Failed to read %s" file)
- nil)
- ((require 'epa nil t)
- (let ((context (epg-make-context epa-protocol))
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (epg-context-set-passphrase-callback
- context #'epa-passphrase-callback-function)
- (epg-context-set-progress-callback
- context
- (cons #'epa-progress-callback-function
- (format "Decrypting %s..." (file-name-nondirectory file))))
- (message "Decrypting %s..." (file-name-nondirectory file))
- (condition-case err
- (let ((full-path (expand-file-name file)))
- ;; `epg-decrypt-file' included in EasyPG 1.0.0, which is
- ;; distributed with Emacs 23.2, requires the expanded full path
- ;; as the argument CIPHER. This is because CIPHER is directly
- ;; used as an argument of the command `gpg'.
- (epg-decrypt-file context full-path nil))
- (error
- (message "%s" (cdr err))
- nil))))
- ((require 'alpaca nil t)
- (with-temp-buffer
- (let ((buffer-file-name (expand-file-name file))
- (alpaca-regex-suffix ".*")
- (coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- (temp-buffer (current-buffer))
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (insert-file-contents-literally file)
- (set-buffer-modified-p nil)
- (condition-case nil
- (progn
- (alpaca-after-find-file)
- (if (eq temp-buffer (current-buffer))
- (buffer-string)
- ;; `alpaca-after-find-file' kills the current buffer
- ;; if the decryption is failed.
- nil))
- (error
- (when (eq temp-buffer (current-buffer))
- (delete-region (point-min) (point-max)))
- nil)))))
- (t
- nil)))
-
-(defun twittering-write-and-encrypt (file str)
- (cond
- ((require 'epg nil t)
- (let ((context (epg-make-context epa-protocol))
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (epg-context-set-passphrase-callback
- context #'epa-passphrase-callback-function)
- (epg-context-set-progress-callback
- context (cons #'epa-progress-callback-function "Encrypting..."))
- (message "Encrypting...")
- (condition-case err
- (unwind-protect
- ;; In order to prevent `epa-file' to encrypt the file double,
- ;; `epa-file-name-regexp' is temorarily changed into the null
- ;; regexp that never matches any string.
- (let ((epa-file-name-regexp "\\`\\'")
- (coding-system-for-read 'binary)
- (coding-system-for-write 'binary))
- (when (fboundp 'epa-file-name-regexp-update)
- (epa-file-name-regexp-update))
- (with-temp-file file
- (set-buffer-multibyte nil)
- (delete-region (point-min) (point-max))
- (insert (epg-encrypt-string context str nil))
- (message "Encrypting...wrote %s" file)
- t))
- (when (fboundp 'epa-file-name-regexp-update)
- (epa-file-name-regexp-update)))
- (error
- (message "%s" (cdr err))
- nil))))
- ((require 'alpaca nil t)
- ;; Create the file.
- ;; This is required because `alpaca-save-buffer' checks its timestamp.
- (with-temp-file file)
- (with-temp-buffer
- (let ((buffer-file-name file)
- (coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (insert str)
- (condition-case nil
- (if (alpaca-save-buffer)
- t
- (delete-file file)
- nil)
- (error
- (when (file-exists-p file)
- (delete-file file))
- nil)))))
- (t
- nil)))
-
-(defun twittering-ensure-private-info ()
- "Ensure that private information is loaded if necessary.
-Return non-nil if `twittering-use-master-password' is nil or private
-information has been already loaded. Also, return non-nil
-if `twittering-use-master-password' is non-nil and this function succeeded
-in loading private information.
-Return nil if private information cannot be loaded."
- (if (or (not twittering-use-master-password)
- (twittering-private-info-loaded-p))
- ;; The private information is unnecessary or already loaded.
- t
- (cond
- ((not (twittering-capable-of-encryption-p))
- (message "You need GnuPG and (EasyPG or alpaca.el) for master password!")
- nil)
- ((and (memq twittering-auth-method '(oauth xauth))
- (file-exists-p twittering-private-info-file))
- (cond
- ((twittering-load-private-info-with-guide)
- (setq twittering-private-info-file-loaded t)
- (message "The authorized token is loaded.")
- t)
- (t
- (message "Failed to load an authorized token from \"%s\"."
- twittering-private-info-file)
- nil)))
- (t
- ;; The file for private infomation does not exist now.
- t))))
-
-;;;;
-;;;; Asynchronous retrieval
-;;;;
-
-(defvar twittering-url-data-hash (make-hash-table :test 'equal))
-(defvar twittering-url-request-list nil)
-(defvar twittering-url-request-sentinel-hash (make-hash-table :test 'equal))
-(defvar twittering-internal-url-queue nil)
-(defvar twittering-url-request-resolving-p nil)
-(defvar twittering-url-request-retry-limit 3)
-(defvar twittering-url-request-sentinel-delay 1.0
- "*Delay from completing retrieval to invoking associated sentinels.
-Sentinels registered by `twittering-url-retrieve-async' will be invoked
-after retrieval is completed and Emacs remains idle a certain time, which
-this variable specifies. The unit is second.")
-
-(defun twittering-remove-redundant-queries (queue)
- (remove nil
- (mapcar
- (lambda (url)
- (let ((current (gethash url twittering-url-data-hash)))
- (when (or (null current)
- (and (integerp current)
- (< current twittering-url-request-retry-limit)))
- url)))
- (twittering-remove-duplicates queue))))
-
-(defun twittering-resolve-url-request ()
- "Resolve requests of asynchronous URL retrieval."
- (when (null twittering-url-request-resolving-p)
- (setq twittering-url-request-resolving-p t)
- ;; It is assumed that the following part is not processed
- ;; in parallel.
- (setq twittering-internal-url-queue
- (append twittering-internal-url-queue twittering-url-request-list))
- (setq twittering-url-request-list nil)
- (setq twittering-internal-url-queue
- (twittering-remove-redundant-queries twittering-internal-url-queue))
- (if (null twittering-internal-url-queue)
- (setq twittering-url-request-resolving-p nil)
- (let* ((url (car twittering-internal-url-queue))
- (request (twittering-make-http-request-from-uri "GET" nil url))
- (additional-info `((uri . ,url))))
- (twittering-send-http-request
- request additional-info
- 'twittering-url-retrieve-async-sentinel
- 'twittering-url-retrieve-async-clean-up-sentinel)))))
-
-(defun twittering-url-retrieve-async-sentinel (proc status connection-info header-info)
- (let ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info)))
- (uri (cdr (assq 'uri (assq 'request connection-info)))))
- (when (string= status-code "200")
- (let ((body (string-as-unibyte (buffer-string))))
- (puthash uri body twittering-url-data-hash)
- (setq twittering-internal-url-queue
- (remove uri twittering-internal-url-queue))
- (let ((sentinels (gethash uri twittering-url-request-sentinel-hash)))
- (when sentinels
- (remhash uri twittering-url-request-sentinel-hash))
- (twittering-run-on-idle twittering-url-request-sentinel-delay
- (lambda (sentinels uri body)
- (mapc (lambda (func)
- (funcall func uri body))
- sentinels)
- ;; Resolve the rest of requests.
- (setq twittering-url-request-resolving-p
- nil)
- (twittering-resolve-url-request))
- sentinels uri body)
- ;; Without the following nil, it seems that the value of
- ;; `sentinels' is displayed.
- nil)))))
-
-(defun twittering-url-retrieve-async-clean-up-sentinel (proc status connection-info)
- (when (memq status '(exit signal closed failed))
- (let* ((uri (cdr (assq 'uri connection-info)))
- (current (gethash uri twittering-url-data-hash)))
- (when (or (null current) (integerp current))
- ;; Increment the counter on failure and then retry retrieval.
- (puthash uri (1+ (or current 0)) twittering-url-data-hash)
- (setq twittering-url-request-resolving-p nil)
- (twittering-resolve-url-request)))))
-
-(defun twittering-url-retrieve-async (url &optional sentinel)
- "Retrieve URL asynchronously and call SENTINEL with the retrieved data.
-The request is placed at the last of queries queue. When the data has been
-retrieved and Emacs remains idle a certain time specified by
-`twittering-url-request-sentinel-delay', SENTINEL will be called as
- (funcall SENTINEL URL url-data).
-The retrieved data can be referred as (gethash URL twittering-url-data-hash)."
- (let ((data (gethash url twittering-url-data-hash)))
- (cond
- ((or (null data) (integerp data))
- (add-to-list 'twittering-url-request-list url t)
- (when sentinel
- (let ((current (gethash url twittering-url-request-sentinel-hash)))
- (unless (member sentinel current)
- (puthash url (cons sentinel current)
- twittering-url-request-sentinel-hash))))
- (twittering-resolve-url-request)
- nil)
- (t
- ;; URL has been already retrieved.
- (twittering-run-on-idle twittering-url-request-sentinel-delay
- sentinel url data)
- data))))
-
-;;;;
-;;;; XML parser
-;;;;
-
-(defun twittering-ucs-to-char-internal (code-point)
- ;; Check (featurep 'unicode) is a workaround with navi2ch to avoid
- ;; error "error in process sentinel: Cannot open load file:
- ;; unicode".
- ;;
- ;; Details: navi2ch prior to 1.8.3 (which is currently last release
- ;; version as of 2010-01-18) always define `ucs-to-char' as autoload
- ;; file "unicode(.el)" (which came from Mule-UCS), hence it breaks
- ;; `ucs-to-char' under non Mule-UCS environment. The problem is
- ;; fixed in navi2ch dated 2010-01-16 or later, but not released yet.
- (if (and (featurep 'unicode) (functionp 'ucs-to-char))
- (ucs-to-char code-point)
- ;; Emacs21 have a partial support for UTF-8 text, so it can decode
- ;; only parts of a text with Japanese.
- (decode-char 'ucs code-point)))
-
-(defvar twittering-unicode-replacement-char
- ;; "Unicode Character 'REPLACEMENT CHARACTER' (U+FFFD)"
- (or (twittering-ucs-to-char-internal #xFFFD)
- ??)
- "*Replacement character returned by `twittering-ucs-to-char' when it fails
-to decode a code.")
-
-(defun twittering-ucs-to-char (code-point)
- "Return a character specified by CODE-POINT in Unicode.
-If it fails to decode the code, return `twittering-unicode-replacement-char'."
- (or (twittering-ucs-to-char-internal code-point)
- twittering-unicode-replacement-char))
-
-(defadvice decode-char (after twittering-add-fail-over-to-decode-char)
- (when (null ad-return-value)
- (setq ad-return-value twittering-unicode-replacement-char)))
-
-(defun twittering-xml-parse-region (&rest args)
- "Wrapped `xml-parse-region' in order to avoid decoding errors.
-After activating the advice `twittering-add-fail-over-to-decode-char',
-`xml-parse-region' is called. This prevents `xml-parse-region' from
-exiting abnormally by decoding unknown numeric character reference."
- (let ((activated (ad-is-active 'decode-char)))
- (ad-enable-advice
- 'decode-char 'after 'twittering-add-fail-over-to-decode-char)
- (ad-activate 'decode-char)
- (unwind-protect
- (condition-case err
- (apply 'xml-parse-region args)
- (error
- (message "Failed to parse the retrieved XML.")
- nil))
- (ad-disable-advice 'decode-char 'after
- 'twittering-add-fail-over-to-decode-char)
- (if activated
- (ad-activate 'decode-char)
- (ad-deactivate 'decode-char)))))
-
-;;;;
-;;;; JSON parser with a fallback character
-;;;;
-
-(defconst twittering-surrogate-pair-regexp
- (if (<= 23 emacs-major-version)
- ;; Literal strings such as "\uXXXX" is not allowed in Emacs 21
- ;; and earlier. A character of invalid code point such as U+D800
- ;; is not allowed in Emacs 22.
- ;; To avoid errors caused by literal strings invalid in Emacs 22
- ;; and earlier, the regexp is generated indirectly.
- (format "[%c-%c][%c-%c]"
- (decode-char 'ucs #xd800)
- (decode-char 'ucs #xdbff)
- (decode-char 'ucs #xdc00)
- (decode-char 'ucs #xdfff))
- ;; A regexp that never matches any strings.
- "\\'\\`")
- "Regexp to match a surrogate pair for CESU-8.
-In Emacs 22 and earlier, this variable is initialized by a regexp
-that never matches any string because code points for a surrogate pair,
-from U+D800 to U+DFFF, are invalid.")
-
-(defun twittering-decode-surrogate-pairs-as-cesu-8 (str)
- "Decode surrogate pairs in STR similarly to CESU-8.
-If STR includes surrogate pairs represented by code points from U+D800 to
-U+DFFF, decode them with CESU-8 and return the result.
-
-A character not in the Basic Multilingual Plane is represented by a surrogate
-pair in JSON (RFC4627). This is similar to CESU-8. But the function
-`json-read' in `json.el' does not correctly decode surrogate pairs. Therefore,
-`json-read' may return a string including invalid code points from U+D800 to
-U+DFFF. This function decodes such invalid code points."
- (let ((str str)
- (prev 0)
- (current 0)
- (result ""))
- (while (setq current
- (string-match twittering-surrogate-pair-regexp str prev))
- (let* ((next (match-end 0))
- (decoded-str
- (decode-coding-string
- (mapconcat
- (lambda (c)
- (let* ((code-point (encode-char c 'ucs))
- (b1 (/ code-point #x100))
- (b2 (% code-point #x100)))
- (unibyte-string b1 b2)))
- (match-string 0 str)
- "")
- 'utf-16)))
- (setq result
- (concat result
- (substring str prev current)
- decoded-str))
- (setq prev next)))
- (setq result (concat result (substring str prev)))
- result))
-
-(defadvice json-read-string (after twittering-decode-surrogate-pairs-as-cesu-8)
- (when (<= 23 emacs-major-version)
- (setq ad-return-value
- (twittering-decode-surrogate-pairs-as-cesu-8 ad-return-value))))
-
-(defun twittering-json-read (&rest args)
- "Wrapped `json-read' in order to avoid decoding errors.
-`json-read' is called after activating the advice
-`twittering-add-fail-over-to-decode-char'.
-This prevents `json-read' from exiting abnormally by decoding an unknown
-numeric character reference."
- (let ((activated (ad-is-active 'decode-char))
- (json-activated (ad-is-active 'json-read-string)))
- (ad-enable-advice
- 'decode-char 'after 'twittering-add-fail-over-to-decode-char)
- (ad-activate 'decode-char)
- (ad-enable-advice 'json-read-string 'after
- 'twittering-decode-surrogate-pairs-as-cesu-8)
- (ad-activate 'json-read-string)
- (unwind-protect
- (condition-case err
- (apply 'json-read args)
- (error
- (message "Failed to parse the retrieved JSON.")
- nil))
- (ad-disable-advice 'decode-char 'after
- 'twittering-add-fail-over-to-decode-char)
- (ad-disable-advice 'json-read-string 'after
- 'twittering-decode-surrogate-pairs-as-cesu-8)
- (if activated
- (ad-activate 'decode-char)
- (ad-deactivate 'decode-char))
- (if json-activated
- (ad-activate 'json-read-string)
- (ad-deactivate 'json-read-string))
- )))
-
-;;;;
-;;;; Window configuration
-;;;;
-
-(defun twittering-set-window-end (window pos)
- (let* ((height (window-text-height window))
- (n (- (- height 1))))
- (while (progn (setq n (1+ n))
- (set-window-start
- window
- (with-current-buffer (window-buffer window)
- (save-excursion
- (goto-char pos)
- (line-beginning-position n))))
- (not (pos-visible-in-window-p pos window))))))
-
-(defun twittering-current-window-config (window-list)
- "Return window parameters of WINDOW-LIST."
- (mapcar (lambda (win)
- (let ((start (window-start win))
- (point (window-point win)))
- `(,win ,start ,point)))
- window-list))
-
-(defun twittering-restore-window-config-after-modification (config beg end)
- "Restore window parameters changed by modification on given region.
-CONFIG is window parameters made by `twittering-current-window-config'.
-BEG and END mean a region that had been modified."
- (mapc (lambda (entry)
- (let ((win (elt entry 0))
- (start (elt entry 1))
- (point (elt entry 2)))
- (when (and (< beg start) (< start end))
- (set-window-start win start))
- (when (and (< beg point) (< point end))
- (set-window-point win point))))
- config))
-
-(defun twittering-pop-to-buffer (buf)
- "Select the buffer BUF in some window.
-The behavior is determined by the function specified by
-`twittering-pop-to-buffer-function'."
- (funcall twittering-pop-to-buffer-function buf))
-
-(defun twittering-pop-to-buffer-simple (buf)
- "Select the buffer BUF by using `pop-to-buffer'."
- (let ((win (selected-window)))
- (pop-to-buffer buf)
- ;; This is required because the new window generated by `pop-to-buffer'
- ;; may hide the region following the current position.
- (twittering-ensure-whole-of-status-is-visible win)))
-
-(defun twittering-pop-to-buffer-in-current-window (buf &optional win)
- "Select the buffer BUF in the window WIN by splitting it.
-If WIN is nil, the selected window is splitted."
- (let* ((win (or win (selected-window)))
- (size
- (let ((rest (- (window-height win) 15)))
- (if (<= rest 3)
- ;; To avoid an error due to a too small window.
- nil
- rest)))
- (new-win (split-window win size)))
- (select-window new-win)
- (switch-to-buffer buf)))
-
-(defun twittering-pop-to-buffer-in-largest-window (buf)
- "Select the buffer BUF in the largest window by splitting it."
- (let ((win
- (lexical-let ((max-area 0)
- (largest-win nil))
- (walk-windows
- (lambda (win)
- (let ((area (* (window-height win) (window-width win))))
- (when (< max-area area)
- (setq max-area area)
- (setq largest-win win)))))
- largest-win)))
- (twittering-pop-to-buffer-in-current-window buf win)))
-
-(defun twittering-pop-to-buffer-in-bottom-largest-window (buf)
- "Select the buffer BUF in the window largest on bottom by splitting it."
- (let* ((bottom-win-list
- (lexical-let ((win-list '())
- (max-bottom 0))
- (walk-windows
- (lambda (win)
- (let ((bottom (nth 3 (window-edges win))))
- (cond
- ((< max-bottom bottom)
- (setq max-bottom bottom)
- (setq win-list `(,win)))
- ((= max-bottom bottom)
- (setq win-list (cons win win-list)))
- (t
- nil)))))
- win-list))
- (win
- (lexical-let ((max-area 0)
- (largest-win nil))
- (mapc (lambda (win)
- (let ((area (* (window-height win) (window-width win))))
- (when (< max-area area)
- (setq largest-win win)
- (setq max-area area))))
- bottom-win-list)
- largest-win)))
- (twittering-pop-to-buffer-in-current-window buf win)))
-
-;;;;
-;;;; URI shortening
-;;;;
-
-(defun twittering-tinyurl-get (longurl &optional service)
- "Shorten LONGURL with the service specified by `twittering-tinyurl-service'."
- (let* ((service (or service twittering-tinyurl-service))
- (api (cdr (assq service twittering-tinyurl-services-map)))
- (request-generator (when (listp api) (elt api 0)))
- (post-process (when (listp api) (elt api 1)))
- (encoded-url (twittering-percent-encode longurl))
- (request
- (cond
- ((stringp api)
- (twittering-make-http-request-from-uri
- "GET" nil (concat api encoded-url)))
- ((stringp request-generator)
- (twittering-make-http-request-from-uri
- "GET" nil (concat request-generator encoded-url)))
- ((functionp request-generator)
- (funcall request-generator service longurl))
- (t
- (error "%s is invalid. try one of %s"
- (symbol-name service)
- (mapconcat (lambda (x) (symbol-name (car x)))
- twittering-tinyurl-services-map ", "))
- nil)))
- (additional-info `((longurl . ,longurl))))
- (cond
- ((null request)
- (error "Failed to generate a HTTP request for shortening %s with %s"
- longurl (symbol-name service))
- nil)
- (t
- (lexical-let ((result 'queried))
- (let ((proc
- (twittering-send-http-request
- request additional-info
- (lambda (proc status connection-info header-info)
- (let ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info))))
- (case-string
- status-code
- (("200")
- (setq result (buffer-string))
- nil)
- (t
- (setq result nil)
- (format "Response: %s" status-line)))))
- (lambda (proc status connection-info)
- (when (and (not (twittering-process-alive-p proc))
- (eq result 'queried))
- (setq result nil))))))
- (twittering-wait-while nil 0.1
- (and (eq result 'queried)
- (twittering-process-alive-p proc)))
- (when (and (eq result 'queried)
- (not (twittering-process-alive-p proc)))
- ;; If the process has been dead, wait a moment because
- ;; Emacs may be in the middle of evaluating the sentinel.
- (twittering-wait-while 10 0.1
- (eq result 'queried)
- nil
- ;; Reset `result' on timeout.
- (setq result nil))))
- (let ((processed-result (if (and result (functionp post-process))
- (funcall post-process service result)
- result)))
- (if processed-result
- processed-result
- (error "Failed to shorten a URL %s with %s"
- longurl (symbol-name service))
- nil)))))))
-
-(defun twittering-tinyurl-replace-at-point ()
- "Replace the url at point with a tiny version."
- (interactive)
- (let ((url-bounds (bounds-of-thing-at-point 'url)))
- (when url-bounds
- (let ((url (twittering-tinyurl-get (thing-at-point 'url))))
- (when url
- (save-restriction
- (narrow-to-region (car url-bounds) (cdr url-bounds))
- (delete-region (point-min) (point-max))
- (insert url)))))))
-
-(defun twittering-make-http-request-for-bitly (service longurl)
- "Make a HTTP request for URL shortening service bit.ly or j.mp.
-Before calling this, you have to configure `twittering-bitly-login' and
-`twittering-bitly-api-key'."
- (let* ((query-string
- (mapconcat
- (lambda (entry)
- (concat (car entry) "=" (cdr entry)))
- `(("login" . ,twittering-bitly-login)
- ("apiKey" . ,twittering-bitly-api-key)
- ("format" . "txt")
- ("longUrl" . ,(twittering-percent-encode longurl)))
- "&"))
- (prefix
- (cdr (assq service '((bit.ly . "http://api.bit.ly/v3/shorten?")
- (j.mp . "http://api.j.mp/v3/shorten?")))))
- (uri (concat prefix query-string)))
- (twittering-make-http-request-from-uri "GET" nil uri)))
-
-;;;;
-;;;; Timeline spec
-;;;;
-
-;;; Timeline spec as S-expression
-;;; - (user USER): timeline of the user whose name is USER. USER is a string.
-;;; - (list USER LIST):
-;;; the list LIST of the user USER. LIST and USER are strings.
-;;;
-;;; - (direct_messages): received direct messages.
-;;; - (direct_messages_sent): sent direct messages.
-;;; - (favorites): favorites timeline for the current user.
-;;; - (favorites USER): favorites timeline for the specified user.
-;;; - (friends): friends timeline.
-;;; - (home): home timeline.
-;;; - (mentions): mentions timeline.
-;;; mentions (status containing @username) for the authenticating user.
-;;; - (public): public timeline.
-;;; - (replies): replies.
-;;; - (retweeted_by_me): retweets posted by the authenticating user.
-;;; - (retweeted_by_user USER): retweets posted by the user.
-;;; - (retweeted_to_me): retweets posted by the authenticating user's friends.
-;;; - (retweeted_to_user USER): retweets posted to the user.
-;;; - (retweets_of_me):
-;;; tweets of the authenticated user that have been retweeted by others.
-;;; - (single ID): the single tweet specified by ID.
-;;;
-;;; - (search STRING): the result of searching with query STRING.
-;;;
-;;; - (exclude-if FUNC SPEC):
-;;; the same timeline as SPEC, except that it does not include tweets
-;;; that FUNC returns non-nil for.
-;;; - (exclude-re REGEXP-STRING SPEC):
-;;; the same timeline as SPEC, except that it does not include tweets
-;;; that matches the regular expression specified by REGEXP-STRING.
-;;;
-;;; - (merge SPEC1 SPEC2 ...): result of merging timelines SPEC1 SPEC2 ...
-;;;
-
-;;; Timeline spec string
-;;;
-;;; SPEC ::= PRIMARY | COMPOSITE
-;;; PRIMARY ::= USER | LIST | DIRECT_MESSSAGES | DIRECT_MESSSAGES_SENT
-;;; | FRIENDS | HOME | MENTIONS | PUBLIC | REPLIES
-;;; | RETWEETED_BY_ME | RETWEETED_BY_USER
-;;; | RETWEETED_TO_ME | RETWEETED_TO_USER | RETWEETS_OF_ME
-;;; | SEARCH
-;;; COMPOSITE ::= EXCLUDE-IF | EXCLUDE-RE | MERGE
-;;;
-;;; USER ::= /[a-zA-Z0-9_-]+/
-;;; LIST ::= USER "/" LISTNAME
-;;; LISTNAME ::= /[a-zA-Z0-9_-]+/
-;;; DIRECT_MESSSAGES ::= ":direct_messages"
-;;; DIRECT_MESSSAGES_SENT ::= ":direct_messages_sent"
-;;; FAVORITES ::= ":favorites" | ":favorites/" USER
-;;; FRIENDS ::= ":friends"
-;;; HOME ::= ":home" | "~"
-;;; MENTIONS ::= ":mentions"
-;;; PUBLIC ::= ":public"
-;;; REPLIES ::= ":replies" | "@"
-;;; RETWEETED_BY_ME ::= ":retweeted_by_me"
-;;; RETWEETED_BY_USER ::= ":retweeted_by_user/" USER
-;;; RETWEETED_TO_ME ::= ":retweeted_to_me"
-;;; RETWEETED_TO_USER ::= ":retweeted_to_user/" USER
-;;; RETWEETS_OF_ME ::= ":retweets_of_me"
-;;; SINGLE ::= ":single/" ID
-;;; ID ::= /[0-9]+/
-;;;
-;;; SEARCH ::= ":search/" QUERY_STRING "/"
-;;; QUERY_STRING ::= any string, where "/" is escaped by a backslash.
-;;;
-;;; EXCLUDE-IF ::= ":exclude-if/" FUNC "/" SPEC
-;;; FUNC ::= LAMBDA EXPRESSION | SYMBOL
-;;; EXCLUDE-RE ::= ":exclude-re/" REGEXP "/" SPEC
-;;;
-;;; MERGE ::= "(" MERGED_SPECS ")"
-;;; MERGED_SPECS ::= SPEC | SPEC "+" MERGED_SPECS
-;;;
-
-(defvar twittering-regexp-hash
- (let ((full-width-number-sign (twittering-ucs-to-char #xff03)))
- ;; Unicode Character 'FULLWIDTH NUMBER SIGN' (U+FF03)
- (concat "\\(?:#\\|" (char-to-string full-width-number-sign) "\\)")))
-
-(defvar twittering-regexp-atmark
- (let ((full-width-commercial-at (twittering-ucs-to-char #xff20)))
- ;; Unicode Character 'FULLWIDTH COMMERCIAL AT' (U+FF20)
- (concat "\\(?:@\\|" (char-to-string full-width-commercial-at) "\\)")))
-
-(defun twittering-timeline-spec-to-string (timeline-spec &optional shorten)
- "Convert TIMELINE-SPEC into a string.
-If SHORTEN is non-nil, the abbreviated expression will be used."
- (let ((type (car timeline-spec))
- (value (cdr timeline-spec)))
- (cond
- ;; user
- ((eq type 'user) (car value))
- ;; list
- ((eq type 'list) (concat (car value) "/" (cadr value)))
- ;; simple
- ((eq type 'direct_messages) ":direct_messages")
- ((eq type 'direct_messages_sent) ":direct_messages_sent")
- ((eq type 'favorites)
- (if value
- (concat ":favorites/" (car value))
- ":favorites"))
- ((eq type 'friends) ":friends")
- ((eq type 'home) (if shorten "~" ":home"))
- ((eq type 'mentions) ":mentions")
- ((eq type 'public) ":public")
- ((eq type 'replies) (if shorten "@" ":replies"))
- ((eq type 'retweeted_by_me) ":retweeted_by_me")
- ((eq type 'retweeted_by_user) (concat ":retweeted_by_user/" (car value)))
- ((eq type 'retweeted_to_me) ":retweeted_to_me")
- ((eq type 'retweeted_to_user) (concat ":retweeted_to_user/" (car value)))
- ((eq type 'retweets_of_me) ":retweets_of_me")
- ((eq type 'single) (concat ":single/" (car value)))
- ((eq type 'search)
- (let ((query (car value)))
- (concat ":search/"
- (replace-regexp-in-string "\\(\\\\\\|/\\)" "\\\\\\1" query)
- "/")))
- ;; composite
- ((eq type 'exclude-if)
- (let ((func (car value))
- (spec (cadr value))
- (print-level nil))
- (concat ":exclude-if/" (prin1-to-string func) "/"
- (twittering-timeline-spec-to-string spec))))
- ((eq type 'exclude-re)
- (let ((regexp-str (car value))
- (spec (cadr value))
- (print-level nil))
- (concat ":exclude-re/"
- (replace-regexp-in-string "/" "\\\\\/" regexp-str)
- "/"
- (twittering-timeline-spec-to-string spec))))
- ((eq type 'merge)
- (concat "("
- (mapconcat 'twittering-timeline-spec-to-string value "+")
- ")"))
- (t
- nil))))
-
-(eval-and-compile
- (defmacro twittering-make-user-timeline-spec-direct (user)
- `(list 'user ,user))
- (defmacro twittering-make-list-timeline-spec-direct (owner listname)
- `(list 'list ,owner ,listname))
- (defmacro twittering-make-hashtag-timeline-spec-direct (tag)
- `(list 'search (concat "#" ,tag)))
- (defmacro twittering-make-hashtag-timeline-spec-string-direct (tag)
- `(concat "#" ,tag)))
-
-(defun twittering-extract-timeline-spec (str &optional unresolved-aliases)
- "Extract one timeline spec from STR.
-Return cons of the spec and the rest string."
- (cond
- ((null str)
- (error "STR is nil")
- nil)
- ((string-match "^\\([a-zA-Z0-9_-]+\\)/\\([[:word:]_-]+\\)" str)
- (let ((user (match-string 1 str))
- (listname (match-string 2 str))
- (rest (substring str (match-end 0))))
- `(,(twittering-make-list-timeline-spec-direct user listname) . ,rest)))
- ((string-match "^\\([a-zA-Z0-9_-]+\\)" str)
- (let ((user (match-string 1 str))
- (rest (substring str (match-end 0))))
- `(,(twittering-make-user-timeline-spec-direct user) . ,rest)))
- ((string-match "^~" str)
- `((home) . ,(substring str (match-end 0))))
- ((string-match (concat "^" twittering-regexp-atmark) str)
- `((mentions) . ,(substring str (match-end 0))))
- ((string-match (concat "^" twittering-regexp-hash "\\([[:alpha:]0-9_-]+\\)")
- str)
- (let* ((tag (match-string 1 str))
- (rest (substring str (match-end 0))))
- `(,(twittering-make-hashtag-timeline-spec-direct tag) . ,rest)))
- ((string-match "^:\\([a-z_-]+\\)" str)
- (let ((type (match-string 1 str))
- (following (substring str (match-end 0)))
- (alist '(("direct_messages" . direct_messages)
- ("direct_messages_sent" . direct_messages_sent)
- ("friends" . friends)
- ("home" . home)
- ("mentions" . mentions)
- ("public" . public)
- ("replies" . replies)
- ("retweeted_by_me" . retweeted_by_me)
- ("retweeted_to_me" . retweeted_to_me)
- ("retweets_of_me" . retweets_of_me))))
- (cond
- ((assoc type alist)
- (let ((first-spec (list (cdr (assoc type alist)))))
- (cons first-spec following)))
- ((string= type "favorites")
- (if (string-match "^:favorites/\\([a-zA-Z0-9_-]+\\)" str)
- (let ((rest (substring str (match-end 0))))
- `((favorites ,(match-string 1 str)) . ,rest))
- `((favorites) . ,following)))
- ((string-match "^:retweeted_by_user/\\([a-zA-Z0-9_-]+\\)" str)
- (let ((user (match-string 1 str))
- (rest (substring str (match-end 0))))
- `((retweeted_by_user ,user) . ,rest)))
- ((string-match "^:retweeted_to_user/\\([a-zA-Z0-9_-]+\\)" str)
- (let ((user (match-string 1 str))
- (rest (substring str (match-end 0))))
- `((retweeted_to_user ,user) . ,rest)))
- ((string-match "^:single/\\([0-9]+\\)" str)
- (let ((id (match-string 1 str))
- (rest (substring str (match-end 0))))
- `((single ,id) . ,rest)))
- ((string= type "search")
- (if (string-match "^:search/\\(\\(.*?[^\\]\\)??\\(\\\\\\\\\\)*\\)??/"
- str)
- (let* ((escaped-query (or (match-string 1 str) ""))
- (query (replace-regexp-in-string "\\\\\\(\\\\\\|/\\)" "\\1"
- escaped-query))
- (rest (substring str (match-end 0))))
- (if (not (string= "" escaped-query))
- `((search ,query) . ,rest)
- (error "\"%s\" has no valid regexp" str)
- nil))))
- ((string= type "exclude-if")
- (let ((result-pair
- (cond
- ((string-match "^:exclude-if/\\([^(/]+\\)/" str)
- `(,(intern (match-string 1 str)) . ,(match-end 1)))
- ((string-match "^:exclude-if/" str)
- (condition-case err
- (read-from-string str (match-end 0))
- (error
- nil))))))
- (if result-pair
- (let ((func (car result-pair))
- (pos (cdr result-pair)))
- (cond
- ((not (functionp func))
- (error "\"%s\" has an invalid function" str)
- nil)
- ((<= (length str) (1+ pos))
- (error "\"%s\" has no timeline spec" str)
- nil)
- ((not (char-equal ?/ (aref str pos)))
- (error "\"%s\" has no delimiter" str)
- nil)
- (t
- (let* ((pair (twittering-extract-timeline-spec
- (substring str (1+ pos)) unresolved-aliases))
- (spec (car pair))
- (rest (cdr pair)))
- `((exclude-if ,func ,spec) . ,rest)))))
- (error "\"%s\" has an invalid function" str)
- nil)))
- ((string= type "exclude-re")
- (cond
- ((string-match "^:exclude-re/\\(\\(.*?[^\\]\\)??\\(\\\\\\\\\\)*\\)??/"
- str)
- (let* ((escaped-regexp (or (match-string 1 str) ""))
- (regexp
- (replace-regexp-in-string "\\\\/" "/" escaped-regexp nil t))
- (following (substring str (match-end 0))))
- (cond
- ((string= "" escaped-regexp)
- (error "\"%s\" has no valid regexp" str)
- nil)
- (t
- (let* ((pair (twittering-extract-timeline-spec
- following unresolved-aliases))
- (spec (car pair))
- (rest (cdr pair)))
- `((exclude-re ,regexp ,spec) . ,rest))))))
- (t
- (error "\"%s\" has no valid regexp" str)
- nil)))
- (t
- (error "\"%s\" is invalid as a timeline spec" str)
- nil))))
- ((string-match "^\\$\\([a-zA-Z0-9_-]+\\)\\(?:(\\([^)]*\\))\\)?" str)
- (let* ((name (match-string 1 str))
- (rest (substring str (match-end 0)))
- (value (cdr-safe (assoc name twittering-timeline-spec-alias)))
- (arg (match-string 2 str)))
- (if (member name unresolved-aliases)
- (error "Alias \"%s\" includes a recursive reference" name)
- (cond
- ((stringp value)
- (twittering-extract-timeline-spec
- (concat value rest)
- (cons name unresolved-aliases)))
- ((functionp value)
- (twittering-extract-timeline-spec
- (funcall value arg)
- (cons name unresolved-aliases)))
- (t
- (error "Alias \"%s\" is undefined" name))))))
- ((string-match "^(" str)
- (let ((rest (concat "+" (substring str (match-end 0))))
- (result '()))
- (while (and rest (string-match "^\\+" rest))
- (let* ((spec-string (substring rest (match-end 0)))
- (pair (twittering-extract-timeline-spec
- spec-string unresolved-aliases))
- (spec (car pair))
- (next-rest (cdr pair)))
- (setq result (cons spec result))
- (setq rest next-rest)))
- (if (and rest (string-match "^)" rest))
- (let ((spec-list
- (twittering-remove-duplicates
- (apply 'append
- (mapcar (lambda (x) (if (eq 'merge (car x))
- (cdr x)
- (list x)))
- (reverse result))))))
- (if (= 1 (length spec-list))
- `(,(car spec-list) . ,(substring rest 1))
- `((merge ,@spec-list) . ,(substring rest 1))))
- (if rest
- ;; The string following the opening parenthesis `('
- ;; can be interpreted without errors,
- ;; but there is no corresponding closing parenthesis.
- (error "\"%s\" lacks a closing parenthesis" str))
- ;; Does not display additional error messages if an error
- ;; occurred on interpreting the string following
- ;; the opening parenthesis `('.
- nil)))
- (t
- (error "\"%s\" is invalid as a timeline spec" str)
- nil)
- ))
-
-(defun twittering-string-to-timeline-spec (spec-str &optional noerror)
- "Convert SPEC-STR into a timeline spec.
-If SPEC-STR is invalid as a timeline spec string, raise an error or return
-nil if NOERROR is non-nil."
- (let ((result-pair
- (condition-case err
- (twittering-extract-timeline-spec spec-str)
- (error
- (if noerror
- nil
- (signal (car err) (cdr err))
- nil)))))
- (if (and result-pair (string= "" (cdr result-pair)))
- (car result-pair)
- nil)))
-
-(defun twittering-timeline-spec-primary-p (spec)
- "Return non-nil if SPEC is a primary timeline spec.
-`primary' means that the spec is not a composite timeline spec such as
-`merge'."
- (let ((primary-spec-types
- '(user list
- direct_messages direct_messages_sent
- favorites friends home mentions public replies
- search
- retweeted_by_me retweeted_by_user
- retweeted_to_me retweeted_to_user
- retweets_of_me
- single))
- (type (car spec)))
- (memq type primary-spec-types)))
-
-(defun twittering-timeline-spec-composite-p (spec)
- "Return non-nil if SPEC is a composite timeline spec.
-`composite' means that the spec depends on other timelines."
- (let ((composite-spec-types
- '(exclude-if exclude-re merge))
- (type (car spec)))
- (memq type composite-spec-types)))
-
-(defun twittering-timeline-spec-depending-on-p (spec base-spec)
- "Return non-nil if SPEC depends on BASE-SPEC."
- (cond
- ((twittering-timeline-spec-primary-p spec)
- (equal spec base-spec))
- ((equal spec base-spec)
- t)
- (t
- (remove
- nil
- (mapcar
- (lambda (direct-base-spec)
- (twittering-timeline-spec-depending-on-p direct-base-spec base-spec))
- (twittering-get-base-timeline-specs spec))))))
-
-(defun twittering-timeline-spec-is-user-p (spec)
- "Return non-nil if SPEC is a user timeline."
- (and (consp spec) (eq 'user (car spec))))
-
-(defun twittering-timeline-spec-is-direct-messages-p (spec)
- "Return non-nil if SPEC is a timeline spec which is related of
-direct_messages."
- (and spec
- (memq (car spec) '(direct_messages direct_messages_sent))))
-
-(defun twittering-timeline-spec-is-search-p (spec)
- "Return non-nil if SPEC is a search timeline spec."
- (and (consp spec)
- (eq 'search (car spec))))
-
-(defun twittering-extract-query-string-from-search-timeline-spec (spec)
- "Return the query string if SPEC is a search timeline spec.
-If SPEC is not a search timeline spec, return nil."
- (and (eq 'search (car spec))
- (cadr spec)))
-
-(defun twittering-equal-string-as-timeline (spec-str1 spec-str2)
- "Return non-nil if SPEC-STR1 equals SPEC-STR2 as a timeline spec.
-If either SPEC-STR1 or SPEC-STR2 is invalid as a timeline spec string,
-return nil."
- (if (and (stringp spec-str1) (stringp spec-str2))
- (let ((spec1 (twittering-string-to-timeline-spec spec-str1 t))
- (spec2 (twittering-string-to-timeline-spec spec-str2 t)))
- (equal spec1 spec2))
- nil))
-
-(defun twittering-get-base-timeline-specs (spec)
- "Return the timeline specs on which the timeline SPEC depends.
-If SPEC is primary, returns a list consisting of itself.
-The result timelines may be a composite timeline."
- (let ((type (car spec)))
- (cond
- ((twittering-timeline-spec-primary-p spec)
- `(,spec))
- ((memq type '(exclude-if exclude-re))
- `(,(elt spec 2)))
- ((eq type 'merge)
- (cdr spec))
- (t
- nil))))
-
-(defun twittering-get-primary-base-timeline-specs (spec)
- "Return the primary timeline specs on which the timeline SPEC depends.
-If SPEC is primary, returns a list consisting of itself.
-The result timelines are primary."
- (if (twittering-timeline-spec-primary-p spec)
- `(,spec)
- (twittering-remove-duplicates
- (apply 'append
- (mapcar 'twittering-get-primary-base-timeline-specs
- (twittering-get-base-timeline-specs spec))))))
-
-(defun twittering-get-dependent-timeline-specs (base-spec)
- "Return a list of timeline specs that depend on BASE-SPEC.
-If BASE-SPEC is a primary timeline spec, the return value consists of
-BASE-SPEC and composite timeline specs that depend on BASE-SPEC and are
-bound to a live buffer.
-If BASE-SPEC is a composite timeline spec, the return value consists of
-composite timeline specs that depend on BASE-SPEC and are bound to a live
-buffer."
- (twittering-remove-duplicates
- `(;; BASE-SPEC may not be bound to a live buffer.
- ,@(when (twittering-timeline-spec-primary-p base-spec)
- `(,base-spec))
- ,@(remove
- nil
- (mapcar
- (lambda (spec)
- (when (twittering-timeline-spec-depending-on-p spec base-spec)
- spec))
- (mapcar 'twittering-get-timeline-spec-for-buffer
- (twittering-get-buffer-list)))))))
-
-(defun twittering-generate-composite-timeline (spec base-spec base-statuses)
- "Generate statuses for the timeline SPEC from BASE-STATUSES.
-BASE-STATUSES must originate from the BASE-SPEC timeline.
-If SPEC is a primary timeline and equals BASE-SPEC, just return BASE-STATUSES.
-If SPEC is a primary timeline and does not equal BASE-SPEC, return nil."
- (let ((type (car spec)))
- (cond
- ((twittering-timeline-spec-primary-p spec)
- (if (equal spec base-spec)
- base-statuses
- nil))
- ((eq type 'exclude-if)
- (let* ((direct-base (car (twittering-get-base-timeline-specs spec)))
- (direct-base-statuses
- (twittering-generate-composite-timeline direct-base
- base-spec base-statuses))
- (func (elt spec 1)))
- (remove nil
- (mapcar (lambda (status)
- (unless (funcall func status)
- status))
- direct-base-statuses))))
- ((eq type 'exclude-re)
- (let* ((direct-base (car (twittering-get-base-timeline-specs spec)))
- (direct-base-statuses
- (twittering-generate-composite-timeline direct-base
- base-spec base-statuses))
- (regexp (elt spec 1)))
- (remove nil
- (mapcar
- (lambda (status)
- (unless (string-match regexp (cdr (assq 'text status)))
- status))
- direct-base-statuses))))
- ((eq type 'merge)
- (sort
- (apply 'append
- (mapcar (lambda (direct-base-spec)
- ;; `copy-sequence' is required because `sort'
- ;; modifies the appended list that may include
- ;; `base-statuses' as a tail.
- ;; `base-statuses' may refer to the original list
- ;; which already retrieved tweets are registered
- ;; with. It must not be modified.
- (copy-sequence
- (twittering-generate-composite-timeline
- direct-base-spec base-spec base-statuses)))
- (twittering-get-base-timeline-specs spec)))
- (lambda (status1 status2)
- (let ((id1 (cdr (assq 'id status1)))
- (id2 (cdr (assq 'id status2))))
- (twittering-status-id< id2 id1)))))
- (t
- nil))))
-
-;;;;
-;;;; Retrieved statuses (timeline data)
-;;;;
-
-(defun twittering-current-timeline-id-table (&optional spec)
- (let ((spec (or spec (twittering-current-timeline-spec))))
- (if spec
- (elt (gethash spec twittering-timeline-data-table) 0)
- nil)))
-
-(defun twittering-current-timeline-referring-id-table (&optional spec)
- "Return the hash from a ID to the ID of the first observed status
-referring the former ID."
- (let* ((spec (or spec (twittering-current-timeline-spec)))
- (type (car spec)))
- (cond
- ((null spec)
- nil)
- ((memq type '(exclude-if exclude-re merge))
- ;; Use the first non-nil table instead of merging the all tables
- ;; because it may take a long time to merge them.
- (car
- (remove
- nil
- (mapcar (lambda (base-spec)
- (elt (gethash base-spec twittering-timeline-data-table) 1))
- (twittering-get-primary-base-timeline-specs spec)))))
- ((eq type 'single)
- ;; Single tweet timelines are registered in a special way.
- ;; See `twittering-retrieve-single-tweet-sentinel'.
- (elt (gethash '(:single) twittering-timeline-data-table) 1))
- (t
- (elt (gethash spec twittering-timeline-data-table) 1)))))
-
-(defun twittering-current-timeline-data (&optional spec)
- (let* ((spec (or spec (twittering-current-timeline-spec)))
- (type (car spec)))
- (cond
- ((null spec)
- nil)
- ((eq type 'single)
- (let* ((id (cadr spec))
- (status (twittering-find-status id)))
- (if status
- `(,status)
- nil)))
- ((memq type '(exclude-if exclude-re merge))
- (let ((primary-base-specs
- (twittering-get-primary-base-timeline-specs spec)))
- (sort
- (apply
- 'append
- (mapcar
- (lambda (primary-spec)
- ;; `copy-sequence' is required to prevent `sort'
- ;; from modifying lists of statuses in the database
- ;; `twittering-timeline-data-table'.
- ;; The result of `twittering-generate-composite-timeline'
- ;; may include a list in the database. If so, the simply
- ;; appended list include it as a tail.
- (copy-sequence
- (twittering-generate-composite-timeline
- spec
- primary-spec (twittering-current-timeline-data primary-spec))))
- primary-base-specs))
- (lambda (status1 status2)
- (let ((id1 (cdr (assq 'id status1)))
- (id2 (cdr (assq 'id status2))))
- (twittering-status-id< id2 id1))))))
- (t
- (elt (gethash spec twittering-timeline-data-table) 2)))))
-
-(defun twittering-remove-timeline-data (&optional spec)
- (let ((spec (or spec (twittering-current-timeline-spec))))
- (remhash spec twittering-timeline-data-table)))
-
-(defun twittering-find-status (id)
- (let ((result nil))
- (maphash
- (lambda (spec pair)
- (let* ((id-table (car pair))
- (entry (gethash id id-table)))
- ;; Take the most detailed status.
- (when (and entry
- (or (null result) (< (length result) (length entry))))
- (setq result entry))))
- twittering-timeline-data-table)
- result))
-
-(defun twittering-delete-status-from-data-table (id)
- (let ((modified-spec nil))
- (maphash
- (lambda (spec data)
- (let* ((id-table (elt data 0))
- (referring-id-table (elt data 1))
- (timeline-data (elt data 2))
- (status (gethash id id-table)))
- (when status
- (remhash id id-table)
- ;; Here, `referring-id-table' is not modified.
- ;; Therefore, the retweet observed secondly will not appear even
- ;; if the retweet observed first for the same tweet is deleted.
- (setq modified-spec
- (cons `(,spec
- ,id-table
- ,referring-id-table
- ,(remove status timeline-data))
- modified-spec)))))
- twittering-timeline-data-table)
- (mapc
- (lambda (spec)
- (let ((buffer (twittering-get-buffer-from-spec spec)))
- (when (buffer-live-p buffer)
- (with-current-buffer buffer
- (save-excursion
- (twittering-for-each-property-region
- 'id
- (lambda (beg end value)
- (when (twittering-status-id= id value)
- (let ((buffer-read-only nil)
- (separator-pos (min (point-max) (1+ end))))
- (delete-region beg separator-pos)
- (goto-char beg))))
- buffer))))))
- (twittering-remove-duplicates
- (apply 'append
- (mapcar
- (lambda (data)
- (let ((spec (car data)))
- ;; Update the entry for `spec' in
- ;; `twittering-timeline-data-table' with the new
- ;; timeline-data that does not include `status'.
- (puthash spec (cdr data) twittering-timeline-data-table)
- (twittering-get-dependent-timeline-specs spec)))
- modified-spec))))))
-
-(defun twittering-get-replied-statuses (id &optional count)
- "Return a list of replied statuses starting from the status specified by ID.
-Statuses are stored in ascending-order with respect to their IDs."
- (let ((result nil)
- (status (twittering-find-status id)))
- (while
- (and (if (numberp count)
- (<= 0 (setq count (1- count)))
- t)
- (let ((replied-id (or (cdr (assq 'in-reply-to-status-id status))
- "")))
- (unless (string= "" replied-id)
- (let ((replied-status (twittering-find-status replied-id)))
- (when replied-status
- (setq result (cons replied-status result))
- (setq status replied-status)
- t))))))
- result))
-
-(defun twittering-have-replied-statuses-p (id)
- (let ((status (twittering-find-status id)))
- (when status
- (let ((replied-id (cdr (assq 'in-reply-to-status-id status))))
- (and replied-id (not (string= "" replied-id)))))))
-
-(defun twittering-add-statuses-to-timeline-data (statuses &optional spec)
- "Add STATUSES as new statuses for SPEC and update derived timelines.
-The function returns a list of lists including an updated timeline spec
-string and the number of new statuses for the timeline."
- (let* ((spec (or spec (twittering-current-timeline-spec)))
- (id-table
- (or (twittering-current-timeline-id-table spec)
- (make-hash-table :test 'equal)))
- (referring-id-table
- (or (twittering-current-timeline-referring-id-table spec)
- (make-hash-table :test 'equal)))
- (timeline-data (twittering-current-timeline-data spec)))
- (let* ((new-statuses
- (remove nil
- (mapcar
- (lambda (status)
- (let ((id (cdr (assq 'id status)))
- (retweeted-id (cdr (assq 'retweeted-id status))))
- (unless (or (not retweeted-id)
- (gethash retweeted-id referring-id-table))
- ;; Store the id of the first observed tweet
- ;; that refers `retweeted-id'.
- (puthash retweeted-id id referring-id-table))
- (if (gethash id id-table)
- nil
- (puthash id status id-table)
- (puthash id id referring-id-table)
- `((source-spec . ,spec)
- ,@status))))
- statuses)))
- (new-statuses
- ;; Sort tweets by ID.
- ;; This is necessary because `twittering-render-timeline' assumes
- ;; that given tweets are ordered.
- (sort new-statuses
- (lambda (status1 status2)
- (let ((id1 (cdr (assq 'id status1)))
- (id2 (cdr (assq 'id status2))))
- (twittering-status-id< id2 id1))))))
- (when new-statuses
- (let ((new-timeline-data
- (sort (append new-statuses timeline-data)
- (lambda (status1 status2)
- (let ((id1 (cdr (assq 'id status1)))
- (id2 (cdr (assq 'id status2))))
- (twittering-status-id< id2 id1))))))
- (puthash spec `(,id-table ,referring-id-table ,new-timeline-data)
- twittering-timeline-data-table))
- (let ((twittering-new-tweets-spec spec)
- (twittering-new-tweets-statuses new-statuses)
- (twittering-new-tweets-count (length new-statuses)))
- (run-hooks 'twittering-new-tweets-hook)))
- ;; Update timelines derived from SPEC and return the number of
- ;; new tweets for each updated timeline.
- (remove
- nil
- (mapcar
- (lambda (buffer)
- (let ((other-spec (twittering-get-timeline-spec-for-buffer buffer))
- (other-spec-string
- (twittering-get-timeline-spec-string-for-buffer buffer)))
- (when (twittering-timeline-spec-depending-on-p other-spec spec)
- (let* ((twittering-new-tweets-spec other-spec)
- (twittering-new-tweets-statuses
- (twittering-generate-composite-timeline
- other-spec spec new-statuses))
- (twittering-new-tweets-count
- (length twittering-new-tweets-statuses))
- (rendered-tweets
- (twittering-render-timeline
- buffer twittering-new-tweets-statuses t)))
- (when rendered-tweets
- (run-hooks 'twittering-new-tweets-hook)
- `(,other-spec-string ,(length rendered-tweets)))))))
- (twittering-get-buffer-list))))))
-
-;;;;
-;;;; URIs related to a tweet
-;;;;
-
-(defun twittering-get-status-url (username &optional id)
- "Generate a URL of a user or a specific status."
- (let ((func
- (cdr (assq
- 'status-url
- (assq twittering-service-method
- twittering-service-method-table)))))
- (funcall func username id)))
-
-(defun twittering-get-status-url-from-alist (status)
- "Generate a URL of a tweet specified by an alist STATUS."
- (let ((username (cdr (assq 'user-screen-name status)))
- (id (cdr (assq 'id status)))
- (func
- (cdr (assq
- 'status-url
- (assq twittering-service-method
- twittering-service-method-table)))))
- (funcall func username id)))
-
-(defun twittering-get-list-url (username listname)
- "Generate a URL of a specific list."
- (let ((func
- (cdr (assq
- 'status-url
- (assq twittering-service-method
- twittering-service-method-table))))
- (str (concat username "/" listname)))
- (funcall func str nil)))
-
-(defun twittering-get-status-url-twitter (username &optional id)
- "Generate status URL for Twitter."
- (if id
- (format "http://%s/%s/status/%s" twittering-web-host username id)
- (format "http://%s/%s" twittering-web-host username)))
-
-(defun twittering-get-status-url-statusnet (username &optional id)
- "Generate status URL for StatusNet."
- (if id
- (format "http://%s/%s/notice/%s" twittering-web-host twittering-web-path-prefix id)
- (format "http://%s/%s/%s" twittering-web-host twittering-web-path-prefix username)))
-
-(defun twittering-get-search-url (query-string)
- "Generate a URL for searching QUERY-STRING."
- (let ((func (cdr (assq
- 'search-url (assq twittering-service-method
- twittering-service-method-table)))))
- (funcall func query-string)))
-
-(defun twittering-get-search-url-twitter (query-string)
- (format "http://%s/search?q=%s"
- twittering-web-host (twittering-percent-encode query-string)))
-
-(defun twittering-get-search-url-statusnet (query-string)
- (if (string-match "^#\\(.+\\)" query-string)
- (format "http://%s/%s/tag/%s"
- twittering-web-host
- twittering-web-path-prefix
- (twittering-percent-encode (match-string 1 query-string)))
- (format "http://%s/search?q=%s"
- twittering-web-host (twittering-percent-encode query-string))))
-
-(defun twittering-extract-id-from-url (url-string)
- "Extract the ID from URL-STRING.
-Return nil if URL-STRING cannot be interpreted as a URL pointing a tweet."
- (when (string-match
- "\\`https?://twitter.com/\\(?:#!/\\)?[^/]+/status\\(?:es\\)?/\\([0-9]+\\)/?\\'"
- url-string)
- (match-string 1 url-string)))
-
-;;;;
-;;;; Utility of status IDs
-;;;;
-
-(defun twittering-status-id< (id1 id2)
- (let ((len1 (length id1))
- (len2 (length id2)))
- (cond
- ((= len1 len2) (string< id1 id2))
- ((< len1 len2) t)
- (t nil))))
-
-(defun twittering-status-id= (id1 id2)
- (equal id1 id2))
-
-(defun twittering-snowflake-epoch-time ()
- "Return the epoch time of Snowflake."
- (require 'calc)
- (let ((epoch-str
- ;; This corresponds to 2010-11-04 01:42:54+00:00 in RFC3339.
- ;; The value comes from the following page.
- ;; https://github.com/twitter/snowflake/blob/6d4634aa490de26e22425538291fe0a03071a170/src/main/scala/com/twitter/service/snowflake/IdWorker.scala#L22
- ;; 22 val twepoch = 1288834974657L
- "1288834974657"))
- (let ((str
- (calc-eval `(,(concat "floor(10#" epoch-str "/10#1000)")
- calc-word-size 64 calc-number-radix 16)))
- (milisec-str
- (calc-eval `(,(concat "10#" epoch-str "%10#1000")
- calc-word-size 64 calc-number-radix 10))))
- (mapcar (lambda (s) (string-to-number s 16))
- `(,(substring str 3 7) ,(substring str 7)
- ,milisec-str)))))
-
-(defun twittering-id-to-time (id)
- "Return the time corresonding to ID generated by Snowflake.
-If ID is a string consisting of 12 or more digits, return the corresponding
-time in Emacs internal representation the same as `encode-time'.
-Otherwise, return nil.
-
-This is because ID consisting of 11 or less digits may not be generated
-by Snowflake."
- (require 'calc)
- (cond
- ((not (stringp id))
- nil)
- ((< (length id) 12)
- ;; The given ID may not be generated by Snowflake.
- ;;
- ;; The first tweet in the example response of
- ;; https://dev.twitter.com/docs/api/1/get/statuses/home_timeline
- ;; has "18700887835" as the ID.
- ;; Assuming that it is generated by Snowflake, it corresponds to
- ;; "2010-11-04 01:42:58+00:00".
- ;; However, the created_at is "Fri Jul 16 16:58:46 +0000 2010".
- ;; It can be confirmed at http://twitter.com/cindyli/status/18700887835 .
- ;;
- ;; Therefore we can not suppose that an ID is generated by Snowflake
- ;; if the ID consists of 11-digits.
- ;; Assuming that an ID reaches 10^11 before Snowflake is turned on at
- ;; Nov 04 2010, the average number of tweets per day will exceed
- ;; 533 million.
- ;; ( 10^11 - 18,700,887,835 > 80,000,000,000
- ;; 80 billion / 5 month (from Jul 16 to Nov 4) > 533 million / day )
- ;;
- ;; It is impossible.
- ;; So, I assume that an ID is generated by Snowflake if the ID consists of
- ;; 12 or more digits.
- ;; The first ID with 12-digits, 100,000,000,000 (10^11), corresponds to
- ;; 2010-11-04 01:43:17+00:00.
- nil)
- (t
- (let* ((epoch (twittering-snowflake-epoch-time))
- (str (calc-eval
- `(,(format "floor(rsh(10#%s,22)/1000)" id)
- calc-word-size 64 calc-number-radix 16)))
- (milisec
- (string-to-number
- (calc-eval
- `(,(format "rsh(10#%s,22)%%1000" id)
- calc-word-size 64 calc-number-radix 10))
- 10)))
- (when (string-match "^16#\\([[:xdigit:]]+\\)" str)
- (let* ((hex-str (match-string 1 str))
- (hex-str
- (if (< (length hex-str) 4)
- (concat "0000" hex-str)
- hex-str)))
- (time-add epoch
- `(,(string-to-number
- (substring hex-str 0 (- (length hex-str) 4)) 16)
- ,(string-to-number
- (substring hex-str (- (length hex-str) 4)) 16)
- ,(* milisec 1000)
- ))))))))
-
-(defun twittering-time-to-id (time)
- "Return the ID corresponding to TIME by Snowflake.
-Bits other than timestamp are zero. The least significant 22 bits are zero.
-TIME must be an Emacs internal representation as a return value of
-`current-time'."
- (require 'calc)
- (let* ((epoch-time (twittering-snowflake-epoch-time))
- (dt (if (time-less-p epoch-time time)
- (time-subtract time epoch-time)
- nil))
- (sec-high (nth 0 dt))
- (sec-low (nth 1 dt))
- (microsec (or (nth 2 dt) "0")))
- (when dt
- (calc-eval
- `(,(format "lsh((16#%04x%04x) * 1000 + floor(%d/1000), 22)"
- sec-high sec-low microsec)
- calc-word-size 64 calc-number-radix 10)))))
-
-;;;;
-;;;; Process info
-;;;;
-
-(defun twittering-register-process (proc spec &optional str)
- (let ((str (or str (twittering-timeline-spec-to-string spec))))
- (add-to-list 'twittering-process-info-alist `(,proc ,spec ,str))))
-
-(defun twittering-release-process (proc)
- (let ((pair (assoc proc twittering-process-info-alist)))
- (when pair
- (setq twittering-process-info-alist
- (delq pair twittering-process-info-alist)))))
-
-(defun twittering-get-timeline-spec-from-process (proc)
- (let ((entry (assoc proc twittering-process-info-alist)))
- (if entry
- (elt entry 1)
- nil)))
-
-(defun twittering-get-timeline-spec-string-from-process (proc)
- (let ((entry (assoc proc twittering-process-info-alist)))
- (if entry
- (elt entry 2)
- nil)))
-
-(defun twittering-find-processes-for-timeline-spec (spec)
- (apply 'append
- (mapcar
- (lambda (pair)
- (let ((proc (car pair))
- (spec-info (cadr pair)))
- (if (equal spec-info spec)
- `(,proc)
- nil)))
- twittering-process-info-alist)))
-
-(defun twittering-remove-inactive-processes ()
- (let ((inactive-statuses '(nil closed exit failed signal)))
- (setq twittering-process-info-alist
- (apply 'append
- (mapcar
- (lambda (pair)
- (let* ((proc (car pair))
- (info (cdr pair))
- (status (process-status proc)))
- (if (memq status inactive-statuses)
- nil
- `((,proc ,@info)))))
- twittering-process-info-alist)))))
-
-(defun twittering-process-active-p (&optional spec)
- (twittering-remove-inactive-processes)
- (if spec
- (twittering-find-processes-for-timeline-spec spec)
- twittering-process-info-alist))
-
-;;;;
-;;;; Server info
-;;;;
-
-(defun twittering-update-api-table (spec api-string)
- "Register a pair of a timeline spec and an API for retrieving the timeline.
-SPEC is a timeline spec. API-STRING is an identifier of an API for retrieving
-the timeline."
- (let ((current (assoc spec twittering-timeline-spec-to-api-table)))
- (if (null current)
- (add-to-list 'twittering-timeline-spec-to-api-table
- `(,spec . ,api-string))
- (setcdr current api-string))))
-
-(defun twittering-make-rate-limit-alist (header-info)
- "Make a rate-limit information alist from HEADER-INFO.
-Key symbols of a returned alist are following; limit, remaining, reset-time.
-Values bound to limit and remaining is a positive integer and
-one bound to reset-time is an Emacs time (result of `seconds-to-time')."
- (let ((symbol-table
- '(("X-Rate-Limit-Limit" . limit)
- ("X-Rate-Limit-Remaining" . remaining)
- ("X-Rate-Limit-Reset" . reset-time)
- ;; For Twitter API v1.0.
- ("X-RateLimit-Limit" . limit)
- ("X-RateLimit-Remaining" . remaining)
- ("X-RateLimit-Reset" . reset-time))))
- (remove
- nil
- (mapcar (lambda (entry)
- (let ((sym
- (cdr
- (twittering-assoc-string (car entry) symbol-table t))))
- (cond
- ((memq sym '(limit remaining))
- `(,sym . ,(string-to-number (cdr entry))))
- ((eq sym 'reset-time)
- `(,sym
- . ,(seconds-to-time (string-to-number (cdr entry)))))
- (t
- nil))))
- header-info))))
-
-(defun twittering-update-rate-limit-info (api-string spec header-info)
- "Register rate-limit information.
-API-STRING is an identifier of an API. SPEC is a timeline spec that had been
-retrieved by the API. HEADER-INFO is an alist generated from the HTTP response
-header of the API."
- (let* ((api-string
- (if (eq twittering-service-method 'twitter)
- ;; The key for Twitter API v1.0 is nil.
- nil
- api-string))
- (current (assoc api-string twittering-api-limit-info-alist))
- (rate-limit-alist (twittering-make-rate-limit-alist header-info)))
- (twittering-update-api-table spec api-string)
- (if (null current)
- (add-to-list 'twittering-api-limit-info-alist
- `(,api-string . ,rate-limit-alist))
- (setcdr current rate-limit-alist))))
-
-(defun twittering-update-server-info (connection-info header-info)
- (let* ((new-entry-list (mapcar 'car header-info))
- (account-info (cdr (assq 'account-info connection-info)))
- (account
- (twittering-get-from-account-info "screen_name" account-info))
- (spec (cdr (assq 'timeline-spec connection-info)))
- (api-string
- (cdr (assq 'uri-without-query (assq 'request connection-info)))))
- (twittering-update-rate-limit-info api-string spec header-info)
- (when (remove t (mapcar
- (lambda (entry)
- (equal (assoc entry header-info)
- (assoc entry twittering-server-info-alist)))
- new-entry-list))
- (setq twittering-server-info-alist
- (append header-info
- (remove nil (mapcar
- (lambda (entry)
- (if (member (car entry) new-entry-list)
- nil
- entry))
- twittering-server-info-alist))))
- (when twittering-display-remaining
- (mapc (lambda (buffer)
- (with-current-buffer buffer
- (twittering-update-mode-line)))
- (twittering-get-buffer-list))))
- ;; cookie
- (let* ((new-cookies
- (twittering-extract-cookie connection-info header-info))
- (old-cookies (cdr (assoc account twittering-cookie-alist)))
- (updated-cookies
- (append new-cookies
- (remove nil
- (mapcar (lambda (cookie)
- (unless (assoc (car cookie) new-cookies)
- cookie))
- old-cookies)))))
- (setq twittering-cookie-alist
- (cons (cons account updated-cookies)
- (remove nil
- (mapcar (lambda (entry)
- (unless (equal account (car entry))
- entry))
- twittering-cookie-alist)))))
- header-info))
-
-(defun twittering-extract-cookie (connection-info header-info)
- (remove
- nil
- (mapcar
- (lambda (entry)
- (let ((header-item (car entry))
- (header-value (cdr entry)))
- (when (and (string= header-item "Set-Cookie")
- (string-match "\\([^= ]*\\) *= *\\([^; ]*\\) *;? *"
- header-value))
- ;; For ease of implementation, the followings are assumed.
- ;; 1. Each response header includes only one cookie.
- ;; 2. `value' of cookie is a token, not a quoted string.
- ;; 3. Attributes except `domain', `expires' and `path' are ignored.
- (let* ((name (downcase (match-string 1 header-value)))
- (value (match-string 2 header-value))
- (attributes
- (mapcar
- (lambda (str)
- (when (string-match "\\` *\\([^ ]*\\) *= *\\(.*\\)\\'"
- str)
- (let ((attr (downcase (match-string 1 str)))
- (value (match-string 2 str)))
- (cond
- ((string= attr "domain")
- `(domain . ,value))
- ((string= attr "expires")
- `(expires
- . ,(apply 'encode-time
- (parse-time-string
- (replace-regexp-in-string
- "-" " " value)))))
- ((string= attr "path")
- `(path . ,value))
- (t
- nil)))))
- (split-string (substring header-value (match-end 0))
- " *; *")))
- (additional-attributes
- `(,@(let* ((domain (cdr (assq 'domain attributes)))
- (request (cdr (assq 'request connection-info)))
- (host (cdr (assq 'host request)))
- (prefix
- (if domain
- (regexp-quote domain)
- (concat "\\`" (regexp-quote host)))))
- `((domain-regexp . ,(concat prefix "\\'")))))))
- `(,name
- (value . ,value)
- ,@attributes
- ,@additional-attributes)))))
- header-info)))
-
-(defun twittering-make-cookie-string (request account-info)
- (let ((account
- (twittering-get-from-account-info "screen_name" account-info))
- (current-time (current-time))
- (host (cdr (assq 'host request))))
- (when account
- (mapconcat
- 'identity
- (remove nil
- (mapcar
- (lambda (entry)
- (let* ((expires (cdr (assq 'expires entry)))
- (not-expired (or (null expires)
- (time-less-p current-time expires)))
- (domain-regexp (cdr (assq 'domain-regexp entry))))
- (when (and not-expired
- (string-match domain-regexp host))
- (format "%s=%s" (car entry) (cdr (assq 'value entry))))))
- (cdr (assoc account twittering-cookie-alist))))
- ";"))))
-
-(defun twittering-get-ratelimit-alist (&optional spec)
- (let ((api-string
- (cdr (assoc spec twittering-timeline-spec-to-api-table))))
- (cdr (assoc api-string twittering-api-limit-info-alist))))
-
-(defun twittering-get-ratelimit-remaining (&optional spec)
- (or (cdr (assq 'remaining (twittering-get-ratelimit-alist spec)))
- 0))
-
-(defun twittering-get-ratelimit-limit (&optional spec)
- (or (cdr (assq 'limit (twittering-get-ratelimit-alist spec)))
- 0))
-
-(defun twittering-get-ratelimit-indicator-string (&optional spec)
- "Make an indicator string of rate-limit information of SPEC."
- (cond
- ((eq twittering-service-method 'twitter)
- ;; Twitter API v1.0.
- (format "%d/%d"
- (twittering-get-ratelimit-remaining)
- (twittering-get-ratelimit-limit)))
- (t
- (mapconcat
- (lambda (api-string)
- (let* ((alist (cdr (assoc api-string twittering-api-limit-info-alist)))
- (remaining (cdr (assq 'remaining alist)))
- (limit (cdr (assq 'limit alist))))
- (format "%s/%s"
- (if remaining (number-to-string remaining) "?")
- (if limit (number-to-string limit) "?"))))
- (twittering-remove-duplicates
- (mapcar (lambda (spec)
- (cdr (assoc spec twittering-timeline-spec-to-api-table)))
- (twittering-get-primary-base-timeline-specs spec)))
- "+"))))
-
-;;;;
-;;;; Abstract layer for Twitter API
-;;;;
-
-(defun twittering-api-path (&rest params)
- (mapconcat 'identity `(,twittering-api-prefix ,@params) ""))
-
-(defun twittering-call-api (command args-alist &optional additional-info)
- "Call Twitter API and return the process object for the request.
-Invoke `twittering-call-api-with-account' with the main account specified
-by `twittering-get-main-account-info'.
-For details of arguments, see `twittering-call-api-with-account'."
- (let ((account-info-alist (twittering-get-main-account-info)))
- (twittering-call-api-with-account account-info-alist command args-alist
- additional-info)))
-
-(defun twittering-call-api-with-account (account-info-alist command args-alist &optional additional-info)
- "Call Twitter API and return the process object for the request.
-COMMAND is a symbol specifying API. ARGS-ALIST is an alist specifying
-arguments for the API corresponding to COMMAND. Each key of ARGS-ALIST is a
-symbol.
-ACCOUNT-INFO-ALIST is an alist storing account information, which has
-the following key;
-\"screen_name\", \"oauth_token\" and \"oauth_token_secret\" for OAuth/xAuth,
-\"screen_name\" and \"password\" for basic authentication.
-ADDITIONAL-INFO is used as an argument ADDITIONAL-INFO of
-`twittering-send-http-request'. Sentinels associated to the returned process
-receives it as the fourth argument. See also the function
-`twittering-send-http-request'.
-
-The valid symbols as COMMAND follows:
-retrieve-timeline -- Retrieve a timeline.
- Valid key symbols in ARGS-ALIST:
- timeline-spec -- the timeline spec to be retrieved.
- timeline-spec-string -- the string representation of the timeline spec.
- format -- (optional) the symbol specifying the format.
- number -- (optional) how many tweets are retrieved. It must be an integer.
- If nil, `twittering-number-of-tweets-on-retrieval' is used instead.
- The maximum for search timeline is 100, and that for other timelines is
- `twittering-max-number-of-tweets-on-retrieval'.
- If the given number exceeds the maximum, the maximum is used instead.
- max_id -- (optional) the maximum ID of retrieved tweets.
- since_id -- (optional) the minimum ID of retrieved tweets.
- sentinel -- (optional) the sentinel that processes the buffer consisting
- of retrieved data.. This is used as an argument SENTINEL of
- `twittering-send-http-request' via `twittering-http-get'.
- If nil, `twittering-http-get-default-sentinel' is used.
- clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
- the buffer associated to the process. This is used as an argument
- CLEAN-UP-SENTINEL of `twittering-send-http-request' via
- `twittering-http-get'.
- page -- (optional and valid only for favorites timeline) which page will
- be retrieved.
-retrieve-single-tweet -- Retrieve a single tweet.
- Valid key symbols in ARGS-ALIST:
- id -- the ID of the tweet to be retrieved.
- username -- (optional) the screen name of the author of the tweet.
- format -- (optional) the symbol specifying the format.
- sentinel -- (optional) the sentinel that processes the buffer consisting
- of retrieved data.. This is used as an argument SENTINEL of
- `twittering-send-http-request' via `twittering-http-get'.
- If nil, `twittering-http-get-default-sentinel' is used.
- clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
- the buffer associated to the process. This is used as an argument
- CLEAN-UP-SENTINEL of `twittering-send-http-request' via
- `twittering-http-get'.
-get-list-index -- Retrieve list names owned by a user.
- Valid key symbols in ARGS-ALIST:
- username -- the username.
- sentinel -- the sentinel that processes retrieved strings. This is used
- as an argument SENTINEL of `twittering-send-http-request'
- via `twittering-http-get'.
- clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
- the buffer associated to the process. This is used as an argument
- CLEAN-UP-SENTINEL of `twittering-send-http-request' via
- `twittering-http-get'.
-get-list-subscriptions -- Retrieve list names followed by a user.
- Valid key symbols in ARGS-ALIST:
- username -- the username.
- sentinel -- the sentinel that processes retrieved strings. This is used
- as an argument SENTINEL of `twittering-send-http-request'
- via `twittering-http-get'.
- clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
- the buffer associated to the process. This is used as an argument
- CLEAN-UP-SENTINEL of `twittering-send-http-request' via
- `twittering-http-get'.
-create-friendships -- Follow a user.
- Valid key symbols in ARGS-ALIST:
- username -- the username which will be followed.
-destroy-friendships -- Unfollow a user.
- Valid key symbols in ARGS-ALIST:
- username -- the username which will be unfollowed.
-create-favorites -- Mark a tweet as a favorite.
- Valid key symbols in ARGS-ALIST:
- id -- the ID of the target tweet.
-destroy-favorites -- Remove a mark of a tweet as a favorite.
- Valid key symbols in ARGS-ALIST:
- id -- the ID of the target tweet.
-update-status -- Post a tweet.
- Valid key symbols in ARGS-ALIST:
- status -- the string to be posted.
- in-reply-to-status-id -- (optional) the ID of a status that this post is
- in reply to.
-destroy-status -- Destroy a tweet posted by the authenticated user itself.
- Valid key symbols in ARGS-ALIST:
- id -- the ID of the target tweet.
-retweet -- Retweet a tweet.
- Valid key symbols in ARGS-ALIST:
- id -- the ID of the target tweet.
-verify-credentials -- Verify the current credentials.
- Valid key symbols in ARGS-ALIST:
- sentinel -- the sentinel that processes returned information. This is used
- as an argument SENTINEL of `twittering-send-http-request'
- via `twittering-http-get'.
- clean-up-sentinel -- the clean-up sentinel that post-processes the buffer
- associated to the process. This is used as an argument CLEAN-UP-SENTINEL
- of `twittering-send-http-request' via `twittering-http-get'.
-send-direct-message -- Send a direct message.
- Valid key symbols in ARGS-ALIST:
- username -- the username who the message is sent to.
- status -- the sent message.
-block -- Block a user.
- Valid key symbols in ARGS-ALIST:
- user-id -- the user-id that will be blocked.
- username -- the username who will be blocked.
- This command requires either of the above key. If both are given, `user-id'
- will be used in REST API.
-block-and-report-as-spammer -- Block a user and report him or her as a spammer.
- Valid key symbols in ARGS-ALIST:
- user-id -- the user-id that will be blocked.
- username -- the username who will be blocked.
- This command requires either of the above key. If both are given, `user-id'
- will be used in REST API.
-get-service-configuration -- Get the configuration of the server.
- Valid key symbols in ARGS-ALIST:
- sentinel -- the sentinel that processes retrieved strings. This is used
- as an argument SENTINEL of `twittering-send-http-request'.
- clean-up-sentinel -- (optional) the clean-up sentinel that post-processes
- the buffer associated to the process. This is used as an argument
- CLEAN-UP-SENTINEL of `twittering-send-http-request'."
- (let* ((additional-info
- `(,@additional-info
- (service-method . ,twittering-service-method))))
- (cond
- ((memq twittering-service-method '(twitter statusnet))
- (twittering-call-api-with-account-in-api1.0
- account-info-alist command args-alist additional-info))
- ((eq twittering-service-method 'twitter-api-v1.1)
- (cond
- ((not (require 'json nil t))
- (error "`json.el' is required to use the Twitter REST API v1.1")
- nil)
- ((not twittering-use-ssl)
- (error "SSL is required to use the Twitter REST API v1.1")
- nil)
- (t
- (twittering-call-api-with-account-in-api1.1
- account-info-alist command args-alist additional-info))))
- (t
- (error "`twittering-service-method' is an invalid service method")
- ))))
-
-(defun twittering-call-api-with-account-in-api1.0 (account-info-alist command args-alist &optional additional-info)
- "Call the Twitter REST API v1.0 and return the process object for the request."
- (cond
- ((eq command 'retrieve-timeline)
- ;; Retrieve a timeline.
- (let* ((spec (cdr (assq 'timeline-spec args-alist)))
- (spec-string (cdr (assq 'timeline-spec-string args-alist)))
- (spec-type (car-safe spec))
- (max-number (if (eq 'search spec-type)
- 100 ;; FIXME: refer to defconst.
- twittering-max-number-of-tweets-on-retrieval))
- (number
- (let ((number
- (or (cdr (assq 'number args-alist))
- (let* ((default-number 20)
- (n twittering-number-of-tweets-on-retrieval))
- (cond
- ((integerp n) n)
- ((string-match "^[0-9]+$" n) (string-to-number n 10))
- (t default-number))))))
- (min (max 1 number) max-number)))
- (number-str (number-to-string number))
- (max_id (cdr (assq 'max_id args-alist)))
- (page (cdr (assq 'page args-alist)))
- (since_id (cdr (assq 'since_id args-alist)))
- (word (when (eq 'search spec-type)
- (cadr spec)))
- (parameters
- (cond
- ((eq spec-type 'favorites)
- `(("include_entities" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ,@(when page `(("page" . ,page)))))
- ((eq spec-type 'retweeted_by_user)
- (let ((username (elt spec 1)))
- `(("count" . ,number-str)
- ,@(when max_id `(("max_id" . ,max_id)))
- ("include_entities" . "true")
- ("screen_name" . ,username)
- ,@(when since_id `(("since_id" . ,since_id))))))
- ((eq spec-type 'retweeted_to_user)
- (let ((username (elt spec 1)))
- `(("count" . ,number-str)
- ("include_entities" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ("screen_name" . ,username)
- ,@(when since_id `(("since_id" . ,since_id))))))
- (t
- `(,@(when max_id `(("max_id" . ,max_id)))
- ,@(when since_id `(("since_id" . ,since_id)))
- ,@(cond
- ((eq spec-type 'search)
- `(("include_entities" . "true")
- ("q" . ,word)
- ("rpp" . ,number-str)
- ("with_twitter_user_id". "true")))
- ((eq spec-type 'list)
- (let ((username (elt spec 1))
- (list-name (elt spec 2)))
- `(("include_entities" . "true")
- ("include_rts" . "true")
- ("owner_screen_name" . ,username)
- ("per_page" . ,number-str)
- ("slug" . ,list-name))))
- ((eq spec-type 'user)
- (let ((username (elt spec 1)))
- `(("count" . ,number-str)
- ("include_entities" . "true")
- ("include_rts" . "true")
- ("screen_name" . ,username))))
- ((memq spec-type '(friends mentions public))
- `(("include_entities" . "true")
- ("count" . ,number-str)
- ("include_rts" . "true")))
- (t
- ;; direct_messages
- ;; direct_messages_sent
- ;; home
- ;; replies
- ;; retweeted_by_me
- ;; retweeted_to_me
- ;; retweets_of_me
- `(("include_entities" . "true")
- ("count" . ,number-str))))))))
- (format
- (let ((format (cdr (assq 'format args-alist))))
- (cond
- ((and format (symbolp format))
- format)
- ((eq spec-type 'search)
- 'atom)
- (t
- 'xml))))
- (format-str (symbol-name format))
- (simple-spec-list
- '((direct_messages . "direct_messages")
- (direct_messages_sent . "direct_messages/sent")
- (friends . "statuses/friends_timeline")
- (home . "statuses/home_timeline")
- (mentions . "statuses/mentions")
- (public . "statuses/public_timeline")
- (replies . "statuses/replies")
- (retweeted_by_me . "statuses/retweeted_by_me")
- (retweeted_to_me . "statuses/retweeted_to_me")
- (retweets_of_me . "statuses/retweets_of_me")
- (user . "statuses/user_timeline")))
- (host (cond ((eq spec-type 'search) twittering-api-search-host)
- (t twittering-api-host)))
- (method
- (cond
- ((eq spec-type 'list)
- (twittering-api-path "lists/statuses"))
- ((eq spec-type 'favorites)
- (let ((user (elt spec 1)))
- (if user
- (twittering-api-path "favorites/" user)
- (twittering-api-path "favorites"))))
- ((eq spec-type 'retweeted_by_user)
- (twittering-api-path "statuses/retweeted_by_user"))
- ((eq spec-type 'retweeted_to_user)
- (twittering-api-path "statuses/retweeted_to_user"))
- ((eq spec-type 'search)
- twittering-search-api-method)
- ((assq spec-type simple-spec-list)
- (twittering-api-path (cdr (assq spec-type simple-spec-list))))
- (t nil)))
- (sentinel (cdr (assq 'sentinel args-alist)))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist)))
- (additional-info `(,@additional-info (format . ,format))))
- (cond
- ((eq spec-type 'single)
- (let ((id (cadr spec))
- (sentinel (or sentinel
- 'twittering-retrieve-single-tweet-sentinel)))
- (if (twittering-find-status id)
- ;; If the status has already retrieved, do nothing.
- nil
- (twittering-call-api 'retrieve-single-tweet
- `((id . ,id)
- (format . ,format)
- (sentinel . ,sentinel)
- (clean-up-sentinel . ,clean-up-sentinel))
- additional-info))))
- ((and host method)
- (twittering-http-get account-info-alist host method parameters
- format-str
- additional-info sentinel clean-up-sentinel))
- (t
- (error "Invalid timeline spec")))))
- ((eq command 'retrieve-single-tweet)
- (let* ((id (cdr (assq 'id args-alist)))
- (user-screen-name (cdr (assq 'username args-alist)))
- (format
- (let ((format (cdr (assq 'format args-alist))))
- (cond
- ((and format (symbolp format))
- format)
- (t
- 'xml))))
- (format-str (symbol-name format))
- (parameters '(("include_entities" . "true")))
- (sentinel (cdr (assq 'sentinel args-alist)))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist)))
- (additional-info `(,@additional-info
- (id . ,id)
- (user-screen-name . ,user-screen-name)
- (format . ,format))))
- (twittering-http-get account-info-alist twittering-api-host
- (twittering-api-path "statuses/show/" id)
- parameters format-str additional-info
- sentinel clean-up-sentinel)))
- ((eq command 'get-list-index)
- ;; Get list names.
- (let* ((username (cdr (assq 'username args-alist)))
- (sentinel (cdr (assq 'sentinel args-alist)))
- (format (if (require 'json nil t) 'json 'xml))
- (format-str (symbol-name format))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
- (twittering-http-get account-info-alist twittering-api-host
- (twittering-api-path username "/lists")
- nil format-str additional-info
- sentinel clean-up-sentinel)))
- ((eq command 'get-list-subscriptions)
- (let* ((username (cdr (assq 'username args-alist)))
- (sentinel (cdr (assq 'sentinel args-alist)))
- (format (if (require 'json nil t) 'json 'xml))
- (format-str (symbol-name format))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
- (twittering-http-get account-info-alist twittering-api-host
- (twittering-api-path username "/lists/subscriptions")
- nil format-str additional-info
- sentinel clean-up-sentinel)))
- ((eq command 'create-friendships)
- ;; Create a friendship.
- (let ((username (cdr (assq 'username args-alist))))
- (twittering-http-post account-info-alist twittering-api-host
- (twittering-api-path "friendships/create")
- `(("screen_name" . ,username))
- nil additional-info)))
- ((eq command 'destroy-friendships)
- ;; Destroy a friendship
- (let ((username (cdr (assq 'username args-alist))))
- (twittering-http-post account-info-alist twittering-api-host
- (twittering-api-path "friendships/destroy")
- `(("screen_name" . ,username))
- nil additional-info)))
- ((eq command 'create-favorites)
- ;; Create a favorite.
- (let ((id (cdr (assq 'id args-alist))))
- (twittering-http-post account-info-alist twittering-api-host
- (twittering-api-path "favorites/create/" id)
- nil nil additional-info)))
- ((eq command 'destroy-favorites)
- ;; Destroy a favorite.
- (let ((id (cdr (assq 'id args-alist))))
- (twittering-http-post account-info-alist twittering-api-host
- (twittering-api-path "favorites/destroy/" id)
- nil nil additional-info)))
- ((eq command 'update-status)
- ;; Post a tweet.
- (let* ((status (cdr (assq 'status args-alist)))
- (id (cdr (assq 'in-reply-to-status-id args-alist)))
- (parameters
- `(("status" . ,status)
- ,@(when (eq twittering-auth-method 'basic)
- '(("source" . "twmode")))
- ,@(when id `(("in_reply_to_status_id" . ,id))))))
- (twittering-http-post account-info-alist twittering-api-host
- (twittering-api-path "statuses/update")
- parameters nil additional-info)))
- ((eq command 'destroy-status)
- ;; Destroy a status.
- (let* ((id (cdr (assq 'id args-alist)))
- (format (if (require 'json nil t) 'json 'xml))
- (format-str (symbol-name format)))
- (twittering-http-post account-info-alist twittering-api-host
- (twittering-api-path "statuses/destroy/" id)
- nil format-str additional-info
- 'twittering-http-post-destroy-status-sentinel)))
- ((eq command 'retweet)
- ;; Post a retweet.
- (let ((id (cdr (assq 'id args-alist))))
- (twittering-http-post account-info-alist twittering-api-host
- (twittering-api-path "statuses/retweet/" id)
- nil nil additional-info)))
- ((eq command 'verify-credentials)
- ;; Verify the account.
- (let ((sentinel (cdr (assq 'sentinel args-alist)))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
- (twittering-http-get account-info-alist twittering-api-host
- (twittering-api-path "account/verify_credentials")
- nil nil additional-info
- sentinel clean-up-sentinel)))
- ((eq command 'send-direct-message)
- ;; Send a direct message.
- (let ((parameters
- `(("screen_name" . ,(cdr (assq 'username args-alist)))
- ("text" . ,(cdr (assq 'status args-alist))))))
- (twittering-http-post account-info-alist twittering-api-host
- (twittering-api-path "direct_messages/new")
- parameters nil additional-info)))
- ((eq command 'block)
- ;; Block a user.
- (let* ((user-id (cdr (assq 'user-id args-alist)))
- (username (cdr (assq 'username args-alist)))
- (parameters (if user-id
- `(("user_id" . ,user-id))
- `(("screen_name" . ,username)))))
- (twittering-http-post twittering-api-host
- (twittering-api-path "blocks/create")
- parameters nil additional-info)))
- ((eq command 'block-and-report-as-spammer)
- ;; Report a user as a spammer and block him or her.
- (let* ((user-id (cdr (assq 'user-id args-alist)))
- (username (cdr (assq 'username args-alist)))
- (parameters (if user-id
- `(("user_id" . ,user-id))
- `(("screen_name" . ,username)))))
- (twittering-http-post twittering-api-host
- (twittering-api-path "report_spam")
- parameters nil additional-info)))
- ((eq command 'get-service-configuration)
- (let* ((format (if (require 'json nil t) 'json 'xml))
- (format-str (symbol-name format))
- (request
- (twittering-make-http-request-from-uri
- "GET" nil
- (concat (if twittering-use-ssl
- "https"
- "http")
- "://" twittering-api-host
- "/"
- (twittering-api-path "help/configuration." format-str))))
- (additional-info nil)
- (sentinel (cdr (assq 'sentinel args-alist)))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
- (twittering-send-http-request request additional-info
- sentinel clean-up-sentinel)))
- (t
- nil)))
-
-(defun twittering-call-api-with-account-in-api1.1 (account-info-alist command args-alist &optional additional-info)
- "Call the Twitter REST API v1.1 and return the process object for the request."
- (cond
- ((eq command 'retrieve-timeline)
- ;; Retrieve a timeline.
- (let* ((args-alist
- (let* ((spec (cdr (assq 'timeline-spec args-alist)))
- (spec-type (car-safe spec))
- (table '((friends . (home))
- (replies . (mentions)))))
- (cond
- ((memq spec-type '(friends replies))
- (let* ((alternative (cdr (assq spec-type table)))
- (alternative-str
- (twittering-timeline-spec-to-string alternative)))
- (message
- "Timeline spec %s is not supported in the Twitter REST API v1.1"
- spec)
- `((timeline-spec . ,alternative)
- (timeline-spec-string . ,alternative-str)
- ,@args-alist)))
- (t
- args-alist))))
- (spec (cdr (assq 'timeline-spec args-alist)))
- (spec-string (cdr (assq 'timeline-spec-string args-alist)))
- (spec-type (car-safe spec))
- (max-number (if (eq 'search spec-type)
- 100 ;; FIXME: refer to defconst.
- twittering-max-number-of-tweets-on-retrieval))
- (number
- (let ((number
- (or (cdr (assq 'number args-alist))
- (let* ((default-number 20)
- (n twittering-number-of-tweets-on-retrieval))
- (cond
- ((integerp n) n)
- ((string-match "^[0-9]+$" n) (string-to-number n 10))
- (t default-number))))))
- (min (max 1 number) max-number)))
- (number-str (number-to-string number))
- (max_id (cdr (assq 'max_id args-alist)))
- (since_id (cdr (assq 'since_id args-alist)))
- (word (when (eq 'search spec-type)
- (cadr spec)))
- (parameters
- (cond
- ((eq spec-type 'user)
- (let ((username (elt spec 1)))
- `("api.twitter.com"
- "1.1/statuses/user_timeline"
- ("count" . ,number-str)
- ("include_entities" . "true")
- ("include_rts" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ("screen_name" . ,username)
- ,@(when since_id `(("since_id" . ,since_id)))
- )))
- ((eq spec-type 'list)
- (let ((username (elt spec 1))
- (list-name (elt spec 2)))
- `("api.twitter.com"
- "1.1/lists/statuses"
- ("count" . ,number-str)
- ("include_entities" . "true")
- ("include_rts" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ("owner_screen_name" . ,username)
- ,@(when since_id `(("since_id" . ,since_id)))
- ("slug" . ,list-name))))
- ((eq spec-type 'direct_messages)
- `("api.twitter.com"
- "1.1/direct_messages"
- ("count" . ,number-str)
- ("include_entities" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ,@(when since_id `(("since_id" . ,since_id)))))
- ((eq spec-type 'direct_messages_sent)
- `("api.twitter.com"
- "1.1/direct_messages/sent"
- ("count" . ,number-str)
- ("include_entities" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ,@(when since_id `(("since_id" . ,since_id)))))
- ((eq spec-type 'favorites)
- (let ((user (elt spec 1)))
- `("api.twitter.com"
- "1.1/favorites/list"
- ("count" . ,number-str)
- ("include_entities" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ,@(when user `(("screen_name" . ,user)))
- ,@(when since_id `(("since_id" . ,since_id))))))
- ((eq spec-type 'home)
- `("api.twitter.com"
- "1.1/statuses/home_timeline"
- ("count" . ,number-str)
- ("include_entities" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ,@(when since_id `(("since_id" . ,since_id)))))
- ((eq spec-type 'mentions)
- `("api.twitter.com"
- "1.1/statuses/mentions_timeline"
- ("count" . ,number-str)
- ("include_entities" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ,@(when since_id `(("since_id" . ,since_id)))))
- ((eq spec-type 'public)
- (error
- "Timeline spec %s is not supported in the Twitter REST API v1.1"
- spec)
- nil)
- ((memq spec-type '(retweeted_by_me
- retweeted_by_user
- retweeted_to_me
- retweeted_to_user))
- (error
- "Timeline spec %s is not supported in the Twitter REST API v1.1"
- spec)
- nil)
- ((eq spec-type 'retweets_of_me)
- `("api.twitter.com"
- "1.1/statuses/retweets_of_me"
- ("count" . ,number-str)
- ("include_entities" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ,@(when since_id `(("since_id" . ,since_id)))))
- ((eq spec-type 'single)
- (let ((id (elt spec 1)))
- `("api.twitter.com"
- "1.1/statuses/show"
- ("id" . ,id)
- ("include_entities" . "true"))))
- ((eq spec-type 'search)
- (let ((word (elt spec 1)))
- `("api.twitter.com"
- "1.1/search/tweets"
- ("count" . ,number-str)
- ("include_entities" . "true")
- ,@(when max_id `(("max_id" . ,max_id)))
- ("q" . ,word)
- ("result_type" . "mixed")
- ,@(when since_id `(("since_id" . ,since_id))))))
- (t
- (error
- "Timeline spec %s is unknown"
- spec-string)
- nil)))
- (format 'json)
- (format-str (symbol-name format))
- (host (elt parameters 0))
- (method (elt parameters 1))
- (http-parameters (nthcdr 2 parameters))
- (sentinel (cdr (assq 'sentinel args-alist)))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist)))
- (additional-info `(,@additional-info (format . ,format)))
- ;; special treatment for single timeline.
- (id (cdr (assoc "id" http-parameters)))
- (sentinel (or sentinel
- (when (eq spec-type 'single)
- 'twittering-retrieve-single-tweet-sentinel))))
- (cond
- ((null parameters)
- nil)
- ((not (and (string= format-str "json")
- (require 'json nil t)))
- (error "The Twitter REST API v1.1 supports only JSON")
- nil)
- ((and (eq spec-type 'single)
- (twittering-find-status id))
- ;; If the status has already retrieved, do nothing.
- nil)
- ((and host method)
- (twittering-http-get account-info-alist host method http-parameters
- format-str
- additional-info sentinel clean-up-sentinel))
- (t
- (error "Invalid timeline spec")
- nil))))
- ((eq command 'retrieve-single-tweet)
- (let* ((id (cdr (assq 'id args-alist)))
- (user-screen-name (cdr (assq 'username args-alist)))
- (format
- (let ((format (cdr (assq 'format args-alist))))
- (cond
- ((and format (symbolp format))
- format)
- (t
- 'json))))
- (format-str (symbol-name format))
- (sentinel (cdr (assq 'sentinel args-alist)))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist)))
- (additional-info `(,@additional-info
- (id . ,id)
- (user-screen-name . ,user-screen-name)
- (format . ,format))))
- (twittering-call-api-with-account-in-api1.1
- account-info-alist 'retrieve-timeline
- `((timeline-spec . (single ,id))
- (format . ,format)
- (sentinel . ,sentinel)
- (clean-up-sentinel . ,clean-up-sentinel))
- additional-info)))
- ((eq command 'get-list-index)
- ;; Get list names.
- (let* ((username (cdr (assq 'username args-alist)))
- (sentinel (cdr (assq 'sentinel args-alist)))
- (host "api.twitter.com")
- (method "1.1/lists/list")
- (http-parameters `(("screen_name" . ,username)))
- (format-str "json")
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
- (twittering-http-get account-info-alist host method http-parameters
- format-str additional-info
- sentinel clean-up-sentinel)))
- ((eq command 'get-list-subscriptions)
- (let* ((username (cdr (assq 'username args-alist)))
- (sentinel (cdr (assq 'sentinel args-alist)))
- (host "api.twitter.com")
- (method "1.1/lists/subscriptions")
- (http-parameters
- `(("count" . "20")
- ("screen_name" . ,username)))
- (format-str "json")
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
- (twittering-http-get account-info-alist host method http-parameters
- format-str additional-info
- sentinel clean-up-sentinel)))
- ((eq command 'create-friendships)
- ;; Create a friendship.
- (let* ((username (cdr (assq 'username args-alist)))
- (host "api.twitter.com")
- (method "1.1/friendships/create")
- (http-parameters
- `(("screen_name" . ,username)))
- (format-str "json"))
- (twittering-http-post account-info-alist host method http-parameters
- format-str additional-info)))
- ((eq command 'destroy-friendships)
- ;; Destroy a friendship
- (let* ((username (cdr (assq 'username args-alist)))
- (host "api.twitter.com")
- (method "1.1/friendships/destroy")
- (http-parameters
- `(("screen_name" . ,username)))
- (format-str "json"))
- (twittering-http-post account-info-alist host method http-parameters
- format-str additional-info)))
- ((eq command 'create-favorites)
- ;; Create a favorite.
- (let* ((id (cdr (assq 'id args-alist)))
- (host "api.twitter.com")
- (method "1.1/favorites/create")
- (http-parameters `(("id" . ,id)))
- (format-str "json"))
- (twittering-http-post account-info-alist host method http-parameters
- format-str additional-info)))
- ((eq command 'destroy-favorites)
- ;; Destroy a favorite.
- (let* ((id (cdr (assq 'id args-alist)))
- (host "api.twitter.com")
- (method "1.1/favorites/destroy")
- (http-parameters `(("id" . ,id)))
- (format-str "json"))
- (twittering-http-post account-info-alist host method http-parameters
- format-str additional-info)))
- ((eq command 'update-status)
- ;; Post a tweet.
- (let* ((status (cdr (assq 'status args-alist)))
- (id (cdr (assq 'in-reply-to-status-id args-alist)))
- (host "api.twitter.com")
- (method "1.1/statuses/update")
- (http-parameters
- `(("status" . ,status)
- ,@(when id `(("in_reply_to_status_id" . ,id)))))
- (format-str "json"))
- (twittering-http-post account-info-alist host method http-parameters
- format-str additional-info)))
- ((eq command 'destroy-status)
- ;; Destroy a status.
- (let* ((id (cdr (assq 'id args-alist)))
- (host "api.twitter.com")
- (method (format "1.1/statuses/destroy/%s" id))
- (http-parameters nil)
- (format-str "json"))
- (twittering-http-post account-info-alist host method http-parameters
- format-str additional-info
- 'twittering-http-post-destroy-status-sentinel)))
- ((eq command 'retweet)
- ;; Post a retweet.
- (let* ((id (cdr (assq 'id args-alist)))
- (host "api.twitter.com")
- (method (format "1.1/statuses/retweet/%s" id))
- (http-parameters nil)
- (format-str "json"))
- (twittering-http-post account-info-alist host method http-parameters
- format-str additional-info)))
- ((eq command 'verify-credentials)
- ;; Verify the account.
- (let* ((host "api.twitter.com")
- (method "1.1/account/verify_credentials")
- (http-parameters nil)
- (format-str "json")
- (sentinel (cdr (assq 'sentinel args-alist)))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
- (twittering-http-get account-info-alist host method http-parameters
- format-str additional-info
- sentinel clean-up-sentinel)))
- ((eq command 'send-direct-message)
- ;; Send a direct message.
- (let* ((host "api.twitter.com")
- (method "1.1/direct_messages/new")
- (http-parameters
- `(("screen_name" . ,(cdr (assq 'username args-alist)))
- ("text" . ,(cdr (assq 'status args-alist)))))
- (format-str "json"))
- (twittering-http-post account-info-alist host method http-parameters
- format-str additional-info)))
- ((eq command 'block)
- ;; Block a user.
- (let* ((user-id (cdr (assq 'user-id args-alist)))
- (username (cdr (assq 'username args-alist)))
- (host "api.twitter.com")
- (method "1.1/blocks/create")
- (http-parameters (if user-id
- `(("user_id" . ,user-id))
- `(("screen_name" . ,username))))
- (format-str "json"))
- (twittering-http-post host method http-parameters
- format-str additional-info)))
- ((eq command 'block-and-report-as-spammer)
- ;; Report a user as a spammer and block him or her.
- (let* ((user-id (cdr (assq 'user-id args-alist)))
- (username (cdr (assq 'username args-alist)))
- (host "api.twitter.com")
- (method "1.1/users/report_spam")
- (http-parameters (if user-id
- `(("user_id" . ,user-id))
- `(("screen_name" . ,username))))
- (format-str "json"))
- (twittering-http-post host method http-parameters
- format-str additional-info)))
- ((eq command 'get-service-configuration)
- (let* ((host "api.twitter.com")
- (method "1.1/help/configuration")
- (http-parameters nil)
- (format-str "json")
- (additional-info nil)
- (sentinel (cdr (assq 'sentinel args-alist)))
- (clean-up-sentinel (cdr (assq 'clean-up-sentinel args-alist))))
- (twittering-http-get account-info-alist host method http-parameters
- format-str additional-info
- sentinel clean-up-sentinel)))
- (t
- nil)))
-
-;;;;
-;;;; Service configuration
-;;;;
-
-(defconst twittering-service-configuration-default
- '((short_url_length . 19)
- (short_url_length_https . 20))
- "Default value of `twittering-service-configuration'.")
-(defvar twittering-service-configuration nil
- "Current server configuration.")
-(defvar twittering-service-configuration-queried nil)
-(defvar twittering-service-configuration-update-interval 86400
- "*Interval of updating `twittering-service-configuration'.")
-
-(defun twittering-get-service-configuration (entry)
- (let ((pair (assq entry twittering-service-configuration)))
- (if (null pair)
- (cdr (assq entry twittering-service-configuration-default))
- (cdr pair))))
-
-(defun twittering-update-service-configuration (&optional ignore-time)
- "Update `twittering-service-configuration' if necessary."
- (when (and
- (memq twittering-service-method '(twitter twitter-api-v1.1))
- (null twittering-service-configuration-queried)
- (or ignore-time
- (let ((current (twittering-get-service-configuration 'time))
- (interval
- (seconds-to-time
- twittering-service-configuration-update-interval)))
- (if (null current)
- t
- ;; If time passed more than `interval',
- ;; update the configuration.
- (time-less-p interval (time-since current))))))
- (setq twittering-service-configuration-queried t)
- (twittering-call-api
- 'get-service-configuration
- '((sentinel . twittering-update-service-configuration-sentinel)
- (clean-up-sentinel
- . twittering-update-service-configuration-clean-up-sentinel)))))
-
-(defun twittering-update-service-configuration-sentinel (proc status connection-info header-info)
- (let ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info)))
- (format
- (twittering-get-content-subtype-symbol-from-header-info header-info)))
- (case-string
- status-code
- (("200")
- (let* ((conf-alist
- (cond
- ((eq format 'xml)
- (let ((xml
- (twittering-xml-parse-region (point-min) (point-max))))
- (mapcar
- (lambda (entry)
- `(,(car entry) . ,(elt entry 2)))
- (cddr (assq 'configuration xml)))))
- ((eq format 'json)
- (twittering-json-read))
- (t
- (error "Format \"%s\" is not supported" format)
- nil)))
- (entries '(short_url_length short_url_length_https)))
- (setq twittering-service-configuration
- `((time . ,(current-time))
- ,@(mapcar (lambda (entry)
- (let ((value (cdr (assq entry conf-alist))))
- (cons
- entry
- (cond
- ((stringp value)
- (string-to-number value))
- (t
- value)))))
- entries)))
- (setq twittering-service-configuration-queried nil)
- nil))
- (("400")
- ;; Rate limit exceeded.
- (setq twittering-service-configuration-queried nil)
- (format "Response: %s"
- (twittering-get-error-message header-info connection-info)))
- (t
- (setq twittering-service-configuration-queried nil)
- (format "Response: %s"
- (twittering-get-error-message header-info connection-info))))))
-
-(defun twittering-update-service-configuration-clean-up-sentinel (proc status connection-info)
- (when (not (twittering-process-alive-p proc))
- (setq twittering-service-configuration-queried nil)))
-
-;;;;
-;;;; Account authorization
-;;;;
-
-(defun twittering-register-account-info (account-info)
- (setq twittering-oauth-access-token-alist account-info))
-
-(defun twittering-get-main-account-info ()
- (cond
- ((eq twittering-auth-method 'basic)
- `(("screen_name" . ,twittering-username)
- ("password" . ,twittering-password)))
- ((memq twittering-auth-method '(oauth xauth))
- twittering-oauth-access-token-alist)))
-
-(defun twittering-get-from-account-info (param account-info)
- (cdr (assoc param account-info)))
-
-(defun twittering-get-username ()
- (let ((account-info (twittering-get-main-account-info)))
- (twittering-get-from-account-info "screen_name" account-info)))
-
-(defun twittering-get-password ()
- (let ((account-info (twittering-get-main-account-info)))
- (twittering-get-from-account-info "password" account-info)))
-
-(defun twittering-make-basic-authentication-string (account-info)
- (concat "Basic "
- (base64-encode-string
- (concat (cdr (assoc "screen_name" account-info))
- ":" (cdr (assoc "password" account-info))))))
-
-(defun twittering-make-oauth-authentication-string (account-info request)
- (let ((method (cdr (assq 'method request)))
- (access-token (cdr (assoc "oauth_token" account-info)))
- (access-token-secret (cdr (assoc "oauth_token_secret" account-info))))
- (unless (and (stringp access-token)
- (stringp access-token-secret))
- (error "`account-info' has no valid OAuth token"))
- (twittering-oauth-auth-str-access
- method
- (cdr (assq 'uri-without-query request))
- (cdr (assq 'encoded-query-alist request))
- twittering-oauth-consumer-key twittering-oauth-consumer-secret
- access-token access-token-secret)))
-
-(defun twittering-account-authorized-p ()
- (eq twittering-account-authorization 'authorized))
-(defun twittering-account-authorization-queried-p ()
- (eq twittering-account-authorization 'queried))
-
-(defun twittering-prepare-account-info ()
- "Return a pair of username and password.
-If `twittering-username' is nil, read it from the minibuffer.
-If `twittering-password' is nil, read it from the minibuffer."
- (let* ((username (or twittering-username
- (read-string "your twitter username: ")))
- (password (or twittering-password
- (read-passwd (format "%s's twitter password: "
- username)))))
- `(,username . ,password)))
-
-(defun twittering-has-oauth-access-token-p ()
- (let* ((required-entries '("oauth_token"
- "oauth_token_secret"
- "user_id"
- "screen_name"))
- (value-list
- (mapcar
- (lambda (key)
- (cdr (assoc key twittering-oauth-access-token-alist)))
- required-entries)))
- (null (remove t (mapcar 'stringp value-list)))))
-
-(defun twittering-verify-credentials ()
- "Verify the account.
-
-This function is an internal function, which should be called from
-`twittering-ensure-account-verification'.
-
-If the account has been authorized already, return t.
-Otherwise, this function tries to authorize the account.
-If the authorization succeeded, return t.
-If the authorization failed, return nil."
- (cond
- ((twittering-account-authorized-p)
- ;; The account has been authorized already.
- t)
- ((not (twittering-account-authorization-queried-p))
- ;; This function must be invoked from
- ;; `twittering-ensure-account-verification', which updates the variable
- ;; `twittering-account-authorization' into the symbol `queried'.
- (error "`twittering-verify-credentials' is invoked multiple times.")
- nil)
- ((and (memq twittering-auth-method '(oauth xauth))
- (or (null twittering-oauth-consumer-key)
- (null twittering-oauth-consumer-secret)))
- (message "Consumer for OAuth is not specified.")
- nil)
- ((twittering-has-oauth-access-token-p)
- (let* ((username (cdr (assoc "screen_name"
- (twittering-get-main-account-info))))
- (proc
- (twittering-call-api-with-account
- (twittering-get-main-account-info)
- 'verify-credentials
- `((sentinel
- . twittering-http-get-verify-credentials-sentinel)
- (clean-up-sentinel
- . twittering-http-get-verify-credentials-clean-up-sentinel)))))
- (cond
- ((null proc)
- (message "Process invocation for authorizing \"%s\" failed." username)
- ;; Failed to authorize the account.
- nil)
- (t
- ;; wait for verification to finish.
- (twittering-wait-while nil 0.1
- (and
- (twittering-account-authorization-queried-p)
- (twittering-process-alive-p proc)))
- (if (not (twittering-account-authorization-queried-p))
- ;; The query is completed.
- (twittering-account-authorized-p)
- ;; If the process has been dead, wait a moment because
- ;; Emacs may be in the middle of evaluating the sentinel.
- (twittering-wait-while
- 10 0.1
- (twittering-account-authorization-queried-p)
- ;; Succeeded in authorizing the account.
- t
- ;; Display a message.
- (message
- "Status of Authorization process is `%s'. Type M-x twit to retry."
- (process-status proc))
- ;; Failed to authorize the account.
- nil))))))
- ((eq twittering-auth-method 'oauth)
- (let* ((scheme (if twittering-oauth-use-ssl
- "https"
- "http"))
- (request-token-url
- (concat scheme twittering-oauth-request-token-url-without-scheme))
- (access-token-url
- (concat scheme twittering-oauth-access-token-url-without-scheme))
- (token-alist
- (twittering-oauth-get-access-token
- request-token-url
- (lambda (token)
- (concat scheme
- twittering-oauth-authorization-url-base-without-scheme
- token))
- access-token-url
- twittering-oauth-consumer-key twittering-oauth-consumer-secret
- "twittering-mode")))
- (cond
- ((and (assoc "oauth_token" token-alist)
- (assoc "oauth_token_secret" token-alist)
- (assoc "screen_name" token-alist))
- (let ((username (cdr (assoc "screen_name" token-alist))))
- (twittering-register-account-info token-alist)
- (message "Authorization for the account \"%s\" succeeded."
- username)
- (when (and twittering-use-master-password
- (twittering-capable-of-encryption-p)
- (not (file-exists-p twittering-private-info-file)))
- (twittering-save-private-info-with-guide))
- ;; Succeeded in authorizing the account.
- t))
- (t
- ;; There is no global account info that should be invalidated.
- ;; Failed to authorize the account.
- (message "Authorization via OAuth failed. Type M-x twit to retry.")
- nil))))
- ((eq twittering-auth-method 'xauth)
- (let* ((account-info (twittering-prepare-account-info))
- (scheme (if twittering-oauth-use-ssl
- "https"
- "http"))
- (access-token-url
- (concat scheme twittering-oauth-access-token-url-without-scheme))
- (token-alist
- (twittering-xauth-get-access-token
- access-token-url
- twittering-oauth-consumer-key twittering-oauth-consumer-secret
- (car account-info)
- (cdr account-info))))
- ;; Dispose of password as recommended by Twitter.
- ;; http://dev.twitter.com/pages/xauth
- (setcdr account-info nil)
- (cond
- ((and token-alist
- (assoc "oauth_token" token-alist)
- (assoc "oauth_token_secret" token-alist))
- (twittering-register-account-info token-alist)
- (message "Authorization for the account \"%s\" succeeded."
- (twittering-get-username))
- (when (and twittering-use-master-password
- (twittering-capable-of-encryption-p)
- (not (file-exists-p twittering-private-info-file)))
- (twittering-save-private-info-with-guide))
- ;; Succeeded in authorizing the account.
- t)
- (t
- ;; Failed to authorize the account.
- (message "Authorization via xAuth failed. Type M-x twit to retry.")
- nil))))
- ((eq twittering-auth-method 'basic)
- (let* ((account-info
- (let ((pair (twittering-prepare-account-info)))
- `(("screen_name" . ,(car pair))
- ("password" . ,(cdr pair)))))
- ;; Bind account information locally to ensure that
- ;; the variables are reset when the verification fails.
- (twittering-username (car account-info))
- (twittering-password (cdr account-info))
- (proc
- (twittering-call-api-with-account
- account-info
- 'verify-credentials
- `((sentinel . twittering-http-get-verify-credentials-sentinel)
- (clean-up-sentinel
- . twittering-http-get-verify-credentials-clean-up-sentinel)))))
- (cond
- ((null proc)
- (message "Process invocation for authorizing \"%s\" failed."
- (twittering-get-from-account-info "screen_name" account-info))
- ;; Failed to authorize the account.
- nil)
- (t
- ;; wait for verification to finish.
- (twittering-wait-while nil 0.1
- (and
- (twittering-account-authorization-queried-p)
- (twittering-process-alive-p proc)))
- (if (not (twittering-account-authorization-queried-p))
- ;; The query is finished.
- (twittering-account-authorized-p)
- ;; If the process has been dead, wait a moment because
- ;; Emacs may be in the middle of evaluating the sentinel.
- (twittering-wait-while
- 10 0.1
- (twittering-account-authorization-queried-p)
- ;; Succeeded in authorizing the account.
- t
- ;; Display a message.
- (message
- "Status of Authorization process is `%s'. Type M-x twit to retry."
- (process-status proc))
- ;; Failed to authorize the account.
- nil))))))
- (t
- (message "%s is invalid as an authorization method."
- twittering-auth-method)
- nil)))
-
-(defun twittering-http-get-verify-credentials-sentinel (proc status connection-info header-info)
- (let* ((status-line (cdr (assq 'status-line header-info)))
- (status-code (cdr (assq 'status-code header-info)))
- (account-info (cdr (assq 'account-info connection-info)))
- (username
- (twittering-get-from-account-info "screen_name" account-info))
- (password
- (twittering-get-from-account-info "password" account-info)))
- (case-string
- status-code
- (("200")
- (twittering-register-account-info account-info)
- (setq twittering-account-authorization 'authorized)
- (message "Authorization for the account \"%s\" succeeded." username)
- nil)
- (("401")
- (setq twittering-account-authorization nil)
- (let ((error-mes
- (format "Authorization for the account \"%s\" failed. Type M-x twit to retry with correct information."
- username)))
- ;; Invalidate the account info.
- (twittering-register-account-info nil)
- (message "%s" error-mes)
- nil))
- (t
- (setq twittering-account-authorization nil)
- (let ((error-mes
- (format "Authorization for the account \"%s\" failed due to \"%s\"."
- username status-line)))
- (message "%s" error-mes)
- nil)))))
-
-(defun twittering-http-get-verify-credentials-clean-up-sentinel (proc status connection-info)
- (when (and (memq status '(exit signal closed failed))
- (eq twittering-account-authorization 'queried))
- (setq twittering-account-authorization nil)
- (let ((exit-status (cond
- ((processp proc) (process-exit-status proc))
- (t 0)))
- (command (process-command proc)))
- (if (= 0 exit-status)
- (message "Authorization failed. Type M-x twit to retry.")
- (message "Authorization failed: %s exited abnormally (exit-status=%s)."
- (car command) exit-status)))
- (setq twittering-username nil)
- (setq twittering-password nil)))
-
-(defun twittering-ensure-account-verification ()
- "Ensure verification of an account.
-
-If an account has been already authorized, return t.
-If a query of authorization is being processed, return nil.
-
-Otherwise, this function tries to authorize an account by calling
-`twittering-verify-credentials'.
-If the authorization succeeded, return t.
-If the authorization failed, return nil."
- (cond
- ((twittering-account-authorized-p)
- ;; The account has been already authorized.
- t)
- ((twittering-account-authorization-queried-p)
- ;; The account has not been authorized yet.
- nil)
- (t
- (setq twittering-account-authorization 'queried)
- (let ((result nil))
- (unwind-protect
- (setq result (twittering-verify-credentials))
- (if result
- (setq twittering-account-authorization 'authorized)
- (setq twittering-account-authorization nil)))
- result))))
-
-;;;;
-;;;; Status retrieval
-;;;;
-
-(defun twittering-add-timeline-history (spec-string)
- (when (or (null twittering-timeline-history)
- (not (string= spec-string (car twittering-timeline-history))))
- (twittering-add-to-history 'twittering-timeline-history spec-string))
- (let ((spec (twittering-string-to-timeline-spec spec-string)))
- (when (and (twittering-timeline-spec-is-user-p spec)
- (or (null twittering-user-history)
- (not (string= spec-string (car twittering-user-history)))))
- (twittering-add-to-history 'twittering-user-history (cadr spec)))))
-
-(defun twittering-remove-timeline-spec-string-from-history (spec-string)
- (setq twittering-timeline-history
- (remove nil
- (mapcar
- (lambda (str)
- (if (twittering-equal-string-as-timeline spec-string str)
- nil
- str))
- twittering-timeline-history))))
-
-(defun twittering-make-alist-of-forbidden-tweet (id &optional user-screen-name)
- (let ((created-at
- (or
- (twittering-id-to-time id)
- (apply 'encode-time
- (parse-time-string "Jan 01 00:00:00 +0000 2012")))))
- `((forbidden . t)
- (id . ,id)
- (created-at . ,created-at)
- (user-name . nil)
- (user-screen-name . ,user-screen-name)
- (text . "SORRY, YOU ARE NOT AUTHORIZED TO SEE THIS TWEET.")
- )))
-
-(defun twittering-make-alist-of-non-existent-tweet (id &optional user-screen-name)
- (let ((created-at
- (or
- (twittering-id-to-time id)
- (apply 'encode-time
- (parse-time-string "Jan 01 00:00:00 +0000 2012")))))
- `((forbidden . t)
- (id . ,id)
- (created-at . ,created-at)
- (user-name . nil)
- (user-screen-name . ,user-screen-name)
- (text . ,(format "THE TWEET WITH ID %s DOES NOT EXIST." id))
- )))
-
-(defun twittering-atom-xmltree-to-status-datum (atom-xml-entry)
- (let* ((id-str (car (cddr (assq 'id atom-xml-entry))))
- (time-str (car (cddr (assq 'updated atom-xml-entry))))
- (author-str (car (cddr (assq 'name (assq 'author atom-xml-entry)))))
- (formatted-time-str
- ;; ISO 8601
- ;; Twitter -> "2010-05-08T05:59:41Z"
- ;; StatusNet -> "2010-05-08T08:44:39+00:00"
- (cond
- ((string-match
- "\\(.*\\)T\\(.*\\)\\(Z\\|\\([-+][0-2][0-9]\\):?\\([0-5][0-9]\\)\\)"
- time-str)
- ;; time-str is formatted as
- ;; "Combined date and time in UTC:" in ISO 8601.
- (let ((timezone (match-string 3 time-str)))
- (format "%s %s %s"
- (match-string 1 time-str) (match-string 2 time-str)
- (if (string= "Z" timezone)
- "+0000"
- (concat (match-string 4 time-str)
- (match-string 5 time-str))))))
- (t
- ;; unknown format?
- time-str))))
- `((created-at . ,(date-to-time formatted-time-str))
- (id . ,(progn
- (string-match ":\\([0-9]+\\)$" id-str)
- (match-string 1 id-str)))
- ,@(let ((source (twittering-decode-html-entities
- (car (cddr (assq 'twitter:source atom-xml-entry))))))
- `(,@(if (string-match "<a href=\"\\(.*?\\)\".*?>\\(.*\\)</a>"
- source)
- (let ((uri (match-string-no-properties 1 source))
- (caption (match-string-no-properties 2 source)))
- `((source . ,caption)
- (source-uri . ,uri)))
- `((source . ,source)
- (source-uri . "")))))
- (text . ,(twittering-decode-html-entities
- (car (cddr (assq 'title atom-xml-entry)))))
- ,@(cond
- ((and (eq twittering-service-method 'statusnet)
- (string-match "^\\([^ ]+\\)\\( (\\(.*\\))\\)?$" author-str))
- ;; StatusNet
- `((user-screen-name . ,(match-string 1 author-str))
- (user-name . ,(or (match-string 3 author-str) ""))))
- ((string-match "^\\([^ ]+\\) (\\(.*\\))$" author-str)
- ;; Twitter (default)
- `((user-screen-name . ,(match-string 1 author-str))
- (user-name . ,(match-string 2 author-str))))
- (t
- '((user-screen-name . "PARSING FAILED!!")
- (user-name . ""))))
- (user-profile-image-url
- . ,(let* ((link-items
- (mapcar
- (lambda (item)
- (when (eq 'link (car-safe item))
- (cadr item)))
- atom-xml-entry))
- (image-urls
- (mapcar
- (lambda (item)
- (cond
- ((and (eq twittering-service-method 'statusnet)
- (member '(rel . "related") item))
- ;; StatusNet
- (cdr (assq 'href item)))
- ((member '(rel . "image") item)
- ;; Twitter (default)
- (cdr (assq 'href item)))
- (t
- nil)))
- link-items)))
- (car-safe (remq nil image-urls)))))))
-
-(defun twittering-atom-xmltree-to-status (atom-xmltree)
- (let ((entry-list
- (apply 'append
- (mapcar (lambda (x)
- (if (eq (car-safe x) 'entry) `(,x) nil))
- (cdar atom-xmltree)))))
- (mapcar 'twittering-atom-xmltree-to-status-datum
- entry-list)))
-
-(eval-and-compile
- (defsubst twittering-make-gap-list (text)
- "Return a list representing index gaps between TEXT and the encoded text.
-Indices included in entities in XML response from Twitter mean the positions
-of characters in the encoded text, where \"<\" and \">\" are encoded as
-\"<\" and \">\" respectively.
-Therefore, the indices differ from the positions in the decoded text.
-
-This function calculates the gaps from TEXT, which is assumed to be decoded.
-This function returns a list of pairs representing the gaps.
-For each pair, the car means the position in the encoded text and the cdr
-means the gap. The (car pair)-th character in the encoded text corresponds
-to the (- (car pair) (cdr pair))-th character in the decoded text."
- (let ((result nil)
- (pos 0)
- (gap 0))
- (while (string-match "[<>]" text pos)
- (let ((shift 3))
- (setq result
- (cons `(,(+ gap (match-end 0)) . ,(+ gap shift)) result))
- (setq gap (+ shift gap)))
- (setq pos (match-end 0)))
- (reverse result)))
-
- (defun twittering-get-gap (pos gap-list)
- "Return the gap at the specific position.
-GAP-LIST must be generated by `twittering-make-gap-list'."
- (let ((rest-gaps gap-list)
- (gap 0))
- (while (and rest-gaps (< (caar rest-gaps) pos))
- (setq gap (cdar rest-gaps))
- (setq rest-gaps (cdr rest-gaps)))
- gap)))
-
-(defun twittering-normalize-raw-status (raw-status &optional ignore-retweet)
- (let* ((status-data (cddr raw-status))
- (raw-retweeted-status (assq 'retweeted_status status-data)))
- (cond
- ((and raw-retweeted-status
- (not ignore-retweet))
- (let ((retweeted-status
- (twittering-normalize-raw-status raw-retweeted-status t))
- (retweeting-status
- (twittering-normalize-raw-status raw-status t))
- (items-overwritten-by-retweet
- '(id)))
- `(,@(mapcar
- (lambda (entry)
- (let ((sym (car entry))
- (value (cdr entry)))
- (if (memq sym items-overwritten-by-retweet)
- (let ((value-on-retweet
- (cdr (assq sym retweeting-status))))
- ;; Replace the value in `retweeted-status' with
- ;; that in `retweeting-status'.
- `(,sym . ,value-on-retweet))
- `(,sym . ,value))))
- retweeted-status)
- ,@(mapcar
- (lambda (entry)
- (let ((sym (car entry))
- (value (cdr entry)))
- `(,(intern (concat "retweeted-" (symbol-name sym)))
- . ,value)))
- retweeted-status)
- ,@(mapcar
- (lambda (entry)
- (let ((sym (car entry))
- (value (cdr entry)))
- `(,(intern (concat "retweeting-" (symbol-name sym)))
- . ,value)))
- retweeting-status))))
- (t
- (flet ((assq-get (item seq)
- (car (cddr (assq item seq)))))
- `(,@(mapcar
- (lambda (entry)
- (let* ((sym (elt entry 0))
- (sym-in-data (elt entry 1))
- (encoded (elt entry 2))
- (data (assq-get sym-in-data status-data)))
- `(,sym . ,(if encoded
- (twittering-decode-entities-after-parsing-xml
- data)
- data))))
- '(;; Raw entries.
- (id id)
- (in-reply-to-screen-name in_reply_to_screen_name)
- (in-reply-to-status-id in_reply_to_status_id)
- (recipient-screen-name recipient_screen_name)
- ;; Encoded entries.
- (text text t)
- ))
- ;; created_at
- (created-at . ,(date-to-time (assq-get 'created_at status-data)))
- ;; Replace "true" and "false" into t and nil.
- ,@(mapcar (lambda (sym)
- `(,sym . ,(string= "true" (assq-get sym status-data))))
- '(favorited truncated))
- ;; Entities.
- ,(let* ((entity-data (cddr (assq 'entities status-data)))
- (encoded-text (assq-get 'text status-data))
- (text
- (twittering-decode-entities-after-parsing-xml encoded-text))
- (gap-list (twittering-make-gap-list text)))
- (list
- 'entity
- ;; hashtags
- (cons
- 'hashtags
- (remove nil
- (mapcar
- (lambda (entry)
- (when (and (consp entry)
- (eq 'hashtag (car entry)))
- (let* ((data (cdr entry))
- (start-str (cdr (assq 'start (car data))))
- (end-str (cdr (assq 'end (car data))))
- (start (if (stringp start-str)
- (string-to-number start-str)
- 0))
- (end (if (stringp end-str)
- (string-to-number end-str)
- 0))
- (gap (twittering-get-gap start gap-list)))
- `((start . ,(- start gap))
- (end . ,(- end gap))
- (text . ,(elt (assq 'text data) 2))))))
- (assq 'hashtags entity-data))))
- ;; mentions
- (cons
- 'mentions
- (remove nil
- (mapcar
- (lambda (entry)
- (when (and (consp entry)
- (eq 'user_mention (car entry)))
- (let* ((data (cdr entry))
- (start-str (cdr (assq 'start (car data))))
- (end-str (cdr (assq 'end (car data))))
- (start (if (stringp start-str)
- (string-to-number start-str)
- 0))
- (end (if (stringp end-str)
- (string-to-number end-str)
- 0))
- (gap (twittering-get-gap start gap-list)))
- `((start . ,(- start gap))
- (end . ,(- end gap))
- (id . ,(elt (assq 'id data) 2))
- (screen-name
- . ,(elt (assq 'screen_name data) 2))
- (name
- . ,(elt (assq 'name data) 2))))))
- (assq 'user_mentions entity-data))))
- ;; urls
- (cons
- 'urls
- (remove nil
- (mapcar
- (lambda (entry)
- (when (and (consp entry)
- (eq 'url (car entry)))
- (let* ((data (cdr entry))
- (start-str (cdr (assq 'start (car data))))
- (end-str (cdr (assq 'end (car data))))
- (start (if (stringp start-str)
- (string-to-number start-str)
- 0))
- (end (if (stringp end-str)
- (string-to-number end-str)
- 0))
- (gap (twittering-get-gap start gap-list)))
- `((start . ,(- start gap))
- (end . ,(- end gap))
- (url . ,(elt (assq 'url data) 2))
- (display-url
- . ,(elt (assq 'display_url data) 2))
- (expanded-url
- . ,(elt (assq 'expanded_url data) 2))))))
- (assq 'urls entity-data))))))
- ;; Source.
- ,@(let ((source (twittering-decode-html-entities
- (assq-get 'source status-data))))
- (if (and source
- (string-match "<a href=\"\\(.*?\\)\".*?>\\(.*\\)</a>"
- source))
- (let ((uri (match-string-no-properties 1 source))
- (caption (match-string-no-properties 2 source)))
- `((source . ,caption)
- (source-uri . ,uri)))
- `((source . ,source)
- (source-uri . ""))))
- ;; Items related to the user that posted the tweet.
- ,@(let ((user-data (cddr (assq 'user status-data))))
- (mapcar
- (lambda (entry)
- (let* ((sym (elt entry 0))
- (sym-in-user-data (elt entry 1))
- (encoded (elt entry 2))
- (value (assq-get sym-in-user-data user-data)))
- `(,sym . ,(if encoded
- (twittering-decode-html-entities value)
- value))))
- '(;; Raw entries.
- (user-id id)
- (user-profile-image-url profile_image_url)
- (user-url url)
- ;; Encoded entries.
- (user-name name t)
- (user-screen-name screen_name t)
- (user-location location t)
- (user-description description t))))
- ,@(let ((user-data (cddr (assq 'user status-data))))
- (mapcar (lambda (entry)
- `(,(car entry)
- . ,(string= "true"
- (assq-get (cdr entry) user-data))))
- '((user-protected . protected))))))))))
-
-(defun twittering-xmltree-to-status (xmltree)
- (setq xmltree
- (cond
- ((eq 'direct-messages (caar xmltree))
- `(,@(mapcar
- (lambda (c-node)
- `(status nil
- (created_at
- nil ,(caddr (assq 'created_at c-node)))
- (id nil ,(caddr (assq 'id c-node)))
- (text nil ,(caddr (assq 'text c-node)))
- (source nil ,(format "%s" (car c-node))) ;; fake
- (truncated nil "false")
- (in_reply_to_status_id nil)
- (in_reply_to_user_id
- nil ,(caddr (assq 'recipient_id c-node)))
- (favorited nil "false")
- (recipient_screen_name
- nil ,(caddr (assq 'recipient_screen_name c-node)))
- (user nil ,@(cdddr (assq 'sender c-node)))
- (entities nil ,@(cdddr (assq 'entities c-node)))))
- (remove nil
- (mapcar
- (lambda (node)
- (and (consp node) (eq 'direct_message (car node))
- node))
- (cdr-safe (assq 'direct-messages xmltree))))
- )))
- ((eq 'statuses (caar xmltree))
- (cddr (car xmltree)))
- (t ;; unknown format?
- nil)))
-
- (mapcar #'twittering-normalize-raw-status
- ;; quirk to treat difference between xml.el in Emacs21 and Emacs22
- ;; On Emacs22, there may be blank strings
- (remove nil (mapcar (lambda (x)
- (if (consp x) x))
- xmltree))))
-
-(defun twittering-decode-entities-after-parsing-xml (encoded-str)
- "Decode ENCODED-STR retrieved by parsing XML and return the result.
-On Emacs 22 and later, `xml-parse-region' resolves numeric character
-references. It is redundant to resolve numeric character references
-again. However, in a XML response from Twitter, the two characters,
-\"<\" and \">\", are doubly escaped as \"&lt;\" and \"&gt;\",
-respectively. Then, they are represented as \"<\" and \">\" in
-the result of `xml-parse-region'. This function decodes them.
-
-On Emacs 21, `xml-parse-region' does not resolve numeric character
-references. This function decodes them."
- (cond
- ((null encoded-str)
- "")
- ((> 22 emacs-major-version)
- (replace-regexp-in-string
- "&#\\([0-9]+\\);"
- (lambda (str)
- (let ((number-entity
- (progn
- (string-match "&#\\([0-9]+\\);" str)
- (match-string 1 str))))
- (char-to-string
- (twittering-ucs-to-char (string-to-number number-entity)))))
- encoded-str))
- (t
- (replace-regexp-in-string
- "&\\(?:\\(gt\\)\\|\\(lt\\)\\);"
- (lambda (str)
- (if (match-beginning 1)
- ">"
- "<"))
- encoded-str))))
-
-(defun twittering-decode-html-entities (encoded-str)
- (if encoded-str
- (let ((cursor 0)
- (found-at nil)
- (result '()))
- (while (setq found-at
- (string-match "&\\(#\\([0-9]+\\)\\|\\([a-zA-Z]+\\)\\);"
- encoded-str cursor))
- (when (> found-at cursor)
- (list-push (substring encoded-str cursor found-at) result))
- (let ((number-entity (match-string-no-properties 2 encoded-str))
- (letter-entity (match-string-no-properties 3 encoded-str)))
- (cond (number-entity
- (list-push
- (char-to-string
- (twittering-ucs-to-char
- (string-to-number number-entity))) result))
- (letter-entity
- (cond ((string= "gt" letter-entity) (list-push ">" result))
- ((string= "lt" letter-entity) (list-push "<" result))
- ((string= "quot" letter-entity) (list-push "\"" result))
- (t (list-push "?" result))))
- (t (list-push "?" result)))
- (setq cursor (match-end 0))))
- (list-push (substring encoded-str cursor) result)
- (apply 'concat (nreverse result)))
- ""))
-
-;; JSON
-(defun twittering-extract-common-element-from-json (json-object)
- "Extract common parameters of a tweet from JSON-OBJECT.
-Return an alist including text, created_at and entities, which are common
-to JSON objects from ordinary timeline and search timeline."
- (let* ((encoded-text (cdr (assq 'text json-object)))
- (text
- (twittering-decode-entities-after-parsing-xml encoded-text))
- (gap-list (twittering-make-gap-list text))
- (entities (cdr (assq 'entities json-object)))
- (urls (cdr (assq 'urls entities)))
- (hashtags (cdr (assq 'hashtags entities)))
- (mentions (cdr (assq 'user_mentions entities))))
- `((text . ,text)
- (created-at
- . ,(apply 'encode-time
- (parse-time-string (cdr (assq 'created_at json-object)))))
- (entity
- (hashtags . ,(mapcar (lambda (entry)
- (let* ((indices (cdr (assq 'indices entry)))
- (start (elt indices 0))
- (end (elt indices 1))
- (gap
- (twittering-get-gap start gap-list)))
- `((start . ,(- start gap))
- (end . ,(- end gap))
- (text . ,(cdr (assq 'text entry))))))
- hashtags))
- (mentions . ,(mapcar (lambda (entry)
- (let* ((indices (cdr (assq 'indices entry)))
- (start (elt indices 0))
- (end (elt indices 1))
- (gap
- (twittering-get-gap start gap-list)))
- `((start . ,(- start gap))
- (end . ,(- end gap))
- (id . ,(cdr (assq 'id_str entry)))
- (name . ,(cdr (assq 'name entry)))
- (screen-name
- . ,(cdr (assq 'screen_name entry))))))
- mentions))
- (urls . ,(mapcar (lambda (entry)
- (let* ((indices (cdr (assq 'indices entry)))
- (start (elt indices 0))
- (end (elt indices 1))
- (gap (twittering-get-gap start gap-list)))
- `((start . ,(- start gap))
- (end . ,(- end gap))
- (url . ,(cdr (assq 'url entry)))
- (display-url
- . ,(cdr (assq 'display_url entry)))
- (expanded-url
- . ,(cdr (assq 'expanded_url entry))))))
- urls))))))
-
-(defun twittering-json-object-to-a-status (json-object)
- "Convert JSON-OBJECT representing a tweet into an alist representation.
-JSON-OBJECT must originate in an ordinary timeline, not a search timeline.
-To convert a JSON object from a search timeline, use
-`twittering-json-object-to-a-status-on-search'."
- (let* ((raw-retweeted-status (cdr (assq 'retweeted_status json-object))))
- (cond
- (raw-retweeted-status
- (let ((retweeted-status
- (twittering-json-object-to-a-status-base raw-retweeted-status))
- (retweeting-status
- (twittering-json-object-to-a-status-base json-object))
- (items-overwritten-by-retweet
- '(id)))
- `(,@(mapcar
- (lambda (entry)
- (let ((sym (car entry))
- (value (cdr entry)))
- (if (memq sym items-overwritten-by-retweet)
- (let ((value-on-retweet
- (cdr (assq sym retweeting-status))))
- ;; Replace the value in `retweeted-status' with
- ;; that in `retweeting-status'.
- `(,sym . ,value-on-retweet))
- `(,sym . ,value))))
- retweeted-status)
- ,@(mapcar
- (lambda (entry)
- (let ((sym (car entry))
- (value (cdr entry)))
- `(,(intern (concat "retweeted-" (symbol-name sym)))
- . ,value)))
- retweeted-status)
- ,@(mapcar
- (lambda (entry)
- (let ((sym (car entry))
- (value (cdr entry)))
- `(,(intern (concat "retweeting-" (symbol-name sym)))
- . ,value)))
- retweeting-status))))
- (t
- (twittering-json-object-to-a-status-base json-object)))))
-
-(defun twittering-json-object-to-a-status-base (json-object)
- (let ((user-data (cdr (assq 'user json-object))))
- `(,@(twittering-extract-common-element-from-json json-object)
- ,@(let ((symbol-table
- '((favorited . favorited)
- (id_str . id)
- (in_reply_to_screen_name . in-reply-to-screen-name)
- (in_reply_to_status_id_str . in-reply-to-status-id)
- (recipient_screen_name . recipient-screen-name)
- (truncated . truncated))))
- (remove nil
- (mapcar
- (lambda (entry)
- (let* ((sym (car entry))
- (value (cdr entry))
- (value
- (if (and (memq sym '(favorited truncated))
- (eq value :json-false))
- nil
- value))
- (dest (cdr (assq sym symbol-table))))
- (when (and dest value)
- `(,dest . ,value))))
- json-object)))
- ;; source
- ,@(let ((source (cdr (assq 'source json-object))))
- (if (and source
- (string-match "<a href=\"\\(.*?\\)\".*?>\\(.*\\)</a>"
- source))
- (let ((uri (match-string-no-properties 1 source))
- (caption (match-string-no-properties 2 source)))
- `((source . ,caption)
- (source-uri . ,uri)))
- `((source . ,source)
- (source-uri . ""))))
- ;; user data
- ,@(let ((symbol-table
- '((id_str . user-id)
- (profile_image_url . user-profile-image-url)
- (url . user-url)
- (protected . user-protected)
- (name . user-name)
- (screen_name . user-screen-name)
- (location . user-location)
- (description . user-description))))
- (remove nil
- (mapcar (lambda (entry)
- (let* ((sym (car entry))
- (value (cdr entry))
- (value
- (if (and (eq sym 'protected)
- (eq value :json-false))
- nil
- value)))
- (when value
- (let ((dest (cdr (assq sym symbol-table))))
- (when dest
- `(,dest . ,value))))))
- user-data))))))
-
-(defun twittering-json-object-to-a-status-on-search (json-object)
- "Convert JSON-OBJECT representing a tweet into an alist representation.
-JSON-OBJECT must originate in a search timeline.
-To convert a JSON object from other timelines, use
-`twittering-json-object-to-a-status'."
- `(,@(twittering-extract-common-element-from-json json-object)
- ,@(let ((symbol-table
- '((id_str . id)
- (to_user . in-reply-to-screen-name)
- (in_reply_to_status_id_str . in-reply-to-status-id)
- ;; user data
- (from_user_id_str . user-id)
- (profile_image_url . user-profile-image-url)
- (from_user_name . user-name)
- (from_user . user-screen-name))))
- (remove nil
- (mapcar
- (lambda (entry)
- (let* ((sym (car entry))
- (value (cdr entry))
- (dest (cdr (assq sym symbol-table))))
- (when (and dest value)
- `(,dest . ,value))))
- json-object)))
- ;; source
- ,@(let ((source
- (twittering-decode-html-entities
- (cdr (assq 'source json-object)))))
- (if (and source
- (string-match "<a href=\"\\(.*?\\)\".*?>\\(.*\\)</a>"
- source))
- (let ((uri (match-string-no-properties 1 source))
- (caption (match-string-no-properties 2 source)))
- `((source . ,caption)
- (source-uri . ,uri)))
- `((source . ,source)
- (source-uri . ""))))))
-
-(defun twittering-json-object-to-a-status-on-direct-messages (json-object)
- "Convert JSON-OBJECT representing a tweet into an alist representation.
-JSON-OBJECT must originate in timelines related to direct messages.
-To convert a JSON object from other timelines, use
-`twittering-json-object-to-a-status'."
- `(,@(twittering-extract-common-element-from-json json-object)
- ,@(let ((symbol-table
- '((id_str . id)
- (recipient_screen_name . recipient-screen-name))))
- (remove nil
- (mapcar
- (lambda (entry)
- (let* ((sym (car entry))
- (value (cdr entry))
- (dest (cdr (assq sym symbol-table))))
- (when (and dest value)
- `(,dest . ,value))))
- json-object)))
- ;; sender
- ,@(let ((symbol-table
- '((id_str . user-id)
- (name . user-name)
- (profile_image_url . user-profile-image-url)
- (protected . user-protected)
- (screen_name . user-screen-name))))
- (remove nil
- (mapcar
- (lambda (entry)
- (let* ((sym (car entry))
- (value (cdr entry))
- (value
- (cond
- ((eq sym 'protected)
- (if (eq value :json-false)
- nil
- t))
- ((eq value :json-false)
- nil)
- (t
- value))))
- (when value
- (let ((dest (cdr (assq sym symbol-table))))
- (when dest
- `(,dest . ,value))))))
- (cdr (assq 'sender json-object)))))))
-
-;;;;
-;;;; List info retrieval
-;;;;
-
-(defun twittering-get-list-index (username)
- (twittering-call-api
- 'get-list-index
- `((username . ,username)
- (sentinel . twittering-http-get-list-index-sentinel))))
-
-(defun twittering-get-list-subscriptions (username)
- (twittering-call-api
- 'get-list-subscriptions
- `((username . ,username)
- (sentinel . twittering-http-get-list-subscriptions-sentinel))))
-
-(defun twittering-get-list-sync (username function)
- (setq twittering-list-index-retrieved nil)
- (let ((proc (funcall function username)))
- (when proc
- (twittering-wait-while nil 0.1
- (and (not twittering-list-index-retrieved)
- (twittering-process-alive-p proc)))
- (when (and (not twittering-list-index-retrieved)
- (not (twittering-process-alive-p proc)))
- ;; If the process has been dead, wait a moment because
- ;; Emacs may be in the middle of evaluating the sentinel.
- (twittering-wait-while 10 0.1
- (not twittering-list-index-retrieved)))))
- (cond
- ((null twittering-list-index-retrieved)
- (message "Failed to retrieve %s's lists." username)
- nil)
- ((stringp twittering-list-index-retrieved)
- (if (string= "" twittering-list-index-retrieved)
- (message "%s does not have a list." username)
- (message "%s" twittering-list-index-retrieved))
- nil)
- ((listp twittering-list-index-retrieved)
- twittering-list-index-retrieved)))
-
-(defun twittering-get-list-index-sync (username)
- (twittering-get-list-sync username 'twittering-get-list-index))
-
-(defun twittering-get-list-subscriptions-sync (username)
- (twittering-get-list-sync username 'twittering-get-list-subscriptions))
-
-;;;;
-;;;; Buffer info
-;;;;
-
-(defvar twittering-buffer-info-list nil
- "List of buffers managed by `twittering-mode'.")
-
-(defun twittering-get-buffer-list ()
- "Return buffers managed by `twittering-mode'."
- (twittering-unregister-killed-buffer)
- twittering-buffer-info-list)
-
-(defun twittering-get-active-buffer-list ()
- "Return active buffers managed by `twittering-mode', where statuses are
-retrieved periodically."
- (twittering-unregister-killed-buffer)
- (remove nil
- (mapcar (lambda (buffer)
- (if (twittering-buffer-active-p buffer)
- buffer
- nil))
- twittering-buffer-info-list)))
-
-(defun twittering-buffer-p (&optional buffer)
- "Return t if BUFFER is managed by `twittering-mode'.
-BUFFER defaults to the the current buffer."
- (let ((buffer (or buffer (current-buffer))))
- (and (buffer-live-p buffer)
- (memq buffer twittering-buffer-info-list))))
-
-(defun twittering-buffer-related-p ()
- "Return t if current buffer relates to `twittering-mode'."
- (or (twittering-buffer-p)
- (eq major-mode 'twittering-edit-mode)
- (string= (buffer-name (current-buffer))
- twittering-debug-buffer)))
-
-(defun twittering-buffer-active-p (&optional buffer)
- "Return t if BUFFER is an active buffer managed by `twittering-mode'.
-BUFFER defaults to the the current buffer."
- (let ((buffer (or buffer (current-buffer))))
- (and (twittering-buffer-p buffer)
- (with-current-buffer buffer
- twittering-active-mode))))
-
-(defun twittering-get-buffer-from-spec (spec)
- "Return the buffer bound to SPEC. If no buffers are bound to SPEC,
-return nil."
- (let* ((spec-string (twittering-timeline-spec-to-string spec))
- (buffers
- (remove
- nil
- (mapcar
- (lambda (buffer)
- (if (twittering-equal-string-as-timeline
- spec-string
- (twittering-get-timeline-spec-string-for-buffer buffer))
- buffer
- nil))
- (twittering-get-buffer-list)))))
- (if buffers
- ;; We assume that the buffer with the same spec is unique.
- (car buffers)
- nil)))
-
-(defun twittering-get-buffer-from-spec-string (spec-string)
- "Return the buffer bound to SPEC-STRING. If no buffers are bound to it,
-return nil."
- (let ((spec (twittering-string-to-timeline-spec spec-string)))
- (and spec (twittering-get-buffer-from-spec spec))))
-
-(defun twittering-get-timeline-spec-for-buffer (buffer)
- "Return the timeline spec bound to BUFFER. If BUFFER is not managed by
-`twittering-mode', return nil."
- (when (twittering-buffer-p buffer)
- (with-current-buffer buffer
- twittering-timeline-spec)))
-
-(defun twittering-get-timeline-spec-string-for-buffer (buffer)
- "Return the timeline spec string bound to BUFFER. If BUFFER is not managed
-by `twittering-mode', return nil."
- (when (twittering-buffer-p buffer)
- (with-current-buffer buffer
- twittering-timeline-spec-string)))
-
-(defun twittering-current-timeline-spec ()
- "Return the timeline spec bound to the current buffer. If it is not managed
-by `twittering-mode', return nil."
- (twittering-get-timeline-spec-for-buffer (current-buffer)))
-
-(defun twittering-current-timeline-spec-string ()
- "Return the timeline spec string bound to the current buffer. If it is not
-managed by `twittering-mode', return nil."
- (twittering-get-timeline-spec-string-for-buffer (current-buffer)))
-
-(defun twittering-unregister-buffer (buffer &optional keep-timer)
- "Unregister BUFFER from `twittering-buffer-info-list'.
-If BUFFER is the last managed buffer and KEEP-TIMER is nil, call
-`twittering-stop' to stop timers."
- (when (memq buffer twittering-buffer-info-list)
- (setq twittering-buffer-info-list
- (delq buffer twittering-buffer-info-list))
- (when (and (null twittering-buffer-info-list)
- (not keep-timer))
- (twittering-stop))))
-
-(defun twittering-unregister-killed-buffer ()
- "Unregister buffers which has been killed."
- (mapc (lambda (buffer)
- (unless (buffer-live-p buffer)
- (twittering-unregister-buffer buffer)))
- twittering-buffer-info-list))
-
-(defun twittering-replace-spec-string-for-buffer (buffer spec-string)
- "Replace the timeline spec string for BUFFER with SPEC-STRING when
-BUFFER is managed by `twittering-mode' and SPEC-STRING is equivalent
-to the current one."
- (when (twittering-buffer-p buffer)
- (let ((current (twittering-get-timeline-spec-string-for-buffer buffer)))
- (when (and (not (string= current spec-string))
- (twittering-equal-string-as-timeline current spec-string))
- (with-current-buffer buffer
- (rename-buffer spec-string t)
- (setq twittering-timeline-spec-string spec-string))))))
-
-(defun twittering-set-active-flag-for-buffer (buffer active)
- "Set ACTIVE to active-flag for BUFFER."
- (when (twittering-buffer-p buffer)
- (let ((current (twittering-buffer-active-p buffer)))
- (when (or (and active (not current))
- (and (not active) current))
- (twittering-toggle-activate-buffer buffer)))))
-
-(defun twittering-toggle-activate-buffer (&optional buffer)
- "Toggle whether to retrieve timeline for the current buffer periodically."
- (interactive)
- (let ((buffer (or buffer (current-buffer))))
- (when (twittering-buffer-p buffer)
- (with-current-buffer buffer
- (let* ((new-mode (not twittering-active-mode))
- (active-buffer-list (twittering-get-active-buffer-list))
- (start-timer (and new-mode (null active-buffer-list))))
- (setq twittering-active-mode new-mode)
- (when start-timer
- (twittering-start))
- (twittering-update-mode-line))))))
-
-(defun twittering-activate-buffer (&optional buffer)
- "Activate BUFFER to retrieve timeline for it periodically."
- (interactive)
- (let ((buffer (or buffer (current-buffer))))
- (twittering-set-active-flag-for-buffer buffer t)))
-
-(defun twittering-deactivate-buffer (&optional buffer)
- "Deactivate BUFFER not to retrieve timeline for it periodically."
- (interactive)
- (let ((buffer (or buffer (current-buffer))))
- (twittering-set-active-flag-for-buffer buffer nil)))
-
-(defun twittering-kill-buffer (&optional buffer)
- "Kill BUFFER managed by `twittering-mode'."
- (interactive)
- (let ((buffer (or buffer (current-buffer))))
- (when (twittering-buffer-p buffer)
- (twittering-deactivate-buffer buffer)
- (kill-buffer buffer)
- (twittering-unregister-killed-buffer))))
-
-(defun twittering-get-managed-buffer (spec)
- "Return the buffer bound to SPEC. If no buffers are bound to SPEC, return
-newly generated buffer.
-SPEC may be a timeline spec or a timeline spec string."
- (let* ((original-spec spec)
- (spec-string (if (stringp spec)
- spec
- (twittering-timeline-spec-to-string spec)))
- ;; `spec-string' without text properties is required because
- ;; Emacs21 displays `spec-string' with its properties on mode-line.
- ;; In addition, copying `spec-string' keeps timeline-data from
- ;; being modified by `minibuf-isearch.el'.
- (spec-string (copy-sequence spec-string))
- (spec (if (stringp spec-string)
- (twittering-string-to-timeline-spec spec-string)
- nil)))
- (when (null spec)
- (error "\"%s\" is invalid as a timeline spec"
- (or spec-string original-spec)))
- (set-text-properties 0 (length spec-string) nil spec-string)
- (twittering-add-timeline-history spec-string)
- (let ((buffer (twittering-get-buffer-from-spec spec)))
- (if buffer
- (progn
- (twittering-replace-spec-string-for-buffer buffer spec-string)
- (twittering-update-mode-line)
- buffer)
- (let ((buffer (generate-new-buffer spec-string))
- (start-timer (null twittering-buffer-info-list)))
- (add-to-list 'twittering-buffer-info-list buffer t)
- (with-current-buffer buffer
- (twittering-mode-setup spec-string)
- (twittering-rerender-timeline-all buffer)
- (when (twittering-account-authorized-p)
- (when start-timer
- ;; If `buffer' is the first managed buffer,
- ;; call `twittering-start' to start timers.
- (twittering-start))
- (unless (and start-timer twittering-active-mode)
- ;; If `buffer' is active and the first managed buffer,
- ;; `twittering-start' invokes
- ;; `twittering-get-and-render-timeline' indirectly.
- ;; Otherwise, `twittering-get-and-render-timeline' should be
- ;; invoked here.
- (twittering-get-and-render-timeline))))
- buffer)))))
-
-;;;;
-;;;; Icon mode
-;;;;
-
-(defvar twittering-icon-mode nil
- "You MUST NOT CHANGE this variable directly.
-You should change through function `twittering-icon-mode'.")
-
-(defun twittering-icon-mode (&optional arg)
- "Toggle display of icon images on timelines.
-With a numeric argument, if the argument is positive, turn on
-icon mode; otherwise, turn off icon mode."
- (interactive "P")
- (let ((prev-mode twittering-icon-mode))
- (setq twittering-icon-mode
- (if (null arg)
- (not twittering-icon-mode)
- (< 0 (prefix-numeric-value arg))))
- (unless (eq prev-mode twittering-icon-mode)
- (twittering-update-mode-line)
- (twittering-rerender-timeline-all (current-buffer) t))))
-
-(defvar twittering-icon-prop-hash (make-hash-table :test 'equal)
- "Hash table for storing display properties of icon. The key is the size of
-icon and the value is a hash. The key of the child hash is URL and its value
-is the display property for the icon.")
-
-(defvar twittering-convert-program (executable-find "convert"))
-(defvar twittering-convert-fix-size 48)
-(defvar twittering-use-convert (not (null twittering-convert-program))
- "*This variable makes a sense only if `twittering-convert-fix-size'
-is non-nil. If this variable is non-nil, icon images are converted by
-invoking \"convert\". Otherwise, cropped images are displayed.")
-
-(defvar twittering-fallback-image-format 'xpm
- "*Fallback format used for displaying an image without a supproted format.
-Images which Emacs does not supports are converted into the fallback image
-format.")
-
-(defvar twittering-use-profile-image-api nil
- "*Whether to use `profile_image' API for retrieving scaled icon images.
-NOTE: This API is rate limited and is obsolete in the Twitter REST API v1.1.")
-
-(defvar twittering-icon-storage-file
- (expand-file-name "~/.twittering-mode-icons.gz")
- "*The file to which icon images are stored.
-`twittering-icon-storage-limit' determines the number icons stored in the
-file.
-The file is loaded with `with-auto-compression-mode'.")
-
-(defvar twittering-use-icon-storage nil
- "*Whether to use the persistent icon storage.
-If this variable is non-nil, icon images are stored to the file specified
-by `twittering-icon-storage-file'.")
-
-(defvar twittering-icon-storage-recent-icons nil
- "List of recently rendered icons.")
-
-(defvar twittering-icon-storage-limit 500
- "*How many icons are stored in the persistent storage.
-If `twittering-use-icon-storage' is nil, this variable is ignored.
-If a positive integer N, `twittering-save-icon-properties' saves N icons that
-have been recently rendered.
-If nil, the function saves all icons.")
-
-(defconst twittering-error-icon-data-pair
- '(xpm . "/* XPM */
-static char * yellow3_xpm[] = {
-\"16 16 2 1\",
-\" c None\",
-\". c #FF0000\",
-\"................\",
-\". .\",
-\". . . .\",
-\". . . .\",
-\". . . .\",
-\". . . .\",
-\". . . .\",
-\". .. .\",
-\". .. .\",
-\". . . .\",
-\". . . .\",
-\". . . .\",
-\". . . .\",
-\". . . .\",
-\". .\",
-\"................\"};
-")
- "Image used when the valid icon cannot be retrieved.")
-
-(defun twittering-update-icon-storage-recent-icons (size image-url spec)
- (unless (null twittering-icon-storage-limit)
- (let ((dummy-icon-properties (twittering-make-display-spec-for-icon
- twittering-error-icon-data-pair)))
- (unless (equal spec dummy-icon-properties)
- (let ((history-delete-duplicates t))
- (twittering-add-to-history 'twittering-icon-storage-recent-icons
- (list size image-url)
- twittering-icon-storage-limit))))))
-
-(defun twittering-get-display-spec-for-icon (image-url)
- (let ((hash
- (gethash twittering-convert-fix-size twittering-icon-prop-hash)))
- (when hash
- (let ((spec (gethash image-url hash))
- (size twittering-convert-fix-size))
- (when spec
- (twittering-update-icon-storage-recent-icons size image-url spec)
- spec)))))
-
-(defun twittering-convert-image-data (image-data dest-type &optional src-type)
- "Convert IMAGE-DATA into XPM format and return it. If it fails to convert,
-return nil."
- (with-temp-buffer
- (set-buffer-multibyte nil)
- (buffer-disable-undo)
- (let ((coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- (require-final-newline nil)
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (insert image-data)
- (let* ((args
- `(,@(when (<= emacs-major-version 22)
- ;; Emacs22 and earlier raises "Color allocation error"
- ;; on decoding a XPM image with opacity. To ignore
- ;; opacity, the option "+matte" is added.
- '("+matte"))
- ,@(unless (fboundp 'create-animated-image)
- '("-flatten"))
- ,(if src-type (format "%s:-" src-type) "-")
- ,@(when (integerp twittering-convert-fix-size)
- `("-resize"
- ,(format "%dx%d" twittering-convert-fix-size
- twittering-convert-fix-size)))
- ,(format "%s:-" dest-type)))
- (exit-status
- (apply 'call-process-region (point-min) (point-max)
- twittering-convert-program t `(t nil) nil args)))
- (if (equal 0 exit-status)
- (buffer-string)
- ;; failed to convert the image.
- nil)))))
-
-(defun twittering-create-image-pair (image-data)
- "Return a pair of image type and image data.
-IMAGE-DATA is converted by `convert' if the image type of IMAGE-DATA is not
-available and `twittering-use-convert' is non-nil."
- (let* ((image-type (and image-data (image-type-from-data image-data)))
- (image-pair `(,image-type . ,image-data))
- (converted-size
- `(,twittering-convert-fix-size . ,twittering-convert-fix-size)))
- (cond
- ((null image-data)
- twittering-error-icon-data-pair)
- ((and (image-type-available-p image-type)
- (or (fboundp 'create-animated-image)
- (not (and twittering-use-convert
- (eq image-type 'gif))))
- (or (not (integerp twittering-convert-fix-size))
- (equal (image-size (create-image image-data image-type t) t)
- converted-size)))
- image-pair)
- (twittering-use-convert
- (let ((converted-data
- (twittering-convert-image-data image-data
- twittering-fallback-image-format)))
- (if converted-data
- `(,twittering-fallback-image-format . ,converted-data)
- twittering-error-icon-data-pair)))
- (t
- twittering-error-icon-data-pair))))
-
-(defun twittering-register-image-spec (image-url spec size)
- (let ((hash (gethash size twittering-icon-prop-hash)))
- (unless hash
- (setq hash (make-hash-table :test 'equal))
- (puthash size hash twittering-icon-prop-hash))
- (puthash image-url spec hash)))
-
-(defun twittering-register-image-data (image-url image-data &optional size)
- (let ((image-pair (twittering-create-image-pair image-data))
- (size (or size twittering-convert-fix-size)))
- (when image-pair
- (let ((spec (twittering-make-display-spec-for-icon image-pair)))
- (twittering-register-image-spec image-url spec size)
- spec))))
-
-(defun twittering-make-slice-spec (image-spec)
- "Return slice property for reducing the image size by cropping it."
- (let* ((size (image-size image-spec t))
- (width (car size))
- (height (cdr size))
- (fixed-length twittering-convert-fix-size)
- (half-fixed-length (/ fixed-length 2)))
- (if (or (< fixed-length width) (< fixed-length height))
- `(slice ,(max 0 (- (/ width 2) half-fixed-length))
- ,(max 0 (- (/ height 2) half-fixed-length))
- ,fixed-length ,fixed-length)
- `(slice 0 0 ,fixed-length ,fixed-length))))
-
-(defun twittering-make-display-spec-for-icon (image-pair)
- "Return the specification for `display' text property, which
-limits the size of an icon image IMAGE-PAIR up to FIXED-LENGTH. If
-the type of the image is not supported, nil is returned.
-
-If the size of the image exceeds FIXED-LENGTH, the center of the
-image are displayed."
- (let* ((type (car-safe image-pair))
- (data (cdr-safe image-pair))
- (raw-image-spec ;; without margins
- (create-image data type t))
- (slice-spec
- (when (and twittering-convert-fix-size (not twittering-use-convert))
- (twittering-make-slice-spec raw-image-spec)))
- (image-spec
- (if (fboundp 'create-animated-image) ;; Emacs24 or later
- (create-animated-image data type t :margin 2 :ascent 'center)
- (create-image data type t :margin 2 :ascent 'center))))
- (if slice-spec
- `(display (,image-spec ,slice-spec))
- `(display ,image-spec))))
-
-(defun twittering-make-icon-string (beg end image-url)
- (let ((display-spec (twittering-get-display-spec-for-icon image-url))
- (image-data (gethash image-url twittering-url-data-hash))
- (properties (and beg (text-properties-at beg)))
- (icon-string (copy-sequence " ")))
- (when properties
- (add-text-properties 0 (length icon-string) properties icon-string))
- (cond
- (display-spec
- (let ((icon-string (apply 'propertize "_"
- (append properties display-spec))))
- ;; Remove the property required no longer.
- (remove-text-properties 0 (length icon-string)
- '(need-to-be-updated nil)
- icon-string)
- icon-string))
- ((and (integerp image-data)
- (<= twittering-url-request-retry-limit image-data))
- ;; Try to retrieve the image no longer.
- (twittering-register-image-data image-url nil)
- (twittering-make-icon-string beg end image-url))
- ((and image-data (not (integerp image-data)))
- (twittering-register-image-data image-url image-data)
- (twittering-make-icon-string beg end image-url))
- (t
- (put-text-property 0 (length icon-string)
- 'need-to-be-updated
- `(twittering-make-icon-string ,image-url)
- icon-string)
- (twittering-url-retrieve-async image-url 'twittering-register-image-data)
- icon-string))))
-
-(defun twittering-save-icon-properties (&optional filename)
- (let ((filename (or filename twittering-icon-storage-file))
- (stored-data
- (cond
- ((null twittering-icon-storage-limit)
- (let ((result nil)
- (dummy-icon-properties (twittering-make-display-spec-for-icon
- twittering-error-icon-data-pair)))
- (maphash
- (lambda (size hash)
- (maphash (lambda (url properties)
- (unless (equal properties dummy-icon-properties)
- (setq result (cons (list size url) result))))
- hash))
- twittering-icon-prop-hash)
- result))
- (t
- (reverse twittering-icon-storage-recent-icons))))
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (when (require 'jka-compr nil t)
- (with-auto-compression-mode
- (let ((coding-system-for-write 'binary))
- (with-temp-file filename
- (insert "( 2 ")
- (prin1 (cons 'emacs-version emacs-version) (current-buffer))
- (insert "(icon-list ")
- (mapc
- (lambda (entry)
- (let* ((size (elt entry 0))
- (url (elt entry 1))
- (properties
- (gethash url
- (gethash size twittering-icon-prop-hash))))
- (insert (if size
- (format "(%d " size)
- "(nil "))
- (prin1 url (current-buffer))
- (insert " ")
- (prin1 properties (current-buffer))
- (insert ")\n")))
- stored-data)
- (insert "))")))))))
-
-(defun twittering-load-icon-properties (&optional filename)
- (let* ((filename (or filename twittering-icon-storage-file))
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory)
- (data
- (with-temp-buffer
- (condition-case err
- (cond
- ((and (require 'jka-compr)
- (file-exists-p filename))
- (with-auto-compression-mode
- (let ((coding-system-for-read 'binary)
- (coding-system-for-write 'binary))
- (insert-file-contents filename)))
- (read (current-buffer)))
- (t
- nil))
- (error
- (message "Failed to load icon images. %s" (cdr err))
- nil)))))
- (cond
- ((equal 2 (car data))
- (let ((version (cdr (assq 'emacs-version data))))
- (cond
- ((or (equal version emacs-version)
- (y-or-n-p
- (format "%s is generated by Emacs %s! Use it?"
- filename version)))
- (mapc (lambda (entry)
- (let ((size (elt entry 0))
- (url (elt entry 1))
- (properties (elt entry 2)))
- (twittering-update-icon-storage-recent-icons size url
- properties)
- (twittering-register-image-spec url properties size)))
- (cdr (assq 'icon-list data))))
- (t
- (message "Stopped loading icons")))))
- (t
- (mapc (lambda (entry)
- (let ((size (car entry))
- (prop-alist (cdr entry)))
- (mapc (lambda (entry)
- (let ((url (car entry))
- (properties (cdr entry)))
- (twittering-update-icon-storage-recent-icons
- size url properties)
- (twittering-register-image-spec url properties
- size)))
- prop-alist)))
- data)))))
-
-;;;;
-;;;; Mode-line
-;;;;
-
-;;; SSL
-(defconst twittering-ssl-indicator-image
- (when (image-type-available-p 'xpm)
- '(image :type xpm
- :ascent center
- :data
- "/* XPM */
-/*
- * Copyright (C) 2003 Yuuichi Teranishi <teranisiNOSPAMgohome.org>
- * Copyright (C) 2003 Kazu Yamamoto <kazuNOSPAMMew.org>
- * Copyright (C) 2004 Yoshifumi Nishida <nishidaNOSPAMcsl.sony.co.jp>
- * Copyright notice is the same as Mew's one.
- */
-static char * yellow3_xpm[] = {
-\"14 14 7 1\",
-\" c None\",
-\". c #B07403\",
-\"+ c #EFEE38\",
-\"@ c #603300\",
-\"# c #D0A607\",
-\"$ c #FAFC90\",
-\"% c #241100\",
-\" .++++@ \",
-\" .+@...+@ \",
-\" .+@ .+@ \",
-\" .+@ .+@ \",
-\" .+@ .+@ \",
-\"++########@@@@\",
-\"+$$++++++++#@@\",
-\"+$++++%@+++#@@\",
-\"+$+++%%%@++#@@\",
-\"+$+++%%%@++#@@\",
-\"+$++++%@+++#@@\",
-\"+$++++%@+++#@@\",
-\"+$+++++++++#@@\",
-\"++@@@@@@@@@@@@\"};
-"
-;;; The above image is copied from `mew-lock.xpm' distributed with Mew.
-;;; The copyright of the image is below, which is copied from `mew.el'.
-
-;;; Copyright Notice:
-
-;; Copyright (C) 1994-2009 Mew developing team.
-;; All rights reserved.
-
-;; Redistribution and use in source and binary forms, with or without
-;; modification, are permitted provided that the following conditions
-;; are met:
-;;
-;; 1. Redistributions of source code must retain the above copyright
-;; notice, this list of conditions and the following disclaimer.
-;; 2. Redistributions in binary form must reproduce the above copyright
-;; notice, this list of conditions and the following disclaimer in the
-;; documentation and/or other materials provided with the distribution.
-;; 3. Neither the name of the team nor the names of its contributors
-;; may be used to endorse or promote products derived from this software
-;; without specific prior written permission.
-;;
-;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
-;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE
-;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ))
- "Image for indicator of SSL state.")
-
-(defconst twittering-modeline-ssl
- (if twittering-ssl-indicator-image
- (propertize "SSL"
- 'display twittering-ssl-indicator-image
- 'help-echo "SSL is enabled.")
- "SSL"))
-
-;;; ACTIVE/INACTIVE
-(defconst twittering-active-indicator-image
- (when (image-type-available-p 'xpm)
- '(image :type xpm
- :ascent center
- :data
- "/* XPM */
-static char *plugged[] = {
-\"32 12 8 1\",
-\" c None\",
-\". c #a6caf0\",
-\"# c #8fa5cf\",
-\"a c #717171\",
-\"b c #5d5d97\",
-\"c c #8488ca\",
-\"d c #9f9f9f\",
-\"e c #7f8080\",
-\" ... \",
-\" .ccb.... \",
-\" accb####. \",
-\" .accb#####.. \",
-\" eeeeeeeeaccb#####.eeeeeeee \",
-\" dddddddcaccb#####.dedddddd \",
-\" dddddddcaccb#####.dedddddd \",
-\" eeeeeeeeaccb#####.eeeeeeee \",
-\" aaccb####aaa \",
-\" accbaaaaa \",
-\" aaaaaaaa \",
-\" aaa \"
-};
-"))
- "Image for indicator of active state."
-;;; The above image is copied from `plugged.xpm' distributed with Wanderlust
-;;; by Yuuichi Teranishi <teranisiNOSPAMgohome.org>.
-;;; The copyright of the image is below, which is copied from `COPYING' of
-;;; Wanderlust 2.14.
-;; Copyright (C) 1998-2001 Yuuichi Teranishi <teranisiNOSPAMgohome.org>
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-)
-
-(defconst twittering-inactive-indicator-image
- (when (image-type-available-p 'xpm)
- '(image :type xpm
- :ascent center
- :data
- "/* XPM */
-static char * unplugged_xpm[] = {
-\"32 12 9 1\",
-\" s None c None\",
-\". c tomato\",
-\"X c #a6caf0\",
-\"o c #8488ca\",
-\"O c #5d5d97\",
-\"+ c #8fa5cf\",
-\"@ c #717171\",
-\"# c #7f8080\",
-\"$ c #9f9f9f\",
-\" XXX...... \",
-\" ... ... \",
-\" ..O ....X \",
-\" ..oO ...+..XX \",
-\" ######.ooO ...+++.X##### \",
-\" $$$$$o.ooO ...@+++.X$#$$$ \",
-\" $$$$$o.ooO ... @+++.X$#$$$ \",
-\" ######.ooO... @+++.X##### \",
-\" ..o... @++..@@ \",
-\" .... @@..@ \",
-\" ... ...@ \",
-\" ...... \"
-};
-"))
- "Image for indicator of inactive state."
-;;; The above image is copied from `unplugged.xpm' distributed with Wanderlust
-;;; by Yuuichi Teranishi <teranisiNOSPAMgohome.org>.
-;;; The copyright of the image is below, which is copied from `COPYING' of
-;;; Wanderlust 2.14.
-;; Copyright (C) 1998-2001 Yuuichi Teranishi <teranisiNOSPAMgohome.org>
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-)
-
-(defconst twittering-modeline-properties
- (when (display-mouse-p)
- `(local-map
- ,(purecopy (make-mode-line-mouse-map
- 'mouse-2 #'twittering-toggle-activate-buffer))
- help-echo "mouse-2 toggles activate buffer")))
-
-(defconst twittering-modeline-active
- (if twittering-active-indicator-image
- (apply 'propertize " "
- `(display ,twittering-active-indicator-image
- ,@twittering-modeline-properties))
- " "))
-
-(defconst twittering-modeline-inactive
- (if twittering-inactive-indicator-image
- (apply 'propertize "INACTIVE"
- `(display ,twittering-inactive-indicator-image
- ,@twittering-modeline-properties))
- "INACTIVE"))
-
-(defun twittering-mode-line-buffer-identification ()
- (let ((active-mode-indicator
- (if twittering-active-mode
- twittering-modeline-active
- twittering-modeline-inactive))
- (enabled-options
- `(,(if twittering-display-connection-method
- (concat
- (when twittering-use-ssl (concat twittering-modeline-ssl ":"))
- (twittering-get-connection-method-name twittering-use-ssl))
- (when twittering-use-ssl twittering-modeline-ssl))
- ,@(when twittering-jojo-mode '("jojo"))
- ,@(when twittering-icon-mode '("icon"))
- ,@(when twittering-reverse-mode '("reverse"))
- ,@(when twittering-proxy-use '("proxy")))))
- (concat active-mode-indicator
- (when twittering-display-remaining
- (let ((spec (twittering-current-timeline-spec)))
- (twittering-get-ratelimit-indicator-string spec)))
- (when enabled-options
- (concat "[" (mapconcat 'identity enabled-options " ") "]")))))
-
-(defun twittering-update-mode-line ()
- "Update mode line."
- (force-mode-line-update))
-
-;;;;
-;;;; Format of a status
-;;;;
-
-(eval-and-compile
- (defsubst twittering-make-common-properties (status)
- "Generate a property list that tweets should have irrespective of format."
- (apply 'append
- (mapcar (lambda (entry)
- (let ((prop-sym (if (consp entry) (car entry) entry))
- (status-sym (if (consp entry) (cdr entry) entry)))
- (list prop-sym (cdr (assq status-sym status)))))
- '(id retweeted-id source-spec
- (username . user-screen-name) text)))))
-
-(defun twittering-get-common-properties (pos)
- "Get a common property list of the tweet rendered at POS.
-The common property list is added to each rendered tweet irrespective
-of format. The common properties follows:
- properites generated by `twittering-make-common-properties',
- `field' and `rendered-as' generated by `twittering-render-a-field' or
- `twittering-make-properties-of-popped-ancestors'."
- (apply 'append
- (mapcar (lambda (prop)
- (let ((value (get-text-property pos prop)))
- (when value
- `(,prop ,value))))
- '(field id rendered-as retweeted-id source-spec
- text username))))
-
-(defun twittering-format-string (string prefix replacement-table)
- "Format STRING according to PREFIX and REPLACEMENT-TABLE.
-PREFIX is a regexp. REPLACEMENT-TABLE is a list of (FROM . TO) pairs,
-where FROM is a regexp and TO is a string or a 2-parameter function.
-
-The pairs in REPLACEMENT-TABLE are stored in order of precedence.
-First, search PREFIX in STRING from left to right.
-If PREFIX is found in STRING, try to match the following string with
-FROM of each pair in the same order of REPLACEMENT-TABLE. If FROM in
-a pair is matched, replace the prefix and the matched string with a
-string generated from TO.
-If TO is a string, the matched string is replaced with TO.
-If TO is a function, the matched string is replaced with the
-return value of (funcall TO CONTEXT), where CONTEXT is an alist.
-Each element of CONTEXT is (KEY . VALUE) and KEY is one of the
-following symbols;
- 'following-string --the matched string following the prefix
- 'match-data --the match-data for the regexp FROM.
- 'prefix --PREFIX.
- 'replacement-table --REPLACEMENT-TABLE.
- 'from --FROM.
- 'processed-string --the already processed string."
- (let ((current-pos 0)
- (result "")
- (case-fold-search nil))
- (while (and (string-match prefix string current-pos)
- (not (eq (match-end 0) current-pos)))
- (let ((found nil)
- (current-table replacement-table)
- (next-pos (match-end 0))
- (matched-string (match-string 0 string))
- (skipped-string
- (substring string current-pos (match-beginning 0))))
- (setq result (concat result skipped-string))
- (setq current-pos next-pos)
- (while (and (not (null current-table))
- (not found))
- (let ((key (caar current-table))
- (value (cdar current-table))
- (following-string (substring string current-pos))
- (case-fold-search nil))
- (if (string-match (concat "\\`" key) following-string)
- (let ((next-pos (+ current-pos (match-end 0)))
- (output
- (if (stringp value)
- value
- (funcall value
- `((following-string . ,following-string)
- (match-data . ,(match-data))
- (prefix . ,prefix)
- (replacement-table . ,replacement-table)
- (from . ,key)
- (processed-string . ,result))))))
- (setq found t)
- (setq current-pos next-pos)
- (setq result (concat result output)))
- (setq current-table (cdr current-table)))))
- (if (not found)
- (setq result (concat result matched-string)))))
- (let ((skipped-string (substring string current-pos)))
- (concat result skipped-string))
- ))
-
-(eval-and-compile
- (defsubst twittering-make-string-with-user-name-property (str status)
- (if str
- (let* ((user-screen-name (cdr (assq 'user-screen-name status)))
- (uri (twittering-get-status-url user-screen-name))
- (spec
- (twittering-make-user-timeline-spec-direct user-screen-name)))
- (propertize str
- 'mouse-face 'highlight
- 'keymap twittering-mode-on-uri-map
- 'uri uri
- 'screen-name-in-text user-screen-name
- 'goto-spec spec
- 'face 'twittering-username-face
- 'front-sticky nil
- 'rear-nonsticky t))
- ""))
-
- (defsubst twittering-make-string-with-source-property (str status)
- (if str
- (let ((uri (cdr (assq 'source-uri status))))
- (propertize str
- 'mouse-face 'highlight
- 'keymap twittering-mode-on-uri-map
- 'uri uri
- 'face 'twittering-uri-face
- 'source str
- 'front-sticky nil
- 'rear-nonsticky t))
- ""))
-
- (defsubst twittering-make-string-with-uri-property (str status)
- (if str
- (let ((uri
- (if (assq 'retweeted-id status)
- (twittering-get-status-url
- (cdr (assq 'retweeted-user-screen-name status))
- (cdr (assq 'retweeted-id status)))
- (twittering-get-status-url
- (cdr (assq 'user-screen-name status))
- (cdr (assq 'id status))))))
- (propertize str
- 'mouse-face 'highlight
- 'keymap twittering-mode-on-uri-map
- 'uri uri
- 'face 'twittering-uri-face
- 'front-sticky nil
- 'rear-nonsticky t))
- "")))
-
-(defun twittering-make-fontified-tweet-text (str-expr regexp-hash regexp-atmark)
- (let ((regexp-str
- (mapconcat
- 'identity
- (list
- ;; hashtag
- (concat regexp-hash "\\([[:alpha:]0-9_-]+\\)")
- ;; @USER/LIST
- (concat regexp-atmark
- "\\(\\([a-zA-Z0-9_-]+\\)/\\([a-zA-Z0-9_-]+\\)\\)")
- ;; @USER
- (concat regexp-atmark "\\([a-zA-Z0-9_-]+\\)")
- ;; URI
- "\\(https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+\\)")
- "\\|")))
- `(let ((pos 0)
- (str (copy-sequence ,str-expr)))
- (while (string-match ,regexp-str str pos)
- (let* ((beg (match-beginning 0))
- (end (match-end 0))
- (range-and-properties
- (cond
- ((get-text-property beg 'face str)
- ;; The matched substring has been already fontified.
- ;; The fontification with entities must fontify the
- ;; head of the matched string.
- nil)
- ((match-string 1 str)
- ;; hashtag
- (let* ((hashtag (match-string 1 str))
- (spec-string
- (twittering-make-hashtag-timeline-spec-string-direct
- hashtag))
- (url (twittering-get-search-url
- (concat "#" hashtag))))
- (list
- beg end
- 'mouse-face 'highlight
- 'keymap twittering-mode-on-uri-map
- 'uri url
- 'goto-spec spec-string
- 'face 'twittering-username-face)))
- ((match-string 2 str)
- ;; @USER/LIST
- (let ((owner (match-string 3 str))
- (list-name (match-string 4 str))
- ;; Properties are added to the matched part only.
- ;; The prefixes `twittering-regexp-atmark' will not
- ;; be highlighted.
- (beg (match-beginning 2)))
- (list
- beg end
- 'mouse-face 'highlight
- 'keymap twittering-mode-on-uri-map
- 'uri (twittering-get-list-url owner list-name)
- 'goto-spec
- (twittering-make-list-timeline-spec-direct owner
- list-name)
- 'face 'twittering-username-face)))
- ((match-string 5 str)
- ;; @USER
- (let ((screen-name (match-string 5 str))
- ;; Properties are added to the matched part only.
- ;; The prefixes `twittering-regexp-atmark' will not
- ;; be highlighted.
- (beg (match-beginning 5)))
- (list
- beg end
- 'mouse-face 'highlight
- 'keymap twittering-mode-on-uri-map
- 'uri (twittering-get-status-url screen-name)
- 'screen-name-in-text screen-name
- 'goto-spec
- (twittering-make-user-timeline-spec-direct screen-name)
- 'face 'twittering-uri-face)))
- ((match-string 6 str)
- ;; URI
- (let ((uri (match-string 6 str)))
- (list
- beg end
- 'mouse-face 'highlight
- 'keymap twittering-mode-on-uri-map
- 'uri uri
- 'uri-origin 'explicit-uri-in-tweet
- 'face 'twittering-uri-face)))))
- (beg (if range-and-properties
- (car range-and-properties)
- beg))
- (end (if range-and-properties
- (cadr range-and-properties)
- end))
- (properties
- `(,@(cddr range-and-properties)
- front-sticky nil
- rear-nonsticky t)))
- (when range-and-properties
- (add-text-properties beg end properties str))
- (setq pos end)))
- str)))
-
-(eval-and-compile
- (defsubst twittering-make-fontified-tweet-text-with-entity (status)
- (let* ((text (copy-sequence (cdr (assq 'text status))))
- (text-length (length text))
- (entities (cdr (assq 'entity status))))
- ;; hashtags
- (mapc (lambda (hashtag)
- (let* ((start (cdr (assq 'start hashtag)))
- (end (min (cdr (assq 'end hashtag)) text-length))
- (tag (cdr (assq 'text hashtag)))
- (spec-string
- (twittering-make-hashtag-timeline-spec-string-direct tag)))
- (set-text-properties
- start end
- `(mouse-face
- highlight
- keymap ,twittering-mode-on-uri-map
- uri ,(twittering-get-search-url (concat "#" tag))
- goto-spec ,spec-string
- face twittering-username-face
- front-sticky nil
- rear-nonsticky t)
- text)))
- (cdr (assq 'hashtags entities)))
- ;; mentions
- (mapc (lambda (mention)
- (let ((start (cdr (assq 'start mention)))
- (end (min (cdr (assq 'end mention)) text-length))
- (screen-name (cdr (assq 'screen-name mention))))
- (set-text-properties
- start end
- `(mouse-face
- highlight
- keymap ,twittering-mode-on-uri-map
- uri ,(twittering-get-status-url screen-name)
- screen-name-in-text ,screen-name
- goto-spec
- ,(twittering-make-user-timeline-spec-direct screen-name)
- face twittering-uri-face
- front-sticky nil
- rear-nonsticky t)
- text)))
- (cdr (assq 'mentions entities)))
- ;; urls
- (let ((offset 0))
- (mapc (lambda (url-info)
- (let* ((text-length (length text))
- (start (cdr (assq 'start url-info)))
- (end (cdr (assq 'end url-info)))
- (url (cdr (assq 'url url-info)))
- (expanded-url
- ;; If the `url' is short and not wrapped,
- ;; `expanded-url' is nil.
- (or (cdr (assq 'expanded-url url-info))
- url))
- (replacement
- (propertize
- expanded-url
- 'mouse-face 'highlight
- 'keymap twittering-mode-on-uri-map
- 'uri url
- 'uri-origin 'explicit-uri-in-tweet
- 'expanded-uri expanded-url
- 'face 'twittering-uri-face
- 'front-sticky nil
- 'rear-nonsticky t)))
- (setq text
- (concat
- (substring text 0 (min (+ offset start) text-length))
- replacement
- (substring text (min (+ offset end) text-length))))
- (setq offset
- (+ offset (- (length expanded-url) (- end start))))))
- (cdr (assq 'urls entities))))
- text)))
-
-(defun twittering-generate-format-table (status-sym prefix-sym)
- `(("%" . "%")
- ("}" . "}")
- ("#" . (cdr (assq 'id ,status-sym)))
- ("'" . (when (cdr (assq 'truncated ,status-sym))
- "..."))
- ("c" .
- (let ((system-time-locale "C"))
- (format-time-string "%a %b %d %H:%M:%S %z %Y"
- (cdr (assq 'created-at ,status-sym)))))
- ("d" . (cdr (assq 'user-description ,status-sym)))
- ("f" .
- (twittering-make-string-with-source-property
- (cdr (assq 'source ,status-sym)) ,status-sym))
- ("i" .
- (when (and twittering-icon-mode window-system)
- (let ((url
- (cond
- ((and twittering-use-profile-image-api
- (eq twittering-service-method 'twitter)
- (or (null twittering-convert-fix-size)
- (member twittering-convert-fix-size '(48 73))))
- (let ((user (cdr (assq 'user-screen-name ,status-sym)))
- (size
- (if (or (null twittering-convert-fix-size)
- (= 48 twittering-convert-fix-size))
- "normal"
- "bigger")))
- (format "http://%s/%s/%s.xml?size=%s" twittering-api-host
- (twittering-api-path "users/profile_image") user size)))
- (t
- (cdr (assq 'user-profile-image-url ,status-sym))))))
- (twittering-make-icon-string nil nil url))))
- ("j" . (cdr (assq 'user-id ,status-sym)))
- ("L" .
- (let ((location (or (cdr (assq 'user-location ,status-sym)) "")))
- (unless (string= "" location)
- (concat " [" location "]"))))
- ("l" . (cdr (assq 'user-location ,status-sym)))
- ("p" . (when (cdr (assq 'user-protected ,status-sym))
- "[x]"))
- ("r" .
- (let ((reply-id (or (cdr (assq 'in-reply-to-status-id ,status-sym)) ""))
- (reply-name (or (cdr (assq 'in-reply-to-screen-name ,status-sym))
- ""))
- (recipient-screen-name
- (cdr (assq 'recipient-screen-name ,status-sym))))
- (let* ((pair
- (cond
- (recipient-screen-name
- (cons (format "sent to %s" recipient-screen-name)
- (twittering-get-status-url recipient-screen-name)))
- ((and (not (string= "" reply-id))
- (not (string= "" reply-name)))
- (cons (format "in reply to %s" reply-name)
- (twittering-get-status-url reply-name reply-id)))
- (t nil)))
- (str (car pair))
- (url (cdr pair))
- (properties
- (list 'mouse-face 'highlight 'face 'twittering-uri-face
- 'keymap twittering-mode-on-uri-map
- 'uri url
- 'front-sticky nil
- 'rear-nonsticky t)))
- (when (and str url)
- (concat " " (apply 'propertize str properties))))))
- ("R" .
- (let ((retweeted-by
- (or (cdr (assq 'retweeting-user-screen-name ,status-sym)) "")))
- (unless (string= "" retweeted-by)
- (concat " (retweeted by " retweeted-by ")"))))
- ("S" .
- (twittering-make-string-with-user-name-property
- (cdr (assq 'user-name ,status-sym)) ,status-sym))
- ("s" .
- (twittering-make-string-with-user-name-property
- (cdr (assq 'user-screen-name ,status-sym)) ,status-sym))
- ("T" .
- ,(twittering-make-fontified-tweet-text
- `(twittering-make-fontified-tweet-text-with-entity ,status-sym)
- twittering-regexp-hash twittering-regexp-atmark))
- ("t" .
- ,(twittering-make-fontified-tweet-text
- `(twittering-make-fontified-tweet-text-with-entity ,status-sym)
- twittering-regexp-hash twittering-regexp-atmark))
- ("u" . (cdr (assq 'user-url ,status-sym)))))
-
-(defun twittering-generate-formater-for-first-spec (format-str status-sym prefix-sym)
- (cond
- ((string-match "\\`}" format-str)
- ;; "}" at the first means the end of the current level.
- `(nil . ,(substring format-str (match-end 0))))
- ((string-match "\\`%" format-str)
- (let* ((following (substring format-str 1))
- (table (twittering-generate-format-table status-sym prefix-sym))
- (regexp (concat "\\`\\(" (mapconcat 'car table "\\|") "\\)"))
- (case-fold-search nil))
- (cond
- ((string-match "\\`@\\({\\([^}]*\\)}\\)?" following)
- (let ((time-format (or (match-string 2 following)
- "%I:%M %p %B %d, %Y"))
- (rest (substring following (match-end 0))))
- `((let* ((created-at (cdr (assq 'created-at ,status-sym)))
- (url
- (if (assq 'retweeted-id ,status-sym)
- (twittering-get-status-url
- (cdr (assq 'retweeted-user-screen-name ,status-sym))
- (cdr (assq 'retweeted-id ,status-sym)))
- (twittering-get-status-url
- (cdr (assq 'user-screen-name ,status-sym))
- (cdr (assq 'id ,status-sym)))))
- (properties
- (list 'mouse-face 'highlight 'face 'twittering-uri-face
- 'keymap twittering-mode-on-uri-map
- 'uri url
- 'front-sticky nil
- 'rear-nonsticky t)))
- (twittering-make-passed-time-string
- nil nil created-at ,time-format properties))
- . ,rest)))
- ((string-match "\\`C\\({\\([^}]*\\)}\\)?" following)
- (let ((time-format (or (match-string 2 following) "%H:%M:%S"))
- (rest (substring following (match-end 0))))
- `((let* ((created-at (cdr (assq 'created-at ,status-sym))))
- (twittering-make-string-with-uri-property
- (format-time-string ,time-format created-at) ,status-sym))
- . ,rest)))
- ((string-match "\\`FACE\\[\\([a-zA-Z0-9:-]+\\)\\]{" following)
- (let* ((face-name-str (match-string 1 following))
- (str-after-brace (substring following (match-end 0)))
- (face-sym (intern face-name-str))
- (pair (twittering-generate-formater-for-current-level
- str-after-brace status-sym prefix-sym))
- (braced-body (car pair))
- (rest (cdr pair)))
- `((propertize (concat ,@braced-body) 'face ',face-sym)
- . ,rest)))
- ((string-match "\\`\\(FILL\\|FOLD\\)\\(\\[\\([^]]*\\)\\]\\)?{"
- following)
- (let* ((str-after-brace (substring following (match-end 0)))
- (specifier (match-string 1 following))
- (prefix-str (match-string 3 following))
- (pair (twittering-generate-formater-for-current-level
- str-after-brace status-sym prefix-sym))
- (filled-body (car pair))
- (formater
- `(lambda (,status-sym ,prefix-sym)
- (let ((,prefix-sym (concat ,prefix-sym ,prefix-str)))
- (concat ,@filled-body))))
- (keep-newline (string= "FOLD" specifier))
- (rest (cdr pair)))
- `((twittering-update-filled-string
- nil nil ,formater ,status-sym ,prefix-sym ,prefix-str
- ,keep-newline)
- . ,rest)))
- ((string-match "\\`RT{" following)
- (let* ((str-after-brace (substring following (match-end 0)))
- (pair (twittering-generate-formater-for-current-level
- str-after-brace 'retweeting prefix-sym))
- (braced-body (car pair))
- (rest (cdr pair)))
- `((when (assq 'retweeted-id ,status-sym)
- (let ((retweeting
- (mapcar (lambda (entry)
- (let ((key-str (symbol-name (car entry)))
- (value (cdr entry)))
- (when (string-match "\\`retweeting-" key-str)
- (let ((new-key
- (intern (substring key-str
- (match-end 0)))))
- (cons new-key value)))))
- ,status-sym)))
- (concat ,@braced-body)))
- . ,rest)))
- ((string-match regexp following)
- (let ((specifier (match-string 1 following))
- (rest (substring following (match-end 0))))
- `(,(cdr (assoc specifier table)) . ,rest)))
- (t
- `("%" . ,following)))))
- ((string-match "\\(%\\|}\\)" format-str)
- (let* ((sep (match-beginning 0))
- (first (substring format-str 0 sep))
- (last (substring format-str sep)))
- ;; Split before "%" or "}".
- `(,first . ,last)))
- (t
- `(,format-str . nil))))
-
-(defun twittering-generate-formater-for-current-level (format-str status-sym prefix-sym)
- (let ((result nil)
- (rest format-str)
- (continue t))
- (while (and continue rest)
- (let* ((pair
- (twittering-generate-formater-for-first-spec
- rest status-sym prefix-sym))
- (current-result (car pair)))
- (if current-result
- (setq result (append result `(,current-result)))
- ;; If `result' is nil, it means the end of the current level.
- (setq continue nil))
- (setq rest (cdr pair))))
- `(,result . ,rest)))
-
-(defun twittering-generate-format-status-function (format-str)
- (let* ((status-sym 'status)
- (prefix-sym 'prefix)
- (pair
- (twittering-generate-formater-for-current-level
- format-str status-sym prefix-sym))
- (body (car pair))
- (rest (cdr pair)))
- (cond
- ((null rest)
- `(lambda (status prefix)
- (let* ((common-properties (twittering-make-common-properties status))
- (str (concat ,@body))
- (str (if prefix
- (replace-regexp-in-string "^" prefix str)
- str))
- (next (next-single-property-change 0 'need-to-be-updated str))
- (need-to-be-updated
- (or (get-text-property 0 'need-to-be-updated str)
- (and next (< next (length str))))))
- (add-text-properties 0 (length str) common-properties str)
- (when (and prefix need-to-be-updated)
- ;; With a prefix, redisplay the total status instead of
- ;; redisplaying partially.
- (remove-text-properties 0 (length str)
- '(need-to-be-updated nil) str)
- (put-text-property 0 (length str) 'need-to-be-updated
- `(twittering-format-status-for-redisplay
- ,status ,prefix)
- str))
- str)))
- (t
- (message "Failed to generate a status formater for `twittering-mode'.")
- nil))))
-
-(defun twittering-update-status-format (&optional format-str)
- "Update the format for rendering a tweet.
-If FORMAT-STR is nil, `twittering-status-format' is used in place of
-FORMAT-STR.
-
-If FORMAT-STR is valid as a format, `twittering-format-status-function'
-is replaced by the result of `twittering-generate-format-status-function'
-for FORMAT-STR.
-If FORMAT-STR is invalid as a format, an error is signaled and
-`twittering-format-status-function' is not updated."
- (let ((format-str (or format-str twittering-status-format)))
- (unless (string= format-str twittering-format-status-function-source)
- (let* ((before (get-buffer "*Compile-Log*"))
- (func (twittering-generate-format-status-function format-str)))
- (cond
- ((and func (functionp func))
- (setq twittering-format-status-function-source format-str)
- (setq twittering-format-status-function (byte-compile func))
- (setq twittering-format-status-function-without-compile func)
- (setq twittering-status-format format-str)
- (let ((current (get-buffer "*Compile-Log*")))
- (when (and (null before) current (= 0 (buffer-size current)))
- (kill-buffer current))))
- (t
- (error "Invalid format: %s" format-str)
- nil))))))
-
-(defun twittering-format-status (status &optional prefix)
- "Format a STATUS by using `twittering-format-status-function'.
-Specification of FORMAT-STR is described in the document for the
-variable `twittering-status-format'."
- (funcall twittering-format-status-function status prefix))
-
-(defun twittering-format-status-for-redisplay (beg end status &optional prefix)
- (twittering-format-status status prefix))
-
-;;;;
-;;;; Rendering
-;;;;
-
-(defun twittering-field-id< (field1 field2)
- (string< field1 field2))
-
-(defun twittering-field-id= (field1 field2)
- (string= field1 field2))
-
-(defun twittering-make-field-id-from-id (id &optional base-id)
- "Generate a field property for the tweet corresponding to ID.
-Tweets are rendered in order of the field on `twittering-mode'.
-
-If BASE-ID is non-nil, generate a field id for a tweet rendered
-as a popped ancestor tweet by `twittering-show-replied-statuses'.
-In the case, BASE-ID means the ID of the descendant."
- (let ((format-func (lambda (id) (format "%02d-%s" (length id) id))))
- (cond
- (base-id
- (format "O:%s:5:ancestor:%s"
- (funcall format-func base-id)
- (funcall format-func id)))
- (t
- (format "O:%s:8" (funcall format-func id))))))
-
-(defun twittering-make-field-id (status &optional base-id)
- "Generate a field property for STATUS.
-Tweets are rendered in order of the field on `twittering-mode'.
-
-If BASE-ID is non-nil, generate a field id for a tweet rendered
-as a popped ancestor tweet by `twittering-show-replied-statuses'.
-In the case, BASE-ID means the ID of the descendant."
- (let ((id (cdr (assq 'id status))))
- (twittering-make-field-id-from-id id base-id)))
-
-(defun twittering-make-properties-of-popped-ancestors (base-id)
- `(rendered-as ((ancestor-of . ,base-id))))
-
-(defun twittering-make-field-id-of-timeline-oldest-end (spec-string)
- "Return the field ID for the oldest end.
-This is given to a special field, header or footer, which does not correspond
-to a tweet.
-It must be less than IDs made by `twittering-make-field-id' for any other
-normal fields in the meaning of `twittering-field-id<'."
- (format "H:%s" spec-string))
-
-(defun twittering-make-field-id-of-timeline-latest-end (spec-string)
- "Return the field ID for the oldest end.
-This is given to a special field, header or footer, which does not correspond
-to a tweet.
-It must be greater than IDs made by `twittering-make-field-id' for any other
-normal fields in the meaning of `twittering-field-id<'."
- (format "U:%s" spec-string))
-
-(defun twittering-field-id-is-timeline-oldest-end (field-id)
- "Return non-nil if FIELD-ID corresponds to the oldest end field.
-Return non-nil if FIELD-ID is made by
-`twittering-make-field-id-of-timeline-oldest-end'."
- (and (stringp field-id) (string= (substring field-id 0 2) "H:")))
-
-(defun twittering-field-id-is-timeline-latest-end (field-id)
- "Return non-nil if FIELD-ID corresponds to the latest end field.
-Return non-nil if FIELD-ID is made by
-`twittering-make-field-id-of-timeline-latest-end'."
- (and (stringp field-id) (string= (substring field-id 0 2) "U:")))
-
-(defun twittering-rendered-as-ancestor-status-p (&optional pos)
- "Return non-nil if the status at POS is rendered as an ancestor.
-Ancestor statuses are rendered by `twittering-show-replied-statuses'."
- (let ((pos (or pos (point))))
- (assq 'ancestor-of (get-text-property pos 'rendered-as))))
-
-(defun twittering-get-base-id-of-ancestor-at (&optional pos)
- "Return the base ID of a popped ancestor status rendered at POS.
-If the status at POS is not a popped ancestor status or no status is
-rendered at POS, return nil."
- (let ((pos (or pos (point))))
- (cdr (assq 'ancestor-of (get-text-property pos 'rendered-as)))))
-
-(eval-and-compile
- (defsubst twittering-fill-string (str &optional adjustment prefix keep-newline)
- (when (and (not (boundp 'kinsoku-limit))
- enable-kinsoku)
- ;; `kinsoku-limit' is defined on loading "international/kinsoku.el".
- ;; Without preloading, "kinsoku.el" will be loaded by auto-loading
- ;; triggered by `fill-region-as-paragraph'.
- ;; In that case, the local binding of `kinsoku-limit' conflicts the
- ;; definition by `defvar' in "kinsoku.el".
- ;; The below warning is displayed;
- ;; "Warning: defvar ignored because kinsoku-limit is let-bound".
- ;; So, we load "kinsoku.el" in advance if necessary.
- (load "international/kinsoku"))
- (let* ((kinsoku-limit 1)
- (adjustment (+ (or adjustment 0)
- (if enable-kinsoku
- kinsoku-limit
- 0)))
- (min-width
- (apply 'min
- (or
- (mapcar 'window-width
- (get-buffer-window-list (current-buffer) nil t))
- ;; Use `(frame-width)' if no windows display
- ;; the current buffer.
- `(,(frame-width)))))
- (temporary-fill-column (- (or twittering-fill-column (1- min-width))
- adjustment)))
- (with-temp-buffer
- (let ((fill-column temporary-fill-column)
- (fill-prefix (or prefix fill-prefix))
- (adaptive-fill-regexp ""))
- (if keep-newline
- (let* ((hard-newline (propertize "\n" 'hard t))
- (str (mapconcat 'identity (split-string str "\n")
- (concat hard-newline fill-prefix))))
- (use-hard-newlines)
- (insert (concat prefix str))
- (fill-region (point-min) (point-max) nil t)
- (remove-text-properties (point-min) (point-max) '(hard nil)))
- (insert (concat prefix str))
- (fill-region-as-paragraph (point-min) (point-max)))
- (buffer-substring (point-min) (point-max))))))
-
- (defsubst twittering-update-filled-string (beg end formater status prefix local-prefix &optional keep-newline)
- (let* ((str (twittering-fill-string (funcall formater status prefix)
- (length prefix) local-prefix
- keep-newline))
- (next (next-single-property-change 0 'need-to-be-updated str)))
- (if (or (get-text-property 0 'need-to-be-updated str)
- (and next (< next (length str))))
- (put-text-property 0 (length str) 'need-to-be-updated
- `(twittering-update-filled-string
- ,formater ,status ,prefix ,local-prefix
- ,keep-newline)
- str)
- ;; Remove the property required no longer.
- (remove-text-properties 0 (length str) '(need-to-be-updated nil) str))
- str))
-
- (defsubst twittering-make-passed-time-string
- (beg end encoded-created-at time-format &optional additional-properties)
- (let* ((now (current-time))
- (secs (+ (* (- (car now) (car encoded-created-at)) 65536)
- (- (cadr now) (cadr encoded-created-at))))
- (time-string
- (cond
- ((< secs 5) "less than 5 seconds ago")
- ((< secs 10) "less than 10 seconds ago")
- ((< secs 20) "less than 20 seconds ago")
- ((< secs 30) "half a minute ago")
- ((< secs 60) "less than a minute ago")
- ((< secs 150) "1 minute ago")
- ((< secs 2400) (format "%d minutes ago"
- (/ (+ secs 30) 60)))
- ((< secs 5400) "about 1 hour ago")
- ((< secs 84600) (format "about %d hours ago"
- (/ (+ secs 1800) 3600)))
- (t (format-time-string time-format encoded-created-at))))
- (properties (append additional-properties
- (and beg (text-properties-at beg))))
- (time-string
- ;; Copy a string and restore properties.
- (apply 'propertize time-string properties)))
- (if (< secs 84600)
- (put-text-property 0 (length time-string)
- 'need-to-be-updated
- `(twittering-make-passed-time-string
- ,encoded-created-at ,time-format)
- time-string)
- ;; Remove the property required no longer.
- (remove-text-properties 0 (length time-string)
- '(need-to-be-updated nil)
- time-string))
- time-string)))
-
-(defmacro twittering-render-a-field (pos field-id generator &optional without-separator)
- "Render a field on the current buffer managed by `twittering-mode'.
-Insert a field to the position pointed by FIELD-ID. The position is searched
-after POS. The string for the field is generated by the GENERATOR expression.
-This function does not render the status if a status with the same field ID
-as FIELD-ID is already rendered.
-Return non-nil if the status is rendered. Otherwise, return nil."
- `(lexical-let ((pos ,pos)
- (field-id ,field-id))
- (while
- (let ((buf-field-id (get-text-property pos 'field)))
- (if (and buf-field-id
- (if twittering-reverse-mode
- (twittering-field-id< buf-field-id field-id)
- (twittering-field-id< field-id buf-field-id)))
- (let ((next-pos
- (twittering-get-next-status-head pos)))
- (setq pos (or next-pos (point-max)))
- next-pos)
- nil)))
- (goto-char pos)
- (unless (twittering-field-id= field-id (get-text-property pos 'field))
- (let ((formatted-status (propertize ,generator 'field ,field-id))
- (separator (if ,without-separator
- ""
- "\n")))
- (if (eq pos (point-max))
- ;; Use `insert' only if no statuses are rendered on the below.
- (insert formatted-status separator)
- ;; Use `insert-before-markers' in order to keep
- ;; which status is pointed by each marker.
- (insert-before-markers formatted-status separator))
- t))))
-
-(defun twittering-render-timeline (buffer timeline-data &optional invoke-hook keep-point)
- "Render statuses for BUFFER and return the list of the rendered statuses.
-TIMELINE-DATA is a list of statuses being rendered.
-If INVOKE-HOOK is non-nil and one or more tweets are rendered, run hooks
-specified by `twittering-new-tweets-rendered-hook'.
-If KEEP-POINT is nil and BUFFER is empty, this function moves cursor positions
-to the latest status.
-
-This function returns a list of the statuses newly rendered by the invocation."
- (with-current-buffer buffer
- (let* ((spec (twittering-get-timeline-spec-for-buffer buffer))
- (referring-id-table
- (twittering-current-timeline-referring-id-table spec))
- (timeline-data
- ;; Collect visible statuses.
- (let ((prev-id nil))
- (remove
- nil
- (mapcar
- (lambda (status)
- (let ((id (cdr (assq 'id status)))
- (retweeted-id (cdr (assq 'retweeted-id status))))
- (if (twittering-status-id= prev-id id)
- ;; `status' is equivalent the previous one.
- nil
- (setq prev-id id)
- (cond
- ((null retweeted-id)
- ;; `status' is not a retweet.
- status)
- ((and retweeted-id
- (twittering-status-id=
- id (gethash retweeted-id referring-id-table)))
- ;; `status' is the first retweet.
- status)
- ((null (gethash retweeted-id referring-id-table))
- ;; If the first ID referring the retweet is unknown,
- ;; render it.
- ;; This is necessary because a referring ID table
- ;; of a composite timeline may lack information of
- ;; some component timelines.
- status)
- (t
- ;; Otherwise, do not render it.
- nil)))))
- timeline-data))))
- (timeline-data (if twittering-reverse-mode
- (reverse timeline-data)
- timeline-data))
- (rendering-entire (null (twittering-get-first-status-head)))
- (result-tweets nil)
- (buffer-read-only nil))
- (twittering-update-status-format)
- (twittering-update-mode-line)
- (save-excursion
- (let ((pos (point-min))
- (spec-string
- (twittering-get-timeline-spec-string-for-buffer buffer)))
- (cond
- (rendering-entire
- (let* ((latest-id
- (twittering-make-field-id-of-timeline-latest-end
- spec-string))
- (oldest-id
- (twittering-make-field-id-of-timeline-oldest-end
- spec-string))
- (footer-id
- (if twittering-reverse-mode
- latest-id
- oldest-id))
- (header-id
- (if twittering-reverse-mode
- oldest-id
- latest-id)))
- (setq
- pos
- (let ((footer
- ;; To avoid adding a face to newlines.
- (mapconcat
- (lambda (substr)
- (propertize substr
- 'face twittering-timeline-footer-face))
- (split-string (or twittering-timeline-footer "") "\n")
- "\n"))
- (header
- ;; To avoid adding a face to newlines.
- (mapconcat
- (lambda (substr)
- (propertize substr
- 'face twittering-timeline-header-face))
- (split-string (or twittering-timeline-header "") "\n")
- "\n")))
- (twittering-render-a-field (point-min) footer-id footer t)
- (twittering-render-a-field (point-min) header-id header t)
- (point)))))
- (t
- (setq pos (twittering-get-first-status-head))))
- (goto-char pos)
- (let* ((rendered-tweets
- (remove nil
- (mapcar
- (lambda (status)
- (when (twittering-render-a-field
- (point)
- (twittering-make-field-id status)
- (twittering-format-status status))
- (when twittering-default-show-replied-tweets
- (twittering-show-replied-statuses
- twittering-default-show-replied-tweets))
- status))
- timeline-data)))
- (twittering-rendered-new-tweets
- (if twittering-reverse-mode
- (reverse rendered-tweets)
- rendered-tweets))
- (twittering-rendered-new-tweets-spec spec)
- (twittering-rendered-new-tweets-spec-string spec-string))
- (setq result-tweets rendered-tweets)
- (when (and invoke-hook twittering-rendered-new-tweets)
- (run-hooks 'twittering-new-tweets-rendered-hook)))))
- (debug-print (current-buffer))
- (cond
- ((and (not keep-point) rendering-entire)
- ;; Go to the latest status of buffer after full insertion.
- (let ((dest (if twittering-reverse-mode
- (or (twittering-get-last-normal-field-head)
- (twittering-get-last-status-head)
- (point-max))
- (or (twittering-get-first-normal-field-head)
- (twittering-get-first-status-head)
- (point-min))))
- (window-list (get-buffer-window-list (current-buffer) nil t)))
- (if window-list
- (mapc
- (lambda (window)
- (set-window-point window dest)
- (if twittering-reverse-mode
- (twittering-set-window-end window (point-max))
- (set-window-start window (point-min))))
- window-list)
- ;; Move the buffer position if the buffer is invisible.
- (goto-char dest))))
- )
- result-tweets)
- ))
-
-(defun twittering-rerender-timeline-all (buffer &optional restore-point)
- "Re-render statuses on BUFFER after clearing BUFFER.
-If RESTORE-POINT is non-nil, positions on buffers bound to the same timeline
-will be restored after rendering statuses."
- (with-current-buffer buffer
- (let* ((window-list (get-buffer-window-list (current-buffer) nil t))
- (point-window-list
- (mapcar (lambda (window)
- (cons (window-point window) window))
- window-list))
- (original-pos (point)))
- (let ((buffer-read-only nil))
- (erase-buffer))
- (twittering-render-timeline
- (current-buffer) (twittering-current-timeline-data) nil restore-point)
- (when restore-point
- ;; Restore points.
- (mapc (lambda (pair)
- (let* ((point (car pair))
- (window (cdr pair))
- (dest (max (point-max) point)))
- (set-window-point window dest)))
- point-window-list)
- (goto-char original-pos)))))
-
-(defun twittering-retrieve-timeline (spec-string noninteractive api-arguments additional-info)
- "Retrieve and render a timeline specified by SPEC-STRING.
-Retrieve a timeline specified by SPEC-STRING, which must be a timeline spec
-string. Any timeline spec string including that for composite timeline can be
-used as SPEC-STRING, though the primitive function `twittering-call-api'
-accepts only a spec of a primary timeline.
-
-NONINTERACTIVE is sent to the sentinel as a parameter `noninteractive' via
-an argument `additional-info' of `twittering-call-api'.
-API-ARGUMENTS is also sent to `twittering-call-api' as its argument
-`args-alist'."
- (let ((spec (twittering-string-to-timeline-spec spec-string)))
- (cond
- ((not (twittering-account-authorized-p))
- ;; ignore any requests if the account has not been authorized.
- (message "No account for Twitter has been authorized.")
- t)
- ((and noninteractive (twittering-process-active-p spec))
- ;; ignore non-interactive request if a process is waiting for responses.
- t)
- ((twittering-timeline-spec-primary-p spec)
- (let* ((args
- `(,@api-arguments
- (timeline-spec . ,spec)
- (timeline-spec-string . ,spec-string)
- (format . ,(when (require 'json nil t)
- 'json))
- (clean-up-sentinel
- . ,(lambda (proc status connection-info)
- (when (memq status '(exit signal closed failed))
- (twittering-release-process proc))))))
- (additional-info
- `(,@additional-info
- (noninteractive . ,noninteractive)
- (timeline-spec . ,spec)
- (timeline-spec-string . ,spec-string)))
- (proc
- (twittering-call-api 'retrieve-timeline args additional-info)))
- (when proc
- (twittering-register-process proc spec spec-string)
- (twittering-initialize-retrieval-count spec))))
- ((twittering-timeline-spec-composite-p spec)
- (mapc
- (lambda (spec)
- (let* ((buffer (twittering-get-buffer-from-spec spec))
- (spec-string
- (if buffer
- (twittering-get-timeline-spec-string-for-buffer buffer)
- (twittering-timeline-spec-to-string spec))))
- (twittering-retrieve-timeline spec-string noninteractive
- api-arguments additional-info)))
- (twittering-get-base-timeline-specs spec)))
- (t
- (let ((type (car spec)))
- (error "%s has not been supported yet" type))))))
-
-(defun twittering-get-and-render-timeline (&optional noninteractive id spec spec-string)
- (let* ((spec (or spec (twittering-current-timeline-spec)))
- (spec-string
- (or spec-string (twittering-current-timeline-spec-string)))
- (latest-status
- ;; Assume that a list which was returned by
- ;; `twittering-current-timeline-data' is sorted.
- (car (twittering-current-timeline-data spec)))
- (since_id (cdr-safe (assq 'id latest-status)))
- (args `(,@(cond
- (id `((max_id . ,id)))
- (since_id `((since_id . ,since_id)))
- (t nil)))))
- (twittering-retrieve-timeline spec-string noninteractive args nil)))
-
-;;;;
-;;;; Map function for statuses on buffer
-;;;;
-
-(defun twittering-for-each-property-region (prop func &optional buffer interrupt)
- "Apply FUNC to each region, where property PROP is non-nil, on BUFFER.
-If INTERRUPT is non-nil, the iteration is stopped if FUNC returns nil."
- (with-current-buffer (or buffer (current-buffer))
- (let ((beg (point-min))
- (end-marker (make-marker)))
- (set-marker-insertion-type end-marker t)
- (while
- (let ((value (get-text-property beg prop)))
- (if value
- (let* ((end (next-single-property-change beg prop))
- (end (or end (point-max)))
- (end-marker (set-marker end-marker end))
- (func-result (funcall func beg end value))
- (end (marker-position end-marker)))
- (when (or (null interrupt) func-result)
- (if (get-text-property end prop)
- (setq beg end)
- (setq beg (next-single-property-change end prop)))))
- (setq beg (next-single-property-change beg prop)))))
- (set-marker end-marker nil))))
-
-;;;;
-;;;; Automatic redisplay of statuses on buffer
-;;;;
-
-(defun twittering-redisplay-status-on-buffer ()
- (mapc (lambda (buffer)
- (unless (with-current-buffer buffer
- (or (and (fboundp 'use-region-p) (use-region-p))
- (and transient-mark-mode mark-active)))
- (twittering-redisplay-status-on-each-buffer buffer)))
- (twittering-get-buffer-list)))
-
-(defun twittering-redisplay-status-on-each-buffer (buffer &optional prop)
- "Redisplay regions with the text property PROP on BUFFER."
- (let ((prop (or prop 'need-to-be-updated))
- (deactivate-mark deactivate-mark)
- (window-list (get-buffer-window-list buffer nil t))
- (marker (with-current-buffer buffer (point-marker)))
- (result nil))
- (with-current-buffer buffer
- (save-excursion
- (twittering-for-each-property-region
- prop
- (lambda (beg end value)
- (let* ((func (car value))
- (args (cdr value))
- (current-str (buffer-substring beg end))
- (updated-str (apply func beg end args))
- (config (twittering-current-window-config window-list))
- (buffer-read-only nil))
- ;; Replace `current-str' if it differs to `updated-str' with
- ;; ignoring properties. This is an ad-hoc solution.
- ;; `current-str' is a part of the displayed status, but it has
- ;; properties which are determined by the whole status.
- ;; (For example, the `id' property.)
- ;; Therefore, we cannot compare the strings with their
- ;; properties.
- (unless (string= current-str updated-str)
- ;; If the region to be modified includes the current position,
- ;; the point moves to the beginning of the region.
- (when (and (< beg marker) (< marker end))
- ;; This is required because the point moves to the center if
- ;; the point becomes outside of the window by the effect of
- ;; `set-window-start'.
- (setq result beg))
- (let ((common-properties
- (twittering-get-common-properties beg)))
- ;; Restore common properties.
- (delete-region beg end)
- (goto-char beg)
- (insert (apply 'propertize updated-str common-properties)))
- (twittering-restore-window-config-after-modification
- config beg end))))
- buffer))
- (set-marker marker nil)
- (when (and result (eq (window-buffer) buffer))
- (let ((win (selected-window)))
- (when (< result (window-start win))
- (set-window-start win result))
- (set-window-point win result))))))
-
-;;;;
-;;;; Display replied statuses
-;;;;
-
-(defun twittering-replied-statuses-visible-p (&optional pos)
- "Return non-nil if a replied status related to POS is visible.
-Return non-nil if a replied status has been rendered at POS by
-`twittering-show-replied-statuses'.
-Return non-nil if a reply is rendered at POS and the replied statuses
-has been rendered by `twittering-show-replied-statuses'.
-Otherwise, return nil."
- (let* ((pos (twittering-get-current-status-head pos))
- (id (twittering-get-id-at pos))
- (prev (twittering-get-previous-status-head pos))
- (next (twittering-get-next-status-head pos)))
- (when id
- ;; If ID is nil, it means that no normal tweets are rendered at POS.
- (or
- (twittering-get-base-id-of-ancestor-at pos)
- (and prev
- (twittering-status-id=
- id (twittering-get-base-id-of-ancestor-at prev)))
- (and next
- (twittering-status-id=
- id (twittering-get-base-id-of-ancestor-at next)))))))
-
-(defun twittering-get-beginning-of-visible-replied-statuses (&optional pos)
- "Return the beginning position of visible replied statuses at POS.
-If POS is nil, the current position is used instead.
-If `twittering-show-replied-statuses' has rendered a replied status at POS,
-return the beginning position of the replied statuses with the common base
-status.
-If a reply is rendered at POS and its ancestors has been rendered by
-`twittering-show-replied-statuses', return the beginning position of the
-replied statuses.
-Otherwise, return nil."
- (let* ((pos (or pos (point)))
- (base-id (twittering-get-base-id-of-ancestor-at pos)))
- (cond
- (base-id
- ;; A replied status is rendered at POS.
- (while
- (let* ((prev (twittering-get-previous-status-head pos))
- (prev-base-id
- (when prev
- (twittering-get-base-id-of-ancestor-at prev))))
- (and prev prev-base-id
- (twittering-status-id= base-id prev-base-id)
- (setq pos prev))))
- (or pos (point-min)))
- ((twittering-replied-statuses-visible-p pos)
- ;; A reply is rendered at POS and its replied statuses are visible.
- (if twittering-reverse-mode
- (twittering-get-beginning-of-visible-replied-statuses
- (twittering-get-previous-status-head pos))
- (twittering-get-next-status-head pos)))
- (t
- nil))))
-
-(defun twittering-get-end-of-visible-replied-statuses (&optional pos)
- "Return the end position of visible replied statuses at POS.
-If POS is nil, the current position is used instead.
-If `twittering-show-replied-statuses' has rendered a replied status at POS,
-return the end position of the replied statuses with the common base status.
-If a reply is rendered at POS and its ancestors has been rendered by
-`twittering-show-replied-statuses', return the beginning position of the
-replied statuses.
-Otherwise, return nil."
- (let* ((pos (or pos (point)))
- (base-id (twittering-get-base-id-of-ancestor-at pos)))
- (cond
- (base-id
- ;; A replied status is rendered at POS.
- (while
- (let ((current-base-id (twittering-get-base-id-of-ancestor-at pos)))
- (and current-base-id
- (twittering-status-id= base-id current-base-id)
- (setq pos (twittering-get-next-status-head pos)))))
- (or pos (point-max)))
- ((twittering-replied-statuses-visible-p pos)
- ;; A reply is rendered at POS and its replied statuses are visible.
- (if twittering-reverse-mode
- (twittering-get-current-status-head pos)
- (twittering-get-end-of-visible-replied-statuses
- (twittering-get-next-status-head pos))))
- (t
- nil))))
-
-(defun twittering-render-replied-statuses (&optional pos count)
- "Render replied statuses on the position specified by POS.
-If POS is nil, the current position is used instead.
-If COUNT is a positive integer, it specifies the number of rendered statuses.
-If COUNT is nil, all ancestor statuses that have been already retrieved are
-rendered.
-
-Return non-nil if one or more statuses are rendered.
-Return nil if no statuses are rendered."
- (let* ((pos (or pos (point)))
- (id
- ;; nil if no normal statuses are rendered at POS.
- (twittering-get-id-at pos))
- (replied-status-are-visible
- (when id
- (twittering-replied-statuses-visible-p pos)))
- (base-id (if replied-status-are-visible
- (or
- ;; If a replied status is rendered at POS.
- (twittering-get-base-id-of-ancestor-at pos)
- ;; If the base reply is rendered at POS.
- id)
- id))
- (statuses
- (when base-id
- (twittering-get-replied-statuses base-id (if (numberp count)
- count))))
- (statuses (if twittering-reverse-mode
- statuses
- (reverse statuses))))
- (cond
- ((null id)
- ;; No normal statuses are rendered here.
- nil)
- (statuses
- (let ((pos
- (cond
- ((twittering-replied-statuses-visible-p pos)
- ;; Some replied statuses have been already rendered.
- (twittering-get-beginning-of-visible-replied-statuses pos))
- (twittering-reverse-mode
- (twittering-get-current-status-head pos))
- (t
- (or (twittering-get-next-status-head pos)
- (point-max)))))
- (prefix " ")
- (buffer-read-only nil))
- (save-excursion
- (goto-char pos)
- (mapc
- (lambda (status)
- (twittering-render-a-field
- (point)
- (twittering-make-field-id status base-id)
- (let ((formatted-status (twittering-format-status status prefix))
- (field-properties
- (twittering-make-properties-of-popped-ancestors base-id)))
- (add-text-properties 0 (length formatted-status)
- field-properties formatted-status)
- formatted-status)))
- statuses)
- t)))
- (t
- nil))))
-
-(defun twittering-render-a-status-with-delay (beg end id prefix)
- "Render a status with a delay.
-It is assumed that this function is used as a property value that is
-processed by the function `twittering-redisplay-status-on-each-buffer'."
- (let ((status (twittering-find-status id)))
- (when status
- (let ((properties (and beg (text-properties-at beg))))
- (apply 'propertize (twittering-format-status status prefix)
- properties)))))
-
-(defun twittering-toggle-or-retrieve-replied-statuses ()
- "Show/Hide all of replied statuses or retrieve a replied status.
-If the cursor points to a reply or one of expanded replied statuses and
-some of ancestor replied statuses have been already retrieved but they have
-not been rendered, render them.
-If the cursor points to a reply or one of expanded replied statuses and
-all of retrieved ancestor statuses have been already rendered but the oldest
-one of them is also a reply, retrieve the replied status.
-If the cursor points to a reply or one of expanded replied statuses and
-all of ancestor replied statuses have been already rendered, hide them by
-`twittering-hide-replied-statuses'."
- (interactive)
- (let* ((pos (point))
- (pos
- ;; POS points to the head of the direct reply of the status being
- ;; retrieved.
- (cond
- ((twittering-replied-statuses-visible-p pos)
- ;; If some replied statuses are visible, find the edge.
- (if twittering-reverse-mode
- (twittering-get-beginning-of-visible-replied-statuses pos)
- (twittering-get-previous-status-head
- (twittering-get-end-of-visible-replied-statuses pos))))
- (t
- (twittering-get-current-status-head pos))))
- (id (twittering-get-id-at pos))
- (status (twittering-find-status id))
- (reply-id (cdr (assq 'in-reply-to-status-id status)))
- (reply-username (cdr (assq 'in-reply-to-screen-name status)))
- (base-id (or (twittering-get-base-id-of-ancestor-at pos)
- id)))
- (cond
- ((twittering-find-status reply-id)
- ;; The status corresponding to REPLY-ID has been already retrieved
- ;; but it has not been rendered.
- ;;
- ;; `twittering-render-replied-statuses' additionally renders all
- ;; of already retrieved statuses.
- (twittering-render-replied-statuses))
- (reply-id
- (let* ((pos
- ;; POS points to the position where the new field will be
- ;; inserted.
- (if twittering-reverse-mode
- pos
- (or (twittering-get-next-status-head pos)
- (point-max))))
- (field-id (twittering-make-field-id-from-id reply-id base-id))
- (prefix " ")
- (label "[RETRIEVING...]")
- (symbol-for-redisplay 'waiting-for-retrieval)
- (properties
- `(,@(twittering-make-properties-of-popped-ancestors base-id)
- ,symbol-for-redisplay
- (twittering-render-a-status-with-delay ,reply-id ,prefix)))
- (str (apply 'propertize (concat prefix label) properties))
- (buffer-read-only nil))
- (twittering-call-api
- 'retrieve-single-tweet
- `((id . ,reply-id)
- (username . ,reply-username)
- (format . ,(when (require 'json nil t)
- 'json))
- (sentinel . twittering-retrieve-single-tweet-sentinel))
- `((buffer . ,(current-buffer))
- (property-to-be-redisplayed . ,symbol-for-redisplay)))
- (save-excursion
- (goto-char pos)
- (twittering-render-a-field (point) field-id str))
- (goto-char pos)))
- ((twittering-replied-statuses-visible-p)
- ;; All ancestor replied statuses have been rendered.
- (twittering-hide-replied-statuses))
- (t
- ;; The pointed status is not a reply.
- (message "This status is not a reply.")))))
-
-(defun twittering-show-replied-statuses (&optional count interactive)
- (interactive)
- (cond
- ((twittering-replied-statuses-visible-p)
- (when interactive
- (message "The replied statuses were already showed.")))
- ((twittering-render-replied-statuses (point) count)
- t)
- (t
- ;; Failed to render replied statuses.
- (when interactive
- (let ((base-id (twittering-get-id-at)))
- (if (twittering-have-replied-statuses-p base-id)
- (message "The status this replies to has not been fetched yet.")
- (message "This status is not a reply.")))))))
-
-(defun twittering-hide-replied-statuses (&optional interactive)
- (interactive)
- (cond
- ((twittering-replied-statuses-visible-p)
- (let* ((pos (twittering-get-current-status-head (point)))
- (base-id (or (twittering-get-base-id-of-ancestor-at pos)
- (twittering-get-id-at pos)))
- (pointing-to-base-status
- (not (twittering-rendered-as-ancestor-status-p pos)))
- (beg (twittering-get-beginning-of-visible-replied-statuses pos))
- (end (twittering-get-end-of-visible-replied-statuses pos))
- (buffer-read-only nil))
- (unless pointing-to-base-status
- (goto-char (if twittering-reverse-mode
- beg
- (or (twittering-get-previous-status-head beg)
- (point-min)))))
- (delete-region beg end)))
- (interactive
- (message "The status this replies to was already hidden."))))
-
-(defun twittering-toggle-show-replied-statuses ()
- (interactive)
- (if (twittering-replied-statuses-visible-p)
- (twittering-hide-replied-statuses (interactive-p))
- (twittering-show-replied-statuses twittering-show-replied-tweets
- (interactive-p))))
-
-;;;;
-;;;; Unread statuses info
-;;;;
-
-(defvar twittering-unread-status-info nil
- "A list of (buffer unread-statuses-counter), where `unread-statuses-counter'
-means the number of statuses retrieved after the last visiting of the buffer.")
-
-(defun twittering-reset-unread-status-info-if-necessary ()
- (when (twittering-buffer-p)
- (twittering-set-number-of-unread (current-buffer) 0)))
-
-(defun twittering-set-number-of-unread (buffer number)
- (let* ((entry (assq buffer twittering-unread-status-info))
- (current (or (cadr entry) 0)))
- (unless (= number current)
- (setq twittering-unread-status-info
- (cons
- `(,buffer ,number)
- (if entry
- (remq entry twittering-unread-status-info)
- twittering-unread-status-info))))))
-
-(defun twittering-make-unread-status-notifier-string ()
- "Generate a string that displays unread statuses."
- (setq twittering-unread-status-info
- (remove nil
- (mapcar (lambda (entry)
- (when (buffer-live-p (car entry))
- entry))
- twittering-unread-status-info)))
- (let ((sum (apply '+ (mapcar 'cadr twittering-unread-status-info))))
- (if (= 0 sum)
- ""
- (format "tw(%d)" sum))))
-
-(defun twittering-update-unread-status-info ()
- "Update `twittering-unread-status-info' with new tweets."
- (let* ((buffer (twittering-get-buffer-from-spec
- twittering-rendered-new-tweets-spec))
- (current (or (cadr (assq buffer twittering-unread-status-info)) 0))
- (result (+ current (length twittering-rendered-new-tweets))))
- (when buffer
- (twittering-set-number-of-unread buffer result))))
-
-(defun twittering-enable-unread-status-notifier ()
- "Enable a notifier of unread statuses on `twittering-mode'."
- (interactive)
- (setq twittering-unread-status-info
- (mapcar (lambda (buffer) `(,buffer ,0))
- (twittering-get-buffer-list)))
- (add-hook 'twittering-new-tweets-rendered-hook
- 'twittering-update-unread-status-info)
- (add-hook 'post-command-hook
- 'twittering-reset-unread-status-info-if-necessary)
- (add-to-list 'global-mode-string
- '(:eval (twittering-make-unread-status-notifier-string))
- t))
-
-(defun twittering-disable-unread-status-notifier ()
- "Disable a notifier of unread statuses on `twittering-mode'."
- (interactive)
- (setq twittering-unread-status-info nil)
- (remove-hook 'twittering-new-tweets-hook
- 'twittering-update-unread-status-info)
- (remove-hook 'post-command-hook
- 'twittering-reset-unread-status-info-if-necessary)
- (setq global-mode-string
- (remove '(:eval (twittering-make-unread-status-notifier-string))
- global-mode-string)))
-
-;;;;
-;;;; Timer
-;;;;
-
-(defvar twittering-idle-timer-for-redisplay nil)
-
-(defun twittering-timer-action (func)
- (let ((buf (twittering-get-active-buffer-list)))
- (if (null buf)
- (twittering-stop)
- (funcall func)
- )))
-
-(defun twittering-run-on-idle (idle-interval func &rest args)
- "Run FUNC the next time Emacs is idle for IDLE-INTERVAL.
-Even if Emacs has been idle longer than IDLE-INTERVAL, run FUNC immediately.
-Since immediate invocation requires `current-idle-time', it is available
-on Emacs 22 and later.
-FUNC is called as (apply FUNC ARGS)."
- (let ((sufficiently-idling
- (and (fboundp 'current-idle-time)
- (current-idle-time)
- (time-less-p (seconds-to-time idle-interval)
- (current-idle-time)))))
- (if (not sufficiently-idling)
- (apply 'run-with-idle-timer idle-interval nil func args)
- (apply func args)
- nil)))
-
-(defun twittering-run-repeatedly-on-idle (check-interval var idle-interval func &rest args)
- "Run FUNC every time Emacs is idle for IDLE-INTERVAL.
-Even if Emacs remains idle longer than IDLE-INTERVAL, run FUNC every
-CHECK-INTERVAL seconds. Since this behavior requires `current-idle-time',
-invocation on long idle time is available on Emacs 22 and later.
-VAR is a symbol of a variable to which the idle-timer is bound.
-FUNC is called as (apply FUNC ARGS)."
- (apply 'run-at-time "0 sec"
- check-interval
- (lambda (var idle-interval func &rest args)
- (let ((registerd (symbol-value var))
- (sufficiently-idling
- (and (fboundp 'current-idle-time)
- (current-idle-time)
- (time-less-p (seconds-to-time idle-interval)
- (current-idle-time)))))
- (when (or (not registerd) sufficiently-idling)
- (when (and registerd sufficiently-idling)
- (cancel-timer (symbol-value var))
- (apply func args))
- (set var (apply 'run-with-idle-timer idle-interval nil
- (lambda (var func &rest args)
- (set var nil)
- (apply func args))
- var func args)))))
- var idle-interval func args))
-
-(defun twittering-start (&optional action)
- (interactive)
- (unless twittering-timer
- (let ((action (or action #'twittering-update-active-buffers)))
- ;; Update all active timelines forcibly.
- (twittering-update-active-buffers t)
- (setq twittering-timer
- (run-at-time (format "%d sec" twittering-timer-interval)
- twittering-timer-interval
- #'twittering-timer-action action))))
- (unless twittering-timer-for-redisplaying
- (setq twittering-timer-for-redisplaying
- (twittering-run-repeatedly-on-idle
- (* 2 twittering-timer-interval-for-redisplaying)
- 'twittering-idle-timer-for-redisplay
- twittering-timer-interval-for-redisplaying
- #'twittering-redisplay-status-on-buffer))))
-
-(defun twittering-stop ()
- (interactive)
- (when twittering-timer
- (cancel-timer twittering-timer)
- (setq twittering-timer nil))
- (when twittering-timer-for-redisplaying
- (when twittering-idle-timer-for-redisplay
- (cancel-timer twittering-idle-timer-for-redisplay)
- (setq twittering-idle-timer-for-redisplay))
- (cancel-timer twittering-timer-for-redisplaying)
- (setq twittering-timer-for-redisplaying nil)))
-
-(defun twittering-get-relative-interval (spec)
- (let* ((spec-string (twittering-timeline-spec-to-string spec))
- (normalized-alist
- (apply 'append
- (mapcar
- (lambda (entry)
- (let ((interval (car (last entry)))
- (regexp-list (butlast entry 1)))
- (when (integerp interval)
- (mapcar (lambda (regexp) `(,regexp . ,interval))
- regexp-list))))
- twittering-relative-retrieval-interval-alist)))
- (rest normalized-alist)
- (current normalized-alist)
- (result 0))
- (while (not
- (or (and (stringp (car current))
- (string-match (car current) spec-string))
- (eq t (car current))))
- (setq current (car rest))
- (setq rest (cdr rest)))
- (if (integerp (cdr current))
- (cdr current)
- ;; The default relative interval is 1.
- 1)))
-
-(defun twittering-get-retrieval-count (spec)
- (cdr (assoc spec twittering-relative-retrieval-count-alist)))
-
-(defun twittering-set-retrieval-count (spec count)
- (let ((current (assoc spec twittering-relative-retrieval-count-alist)))
- (if (null current)
- (add-to-list 'twittering-relative-retrieval-count-alist
- `(,spec . ,count))
- (setcdr current count))))
-
-(defun twittering-initialize-retrieval-count (spec)
- (twittering-set-retrieval-count spec
- (twittering-get-relative-interval spec)))
-
-(defun twittering-update-active-buffers (&optional force noninteractive)
- "Update active buffers managed by `twittering-mode' at a certain interval.
-
-If FORCE is nil, each active buffer is updated at a relative interval
-determined by `twittering-relative-retrieval-interval-alist'.
-If a relative interval of a timeline is 3, the timeline is updated once
-by three invocations of this function.
-
-If FORCE is non-nil, all active buffers are updated forcibly."
- (when (twittering-account-authorized-p)
- (twittering-update-service-configuration)
- (let* ((buffer-list (twittering-get-active-buffer-list))
- (primary-spec-list
- (twittering-remove-duplicates
- (apply 'append
- (mapcar
- (lambda (buffer)
- (twittering-get-primary-base-timeline-specs
- (twittering-get-timeline-spec-for-buffer buffer)))
- buffer-list)))))
- (mapc
- (lambda (spec)
- (let ((current
- (if force
- 1
- (twittering-get-retrieval-count spec))))
- (cond
- ((null current)
- ;; Initialize the count if no entry for the primary timeline
- ;; exists.
- (twittering-initialize-retrieval-count spec))
- ((and (integerp current) (= 0 current))
- ;; Do nothing.
- )
- ((and (integerp current) (= 1 current))
- ;; Retrieve the timeline and initialize count.
- (let ((spec-string
- (twittering-timeline-spec-to-string spec)))
- (twittering-get-and-render-timeline
- noninteractive nil spec spec-string)
- (twittering-initialize-retrieval-count spec)))
- ((and (integerp current) (< 1 current))
- ;; Decrement count.
- (twittering-set-retrieval-count spec (1- current)))
- (t
- nil))))
- primary-spec-list))))
-
-;;;;
-;;;; Keymap
-;;;;
-
-(if twittering-mode-map
- (let ((km twittering-mode-map))
- (define-key km (kbd "C-c C-f") 'twittering-friends-timeline)
- (define-key km (kbd "C-c C-r") 'twittering-replies-timeline)
- (define-key km (kbd "C-c C-u") 'twittering-user-timeline)
- (define-key km (kbd "C-c C-d") 'twittering-direct-messages-timeline)
- (define-key km (kbd "C-c C-s") 'twittering-update-status-interactive)
- (define-key km (kbd "C-c C-e") 'twittering-erase-old-statuses)
- (define-key km (kbd "C-c C-m") 'twittering-retweet)
- (define-key km (kbd "C-c C-t") 'twittering-set-current-hashtag)
- (define-key km (kbd "C-m") 'twittering-enter)
- (define-key km (kbd "C-c C-l") 'twittering-update-lambda)
- (define-key km (kbd "<mouse-1>") 'twittering-click)
- (define-key km (kbd "C-<down-mouse-3>") 'mouse-set-point)
- (define-key km (kbd "C-<mouse-3>") 'twittering-push-tweet-onto-kill-ring)
- (define-key km (kbd "C-c C-v") 'twittering-view-user-page)
- (define-key km (kbd "C-c D") 'twittering-delete-status)
- (define-key km (kbd "C-c C-w") 'twittering-delete-status)
- (define-key km (kbd "a") 'twittering-toggle-activate-buffer)
- (define-key km (kbd "g") 'twittering-current-timeline)
- (define-key km (kbd "u") 'twittering-update-status-interactive)
- (define-key km (kbd "U") 'twittering-push-uri-onto-kill-ring)
- (define-key km (kbd "d") 'twittering-direct-message)
- (define-key km (kbd "v") 'twittering-other-user-timeline)
- (define-key km (kbd "V") 'twittering-visit-timeline)
- (define-key km (kbd "L") 'twittering-other-user-list-interactive)
- (define-key km (kbd "f") 'twittering-switch-to-next-timeline)
- (define-key km (kbd "b") 'twittering-switch-to-previous-timeline)
- ;; (define-key km (kbd "j") 'next-line)
- ;; (define-key km (kbd "k") 'previous-line)
- (define-key km (kbd "j") 'twittering-goto-next-status)
- (define-key km (kbd "k") 'twittering-goto-previous-status)
- (define-key km (kbd "l") 'forward-char)
- (define-key km (kbd "h") 'backward-char)
- (define-key km (kbd "0") 'beginning-of-line)
- (define-key km (kbd "^") 'beginning-of-line-text)
- (define-key km (kbd "$") 'end-of-line)
- (define-key km (kbd "n") 'twittering-goto-next-status-of-user)
- (define-key km (kbd "p") 'twittering-goto-previous-status-of-user)
- (define-key km (kbd "C-i") 'twittering-goto-next-thing)
- (define-key km (kbd "M-C-i") 'twittering-goto-previous-thing)
- (define-key km (kbd "<backtab>") 'twittering-goto-previous-thing)
- (define-key km (kbd "<backspace>") 'twittering-scroll-down)
- (define-key km (kbd "M-v") 'twittering-scroll-down)
- (define-key km (kbd "SPC") 'twittering-scroll-up)
- (define-key km (kbd "C-v") 'twittering-scroll-up)
- (define-key km (kbd "G") 'twittering-goto-last-status)
- (define-key km (kbd "H") 'twittering-goto-first-status)
- (define-key km (kbd "i") 'twittering-icon-mode)
- (define-key km (kbd "r") 'twittering-toggle-show-replied-statuses)
- (define-key km (kbd "R") 'twittering-toggle-or-retrieve-replied-statuses)
- (define-key km (kbd "t") 'twittering-toggle-proxy)
- (define-key km (kbd "C-c C-p") 'twittering-toggle-proxy)
- (define-key km (kbd "q") 'twittering-kill-buffer)
- (define-key km (kbd "C-c C-q") 'twittering-search)
- nil))
-
-(let ((km twittering-mode-menu-on-uri-map))
- (when km
- (define-key km [ct] '("Copy tweet" . twittering-push-tweet-onto-kill-ring))
- (define-key km [cl] '("Copy link" . twittering-push-uri-onto-kill-ring))
- (define-key km [ll] '("Load link" . twittering-click))
- (let ((km-on-uri twittering-mode-on-uri-map))
- (when km-on-uri
- (define-key km-on-uri (kbd "C-<down-mouse-3>") 'mouse-set-point)
- (define-key km-on-uri (kbd "C-<mouse-3>") km)))))
-
-(defun twittering-keybind-message ()
- (let ((important-commands
- '(("Timeline" . twittering-friends-timeline)
- ("Replies" . twittering-replies-timeline)
- ("Update status" . twittering-update-status-interactive)
- ("Next" . twittering-goto-next-status)
- ("Prev" . twittering-goto-previous-status))))
- (mapconcat (lambda (command-spec)
- (let ((descr (car command-spec))
- (command (cdr command-spec)))
- (format "%s: %s" descr (key-description
- (where-is-internal
- command
- overriding-local-map t)))))
- important-commands ", ")))
-
-;; (run-with-idle-timer
-;; 0.1 t
-;; '(lambda ()
-;; (when (equal (buffer-name (current-buffer)) twittering-buffer)
-;; (message (twittering-keybind-message)))))
-
-
-;;;;
-;;;; Initialization
-;;;;
-
-(defvar twittering-initialized nil)
-(defvar twittering-mode-syntax-table nil "")
-
-(unless twittering-mode-syntax-table
- (setq twittering-mode-syntax-table (make-syntax-table))
- ;; (modify-syntax-entry ? "" twittering-mode-syntax-table)
- (modify-syntax-entry ?\" "w" twittering-mode-syntax-table)
- )
-
-(defun twittering-initialize-global-variables-if-necessary ()
- "Initialize global variables for `twittering-mode' if they have not
-been initialized yet."
- (unless twittering-initialized
- (defface twittering-username-face
- `((t ,(append '(:underline t)
- (face-attr-construct
- (if (facep 'font-lock-string-face)
- 'font-lock-string-face
- 'bold)))))
- "" :group 'faces)
- (defface twittering-uri-face `((t (:underline t))) "" :group 'faces)
- (defface twittering-timeline-header-face
- `((t ,(face-attr-construct
- (if (facep 'font-lock-preprocessor-face)
- 'font-lock-preprocessor-face
- 'bold))))
- "Timeline header on twittering-mode" :group 'faces)
- (defface twittering-timeline-footer-face
- `((t ,(face-attr-construct
- (if (facep 'font-lock-preprocessor-face)
- 'font-lock-preprocessor-face
- 'bold))))
- "Timeline footer on twittering-mode" :group 'faces)
- (twittering-update-status-format)
- (when twittering-use-convert
- (if (null twittering-convert-program)
- (setq twittering-use-convert nil)
- (with-temp-buffer
- (let ((coding-system-for-read 'iso-safe)
- (coding-system-for-write 'iso-safe)
- ;; Bind `default-directory' to the temporary directory
- ;; because it is possible that the directory pointed by
- ;; `default-directory' has been already removed.
- (default-directory temporary-file-directory))
- (call-process twittering-convert-program nil (current-buffer) nil
- "-version")
- (goto-char (point-min))
- (if (null (search-forward-regexp "\\(Image\\|Graphics\\)Magick"
- nil t))
- (setq twittering-use-convert nil))))))
- (twittering-setup-proxy)
- (when twittering-use-icon-storage
- (cond
- ((require 'jka-compr nil t)
- (twittering-load-icon-properties)
- (add-hook 'kill-emacs-hook 'twittering-save-icon-properties))
- (t
- (setq twittering-use-icon-storage nil)
- (error "Disabled icon-storage because it failed to load jka-compr."))))
- (cond
- ((and
- (boundp 'twittering-sign-simple-string)
- twittering-sign-simple-string
- (or (not (boundp 'twittering-sign-string-function))
- (null twittering-sign-string-function))
- (eq twittering-edit-skeleton 'none)
- (or (null twittering-edit-skeleton-footer)
- (string= twittering-edit-skeleton-footer "")))
- ;; Configure `twittering-edit-skeleton' as an alternative of
- ;; `twittering-sign-simple-string'.
- (twittering-edit-skeleton-change-footer
- (format " [%s]" twittering-sign-simple-string))
- (setq twittering-edit-skeleton 'footer)
- (message "Warning: `twittering-sign-simple-string' is obsolete. Use `twittering-edit-skeleton-footer' instead."))
- ((or (boundp 'twittering-sign-simple-string)
- (boundp 'twittering-sign-string-function))
- (message "Warning: `twittering-sign-simple-string' and `twittering-sign-string-function' are obsolete. Use the new feature `twittering-edit-skeleton'.")
- ))
- (add-hook 'twittering-new-tweets-rendered-hook
- 'twittering-jojo-mode-hook-function)
- (run-hooks 'twittering-mode-init-hook)
- (setq twittering-initialized t)))
-
-(defun twittering-mode-setup (spec-string)
- "Set up the current buffer for `twittering-mode'."
- (kill-all-local-variables)
- (setq major-mode 'twittering-mode)
- (setq buffer-read-only t)
- (buffer-disable-undo)
- (setq mode-name "twittering-mode")
- (setq mode-line-buffer-identification
- `(,(default-value 'mode-line-buffer-identification)
- (:eval (twittering-mode-line-buffer-identification))))
-
- ;; Prevent `global-font-lock-mode' enabling `font-lock-mode'.
- ;; This technique is derived from `lisp/bs.el' distributed with Emacs 22.2.
- (make-local-variable 'font-lock-global-modes)
- (setq font-lock-global-modes '(not twittering-mode))
-
- ;; Prevent the field property attached to tweets from interfering
- ;; the cursor motion based on logical lines.
- (make-local-variable 'inhibit-field-text-motion)
- (setq inhibit-field-text-motion t)
-
- (make-local-variable 'twittering-timeline-spec)
- (make-local-variable 'twittering-timeline-spec-string)
- (make-local-variable 'twittering-active-mode)
- (make-local-variable 'twittering-icon-mode)
- (make-local-variable 'twittering-jojo-mode)
- (make-local-variable 'twittering-reverse-mode)
-
- (setq twittering-timeline-spec-string spec-string)
- (setq twittering-timeline-spec
- (twittering-string-to-timeline-spec spec-string))
- (setq twittering-active-mode t)
-
- (use-local-map twittering-mode-map)
- (twittering-update-mode-line)
- (set-syntax-table twittering-mode-syntax-table)
- (when (and (boundp 'font-lock-mode) font-lock-mode)
- (font-lock-mode -1))
- (add-to-list 'twittering-buffer-info-list (current-buffer) t)
- (run-hooks 'twittering-mode-hook))
-
-(defun twittering-mode ()
- "Major mode for Twitter
-\\{twittering-mode-map}"
- (interactive)
- (let ((timeline-spec-list
- (if (listp twittering-initial-timeline-spec-string)
- twittering-initial-timeline-spec-string
- (cons twittering-initial-timeline-spec-string nil))))
- (twittering-visit-timeline (car timeline-spec-list))
- (when (twittering-account-authorized-p)
- (mapc 'twittering-visit-timeline (cdr timeline-spec-list)))))
-
-;;;;
-;;;; Preparation for invoking APIs
-;;;;
-
-(defun twittering-api-invocation-is-ready-p ()
- "Return non-nil if the preparation for invoking APIs has been completed."
- (and
- ;; The global variables are initialized.
- twittering-initialized
- ;; A connection method is prepared.
- (let ((use-ssl (or twittering-use-ssl twittering-oauth-use-ssl)))
- (twittering-lookup-connection-type use-ssl))
- ;; The account has been already authorized.
- (twittering-account-authorized-p)))
-
-(defun twittering-ensure-preparation-for-api-invocation ()
- "Ensure prerequisites for invoking APIs. Return non-nil in success.
-If prerequisites has been already satisifed, just return non-nil.
-If prerequisites are not satisfied, this function try to satisfy them.
-Then, return non-nil if they has been satisfied and return nil otherwise."
- (twittering-initialize-global-variables-if-necessary)
- (and (twittering-ensure-connection-method)
- (twittering-ensure-private-info)
- (twittering-ensure-account-verification)))
-
-;;;;
-;;;; Edit mode skeleton
-;;;;
-
-(defvar twittering-edit-skeleton-footer "")
-(defvar twittering-edit-skeleton-footer-history nil)
-(defvar twittering-edit-skeleton-alist
- '((none . nil)
- (footer . ((nil _ twittering-edit-skeleton-footer)))
- (footer-only-normal
- . ((nil _ twittering-edit-skeleton-footer) . normal))
- (inherit-hashtags
- . [(twittering-edit-skeleton-inherit-hashtags . normal)
- (twittering-edit-skeleton-inherit-hashtags . reply)])
- (inherit-mentions
- . (twittering-edit-skeleton-inherit-mentions . reply))
- (inherit-any
- . [(twittering-edit-skeleton-inherit-mentions . reply)
- (twittering-edit-skeleton-inherit-hashtags . normal)
- (twittering-edit-skeleton-inherit-hashtags . reply)]))
- "*Alist of skeletons performed on `twittering-update-status-interactive'.
-A key of the alist is a symbol and each value is nil, (SKELETON . PRED),
- (FUNC . PRED) or a vector of them.
-
-When invoking `twittering-update-status-interactive', the value corresponding
-to the key specified `twittering-edit-skeleton' are performed.
-
-The value like (SKELETON . PRED) or (FUNC . PRED) is performed when the
-current context matches with PRED.
-PRED is nil, a symbol or a function.
-If PRED is nil, the value is unconditionally performed.
-If PRED is a symbol, the value is performed only when it equals to the
-type of the tweet being edited. The type is one of 'direct-message, 'normal,
-'organic-retweet and 'reply.
-If PRED is a function, the value is performed only when the predicate
-function PRED returns non-nil. PRED is invoked with three arguments
-TWEET-TYPE, IN-REPLY-TO-ID and CURRENT-SPEC.
-TWEET-TYPE is a symbol, which is one of 'direct-message, 'normal,
-'organic-retweet and 'reply, specifying which type of tweet will be edited.
-If the tweet will be edited as a reply or an organic retweet, IN-REPLY-TO-ID
-is a string specifying the replied tweet. Otherwise, IN-REPLY-TO-ID is nil.
-CURRENT-SPEC specifies where the action of posting a tweet is performed.
-If the action is performed on a twittering-mode buffer, CURRENT-SPEC is
-a timeline spec string of the buffer.
-If the action is performed on other buffers, CURRENT-SPEC is nil.
-If the option IGNORE-CURRENT-SPEC for `twittering-update-status' is non-nil,
-CURRENT-SPEC is also nil.
-
-If PRED matches the current context, the value is performed as follows.
-The value like (SKELETON . PRED) is performed by directly using SKELETON as an
-argument of `skeleton-insert'.
-The value like (FUNC . PRED) is performed by invoking FUNC with three
-arguments, TWEET-TYPE, IN-REPLY-TO-ID and CURRENT-SPEC as same as PRED.
-
-If the value is a vector, each element is performed in order of elements
-in the vector.
-
-Note that the effective skeleton is invoked after inserting a
-recipient.")
-(defvar twittering-edit-skeleton 'none
- "*A symbol specifying an effective skeleton.
-It must be one of a symbol in `twittering-edit-skeleton-alist'.
-When entering `twittering-edit-mode', the skeletons in the specified
-entry in `twittering-edit-skeleton-alist' are performed.")
-
-(defun twittering-switch-edit-skeleton ()
- (interactive)
- (let ((skeleton-keys
- (mapcar (lambda (entry) (symbol-name (car entry)))
- twittering-edit-skeleton-alist))
- (current (symbol-name (or twittering-edit-skeleton 'none))))
- (let ((selected
- (twittering-completing-read
- (format "Skeleton (%s): " current)
- skeleton-keys nil t nil nil current)))
- (when selected
- (setq twittering-edit-skeleton (intern selected)))))
- (when (null twittering-edit-skeleton)
- (setq twittering-edit-skeleton 'none))
- (message "Current skeleton: %s" twittering-edit-skeleton))
-
-(defun twittering-edit-skeleton-change-footer (&optional footer-str)
- (interactive)
- (let ((footer-str
- (or footer-str
- (read-from-minibuffer "Footer: " twittering-edit-skeleton-footer
- nil nil
- 'twittering-edit-skeleton-footer-history))))
- (when footer-str
- (setq twittering-edit-skeleton-footer footer-str)))
- (message "Current footer: [%s]" twittering-edit-skeleton-footer))
-
-(defun twittering-edit-skeleton-insert-base (&optional tweet-type in-reply-to-id current-spec)
- (let ((entry
- (cdr (assq twittering-edit-skeleton twittering-edit-skeleton-alist))))
- (when entry
- (require 'skeleton)
- (let ((skeletons (if (vectorp entry)
- entry
- (list entry))))
- (mapcar (lambda (def)
- (let ((skeleton-or-func (car def))
- (pred (cdr def)))
- (when (or (null pred)
- (and (functionp pred)
- (funcall pred tweet-type in-reply-to-id))
- (and (symbolp pred)
- (eq pred tweet-type)))
- (cond
- ((functionp skeleton-or-func)
- (funcall skeleton-or-func tweet-type in-reply-to-id
- current-spec))
- (t
- (skeleton-insert skeleton-or-func))))))
- skeletons)))))
-
-(defun twittering-edit-skeleton-insert (&optional tweet-type in-reply-to-id current-spec)
- (if (> 22 emacs-major-version)
- ;; This prevents Emacs21 from inserting skeletons before the cursor.
- (let ((current (point))
- (pair (with-temp-buffer
- (twittering-edit-skeleton-insert-base tweet-type
- in-reply-to-id
- current-spec)
- `(,(buffer-string) . ,(point)))))
- (insert (car pair))
- (goto-char (+ -1 current (cdr pair))))
- (twittering-edit-skeleton-insert-base tweet-type in-reply-to-id
- current-spec)))
-
-(defun twittering-edit-skeleton-inherit-hashtags (tweet-type in-reply-to-id current-spec)
- (cond
- (in-reply-to-id
- (let* ((status (twittering-find-status in-reply-to-id))
- (text (cdr (assq 'text status)))
- (hashtags
- (twittering-extract-matched-substring-all
- (concat twittering-regexp-hash
- "\\([[:alpha:]0-9_-]+\\)")
- text))
- (footer
- (mapconcat (lambda (tag) (concat "#" tag))
- hashtags " ")))
- (when hashtags
- (skeleton-insert `(nil _ " " ,footer)))))
- ((twittering-timeline-spec-is-search-p current-spec)
- (let* ((query-string
- (twittering-extract-query-string-from-search-timeline-spec
- current-spec))
- (hashtag-list
- (twittering-extract-matched-substring-all
- (concat "\\(" twittering-regexp-hash "[[:alpha:]0-9_-]+\\)")
- query-string)))
- (when hashtag-list
- (let ((footer (mapconcat 'identity hashtag-list " ")))
- (skeleton-insert `(nil _ " " ,footer))))))))
-
-(defun twittering-edit-skeleton-inherit-mentions (tweet-type in-reply-to-id current-spec)
- (when in-reply-to-id
- (let* ((status (twittering-find-status in-reply-to-id))
- (text (cdr (assq 'text status)))
- (recipient (cdr (assq 'user-screen-name status)))
- (mentions
- (twittering-extract-matched-substring-all
- (concat twittering-regexp-atmark
- "\\([a-zA-Z0-9_-]+\\)")
- text))
- (reduced-mentions
- (remove nil
- (mapcar
- (lambda (mention)
- (unless (or (string= mention recipient)
- (string= mention (twittering-get-username)))
- mention))
- mentions))))
- (when reduced-mentions
- (let ((header (mapconcat (lambda (user) (concat "@" user))
- reduced-mentions " ")))
- (skeleton-insert `(nil ,header " " _)))))))
-
-;;;;
-;;;; Edit mode
-;;;;
-
-(defvar twittering-edit-buffer "*twittering-edit*")
-(defvar twittering-pre-edit-window-configuration nil)
-(defvar twittering-edit-history nil)
-(defvar twittering-edit-local-history nil)
-(defvar twittering-edit-local-history-idx nil)
-(defvar twittering-warning-overlay nil)
-
-(define-derived-mode twittering-edit-mode nil "twmode-status-edit"
- (use-local-map twittering-edit-mode-map)
-
- ;; Prevent `global-font-lock-mode' enabling `font-lock-mode'.
- ;; This technique is derived from `lisp/bs.el' distributed with Emacs 22.2.
- (make-local-variable 'font-lock-global-modes)
- (setq font-lock-global-modes '(not twittering-edit-mode))
-
- (make-local-variable 'twittering-warning-overlay)
- (setq twittering-warning-overlay (make-overlay 1 1 nil nil nil))
- (overlay-put twittering-warning-overlay 'face 'font-lock-warning-face)
-
- (make-local-variable 'twittering-edit-local-history)
- (setq twittering-edit-local-history (cons (buffer-string)
- twittering-edit-history))
- (make-local-variable 'twittering-edit-local-history-idx)
- (setq twittering-edit-local-history-idx 0)
-
- (make-local-variable 'after-change-functions)
- (add-to-list 'after-change-functions 'twittering-edit-length-check)
- )
-
-(when twittering-edit-mode-map
- (let ((km twittering-edit-mode-map))
- (define-key km (kbd "C-c C-c") 'twittering-edit-post-status)
- (define-key km (kbd "C-c C-k") 'twittering-edit-cancel-status)
- (define-key km (kbd "C-c C-r") 'twittering-edit-toggle-reply)
- (define-key km (kbd "M-n") 'twittering-edit-next-history)
- (define-key km (kbd "M-p") 'twittering-edit-previous-history)
- (define-key km (kbd "<f4>") 'twittering-edit-replace-at-point)))
-
-(defun twittering-effective-length (str &optional short-length-http short-length-https)
- "Return the effective length of STR with taking account of shortening URIs.
-
-The returned length is calculated with taking account of shortening URIs
-if `twittering-service-method' is the symbol `twitter' or `twitter-api-v1.1'.
-It is assumed that a URI via HTTP will be converted into a URI consisting of
-SHORT-LENGTH-HTTP characters.
-It is assumed that a URI via HTTPS will be converted into a URI consisting of
-SHORT-LENGTH-HTTPS characters.
-
-If SHORT-LENGTH-HTTP is nil, the value of
- (twittering-get-service-configuration 'short_url_length) is used instead.
-If SHORT-LENGTH-HTTPS is nil, the value of
- (twittering-get-service-configuration 'short_url_length_https) is used
-instead."
- (cond
- ((memq twittering-service-method '(twitter twitter-api-v1.1))
- (let ((regexp "\\(?:^\\|[[:space:]]\\)\\(http\\(s\\)?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+\\)")
- (short-length-http
- (or short-length-http
- (twittering-get-service-configuration 'short_url_length)))
- (short-length-https
- (or short-length-https
- (twittering-get-service-configuration 'short_url_length_https)))
- (rest str)
- (pos 0)
- (len 0))
- (save-match-data
- (while (string-match regexp str pos)
- (let ((beg (match-beginning 1))
- (end (match-end 1))
- (short-len (if (match-beginning 2)
- short-length-https
- short-length-http)))
- (let ((additional-length
- ;; Ignore the original length to follow the change
- ;; of t.co URL wrapper.
- ;;
- ;; https://dev.twitter.com/docs/tco-url-wrapper
- ;; As of October 10, 2011 the t.co URL wrapper
- ;; automatically wraps all links submitted to
- ;; Twitter, regardless of length. This includes
- ;; so-called URLs without protocols.
- (+ (- beg pos) short-len)))
- (setq len (+ len additional-length))
- (setq pos end)))))
- (+ len (- (length str) pos))))
- (t
- (length str))))
-
-(defun twittering-edit-length-check (&optional beg end len)
- (let* ((status (twittering-edit-extract-status))
- (maxlen 140)
- (length (twittering-effective-length status)))
- (setq mode-name
- (format "twmode-status-edit[%d/%d]" length maxlen))
- (force-mode-line-update)
- (unless twittering-disable-overlay-on-too-long-string
- (if (< maxlen length)
- (move-overlay twittering-warning-overlay
- (- (point-max) (- length maxlen)) (point-max))
- (move-overlay twittering-warning-overlay 1 1)))))
-
-(defun twittering-edit-get-help-end ()
- "Return the end position of the help on `twittering-edit-mode'."
- (when (eq major-mode 'twittering-edit-mode)
- (next-single-property-change (point-min) 'read-only nil (point-max))))
-
-(defun twittering-edit-extract-status ()
- "Return the text of the status being edited on `twittering-edit-mode'."
- (if (eq major-mode 'twittering-edit-mode)
- (buffer-substring-no-properties (twittering-edit-get-help-end)
- (point-max))
- ""))
-
-(defun twittering-edit-reset-status (str)
- "Reset the contents of the current `twittering-edit-mode' buffer with STR."
- (when (eq major-mode 'twittering-edit-mode)
- (let ((help-end (twittering-edit-get-help-end)))
- (delete-region help-end (point-max))
- (goto-char help-end)
- (insert str)
- (goto-char help-end))))
-
-(defun twittering-edit-set-help-string (str)
- "Render STR as a help for `twittering-edit-mode' to the current buffer."
- (let* ((help-str (propertize str 'read-only t))
- (len (length help-str)))
- (add-text-properties 0 1 '(front-sticky (read-only)) help-str)
- (add-text-properties (1- len) len '(rear-nonsticky t) help-str)
- (save-excursion
- (let ((inhibit-read-only t)
- (inhibit-modification-hooks t)
- (help-end (twittering-edit-get-help-end)))
- (goto-char help-end)
- (if (= (point-min) help-end)
- ;; When no helps are rendered, the all markers should be
- ;; placed after the new help.
- (insert help-str)
- ;; Use `insert-before-markers' because the marker of the current
- ;; position should follow the new help.
- ;; Delete the old help after inserting the new help to make
- ;; the new help visible if possible.
- (insert-before-markers help-str)
- (delete-region (point-min) help-end))))))
-
-(defun twittering-edit-setup-help ()
- (let* ((direct-message-recipient
- (cdr (assq 'direct-message-recipient twittering-edit-mode-info)))
- (tweet-type (cdr (assq 'tweet-type twittering-edit-mode-info)))
- (cited-id (cdr (assq 'cited-id twittering-edit-mode-info)))
- (item (cond
- ((eq tweet-type 'direct-message)
- (format "a direct message to %s" direct-message-recipient))
- ((eq tweet-type 'reply)
- "a reply")
- (t
- "a tweet")))
- (status-format
- (cond
- ((eq tweet-type 'direct-message)
- (format "%%FILL{DIRECT MESSAGE to %s}\n" direct-message-recipient))
- ((eq tweet-type 'reply)
- "%FILL{REPLY to the tweet by %s at %C{%y/%m/%d %H:%M:%S};}\n%FILL{%FACE[font-lock-doc-face]{\"%T\"}}\n")
- (t
- nil)))
- (func (when status-format
- (twittering-generate-format-status-function status-format)))
- (help-str
- (apply 'concat
- `(,@(when func
- `(,(funcall func
- (twittering-find-status cited-id)
- nil)))
- ,(propertize (format (substitute-command-keys "Keymap:
- \\[twittering-edit-post-status]: send %s
- \\[twittering-edit-cancel-status]: cancel %s
- \\[twittering-edit-toggle-reply]: toggle a normal tweet and a reply.
- \\[twittering-edit-next-history]: next history element
- \\[twittering-edit-previous-history]: previous history element
- \\[twittering-edit-replace-at-point]: shorten URL at point
-
----- text above this line is ignored ----
-") item item)
- 'face 'font-lock-comment-face)))))
- (twittering-edit-set-help-string help-str)))
-
-(defun twittering-edit-close ()
- (kill-buffer (current-buffer))
- (when twittering-pre-edit-window-configuration
- (set-window-configuration twittering-pre-edit-window-configuration)
- (setq twittering-pre-edit-window-configuration nil)))
-
-(defvar twittering-edit-mode-info nil
- "Alist of a tweet being edited.
-Pairs of a key symbol and an associated value are following:
- direct-message-recipient -- the recipient when the edited message is
- sent as a direct message.
- cited-id -- the id of the tweet that the edited message refers to.
- tweet-type -- the type of the edited message, which is one of the
- following symbol; normal, reply or direct-message.")
-
-(defun twittering-ensure-whole-of-status-is-visible (&optional window)
- "Ensure that the whole of the tweet on the current point is visible."
- (interactive)
- (let* ((window (or window (selected-window)))
- (buffer (window-buffer window)))
- (when (twittering-buffer-p buffer)
- (with-current-buffer buffer
- (save-excursion
- (let* ((next-head (or (twittering-get-next-status-head) (point-max)))
- (current-tail (max (1- next-head) (point-min))))
- (when (< (window-end window t) current-tail)
- (twittering-set-window-end window current-tail))))))))
-
-(defun twittering-update-status-from-pop-up-buffer (&optional init-string-or-skeleton reply-to-id username tweet-type current-spec)
- (interactive)
- (let ((buf (generate-new-buffer twittering-edit-buffer)))
- (setq twittering-pre-edit-window-configuration
- (current-window-configuration))
- (twittering-pop-to-buffer buf)
- (twittering-edit-mode)
- (make-local-variable 'twittering-edit-mode-info)
- (setq twittering-edit-mode-info
- `((cited-id . ,reply-to-id)
- (tweet-type . ,(cdr (assq tweet-type
- '((direct-message . direct-message)
- (normal . normal)
- (organic-retweet . normal)
- (reply . reply)))))
- (direct-message-recipient . ,username)))
- (twittering-edit-setup-help)
- (setq buffer-undo-list nil)
- (goto-char (twittering-edit-get-help-end))
- (if (eq tweet-type 'direct-message)
- (message "C-c C-c to send, C-c C-k to cancel")
- (and (null init-string-or-skeleton)
- twittering-current-hashtag
- (setq init-string-or-skeleton
- (format " #%s " twittering-current-hashtag)))
- (message "C-c C-c to post, C-c C-k to cancel"))
- (when init-string-or-skeleton
- (require 'skeleton)
- (cond
- ((stringp init-string-or-skeleton)
- (insert init-string-or-skeleton))
- ((listp init-string-or-skeleton)
- (skeleton-insert init-string-or-skeleton))))
- (twittering-edit-skeleton-insert tweet-type reply-to-id
- current-spec)
- (set-buffer-modified-p nil)))
-
-(defun twittering-edit-post-status ()
- (interactive)
- (let* ((status (twittering-edit-extract-status))
- (cited-id (cdr (assq 'cited-id twittering-edit-mode-info)))
- (cited-tweet (twittering-find-status cited-id))
- (cited-username (cdr (assq 'user-screen-name cited-tweet)))
- (direct-message-recipient
- (cdr (assq 'direct-message-recipient twittering-edit-mode-info)))
- (tweet-type (cdr (assq 'tweet-type twittering-edit-mode-info))))
- (cond
- ((string-match "\\` *\\'" status)
- (message "Empty tweet!"))
- ((< 140 (twittering-effective-length status))
- (message "Tweet is too long!"))
- ((cond
- ((and (eq tweet-type 'reply)
- (not (string-match
- (concat "@" cited-username "\\(?:[\n\r \t]+\\)*") status)))
- (y-or-n-p
- "Send this tweet without mentions as a normal tweet (not a reply)? "))
- (twittering-request-confirmation-on-posting
- (y-or-n-p "Send this tweet? "))
- (t
- t))
- (setq twittering-edit-history
- (cons status twittering-edit-history))
- (cond
- ((eq tweet-type 'direct-message)
- (if direct-message-recipient
- (twittering-call-api 'send-direct-message
- `((username . ,direct-message-recipient)
- (status . ,status)))
- (message "No username specified")))
- ((eq tweet-type 'reply)
- (twittering-call-api 'update-status
- `((status . ,status)
- (in-reply-to-status-id . ,cited-id))))
- (t
- (twittering-call-api 'update-status `((status . ,status)))))
- (twittering-edit-close))
- (t
- nil))))
-
-(defun twittering-edit-cancel-status ()
- (interactive)
- (when (or (not (buffer-modified-p))
- (prog1 (if (y-or-n-p "Cancel this tweet? ")
- (message "Request canceled")
- (message nil))))
- (twittering-edit-close)))
-
-(defun twittering-edit-next-history ()
- (interactive)
- (if (>= 0 twittering-edit-local-history-idx)
- (message "End of history.")
- (let ((current-history (nthcdr twittering-edit-local-history-idx
- twittering-edit-local-history)))
- (setcar current-history (twittering-edit-extract-status))
- (decf twittering-edit-local-history-idx)
- (twittering-edit-reset-status (nth twittering-edit-local-history-idx
- twittering-edit-local-history)))))
-
-(defun twittering-edit-previous-history ()
- (interactive)
- (if (>= twittering-edit-local-history-idx
- (- (length twittering-edit-local-history) 1))
- (message "Beginning of history.")
- (let ((current-history (nthcdr twittering-edit-local-history-idx
- twittering-edit-local-history)))
- (setcar current-history (twittering-edit-extract-status))
- (incf twittering-edit-local-history-idx)
- (twittering-edit-reset-status (nth twittering-edit-local-history-idx
- twittering-edit-local-history)))))
-
-(defun twittering-edit-replace-at-point ()
- (interactive)
- (when (eq major-mode 'twittering-edit-mode)
- (twittering-tinyurl-replace-at-point)
- (twittering-edit-length-check)))
-
-(defun twittering-edit-toggle-reply ()
- "Toggle whether the tweet being edited will be sent as a reply or not."
- (interactive)
- (let ((tweet-type (cdr (assq 'tweet-type twittering-edit-mode-info)))
- (cited-id (cdr (assq 'cited-id twittering-edit-mode-info))))
- (cond
- ((eq tweet-type 'direct-message)
- (message "The current message is a direct message."))
- ((null cited-id)
- (message "The current message does not have a reply target."))
- (t
- (setq twittering-edit-mode-info
- (mapcar (lambda (entry)
- (if (eq (car entry) 'tweet-type)
- `(tweet-type
- . ,(cdr (assq (cdr entry)
- '((normal . reply)
- (reply . normal)))))
- entry))
- twittering-edit-mode-info))
- (twittering-edit-setup-help)))))
-
-;;;;
-;;;; Edit a status on minibuffer
-;;;;
-
-(defun twittering-show-minibuffer-length (&optional beg end len)
- "Show the number of characters in minibuffer."
- (when (minibuffer-window-active-p (selected-window))
- (if (and transient-mark-mode deactivate-mark)
- (deactivate-mark))
- (let* ((deactivate-mark deactivate-mark)
- (status-len (- (twittering-effective-length (buffer-string))
- (minibuffer-prompt-width)))
- (mes (format "%d" status-len)))
- (if (<= 23 emacs-major-version)
- (minibuffer-message mes) ;; Emacs23 or later
- (minibuffer-message (concat " (" mes ")")))
- )))
-
-(defun twittering-setup-minibuffer ()
- (add-hook 'post-command-hook 'twittering-show-minibuffer-length t t))
-
-(defun twittering-finish-minibuffer ()
- (remove-hook 'post-command-hook 'twittering-show-minibuffer-length t))
-
-(defun twittering-status-not-blank-p (status)
- (let ((coding-system-for-read 'binary)
- (coding-system-for-write 'binary))
- (with-temp-buffer
- (insert status)
- (goto-char (point-min))
- ;; skip user name
- (re-search-forward "\\`[[:space:]]*@[a-zA-Z0-9_-]+\\([[:space:]]+@[a-zA-Z0-9_-]+\\)*" nil t)
- (re-search-forward "[^[:space:]]" nil t))))
-
-(defun twittering-update-status-from-minibuffer (&optional init-string-or-skeleton reply-to-id username tweet-type current-spec)
- (and (not (eq tweet-type 'direct-message))
- (null init-string-or-skeleton)
- twittering-current-hashtag
- (setq init-string-or-skeleton
- (format " #%s " twittering-current-hashtag)))
- (let ((status
- (with-temp-buffer
- (when init-string-or-skeleton
- (require 'skeleton)
- (cond
- ((stringp init-string-or-skeleton)
- (insert init-string-or-skeleton))
- ((listp init-string-or-skeleton)
- (skeleton-insert init-string-or-skeleton))))
- (twittering-edit-skeleton-insert tweet-type reply-to-id
- current-spec)
- `(,(buffer-string) . ,(point))))
- (not-posted-p t)
- (prompt "status: ")
- (map minibuffer-local-map)
- (minibuffer-message-timeout nil))
- (define-key map (kbd "<f4>") 'twittering-tinyurl-replace-at-point)
- (when twittering-use-show-minibuffer-length
- (add-hook 'minibuffer-setup-hook 'twittering-setup-minibuffer t)
- (add-hook 'minibuffer-exit-hook 'twittering-finish-minibuffer t))
- (unwind-protect
- (while not-posted-p
- (setq status (read-from-minibuffer prompt status map nil 'twittering-tweet-history nil t))
- (let ((status status))
- (if (< 140 (twittering-effective-length status))
- (setq prompt "status (too long): ")
- (setq prompt "status: ")
- (when (twittering-status-not-blank-p status)
- (cond
- ((eq tweet-type 'direct-message)
- (if username
- (twittering-call-api 'send-direct-message
- `((username . ,username)
- (status . ,status)))
- (message "No username specified")))
- (t
- (let ((parameters `(("status" . ,status)))
- (as-reply
- (and reply-to-id
- username
- (eq tweet-type 'reply)
- (string-match
- (concat "@" username "\\(?:[\n\r \t]+\\)*")
- status))))
- ;; Add in_reply_to_status_id only when a posting
- ;; status begins with @username.
- (twittering-call-api
- 'update-status
- `((status . ,status)
- ,@(when as-reply
- `((in-reply-to-status-id
- . ,(format "%s" reply-to-id))))))
- )))
- (setq not-posted-p nil))
- )))
- ;; unwindforms
- (when (memq 'twittering-setup-minibuffer minibuffer-setup-hook)
- (remove-hook 'minibuffer-setup-hook 'twittering-setup-minibuffer))
- (when (memq 'twittering-finish-minibuffer minibuffer-exit-hook)
- (remove-hook 'minibuffer-exit-hook 'twittering-finish-minibuffer))
- )))
-
-;;;;
-;;;; Reading username/listname with completion
-;;;;
-
-(defun twittering-get-usernames-from-timeline (&optional timeline-data)
- (let ((timeline-data (or timeline-data (twittering-current-timeline-data))))
- (twittering-remove-duplicates
- (mapcar
- (lambda (status)
- (let* ((base-str (cdr (assq 'user-screen-name status)))
- ;; `copied-str' is independent of the string in timeline-data.
- ;; This isolation is required for `minibuf-isearch.el',
- ;; which removes the text properties of strings in history.
- (copied-str (copy-sequence base-str)))
- (set-text-properties 0 (length copied-str) nil copied-str)
- copied-str))
- timeline-data))))
-
-(defun twittering-read-username-with-completion (prompt init-user &optional history)
- (let ((collection (append twittering-user-history
- (twittering-get-usernames-from-timeline))))
- (twittering-completing-read prompt collection nil nil init-user history)))
-
-(defun twittering-read-list-name (username &optional list-index)
- (let* ((list-index (or list-index
- (twittering-get-list-index-sync username)))
- (username (prog1 (copy-sequence username)
- (set-text-properties 0 (length username) nil username)))
- (prompt (format "%s's list: " username))
- (listname
- (if list-index
- (twittering-completing-read prompt list-index nil t nil)
- nil)))
- (if (string= "" listname)
- nil
- listname)))
-
-(defun twittering-read-subscription-list-name (username &optional list-index)
- (let* ((list-index (or list-index
- (twittering-get-list-subscriptions-sync username)))
- (username (prog1 (copy-sequence username)
- (set-text-properties 0 (length username) nil username)))
- (prompt (format "%s's subscription: " username))
- (listname
- (if list-index
- (twittering-completing-read prompt list-index nil t nil)
- nil)))
- (if (string= "" listname)
- nil
- listname)))
-
-(defun twittering-read-timeline-spec-with-completion (prompt initial &optional as-string)
- (let* ((dummy-hist
- (append twittering-timeline-history
- (twittering-get-usernames-from-timeline)
- '(":direct_messages" ":direct_messages_sent"
- ":favorites" ":friends"
- ":home" ":mentions" ":public" ":replies"
- ":retweeted_by_me" ":retweeted_by_user/"
- ":retweeted_to_me" ":retweeted_to_user/"
- ":retweets_of_me")
- (mapcar (lambda (cell)
- (concat "$" (car cell) (if (listp (cdr cell)) "()" "")))
- twittering-timeline-spec-alias)))
- (spec-with-username
- '((":favorites/" . "Whose favorites: ")
- (":retweeted_by_user/" . "Who has retweeted? ")
- (":retweeted_to_user/" . "Who has received the retweets? ")))
- (regexp-spec-with-username
- (concat "\\`\\("
- (mapconcat (lambda (entry) (car entry))
- spec-with-username "\\|")
- "\\)\\'"))
- (spec-string (twittering-completing-read prompt dummy-hist
- nil nil initial 'dummy-hist))
- (spec-string
- (cond
- ((string-match regexp-spec-with-username spec-string)
- (let* ((spec-and-prompt
- (assoc (match-string 1 spec-string)
- spec-with-username))
- (prefix (car spec-and-prompt))
- (prompt (cdr spec-and-prompt))
- (username
- (twittering-read-username-with-completion
- prompt ""
- 'twittering-user-history)))
- (if username
- (concat prefix username)
- nil)))
- ((string-match "^\\([a-zA-Z0-9_-]+\\)/$" spec-string)
- (let* ((username (match-string 1 spec-string))
- (list-index (twittering-get-list-index-sync username))
- (listname
- (if list-index
- (twittering-read-list-name username list-index)
- nil)))
- (if listname
- (concat username "/" listname)
- nil)))
- (t
- spec-string)))
- (spec (if (stringp spec-string)
- (condition-case error-str
- (twittering-string-to-timeline-spec spec-string)
- (error
- (message "Invalid timeline spec: %s" error-str)
- nil))
- nil)))
- (cond
- ((null spec)
- nil)
- (spec (if as-string
- spec-string
- spec))
- ((string= "" spec-string)
- (message "No timeline specs are specified.")
- nil)
- (t
- (message "\"%s\" is invalid as a timeline spec." spec-string)
- nil))))
-
-;;;;
-;;;; Commands
-;;;;
-
-;;;; Commands for changing modes
-(defun twittering-jojo-mode (&optional arg)
- (interactive "P")
- (let ((prev-mode twittering-jojo-mode))
- (setq twittering-jojo-mode
- (if (null arg)
- (not twittering-jojo-mode)
- (< 0 (prefix-numeric-value arg))))
- (unless (eq prev-mode twittering-jojo-mode)
- (twittering-update-mode-line))))
-
-(defun twittering-toggle-reverse-mode (&optional arg)
- (interactive "P")
- (let ((prev-mode twittering-reverse-mode))
- (setq twittering-reverse-mode
- (if (null arg)
- (not twittering-reverse-mode)
- (< 0 (prefix-numeric-value arg))))
- (unless (eq prev-mode twittering-reverse-mode)
- (twittering-update-mode-line)
- (twittering-rerender-timeline-all (current-buffer)))))
-
-(defun twittering-set-current-hashtag (&optional tag)
- (interactive)
- (unless tag
- (setq tag (twittering-completing-read "hashtag (blank to clear): #"
- twittering-hashtag-history
- nil nil
- twittering-current-hashtag
- 'twittering-hashtag-history))
- (message
- (if (eq 0 (length tag))
- (progn (setq twittering-current-hashtag nil)
- "Current hashtag is not set.")
- (progn
- (setq twittering-current-hashtag tag)
- (format "Current hashtag is #%s" twittering-current-hashtag))))))
-
-;;;; Commands for switching buffers
-(defun twittering-switch-to-next-timeline ()
- (interactive)
- (when (twittering-buffer-p)
- (let* ((buffer-list (twittering-get-buffer-list))
- (following-buffers (cdr (memq (current-buffer) buffer-list)))
- (next (if following-buffers
- (car following-buffers)
- (car buffer-list))))
- (unless (eq (current-buffer) next)
- (switch-to-buffer next)))))
-
-(defun twittering-switch-to-previous-timeline ()
- (interactive)
- (when (twittering-buffer-p)
- (let* ((buffer-list (reverse (twittering-get-buffer-list)))
- (preceding-buffers (cdr (memq (current-buffer) buffer-list)))
- (previous (if preceding-buffers
- (car preceding-buffers)
- (car buffer-list))))
- (unless (eq (current-buffer) previous)
- (switch-to-buffer previous)))))
-
-;;;; Commands for visiting a timeline
-(defun twittering-visit-timeline (&optional timeline-spec initial)
- (interactive)
- (cond
- ((twittering-ensure-preparation-for-api-invocation)
- (let ((timeline-spec
- (or timeline-spec
- (twittering-read-timeline-spec-with-completion
- "timeline: " initial t))))
- (when timeline-spec
- (switch-to-buffer (twittering-get-managed-buffer timeline-spec)))))
- (t
- nil)))
-
-(defun twittering-friends-timeline ()
- (interactive)
- (twittering-visit-timeline '(friends)))
-
-(defun twittering-home-timeline ()
- (interactive)
- (twittering-visit-timeline '(home)))
-
-(defun twittering-replies-timeline ()
- (interactive)
- (twittering-visit-timeline '(replies)))
-
-(defun twittering-public-timeline ()
- (interactive)
- (twittering-visit-timeline '(public)))
-
-(defun twittering-user-timeline ()
- (interactive)
- (twittering-visit-timeline `(user ,(twittering-get-username))))
-
-(defun twittering-direct-messages-timeline ()
- (interactive)
- (twittering-visit-timeline '(direct_messages)))
-
-(defun twittering-sent-direct-messages-timeline ()
- (interactive)
- (twittering-visit-timeline '(direct_messages_sent)))
-
-(defun twittering-other-user-timeline ()
- (interactive)
- (let* ((username (get-text-property (point) 'username))
- (goto-spec (get-text-property (point) 'goto-spec))
- (screen-name-in-text
- (get-text-property (point) 'screen-name-in-text))
- (uri (or (get-text-property (point) 'expanded-uri)
- (get-text-property (point) 'uri)))
- (mentioned-id (when uri
- (twittering-extract-id-from-url uri)))
- (spec (cond (goto-spec goto-spec)
- (screen-name-in-text `(user ,screen-name-in-text))
- (mentioned-id `(single ,mentioned-id))
- (username `(user ,username))
- (t nil))))
- (if spec
- (twittering-visit-timeline spec)
- (message "No user selected"))))
-
-(defun twittering-other-user-timeline-interactive ()
- (interactive)
- (let ((username (or (twittering-read-username-with-completion
- "user: " nil
- 'twittering-user-history)
- "")))
- (if (string= "" username)
- (message "No user selected")
- (twittering-visit-timeline `(user ,username)))))
-
-(defun twittering-other-user-list-interactive (&optional subscriptions)
- (interactive "P")
- (let* ((username (copy-sequence (get-text-property (point) 'username)))
- (username (progn
- (set-text-properties 0 (length username) nil username)
- (or (twittering-read-username-with-completion
- (if subscriptions
- "Whose subscription: "
- "Whose list: ")
- username
- 'twittering-user-history)
- ""))))
- (if (string= "" username)
- (message "No user selected")
- (let* ((list-name (if subscriptions
- (twittering-read-subscription-list-name username)
- (twittering-read-list-name username)))
- (spec (cond
- ((null list-name)
- nil)
- (subscriptions
- (and (string-match "\\`\\(.*\\)/\\(.*\\)\\'" list-name)
- `(list ,(match-string 1 list-name)
- ,(match-string 2 list-name))))
- (t
- `(list ,username ,list-name)))))
- (if spec
- (twittering-visit-timeline spec)
- ;; Don't show message here to prevent an overwrite of a
- ;; message which is outputted by `twittering-read-list-name'.
- )))))
-
-(defun twittering-search (&optional word)
- (interactive)
- (let ((word (or word
- (read-from-minibuffer "search: " nil nil nil
- 'twittering-search-history nil t)
- "")))
- (if (string= "" word)
- (message "No query string")
- (let ((spec `(search ,word)))
- (twittering-visit-timeline spec)))))
-
-;;;; Commands for retrieving statuses
-
-(defun twittering-current-timeline-noninteractive ()
- (twittering-current-timeline t))
-
-(defun twittering-current-timeline (&optional noninteractive)
- (interactive)
- (when (twittering-buffer-p)
- (let ((spec-string (twittering-current-timeline-spec-string)))
- (twittering-get-and-render-timeline noninteractive))))
-
-(defun twittering-get-tweets-within-specific-time-range (time-beg time-end)
- "Get tweets within a time range between TIME-BEG and TIME-END.
-TIME-BEG and TIME-END must be nil or an internal representation of time as
-same as the returned value of `current-time'."
- (let* ((since_id (when time-beg
- (twittering-time-to-id time-beg)))
- (max_id (when time-end
- (twittering-time-to-id time-end)))
- (spec-string (twittering-current-timeline-spec-string))
- (noninteractive t)
- (args
- `(,@(cond
- (max_id `((max_id . ,max_id)))
- (since_id `((since_id . ,since_id)))
- (t nil)))))
- (twittering-retrieve-timeline spec-string noninteractive args nil)))
-
-(defun twittering-get-tweets-before (&optional before-str)
- (interactive)
- (let* ((id (when (null before-str)
- (twittering-get-id-at)))
- (init-str
- (when id
- (let* ((status (twittering-find-status id))
- (init-time
- (or (cdr (assq 'retweeting-created-at status))
- (cdr (assq 'created-at status)))))
- (format-time-string "%Y-%m-%d %T" init-time))))
- (before-str
- (or before-str
- (read-string "before [YYYY-MM-DD [HH:MM:SS]]: " init-str)))
- (time-beg nil)
- (time-end
- (apply 'encode-time (twittering-parse-time-string before-str t))))
- (twittering-get-tweets-within-specific-time-range time-beg time-end)))
-
-;;;; Commands for posting a status
-
-(defun twittering-update-status (&optional init-string-or-skeleton reply-to-id username tweet-type ignore-current-spec)
- "Post a tweet.
-The first argument INIT-STRING-OR-SKELETON is nil, an initial text or a
-skeleton to be inserted with `skeleton-insert'.
-REPLY-TO-ID is an ID of a tweet which you are going to cite or reply to.
-USERNAME is a recipient of a direct message.
-TWEET-TYPE is a symbol meaning the type of the tweet being edited. It must
-be one of 'direct-message, 'normal, 'organic-retweet and 'reply.
-If TWEET-TYPE is nil, it is equivalent to 'normal, which means that a tweet
-is edited as a normal tweet.
-If IGNORE-CURRENT-SPEC is non-nil, the timeline spec of the current buffer
-is sent to the function specified by `twittering-update-status-function'.
-
-How to edit a tweet is determined by `twittering-update-status-funcion'."
- (let ((current-spec (unless ignore-current-spec
- (twittering-current-timeline-spec)))
- (tweet-type (or tweet-type 'normal)))
- (funcall twittering-update-status-function init-string-or-skeleton
- reply-to-id username
- tweet-type current-spec)))
-
-(defun twittering-update-status-interactive ()
- (interactive)
- (twittering-update-status))
-
-(defun twittering-update-lambda ()
- (interactive)
- (when (and (string= "Japanese" current-language-environment)
- (or (< 21 emacs-major-version)
- (eq 'utf-8 (terminal-coding-system))))
- (let ((text (mapconcat
- 'char-to-string
- (mapcar 'twittering-ucs-to-char
- '(955 12363 12431 12356 12356 12424 955)) "")))
- (twittering-call-api 'update-status `((status . ,text))))))
-
-(defun twittering-post-predicted-message-like-jojo (status)
- (let ((screen-name (cdr (assq 'user-screen-name status)))
- (text (cdr (assq 'text status))))
- (when (and (not (string= screen-name (twittering-get-username)))
- (string-match
- (mapconcat 'char-to-string
- (mapcar
- 'twittering-ucs-to-char
- '(#x6b21 #x306b #x005c #x0028 #x304a #x524d
- #x005c #x007c #x8cb4 #x69d8 #x005c #x0029
- #x306f #x300c #x005c #x0028 #x005b #x005e
- #x300d #x005d #x002b #x005c #x0029 #x300d
- #x3068 #x8a00 #x3046))
- "")
- text))
- (let ((text
- (concat "@" screen-name " "
- (match-string-no-properties 2 text)
- (mapconcat 'char-to-string
- (mapcar 'twittering-ucs-to-char
- '(#x3000 #x306f #x3063 #x0021 #x003f))
- ""))))
- (twittering-call-api 'update-status `((status . ,text)))))))
-
-(defun twittering-jojo-mode-hook-function ()
- (when (and twittering-jojo-mode
- (string= "Japanese" current-language-environment)
- (or (< 21 emacs-major-version)
- (eq 'utf-8 (terminal-coding-system))))
- (mapcar 'twittering-post-predicted-message-like-jojo
- twittering-rendered-new-tweets)))
-
-(defun twittering-direct-message ()
- (interactive)
- (let ((username (twittering-read-username-with-completion
- "Who would you like to receive the DM? "
- (get-text-property (point) 'username)
- 'twittering-user-history)))
- (if (string= "" username)
- (message "No user selected")
- (twittering-update-status nil nil username 'direct-message))))
-
-(defun twittering-reply-to-user ()
- (interactive)
- (let ((username (get-text-property (point) 'username)))
- (if username
- (twittering-update-status (concat "@" username " "))
- (message "No user selected"))))
-
-;;;; Command for deleting a status
-
-(defun twittering-delete-status (&optional id)
- (interactive)
- (let* ((id (twittering-get-id-at))
- (status (twittering-find-status id))
- (is-retweet (assq 'retweeted-id status))
- (username (if is-retweet
- (cdr (assq 'retweeting-user-screen-name status))
- (cdr (assq 'user-screen-name status))))
- (text (if is-retweet
- (cdr (assq 'retweeting-text status))
- (cdr (assq 'text status))))
- (width (max 40 ;; XXX
- (- (frame-width)
- 1 ;; margin for wide characters
- 11 ;; == (length (concat "Delete \"" "\"? "))
- 9) ;; == (length "(y or n) ")
- ))
- (mes (format "Delete \"%s\"? "
- (if (< width (string-width text))
- (concat
- (truncate-string-to-width text (- width 3))
- "...")
- text))))
- (cond
- ((not (string= username (twittering-get-username)))
- (message "The status is not yours!"))
- ((not id)
- (message "No status selected"))
- ((y-or-n-p mes)
- (twittering-call-api 'destroy-status `((id . ,id))))
- (t
- (message "Request canceled")))))
-
-;;;; Commands for retweet
-
-(defun twittering-retweet (&optional arg)
- (interactive "P")
- (let ((use-native-retweet-flag (if arg
- (not twittering-use-native-retweet)
- twittering-use-native-retweet)))
- (if use-native-retweet-flag
- (twittering-native-retweet)
- (twittering-organic-retweet))))
-
-(defun twittering-organic-retweet ()
- (interactive)
- (let* ((id (twittering-get-id-at))
- (status (twittering-find-status id))
- (username (cdr (assq 'user-screen-name status)))
- (text (cdr (assq 'text status)))
- (retweet-time (current-time))
- (skeleton-with-format-string
- (cond
- ((null twittering-retweet-format)
- '(nil _ " RT: %t (via @%s)"))
- ((stringp twittering-retweet-format)
- `(nil ,twittering-retweet-format _))
- ((listp twittering-retweet-format)
- twittering-retweet-format)
- (t
- nil))))
- (cond
- ((cdr (assq 'user-protected status))
- (error "Cannot retweet protected tweets."))
- (username
- (let ((prefix "%")
- (replace-table
- `(("%" . "%")
- ("s" . ,username)
- ("t" . ,text)
- ("#" . ,id)
- ("u" . ,(twittering-get-status-url-from-alist status))
- ("C{\\([^}]*\\)}" .
- (lambda (context)
- (let ((str (cdr (assq 'following-string context)))
- (match-data (cdr (assq 'match-data context))))
- (store-match-data match-data)
- (format-time-string (match-string 1 str) ',retweet-time))))
- ))
- )
- (twittering-update-status
- (mapcar (lambda (element)
- (if (stringp element)
- (twittering-format-string element prefix replace-table)
- element))
- skeleton-with-format-string)
- id nil 'organic-retweet)
- )))))
-
-(defun twittering-native-retweet ()
- (interactive)
- (let ((id (or (get-text-property (point) 'retweeted-id)
- (get-text-property (point) 'id)))
- (text (copy-sequence (get-text-property (point) 'text)))
- (user (get-text-property (point) 'username))
- (width (max 40 ;; XXX
- (- (frame-width)
- 1 ;; margin for wide characters
- 12 ;; == (length (concat "Retweet \"" "\"? "))
- 9) ;; == (length "(y or n) ")
- )))
- (set-text-properties 0 (length text) nil text)
- (if id
- (if (not (string= user twittering-username))
- (let ((mes (format "Retweet \"%s\"? "
- (if (< width (string-width text))
- (concat
- (truncate-string-to-width text (- width 3))
- "...")
- text))))
- (if (y-or-n-p mes)
- (twittering-call-api 'retweet `((id . ,id)))
- (message "Request canceled")))
- (message "Cannot retweet your own tweet"))
- (message "No status selected"))))
-
-;;;; Commands for browsing information related to a status
-
-(defun twittering-click ()
- (interactive)
- (let ((uri (get-text-property (point) 'uri)))
- (if uri
- (browse-url uri))))
-
-(defun twittering-enter ()
- (interactive)
- (let* ((username (get-text-property (point) 'username))
- (id (twittering-get-id-at (point)))
- (uri (get-text-property (point) 'uri))
- (tweet-type
- (cond
- ((twittering-timeline-spec-is-direct-messages-p
- (get-text-property (point) 'source-spec))
- 'direct-message)
- (t
- 'reply)))
- (screen-name-in-text
- (get-text-property (point) 'screen-name-in-text))
- (initial-str
- (when (and (not (eq tweet-type 'direct-message))
- (or screen-name-in-text username))
- (concat "@" (or screen-name-in-text username) " ")))
- (field-id (get-text-property (point) 'field))
- (is-latest-end (twittering-field-id-is-timeline-latest-end field-id))
- (is-oldest-end (twittering-field-id-is-timeline-oldest-end field-id)))
- (cond
- (is-latest-end
- (message "Get more of the recent timeline...")
- (if twittering-reverse-mode
- (twittering-goto-last-normal-field)
- (twittering-goto-first-normal-field))
- (twittering-get-and-render-timeline))
- (is-oldest-end
- (let* ((oldest-status (car (last (twittering-current-timeline-data))))
- (oldest-id (cdr (assq 'id oldest-status))))
- (message "Get more of the previous timeline...")
- (if twittering-reverse-mode
- (twittering-goto-first-normal-field)
- (twittering-goto-last-normal-field))
- (twittering-get-and-render-timeline nil oldest-id)))
- (screen-name-in-text
- (twittering-update-status initial-str
- id screen-name-in-text tweet-type))
- (uri
- (browse-url uri))
- (username
- (twittering-update-status initial-str id username tweet-type)))))
-
-(defun twittering-view-user-page ()
- (interactive)
- (let ((uri (get-text-property (point) 'uri)))
- (if uri
- (browse-url uri))))
-
-;;;;
-;;;; Commands corresponding to operations on Twitter
-;;;;
-
-(defun twittering-follow (&optional remove)
- (interactive "P")
- (let* ((method (if remove 'destroy-friendships 'create-friendships))
- (mes (if remove "unfollow" "follow"))
- (id (twittering-get-id-at))
- (status (when id (twittering-find-status id)))
- (username
- (cond
- ((assq 'retweeted-id status)
- (let* ((retweeting-username
- (cdr (assq 'retweeting-user-screen-name status)))
- (retweeted-username
- (cdr (assq 'retweeted-user-screen-name status)))
- (default (if remove
- retweeting-username
- retweeted-username))
- (prompt (format "Who do you %s? (default:%s): "
- mes default))
- (candidates (list retweeted-username retweeting-username)))
- (twittering-completing-read prompt candidates nil t
- nil nil default)))
- (status
- (cdr (assq 'user-screen-name status)))
- (t
- (twittering-read-username-with-completion
- (format "Who do you %s? " mes) "" 'twittering-user-history)))))
- (if (string= "" username)
- (message "No user selected")
- (if (y-or-n-p (format "%s %s? " (capitalize mes) username))
- (twittering-call-api method `((username . ,username)))
- (message "Request canceled")))))
-
-(defun twittering-unfollow ()
- (interactive)
- (twittering-follow t))
-
-(defun twittering-favorite (&optional remove)
- (interactive "P")
- (let ((id (get-text-property (point) 'id))
- (text (copy-sequence (get-text-property (point) 'text)))
- (width (max 40 ;; XXX
- (- (frame-width)
- 1 ;; margin for wide characters
- 15 ;; == (length (concat "Unfavorite \"" "\"? "))
- 9) ;; == (length "(y or n) ")
- ))
- (method (if remove 'destroy-favorites 'create-favorites)))
- (set-text-properties 0 (length text) nil text)
- (if id
- (let ((mes (format "%s \"%s\"? "
- (if remove "Unfavorite" "Favorite")
- (if (< width (string-width text))
- (concat
- (truncate-string-to-width text (- width 3))
- "...")
- text))))
- (if (y-or-n-p mes)
- (twittering-call-api method `((id . ,id)))
- (message "Request canceled")))
- (message "No status selected"))))
-
-(defun twittering-unfavorite ()
- (interactive)
- (twittering-favorite t))
-
-(defun twittering-block ()
- "Block a user who posted the tweet at the current position."
- (interactive)
- (let* ((id (twittering-get-id-at))
- (status (when id (twittering-find-status id)))
- (username
- (cond
- ((assq 'retweeted-id status)
- (let* ((retweeting-username
- (cdr (assq 'retweeting-user-screen-name status)))
- (retweeted-username
- (cdr (assq 'retweeted-user-screen-name status)))
- (prompt "Who do you block? ")
- (candidates (list retweeted-username retweeting-username)))
- (twittering-completing-read prompt candidates nil t)))
- (status
- (cdr (assq 'user-screen-name status)))
- (t
- nil))))
- (cond
- ((or (null username) (string= "" username))
- (message "No user selected"))
- ((yes-or-no-p (format "Really block \"%s\"? " username))
- (twittering-call-api 'block `((username . ,username))))
- (t
- (message "Request canceled")))))
-
-(defun twittering-block-and-report-as-spammer ()
- "Report a user who posted the tweet at the current position as a spammer.
-The user is also blocked."
- (interactive)
- (let* ((id (twittering-get-id-at))
- (status (when id (twittering-find-status id)))
- (username
- (cond
- ((assq 'retweeted-id status)
- (let* ((retweeting-username
- (cdr (assq 'retweeting-user-screen-name status)))
- (retweeted-username
- (cdr (assq 'retweeted-user-screen-name status)))
- (prompt "Who do you report as a spammer? ")
- (candidates (list retweeted-username retweeting-username)))
- (twittering-completing-read prompt candidates nil t)))
- (status
- (cdr (assq 'user-screen-name status)))
- (t
- nil))))
- (cond
- ((or (null username) (string= "" username))
- (message "No user selected"))
- ((yes-or-no-p
- (format "Really block \"%s\" and report him or her as a spammer? "
- username))
- (twittering-call-api 'block-and-report-as-spammer
- `((username . ,username))))
- (t
- (message "Request canceled")))))
-
-;;;; Commands for clearing stored statuses.
-
-(defun twittering-erase-old-statuses ()
- (interactive)
- (when (twittering-buffer-p)
- (let ((spec (twittering-current-timeline-spec)))
- (twittering-remove-timeline-data spec) ;; clear current timeline.
- (twittering-rerender-timeline-all (current-buffer)) ;; clear buffer.
- (twittering-get-and-render-timeline))))
-
-;;;; Cursor motion
-
-(defun twittering-get-id-at (&optional pos)
- "Return ID of the status at POS. If a separator is rendered at POS, return
-the ID of the status rendered before the separator. The default value of POS
-is `(point)'."
- (let ((pos (or pos (point))))
- (or (get-text-property pos 'id)
- (let ((prev (or (twittering-get-current-status-head pos)
- (point-min))))
- (and prev (get-text-property prev 'id))))))
-
-(defun twittering-get-current-status-head (&optional pos)
- "Return the head position of the status at POS.
-If POS is nil, the value of point is used for POS.
-If a separator is rendered at POS, return the head of the status followed
-by the separator.
-Return POS if no statuses are rendered."
- (let* ((pos (or pos (point)))
- (field-id (get-text-property pos 'field))
- ;; Find the beginning of the field regardless of stickiness.
- (head (field-beginning pos t)))
- (cond
- ((null field-id)
- ;; A separator is rendered at `pos'.
- (if (get-text-property head 'field)
- ;; When `pos' points the head of the separator, `head' points
- ;; to the beginning of the status followed by the separator.
- head
- ;; In the case that `pos' points to a character of the separator,
- ;; but not to the head of the separator.
- (field-beginning head t)))
- ((null (get-text-property head 'field))
- ;; When `head' points to a separator, `pos' points to the head
- ;; of a status.
- pos)
- ((not (twittering-field-id= field-id (get-text-property head 'field)))
- ;; When `pos' points to the beginning of the field and it also
- ;; points to the end of the previous field, `head' points to the
- ;; head of the previous status.
- pos)
- (t
- head))))
-
-(defun twittering-goto-first-status ()
- "Go to the first status."
- (interactive)
- (goto-char (or (twittering-get-first-status-head)
- (point-min))))
-
-(defun twittering-get-first-status-head ()
- "Return the head position of the first status in the current buffer.
-Return nil if no statuses are rendered."
- (if (get-text-property (point-min) 'field)
- (point-min)
- (twittering-get-next-status-head (point-min))))
-
-(defun twittering-goto-last-status ()
- "Go to the last status."
- (interactive)
- (goto-char (or (twittering-get-last-status-head)
- (point-min))))
-
-(defun twittering-get-last-status-head ()
- "Return the head position of the last status in the current buffer.
-Return nil if no statuses are rendered."
- (if (get-text-property (point-max) 'field)
- (point-max)
- (twittering-get-previous-status-head (point-max))))
-
-(defun twittering-goto-first-normal-field ()
- "Go to the first normal field.
-A normal field is a field corresponding to a tweet."
- (interactive)
- (goto-char (or (twittering-get-first-normal-field-head)
- (point-min))))
-
-(defun twittering-goto-last-normal-field ()
- "Go to the last normal field.
-A normal field is a field corresponding to a tweet."
- (interactive)
- (goto-char (or (twittering-get-last-normal-field-head)
- (point-max))))
-
-(defun twittering-get-first-normal-field-head ()
- "Return the head position of the first normal field in the current buffer.
-A normal field is a field corresponding to a tweet.
-Return nil if no statuses are rendered."
- (let ((pos (twittering-get-first-status-head)))
- (while (and pos
- (< pos (point-max))
- (null (get-text-property pos 'id)))
- (setq pos (twittering-get-next-status-head pos)))
- (when (and pos (< pos (point-max)) (get-text-property pos 'id))
- pos)))
-
-(defun twittering-get-last-normal-field-head ()
- "Return the head position of the last normal field in the current buffer.
-A normal field is a field corresponding to a tweet.
-Return nil if no statuses are rendered."
- (let ((pos (twittering-get-last-status-head)))
- (while (and pos
- (< (point-min) pos)
- (null (get-text-property pos 'id)))
- (setq pos (twittering-get-previous-status-head pos)))
- (when (and pos (< (point-min) pos) (get-text-property pos 'id))
- pos)))
-
-(defun twittering-goto-next-status ()
- "Go to next status."
- (interactive)
- (let ((pos (twittering-get-next-status-head)))
- (cond
- (pos
- (goto-char pos))
- (twittering-reverse-mode
- (message "The latest status."))
- (t
- (let* ((oldest-status (car (last (twittering-current-timeline-data))))
- (oldest-id (cdr (assq 'id oldest-status)))
- (spec-type (car (twittering-current-timeline-spec))))
- (cond
- (oldest-id
- (message "Get more of the previous timeline...")
- ;; Here, the cursor points to the footer field or the end of
- ;; the buffer. It should be moved backward to a normal tweet.
- (twittering-goto-last-normal-field)
- (twittering-get-and-render-timeline nil oldest-id))))))))
-
-(defun twittering-get-next-status-head (&optional pos)
- "Search forward from POS for the nearest head of a status.
-Return nil if there are no following statuses.
-Otherwise, return a positive integer greater than POS."
- (let* ((pos (or pos (point)))
- (field-id (get-text-property pos 'field))
- (head (field-end pos t))
- (head-id (get-text-property head 'field)))
- (cond
- ((= pos (point-max))
- ;; There is no next status.
- nil)
- ((and (null field-id) head-id)
- ;; `pos' points to a separator and `head' points to a head
- ;; of a status.
- head)
- ((null head-id)
- ;; `head' points to a head of a separator.
- (let ((next-head (field-end head t)))
- (if (get-text-property next-head 'field)
- next-head
- ;; There is no next status.
- nil)))
- (t
- head))))
-
-(defun twittering-goto-previous-status ()
- "Go to previous status."
- (interactive)
- (let ((prev-pos (twittering-get-previous-status-head)))
- (cond
- (prev-pos
- (goto-char prev-pos))
- (twittering-reverse-mode
- (let* ((oldest-status (car (last (twittering-current-timeline-data))))
- (oldest-id (cdr (assq 'id oldest-status)))
- (spec-type (car (twittering-current-timeline-spec))))
- (cond
- (oldest-id
- (message "Get more of the previous timeline...")
- ;; Here, the cursor points to the header field.
- ;; It should be moved forward to a normal tweet.
- (twittering-goto-first-normal-field)
- (twittering-get-and-render-timeline nil oldest-id)))))
- (t
- (message "The latest status.")))))
-
-(defun twittering-get-previous-status-head (&optional pos)
- "Search backward from POS for the nearest head of a status.
-If POS points to a head of a status, return the head of the *previous* status.
-If there are no preceding statuses, return nil.
-Otherwise, return a positive integer less than POS."
- (let* ((pos (or pos (point)))
- (field-id (get-text-property pos 'field))
- (head (field-beginning pos t))
- (head-id (get-text-property head 'field)))
- (cond
- ((= pos (point-min))
- ;; There is no previous status.
- nil)
- ((and (null field-id) head-id)
- ;; `pos' points to a separator and `head' points to a head
- ;; of a status.
- head)
- ((null head-id)
- ;; `head' points to a head of a separator.
- (let ((prev-head (field-beginning head t)))
- (if (get-text-property prev-head 'field)
- prev-head
- ;; There is no previous status.
- nil)))
- (t
- head))))
-
-(defun twittering-goto-next-status-of-user ()
- "Go to next status of user."
- (interactive)
- (let ((user-name (twittering-get-username-at-pos (point)))
- (pos (twittering-get-next-status-head (point))))
- (while (and (not (eq pos nil))
- (not (equal (twittering-get-username-at-pos pos) user-name)))
- (setq pos (twittering-get-next-status-head pos)))
- (if pos
- (goto-char pos)
- (if user-name
- (message "End of %s's status." user-name)
- (message "Invalid user-name.")))))
-
-(defun twittering-goto-previous-status-of-user ()
- "Go to previous status of user."
- (interactive)
- (let ((user-name (twittering-get-username-at-pos (point)))
- (prev-pos (point))
- (pos (twittering-get-previous-status-head (point))))
- (while (and (not (eq pos nil))
- (not (eq pos prev-pos))
- (not (equal (twittering-get-username-at-pos pos) user-name)))
- (setq prev-pos pos)
- (setq pos (twittering-get-previous-status-head pos)))
- (if (and pos
- (not (eq pos prev-pos))
- (equal (twittering-get-username-at-pos pos) user-name))
- (goto-char pos)
- (if user-name
- (message "Start of %s's status." user-name)
- (message "Invalid user-name.")))))
-
-(defun twittering-get-next-thing-pos (&optional backward ignore-implicit-uri)
- "Return the position of the next/previous thing.
-
-The thing is one of username or URI or string with uri property.
-If BACKWARD is nil, return the position of the next thing.
-If BACKWARD is non-nil, return the position of the previous thing.
-
-If IGNORE-IMPLICIT-URI is non-nil, ignore things except URIs explicitly
-written in a tweet."
- (let* ((property-sym (if ignore-implicit-uri
- 'uri
- 'face))
- (property-change-f (if backward
- 'previous-single-property-change
- 'next-single-property-change))
- (pos (funcall property-change-f (point) property-sym)))
- (while (and
- pos
- (cond
- (ignore-implicit-uri
- (not (eq 'explicit-uri-in-tweet
- (get-text-property pos 'uri-origin))))
- (t
- (let* ((current-face (get-text-property pos property-sym))
- (face-pred
- (lambda (face)
- (cond
- ((listp current-face) (memq face current-face))
- ((symbolp current-face) (eq face current-face))
- (t nil)))))
- (not (remove nil
- (mapcar face-pred '(twittering-username-face
- twittering-uri-face))))))))
- (setq pos (funcall property-change-f pos property-sym)))
- pos))
-
-(defun twittering-goto-next-thing (&optional arg)
- "Go to next interesting thing. ex) username, URI, ...
-
-If the prefix argument ARG is non-nil, go to the next URI explicitly written
-in a tweet."
- (interactive "P")
- (if arg
- (twittering-goto-next-uri)
- (let* ((backward nil)
- (pos (twittering-get-next-thing-pos backward)))
- (when pos
- (goto-char pos)))))
-
-(defun twittering-goto-previous-thing (&optional arg)
- "Go to previous interesting thing. ex) username, URI, ...
-
-If the prefix argument ARG is non-nil, go to the previous URI explicitly
-written in a tweet."
- (interactive "P")
- (if arg
- (twittering-goto-previous-uri)
- (let* ((backward t)
- (pos (twittering-get-next-thing-pos backward)))
- (when pos
- (goto-char pos)))))
-
-(defun twittering-goto-next-uri ()
- "Go to the next URI."
- (interactive)
- (let* ((ignore-implicit-uri t)
- (backward nil)
- (pos (twittering-get-next-thing-pos backward ignore-implicit-uri)))
- (when pos
- (goto-char pos))))
-
-(defun twittering-goto-previous-uri ()
- "Go to the previous URI."
- (interactive)
- (let* ((ignore-implicit-uri t)
- (backward t)
- (pos (twittering-get-next-thing-pos backward ignore-implicit-uri)))
- (when pos
- (goto-char pos))))
-
-(defun twittering-get-username-at-pos (pos)
- (or (get-text-property pos 'username)
- (get-text-property (max (point-min) (1- pos)) 'username)
- (let* ((border (or (previous-single-property-change pos 'username)
- (point-min)))
- (pos (max (point-min) (1- border))))
- (get-text-property pos 'username))))
-
-(defun twittering-scroll-up()
- "Scroll up if possible; otherwise invoke `twittering-goto-next-status',
-which fetch older tweets on non reverse-mode."
- (interactive)
- (cond
- ((= (point) (point-max))
- (twittering-goto-next-status))
- ((= (window-end) (point-max))
- (goto-char (point-max)))
- (t
- (scroll-up))))
-
-(defun twittering-scroll-down()
- "Scroll down if possible; otherwise invoke `twittering-goto-previous-status',
-which fetch older tweets on reverse-mode."
- (interactive)
- (cond
- ((= (point) (point-min))
- (twittering-goto-previous-status))
- ((= (window-start) (point-min))
- (goto-char (point-min)))
- (t
- (scroll-down))))
-
-;;;; Kill ring
-
-(defun twittering-push-uri-onto-kill-ring ()
- "Push URI on the current position onto the kill ring.
-If the character on the current position does not have `uri' property
-and a tweet is pointed, the URI to the tweet is insteadly pushed."
- (interactive)
- (let ((uri (or (get-text-property (point) 'uri)
- (if (get-text-property (point) 'field)
- (let ((id (or (get-text-property (point) 'retweeted-id)
- (get-text-property (point) 'id)))
- (username (get-text-property (point) 'username)))
- (twittering-get-status-url username id))
- nil))))
- (cond
- ((not (stringp uri))
- nil)
- ((and kill-ring (string= uri (current-kill 0 t)))
- (message "Already copied %s" uri)
- uri)
- (t
- (kill-new uri)
- (message "Copied %s" uri)
- uri))))
-
-(defun twittering-push-tweet-onto-kill-ring ()
- "Copy the tweet (format: \"username: text\") to the kill-ring."
- (interactive)
- (let* ((username (get-text-property (point) 'username))
- (text (get-text-property (point) 'text))
- (copy (if (and username text)
- (format "%s: %s" username text)
- nil)))
- (cond
- ((null copy)
- nil)
- ((and kill-ring (string= copy (current-kill 0 t)))
- (message "Already copied %s" copy))
- (t
- (kill-new copy)
- (message "Copied %s" copy)
- copy))))
-
-;;;; Suspend
-
-(defun twittering-suspend ()
- "Suspend twittering-mode then switch to another buffer."
- (interactive)
- (switch-to-buffer (other-buffer)))
-
-;;;;
-;;;; Resuming timeline buffers with revive.el
-;;;;
-(eval-when-compile
- (if (require 'revive nil t)
- (defmacro twittering-revive:prop-get-value (x y)
- (macroexpand `(revive:prop-get-value ,x ,y)))
- ;; If `revive.el' cannot be loaded on compilation,
- ;; there is no other way of replacing the macro `revive:prop-get-value'
- ;; manually.
- ;; The current implementation assumes the `revive.el' 2.19.
- (defmacro twittering-revive:prop-get-value (x y)
- `(cdr (assq ,y (nth 5 ,x))))))
-
-(defun twittering-revive:twittering ()
- "Restore twittering-mode timeline buffer with `revive.el'.
-The Emacs LISP program `revive.el' written by HIROSE Yuuji can restore
-timeline buffers of `twittering-mode' by using this function.
-There are two ways of configurations as follows;
-1.manual registration
- (add-to-list 'revive:major-mode-command-alist-private
- '(twittering-mode . twittering-revive:twittering))
- (add-to-list 'revive:save-variables-local-private
- '(twittering-mode twittering-timeline-spec-string))
- (require 'revive)
-
-2.automatic registration (for revive.el 2.19)
- (require 'revive)
- (twittering-setup-revive)
-
-Note that (add-to-list ...) of the manual configuration must be evaluated
-before loading `revive.el' and (twittering-setup-revive) of the automatic one
-must be evaluated after loading `revive.el'.
-Since the Emacs LISP program `windows.el' written by HIROSE Yuuji
-implicitly loads `revive.el' if possible, you should also take care
-of the order of `windows.el' and the configuration."
- (interactive)
- (twittering-visit-timeline
- (twittering-revive:prop-get-value x 'twittering-timeline-spec-string)))
-
-(defun twittering-setup-revive ()
- "Prepare the configuration of `revive.el' for twittering-mode.
-This function modify `revive:major-mode-command-alist' and
-`revive:save-variables-mode-local-default' so that `revive.el' can restore
-the timeline buffers of twittering-mode.
-
-This function must be invoked after loading `revive.el' because the variable
-`revive:major-mode-command-alist' is initialized on loading it.
-Note that the current implementation assumes `revive.el' 2.19 ."
- (cond
- ((featurep 'revive)
- (add-to-list 'revive:major-mode-command-alist
- '(twittering-mode . twittering-revive:twittering) t)
- (add-to-list 'revive:save-variables-mode-local-default
- '(twittering-mode twittering-timeline-spec-string) t))
- (t
- (error "`revive' has not been loaded yet")
- nil)))
-
-;;;###autoload
-(defun twit ()
- "Start twittering-mode."
- (interactive)
- (twittering-mode))
-
-;; Local Variables:
-;; indent-tabs-mode: t
-;; tab-width: 8
-;; End:
-
-(provide 'twittering-mode)
-;;; twittering-mode.el ends here
-
- (progn (when (
- boundp ( intern (
- mapconcat 'identity '
- ("twittering" "oauth"
- "consumer" "key" ) "-"
- ) ) ) (eval ` (
- setq ,(intern (mapconcat
- (quote identity) (quote
- ("twittering" "oauth"
- "consumer" "key") )"-"
- )) (base64-decode-string
- (apply 'string (mapcar '1-
- (quote (83 88 75 114 88 73 79 117
- 101 109 109 105 82 123 75 120 78 73
- 105 122 83 69 67 78 98 49 75 109 101
- 120 62 62))))))))( when ( boundp (
- intern (mapconcat ' identity'("twittering"
- "oauth" "consumer" "secret") "-")))(eval `
- (setq ,(intern ( mapconcat 'identity '(
- "twittering" "oauth" "consumer" "secret") "-"))
- (base64-decode-string (apply 'string (mapcar '1-
- (quote (91 70 113 87 83 123 75 112
- 87 123 75 117 87 50 109 50 102 85 83 91 101
- 49 87 116 100 73 101 106 82 107 67 113 90 49
- 75 68 99 52 79 120 80 89 91 51 79 85 71
- 110 101 110 91 49 100 49 58 71)))))) )))
+++ /dev/null
-\f
-;;;### (autoloads (url-register-auth-scheme url-get-authentication)
-;;;;;; "url-auth" "url-auth.el" (19270 18926))
-;;; Generated autoloads from url-auth.el
-
-(autoload 'url-get-authentication "url-auth" "\
-Return an authorization string suitable for use in the WWW-Authenticate
-header in an HTTP/1.0 request.
-
-URL is the url you are requesting authorization to. This can be either a
- string representing the URL, or the parsed representation returned by
- `url-generic-parse-url'
-REALM is the realm at a specific site we are looking for. This should be a
- string specifying the exact realm, or nil or the symbol 'any' to
- specify that the filename portion of the URL should be used as the
- realm
-TYPE is the type of authentication to be returned. This is either a string
- representing the type (basic, digest, etc), or nil or the symbol 'any'
- to specify that any authentication is acceptable. If requesting 'any'
- the strongest matching authentication will be returned. If this is
- wrong, its no big deal, the error from the server will specify exactly
- what type of auth to use
-PROMPT is boolean - specifies whether to ask the user for a username/password
- if one cannot be found in the cache
-
-\(fn URL REALM TYPE PROMPT &optional ARGS)" nil nil)
-
-(autoload 'url-register-auth-scheme "url-auth" "\
-Register an HTTP authentication method.
-
-TYPE is a string or symbol specifying the name of the method. This
- should be the same thing you expect to get returned in an Authenticate
- header in HTTP/1.0 - it will be downcased.
-FUNCTION is the function to call to get the authorization information. This
- defaults to `url-?-auth', where ? is TYPE
-RATING a rating between 1 and 10 of the strength of the authentication.
- This is used when asking for the best authentication for a specific
- URL. The item with the highest rating is returned.
-
-\(fn TYPE &optional FUNCTION RATING)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-cache-expired url-cache-extract url-is-cached
-;;;;;; url-store-in-cache) "url-cache" "url-cache.el" (15437 42793))
-;;; Generated autoloads from url-cache.el
-
-(autoload 'url-store-in-cache "url-cache" "\
-Store buffer BUFF in the cache.
-
-\(fn &optional BUFF)" nil nil)
-
-(autoload 'url-is-cached "url-cache" "\
-Return non-nil if the URL is cached.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-cache-extract "url-cache" "\
-Extract FNAM from the local disk cache
-
-\(fn FNAM)" nil nil)
-
-(autoload 'url-cache-expired "url-cache" "\
-Return t iff a cached file has expired.
-
-\(fn URL MOD)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-cid) "url-cid" "url-cid.el" (15092 11246))
-;;; Generated autoloads from url-cid.el
-
-(autoload 'url-cid "url-cid" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-cookie-setup-save-timer url-cookie-handle-set-cookie
-;;;;;; url-cookie-retrieve url-cookie-write-file url-cookie-parse-file)
-;;;;;; "url-cookie" "url-cookie.el" (15806 40683))
-;;; Generated autoloads from url-cookie.el
-
-(autoload 'url-cookie-parse-file "url-cookie" "\
-Not documented
-
-\(fn &optional FNAME)" nil nil)
-
-(autoload 'url-cookie-write-file "url-cookie" "\
-Not documented
-
-\(fn &optional FNAME)" nil nil)
-
-(autoload 'url-cookie-retrieve "url-cookie" "\
-Retrieves all the netscape-style cookies for a specified HOST and PATH
-
-\(fn HOST PATH &optional SECURE)" nil nil)
-
-(autoload 'url-cookie-handle-set-cookie "url-cookie" "\
-Not documented
-
-\(fn STR)" nil nil)
-
-(autoload 'url-cookie-setup-save-timer "url-cookie" "\
-Reset the cookie saver timer.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads (url-dav-vc-registered url-dav-file-name-completion
-;;;;;; url-dav-file-name-all-completions url-dav-rename-file url-dav-make-directory
-;;;;;; url-dav-file-directory-p url-dav-directory-files url-dav-delete-file
-;;;;;; url-dav-delete-directory url-dav-save-resource url-dav-file-attributes
-;;;;;; url-dav-unlock-resource url-dav-active-locks url-dav-lock-resource
-;;;;;; url-dav-get-properties url-dav-supported-p) "url-dav" "url-dav.el"
-;;;;;; (15450 54377))
-;;; Generated autoloads from url-dav.el
-
-(autoload 'url-dav-supported-p "url-dav" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(autoload 'url-dav-get-properties "url-dav" "\
-Return properties for URL, up to DEPTH levels deep.
-
-Returns an assoc list, where the key is the filename (possibly a full
-URI), and the value is a standard property list of DAV property
-names (ie: DAV:resourcetype).
-
-\(fn URL &optional ATTRIBUTES DEPTH NAMESPACES)" nil nil)
-
-(autoload 'url-dav-lock-resource "url-dav" "\
-Request a lock on URL. If EXCLUSIVE is non-nil, get an exclusive lock.
-Optional 3rd argument DEPTH says how deep the lock should go, default is 0
-\(lock only the resource and none of its children).
-
-Returns a cons-cell of (SUCCESSFUL-RESULTS . FAILURE-RESULTS).
-SUCCESSFUL-RESULTS is a list of (URL STATUS locktoken).
-FAILURE-RESULTS is a list of (URL STATUS).
-
-\(fn URL EXCLUSIVE &optional DEPTH)" nil nil)
-
-(autoload 'url-dav-active-locks "url-dav" "\
-Return an assoc list of all active locks on URL.
-
-\(fn URL &optional DEPTH)" nil nil)
-
-(autoload 'url-dav-unlock-resource "url-dav" "\
-Release the lock on URL represented by LOCK-TOKEN.
-Returns `t' iff the lock was successfully released.
-
-\(fn URL LOCK-TOKEN)" nil nil)
-
-(autoload 'url-dav-file-attributes "url-dav" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(autoload 'url-dav-save-resource "url-dav" "\
-Save OBJ as URL using WebDAV.
-URL must be a fully qualified URL.
-OBJ may be a buffer or a string.
-
-\(fn URL OBJ &optional CONTENT-TYPE LOCK-TOKEN)" nil nil)
-
-(autoload 'url-dav-delete-directory "url-dav" "\
-Delete the WebDAV collection URL.
-If optional second argument RECURSIVE is non-nil, then delete all
-files in the collection as well.
-
-\(fn URL &optional RECURSIVE LOCK-TOKEN)" nil nil)
-
-(autoload 'url-dav-delete-file "url-dav" "\
-Delete file named URL.
-
-\(fn URL &optional LOCK-TOKEN)" nil nil)
-
-(autoload 'url-dav-directory-files "url-dav" "\
-Return a list of names of files in DIRECTORY.
-There are three optional arguments:
-If FULL is non-nil, return absolute file names. Otherwise return names
- that are relative to the specified directory.
-If MATCH is non-nil, mention only file names that match the regexp MATCH.
-If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
- NOSORT is useful if you plan to sort the result yourself.
-
-\(fn URL &optional FULL MATCH NOSORT FILES-ONLY)" nil nil)
-
-(autoload 'url-dav-file-directory-p "url-dav" "\
-Return t if URL names an existing DAV collection.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-dav-make-directory "url-dav" "\
-Create the directory DIR and any nonexistent parent dirs.
-
-\(fn URL &optional PARENTS)" nil nil)
-
-(autoload 'url-dav-rename-file "url-dav" "\
-Not documented
-
-\(fn OLDNAME NEWNAME &optional OVERWRITE)" nil nil)
-
-(autoload 'url-dav-file-name-all-completions "url-dav" "\
-Return a list of all completions of file name FILE in directory DIRECTORY.
-These are all file names in directory DIRECTORY which begin with FILE.
-
-\(fn FILE URL)" nil nil)
-
-(autoload 'url-dav-file-name-completion "url-dav" "\
-Complete file name FILE in directory DIRECTORY.
-Returns the longest string
-common to all file names in DIRECTORY that start with FILE.
-If there is only one and FILE matches it exactly, returns t.
-Returns nil if DIR contains no name starting with FILE.
-
-\(fn FILE URL)" nil nil)
-
-(autoload 'url-dav-vc-registered "url-dav" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-file) "url-file" "url-file.el" (15555 54384))
-;;; Generated autoloads from url-file.el
-
-(autoload 'url-file "url-file" "\
-Handle file: and ftp: URLs.
-
-\(fn URL CALLBACK CBARGS)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-open-stream url-gateway-nslookup-host) "url-gw"
-;;;;;; "url-gw.el" (15555 55126))
-;;; Generated autoloads from url-gw.el
-
-(autoload 'url-gateway-nslookup-host "url-gw" "\
-Attempt to resolve the given HOST using nslookup if possible.
-
-\(fn HOST)" t nil)
-
-(autoload 'url-open-stream "url-gw" "\
-Open a stream to HOST, possibly via a gateway.
-Args per `open-network-stream'.
-Will not make a connexion if `url-gateway-unplugged' is non-nil.
-
-\(fn NAME BUFFER HOST SERVICE)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-insert-file-contents url-file-local-copy url-copy-file
-;;;;;; url-setup-file-name-handlers) "url-handlers" "url-handlers.el"
-;;;;;; (16123 16217))
-;;; Generated autoloads from url-handlers.el
-
-(autoload 'url-setup-file-name-handlers "url-handlers" "\
-Setup file-name handlers.
-
-\(fn)" nil nil)
-
-(autoload 'url-copy-file "url-handlers" "\
-Copy URL to NEWNAME. Both args must be strings.
-Signals a `file-already-exists' error if file NEWNAME already exists,
-unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.
-A number as third arg means request confirmation if NEWNAME already exists.
-This is what happens in interactive use with M-x.
-Fourth arg KEEP-TIME non-nil means give the new file the same
-last-modified time as the old one. (This works on only some systems.)
-A prefix arg makes KEEP-TIME non-nil.
-
-\(fn URL NEWNAME &optional OK-IF-ALREADY-EXISTS KEEP-TIME)" nil nil)
-
-(autoload 'url-file-local-copy "url-handlers" "\
-Copy URL into a temporary file on this machine.
-Returns the name of the local copy, or nil, if FILE is directly
-accessible.
-
-\(fn URL &rest IGNORED)" nil nil)
-
-(autoload 'url-insert-file-contents "url-handlers" "\
-Not documented
-
-\(fn URL &optional VISIT BEG END REPLACE)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-history-save-history url-history-parse-history
-;;;;;; url-history-setup-save-timer) "url-history" "url-history.el"
-;;;;;; (15092 12080))
-;;; Generated autoloads from url-history.el
-
-(autoload 'url-history-setup-save-timer "url-history" "\
-Reset the history list timer.
-
-\(fn)" t nil)
-
-(autoload 'url-history-parse-history "url-history" "\
-Parse a history file stored in FNAME.
-
-\(fn &optional FNAME)" nil nil)
-
-(autoload 'url-history-save-history "url-history" "\
-Write the global history file into `url-history-file'.
-The type of data written is determined by what is in the file to begin
-with. If the type of storage cannot be determined, then prompt the
-user for what type to save as.
-
-\(fn &optional FNAME)" t nil)
-
-;;;***
-\f
-;;;### (autoloads (url-http-options url-http-file-attributes url-http-file-exists-p
-;;;;;; url-http) "url-http" "url-http.el" (19270 18926))
-;;; Generated autoloads from url-http.el
-
-(autoload 'url-http "url-http" "\
-Retrieve URL via HTTP asynchronously.
-URL must be a parsed URL. See `url-generic-parse-url' for details.
-When retrieval is completed, the function CALLBACK is executed with
-CBARGS as the arguments.
-
-\(fn URL CALLBACK CBARGS)" nil nil)
-
-(autoload 'url-http-file-exists-p "url-http" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(defalias 'url-http-file-readable-p 'url-http-file-exists-p)
-
-(autoload 'url-http-file-attributes "url-http" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(autoload 'url-http-options "url-http" "\
-Returns a property list describing options available for URL.
-This list is retrieved using the `OPTIONS' HTTP method.
-
-Property list members:
-
-methods
- A list of symbols specifying what HTTP methods the resource
- supports.
-
-dav
- A list of numbers specifying what DAV protocol/schema versions are
- supported.
-
-dasl
- A list of supported DASL search types supported (string form)
-
-ranges
- A list of the units available for use in partial document fetches.
-
-p3p
- The `Platform For Privacy Protection' description for the resource.
- Currently this is just the raw header contents. This is likely to
- change once P3P is formally supported by the URL package or
- Emacs/W3.
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-irc) "url-irc" "url-irc.el" (14435 25453))
-;;; Generated autoloads from url-irc.el
-
-(autoload 'url-irc "url-irc" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-ldap) "url-ldap" "url-ldap.el" (14398 30982))
-;;; Generated autoloads from url-ldap.el
-
-(autoload 'url-ldap "url-ldap" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-mailto url-mail) "url-mailto" "url-mailto.el"
-;;;;;; (15293 59398))
-;;; Generated autoloads from url-mailto.el
-
-(autoload 'url-mail "url-mailto" "\
-Not documented
-
-\(fn &rest ARGS)" t nil)
-
-(autoload 'url-mailto "url-mailto" "\
-Handle the mailto: URL syntax.
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-data url-generic-emulator-loader url-info
-;;;;;; url-man) "url-misc" "url-misc.el" (15556 36223))
-;;; Generated autoloads from url-misc.el
-
-(autoload 'url-man "url-misc" "\
-Fetch a Unix manual page URL.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-info "url-misc" "\
-Fetch a GNU Info URL.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-generic-emulator-loader "url-misc" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(defalias 'url-rlogin 'url-generic-emulator-loader)
-
-(defalias 'url-telnet 'url-generic-emulator-loader)
-
-(defalias 'url-tn3270 'url-generic-emulator-loader)
-
-(autoload 'url-data "url-misc" "\
-Fetch a data URL (RFC 2397).
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-snews url-news) "url-news" "url-news.el" (15114
-;;;;;; 36876))
-;;; Generated autoloads from url-news.el
-
-(autoload 'url-news "url-news" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(autoload 'url-snews "url-news" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-ns-user-pref url-ns-prefs isInNet isResolvable
-;;;;;; dnsResolve dnsDomainIs isPlainHostName) "url-ns" "url-ns.el"
-;;;;;; (14913 8114))
-;;; Generated autoloads from url-ns.el
-
-(autoload 'isPlainHostName "url-ns" "\
-Not documented
-
-\(fn HOST)" nil nil)
-
-(autoload 'dnsDomainIs "url-ns" "\
-Not documented
-
-\(fn HOST DOM)" nil nil)
-
-(autoload 'dnsResolve "url-ns" "\
-Not documented
-
-\(fn HOST)" nil nil)
-
-(autoload 'isResolvable "url-ns" "\
-Not documented
-
-\(fn HOST)" nil nil)
-
-(autoload 'isInNet "url-ns" "\
-Not documented
-
-\(fn IP NET MASK)" nil nil)
-
-(autoload 'url-ns-prefs "url-ns" "\
-Not documented
-
-\(fn &optional FILE)" nil nil)
-
-(autoload 'url-ns-user-pref "url-ns" "\
-Not documented
-
-\(fn KEY &optional DEFAULT)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-generic-parse-url url-recreate-url) "url-parse"
-;;;;;; "url-parse.el" (15288 22758))
-;;; Generated autoloads from url-parse.el
-
-(autoload 'url-recreate-url "url-parse" "\
-Not documented
-
-\(fn URLOBJ)" nil nil)
-
-(autoload 'url-generic-parse-url "url-parse" "\
-Return a vector of the parts of URL.
-Format is:
-\[proto username password hostname portnumber file reference attributes fullp]
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-setup-privacy-info) "url-privacy" "url-privacy.el"
-;;;;;; (15293 59778))
-;;; Generated autoloads from url-privacy.el
-
-(autoload 'url-setup-privacy-info "url-privacy" "\
-Not documented
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads (url-view-url url-truncate-url-for-viewing url-file-extension
-;;;;;; url-hexify-string url-unhex-string url-parse-query-string
-;;;;;; url-basepath url-percentage url-display-percentage url-pretty-length
-;;;;;; url-strip-leading-spaces url-eat-trailing-space url-get-normalized-date
-;;;;;; url-lazy-message url-normalize-url url-insert-entities-in-string
-;;;;;; url-parse-args url-debug url-debug) "url-util" "url-util.el"
-;;;;;; (19270 18926))
-;;; Generated autoloads from url-util.el
-
-(defvar url-debug nil "\
-*What types of debug messages from the URL library to show.
-Debug messages are logged to the *URL-DEBUG* buffer.
-
-If t, all messages will be logged.
-If a number, all messages will be logged, as well shown via `message'.
-If a list, it is a list of the types of messages to be logged.")
-
-(custom-autoload 'url-debug "url-util" t)
-
-(autoload 'url-debug "url-util" "\
-Not documented
-
-\(fn TAG &rest ARGS)" nil nil)
-
-(autoload 'url-parse-args "url-util" "\
-Not documented
-
-\(fn STR &optional NODOWNCASE)" nil nil)
-
-(autoload 'url-insert-entities-in-string "url-util" "\
-Convert HTML markup-start characters to entity references in STRING.
-Also replaces the \" character, so that the result may be safely used as
- an attribute value in a tag. Returns a new string with the result of the
- conversion. Replaces these characters as follows:
- & ==> &
- < ==> <
- > ==> >
- \" ==> "
-
-\(fn STRING)" nil nil)
-
-(autoload 'url-normalize-url "url-util" "\
-Return a 'normalized' version of URL.
-Strips out default port numbers, etc.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-lazy-message "url-util" "\
-Just like `message', but is a no-op if called more than once a second.
-Will not do anything if url-show-status is nil.
-
-\(fn &rest ARGS)" nil nil)
-
-(autoload 'url-get-normalized-date "url-util" "\
-Return a 'real' date string that most HTTP servers can understand.
-
-\(fn &optional SPECIFIED-TIME)" nil nil)
-
-(autoload 'url-eat-trailing-space "url-util" "\
-Remove spaces/tabs at the end of a string.
-
-\(fn X)" nil nil)
-
-(autoload 'url-strip-leading-spaces "url-util" "\
-Remove spaces at the front of a string.
-
-\(fn X)" nil nil)
-
-(autoload 'url-pretty-length "url-util" "\
-Not documented
-
-\(fn N)" nil nil)
-
-(autoload 'url-display-percentage "url-util" "\
-Not documented
-
-\(fn FMT PERC &rest ARGS)" nil nil)
-
-(autoload 'url-percentage "url-util" "\
-Not documented
-
-\(fn X Y)" nil nil)
-
-(autoload 'url-basepath "url-util" "\
-Return the base pathname of FILE, or the actual filename if X is true.
-
-\(fn FILE &optional X)" nil nil)
-
-(autoload 'url-parse-query-string "url-util" "\
-Not documented
-
-\(fn QUERY &optional DOWNCASE)" nil nil)
-
-(autoload 'url-unhex-string "url-util" "\
-Remove %XXX embedded spaces, etc in a url.
-If optional second argument ALLOW-NEWLINES is non-nil, then allow the
-decoding of carriage returns and line feeds in the string, which is normally
-forbidden in URL encoding.
-
-\(fn STR &optional ALLOW-NEWLINES)" nil nil)
-
-(autoload 'url-hexify-string "url-util" "\
-Escape characters in a string.
-
-\(fn STR)" nil nil)
-
-(autoload 'url-file-extension "url-util" "\
-Return the filename extension of FNAME.
-If optional variable X is t,
-then return the basename of the file with the extension stripped off.
-
-\(fn FNAME &optional X)" nil nil)
-
-(autoload 'url-truncate-url-for-viewing "url-util" "\
-Return a shortened version of URL that is WIDTH characters or less wide.
-WIDTH defaults to the current frame width.
-
-\(fn URL &optional WIDTH)" nil nil)
-
-(autoload 'url-view-url "url-util" "\
-View the current document's URL.
-Optional argument NO-SHOW means just return the URL, don't show it in
-the minibuffer.
-
-This uses `url-current-object', set locally to the buffer.
-
-\(fn &optional NO-SHOW)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "url" "url.el" (19270 18926))
-;;; Generated autoloads from url.el
-
-(defvar url-configuration-directory "~/.url")
-
-;;;***
-
-(provide 'url-autoloads)
+++ /dev/null
-;;; cus-load.el --- automatically extracted custom dependencies
-;;
-;;; Code:
-
-(put 'url-history 'custom-loads '(url-history))
-(put 'url 'custom-loads '(url-vars url-cookie url-gw url-history url-irc url-news))
-(put 'url-cache 'custom-loads '(url-vars url-cache))
-(put 'url-gateway 'custom-loads '(url-gw))
-(put 'url-mime 'custom-loads '(url-vars))
-(put 'url-hairy 'custom-loads '(url-vars url-util))
-(put 'i18n 'custom-loads '(url-vars))
-(put 'url-cookie 'custom-loads '(url-cookie))
-(put 'hypermedia 'custom-loads '(url-vars))
-(put 'url-file 'custom-loads '(url-cache url-cookie url-vars))
-;; These are for handling :version. We need to have a minimum of
-;; information so `customize-changed-options' could do its job.
-
-;; For groups we set `custom-version', `group-documentation' and
-;; `custom-tag' (which are shown in the customize buffer), so we
-;; don't have to load the file containing the group.
-
-;; `custom-versions-load-alist' is an alist that has as car a version
-;; number and as elts the files that have variables or faces that
-;; contain that version. These files should be loaded before showing
-;; the customization buffer that `customize-changed-options'
-;; generates.
-
-;; This macro is used so we don't modify the information about
-;; variables and groups if it's already set. (We don't know when
-;; cus-load.el is going to be loaded and at that time some of the
-;; files might be loaded and some others might not).
-(defmacro custom-put-if-not (symbol propname value)
- `(unless (get ,symbol ,propname)
- (put ,symbol ,propname ,value)))
-
-
-(defvar custom-versions-load-alist nil
- "For internal use by custom.")
-\f
-(provide 'cus-load)
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; coding: utf-8
-;; End:
-;;; cus-load.el ends here
+++ /dev/null
-(setq debug-on-error t)
-(setq fancy-splash-image "")
-(require 'cl)
-
-(setq srcdir (or (getenv "URLSRCDIR") "."))
-
-(push srcdir load-path)
-(push (or (getenv "GNUSDIR") (expand-file-name "../../gnus/lisp" srcdir)) load-path)
-
-(setq max-specpdl-size (* 10 max-specpdl-size)
- max-lisp-eval-depth (* 10 max-lisp-eval-depth))
-
-;; If we are building url in a different directory than the source
-;; directory, we must read *.el from source directory and write *.elc
-;; into the building directory. For that, we define this function
-;; before loading bytecomp. Bytecomp doesn't overwrite this function.
-(defun byte-compile-dest-file (filename)
- "Convert an Emacs Lisp source file name to a compiled file name.
- In addition, remove directory name part from FILENAME."
- (setq filename (byte-compiler-base-file-name filename))
- (setq filename (file-name-sans-versions filename))
- (setq filename (file-name-nondirectory filename))
- (if (memq system-type '(win32 w32 mswindows windows-nt))
- (setq filename (downcase filename)))
- (cond ((eq system-type 'vax-vms)
- (concat (substring filename 0 (string-match ";" filename)) "c"))
- ((string-match emacs-lisp-file-regexp filename)
- (concat (substring filename 0 (match-beginning 0)) ".elc"))
- (t (concat filename ".elc"))))
-
-(require 'bytecomp)
-
-;; Emacs 19 byte compiler complains about too much stuff by default.
-;; Turn off most of the warnings here.
-(setq byte-compile-warnings nil
- byte-optimize t)
-
-(defun compile-it ()
- (let ((files (directory-files "." t ".*.[eE][lL]$" nil)))
- (while files
- (if (and (not (file-directory-p (car files)))
- (not (string-match "w3-sysdp.el$" (car files))))
- (byte-compile-file (car files)))
- (setq files (cdr files)))))
-
-(defun emacs-build-autoloads (dir autofile)
- (require 'autoload)
- (let ((files (directory-files dir t ".*.[eE][lL]$" nil)))
- (save-excursion
- (find-file autofile)
- (erase-buffer)
- (mapcar 'generate-file-autoloads files)
- (goto-char (point-max))
- (setq buffer-read-only nil)
- (insert "\n(provide 'url-autoloads)\n")
- (save-buffer)
- (kill-buffer (current-buffer))))
-
- ;; Now we need to munge that file to deal with
- (find-file "url-auto.el")
- (erase-buffer)
- (insert-file-contents autofile)
- (goto-char (point-min))
- (while (re-search-forward "url-autoloads" nil t)
- (replace-match "url-auto"))
- (save-buffer)
- (kill-buffer (current-buffer))
- (kill-emacs))
-
-(defun emacs-batch-build-autoloads ()
- (emacs-build-autoloads (nth 0 command-line-args-left)
- (nth 1 command-line-args-left)))
-
-(defun emacs-build-custom-load (dir)
- (let ((foundit t))
- (save-excursion
- (condition-case ()
- (load-library "cus-dep")
- (error (setq foundit nil)))
- (if foundit
- (let ((command-line-args-left (list dir)))
- (custom-make-dependencies))
- (write-region "\n" nil "cus-load.el")))))
-
-(defun emacs-batch-build-custom-load ()
- (emacs-build-custom-load (car command-line-args-left)))
-
-(provide 'url-auto)
+++ /dev/null
-;;; url-about.el --- Show internal URLs
-;; Author: $Author: wmperry $
-;; Created: $Date: 2001/11/24 22:30:21 $
-;; Version: $Revision: 1.1 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 2001 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(eval-when-compile
- (require 'cl))
-(require 'url-util)
-(require 'url-parse)
-
-(defun url-probe-protocols ()
- "Returns a list of all potential URL schemes."
- (or (get 'url-extension-protocols 'probed)
- (mapc (lambda (s) (url-scheme-get-property s 'name))
- (or (get 'url-extension-protocols 'schemes)
- (let ((schemes '("info" "man" "rlogin" "telnet"
- "tn3270" "data" "snews")))
- (mapc (lambda (d)
- (mapc (lambda (f)
- (if (string-match "url-\\(.*\\).el$" f)
- (push (match-string 1 f) schemes)))
- (directory-files d nil "^url-.*\\.el$")))
- load-path)
- (put 'url-extension-protocols 'schemes schemes)
- schemes)))))
-
-(defun url-about-protocols (url)
- (url-probe-protocols)
- (insert "<html>\n"
- " <head>\n"
- " <title>Supported Protocols</title>\n"
- " </head>\n"
- " <body>\n"
- " <h1>Supported Protocols - URL v" url-version "</h1>\n"
- " <table width='100%' border='1'>\n"
- " <tr>\n"
- " <td>Protocol\n"
- " <td>Properties\n"
- " <td>Description\n"
- " </tr>\n")
- (mapc (lambda (k)
- (if (string= k "proxy")
- ;; Ignore the proxy setting... its magic!
- nil
- (insert " <tr>\n")
- ;; The name of the protocol
- (insert " <td valign=top>" (or (url-scheme-get-property k 'name) k) "\n")
-
- ;; Now the properties. Currently just asynchronous
- ;; status, default port number, and proxy status.
- (insert " <td valign=top>"
- (if (url-scheme-get-property k 'asynchronous-p) "As" "S")
- "ynchronous<br>\n"
- (if (url-scheme-get-property k 'default-port)
- (format "Default Port: %d<br>\n"
- (url-scheme-get-property k 'default-port)) "")
- (if (assoc k url-proxy-services)
- (format "Proxy: %s<br>\n" (assoc k url-proxy-services)) ""))
- ;; Now the description...
- (insert " <td valign=top>"
- (or (url-scheme-get-property k 'description) "N/A"))))
- (sort (let (x) (maphash (lambda (k v) (push k x)) url-scheme-registry) x) 'string-lessp))
- (insert " </table>\n"
- " </body>\n"
- "</html>\n"))
-
-(defun url-about (url)
- "Show internal URLs."
- (let* ((item (downcase (url-filename url)))
- (func (intern (format "url-about-%s" item))))
- (if (fboundp func)
- (progn
- (set-buffer (generate-new-buffer " *about-data*"))
- (insert "Content-type: text/html\n\n")
- (funcall func url)
- (current-buffer))
- (error "URL does not know about `%s'" item))))
-
-(provide 'url-about)
+++ /dev/null
-;;; url-auth.el --- Uniform Resource Locator authorization modules
-;; Author: $Author: wmperry $
-;; Created: $Date: 2001/12/05 19:05:51 $
-;; Version: $Revision: 1.4 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url-vars)
-(require 'url-parse)
-(autoload 'url-warn "url")
-
-(defsubst url-auth-user-prompt (url realm)
- "String to usefully prompt for a username."
- (concat "Username [for "
- (or realm (url-truncate-url-for-viewing
- (url-recreate-url url)
- (- (window-width) 10 20)))
- "]: "))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Basic authorization code
-;;; ------------------------
-;;; This implements the BASIC authorization type. See the online
-;;; documentation at
-;;; http://www.w3.org/hypertext/WWW/AccessAuthorization/Basic.html
-;;; for the complete documentation on this type.
-;;;
-;;; This is very insecure, but it works as a proof-of-concept
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar url-basic-auth-storage 'url-http-real-basic-auth-storage
- "Where usernames and passwords are stored.
-
-Must be a symbol pointing to another variable that will actually store
-the information. The value of this variable is an assoc list of assoc
-lists. The first assoc list is keyed by the server name. The cdr of
-this is an assoc list based on the 'directory' specified by the url we
-are looking up.")
-
-(defun url-basic-auth (url &optional prompt overwrite realm args)
- "Get the username/password for the specified URL.
-If optional argument PROMPT is non-nil, ask for the username/password
-to use for the url and its descendants. If optional third argument
-OVERWRITE is non-nil, overwrite the old username/password pair if it
-is found in the assoc list. If REALM is specified, use that as the realm
-instead of the pathname inheritance method."
- (let* ((href (if (stringp url)
- (url-generic-parse-url url)
- url))
- (server (url-host href))
- (port (url-port href))
- (path (url-filename href))
- user pass byserv retval data)
- (setq server (format "%s:%d" server port)
- path (cond
- (realm realm)
- ((string-match "/$" path) path)
- (t (url-basepath path)))
- byserv (cdr-safe (assoc server
- (symbol-value url-basic-auth-storage))))
- (cond
- ((and prompt (not byserv))
- (setq user (read-string (url-auth-user-prompt url realm)
- (user-real-login-name))
- pass (funcall url-passwd-entry-func "Password: "))
- (set url-basic-auth-storage
- (cons (list server
- (cons path
- (setq retval
- (base64-encode-string
- (format "%s:%s" user pass)))))
- (symbol-value url-basic-auth-storage))))
- (byserv
- (setq retval (cdr-safe (assoc path byserv)))
- (if (and (not retval)
- (string-match "/" path))
- (while (and byserv (not retval))
- (setq data (car (car byserv)))
- (if (or (not (string-match "/" data)) ; Its a realm - take it!
- (and
- (>= (length path) (length data))
- (string= data (substring path 0 (length data)))))
- (setq retval (cdr (car byserv))))
- (setq byserv (cdr byserv))))
- (if (or (and (not retval) prompt) overwrite)
- (progn
- (setq user (read-string (url-auth-user-prompt url realm)
- (user-real-login-name))
- pass (funcall url-passwd-entry-func "Password: ")
- retval (base64-encode-string (format "%s:%s" user pass))
- byserv (assoc server (symbol-value url-basic-auth-storage)))
- (setcdr byserv
- (cons (cons path retval) (cdr byserv))))))
- (t (setq retval nil)))
- (if retval (setq retval (concat "Basic " retval)))
- retval))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Digest authorization code
-;;; ------------------------
-;;; This implements the DIGEST authorization type. See the internet draft
-;;; ftp://ds.internic.net/internet-drafts/draft-ietf-http-digest-aa-01.txt
-;;; for the complete documentation on this type.
-;;;
-;;; This is very secure
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar url-digest-auth-storage nil
- "Where usernames and passwords are stored. Its value is an assoc list of
-assoc lists. The first assoc list is keyed by the server name. The cdr of
-this is an assoc list based on the 'directory' specified by the url we are
-looking up.")
-
-(defun url-digest-auth-create-key (username password realm method uri)
- "Create a key for digest authentication method"
- (let* ((info (if (stringp uri)
- (url-generic-parse-url uri)
- uri))
- (a1 (md5 (concat username ":" realm ":" password)))
- (a2 (md5 (concat method ":" (url-filename info)))))
- (list a1 a2)))
-
-(defun url-digest-auth (url &optional prompt overwrite realm args)
- "Get the username/password for the specified URL.
-If optional argument PROMPT is non-nil, ask for the username/password
-to use for the url and its descendants. If optional third argument
-OVERWRITE is non-nil, overwrite the old username/password pair if it
-is found in the assoc list. If REALM is specified, use that as the realm
-instead of hostname:portnum."
- (if args
- (let* ((href (if (stringp url)
- (url-generic-parse-url url)
- url))
- (server (url-host href))
- (port (url-port href))
- (path (url-filename href))
- user pass byserv retval data)
- (setq path (cond
- (realm realm)
- ((string-match "/$" path) path)
- (t (url-basepath path)))
- server (format "%s:%d" server port)
- byserv (cdr-safe (assoc server url-digest-auth-storage)))
- (cond
- ((and prompt (not byserv))
- (setq user (read-string (url-auth-user-prompt url realm)
- (user-real-login-name))
- pass (funcall url-passwd-entry-func "Password: ")
- url-digest-auth-storage
- (cons (list server
- (cons path
- (setq retval
- (cons user
- (url-digest-auth-create-key
- user pass realm
- (or url-request-method "GET")
- url)))))
- url-digest-auth-storage)))
- (byserv
- (setq retval (cdr-safe (assoc path byserv)))
- (if (and (not retval) ; no exact match, check directories
- (string-match "/" path)) ; not looking for a realm
- (while (and byserv (not retval))
- (setq data (car (car byserv)))
- (if (or (not (string-match "/" data))
- (and
- (>= (length path) (length data))
- (string= data (substring path 0 (length data)))))
- (setq retval (cdr (car byserv))))
- (setq byserv (cdr byserv))))
- (if (or (and (not retval) prompt) overwrite)
- (progn
- (setq user (read-string (url-auth-user-prompt url realm)
- (user-real-login-name))
- pass (funcall url-passwd-entry-func "Password: ")
- retval (setq retval
- (cons user
- (url-digest-auth-create-key
- user pass realm
- (or url-request-method "GET")
- url)))
- byserv (assoc server url-digest-auth-storage))
- (setcdr byserv
- (cons (cons path retval) (cdr byserv))))))
- (t (setq retval nil)))
- (if retval
- (let ((nonce (or (cdr-safe (assoc "nonce" args)) "nonegiven"))
- (opaque (or (cdr-safe (assoc "opaque" args)) "nonegiven")))
- (format
- (concat "Digest username=\"%s\", realm=\"%s\","
- "nonce=\"%s\", uri=\"%s\","
- "response=\"%s\", opaque=\"%s\"")
- (nth 0 retval) realm nonce (url-filename href)
- (md5 (concat (nth 1 retval) ":" nonce ":"
- (nth 2 retval))) opaque))))))
-
-(defvar url-registered-auth-schemes nil
- "A list of the registered authorization schemes and various and sundry
-information associated with them.")
-
-;;;###autoload
-(defun url-get-authentication (url realm type prompt &optional args)
- "Return an authorization string suitable for use in the WWW-Authenticate
-header in an HTTP/1.0 request.
-
-URL is the url you are requesting authorization to. This can be either a
- string representing the URL, or the parsed representation returned by
- `url-generic-parse-url'
-REALM is the realm at a specific site we are looking for. This should be a
- string specifying the exact realm, or nil or the symbol 'any' to
- specify that the filename portion of the URL should be used as the
- realm
-TYPE is the type of authentication to be returned. This is either a string
- representing the type (basic, digest, etc), or nil or the symbol 'any'
- to specify that any authentication is acceptable. If requesting 'any'
- the strongest matching authentication will be returned. If this is
- wrong, its no big deal, the error from the server will specify exactly
- what type of auth to use
-PROMPT is boolean - specifies whether to ask the user for a username/password
- if one cannot be found in the cache"
- (if (not realm)
- (setq realm (cdr-safe (assoc "realm" args))))
- (if (stringp url)
- (setq url (url-generic-parse-url url)))
- (if (or (null type) (eq type 'any))
- ;; Whooo doogies!
- ;; Go through and get _all_ the authorization strings that could apply
- ;; to this URL, store them along with the 'rating' we have in the list
- ;; of schemes, then sort them so that the 'best' is at the front of the
- ;; list, then get the car, then get the cdr.
- ;; Zooom zooom zoooooom
- (cdr-safe
- (car-safe
- (sort
- (mapcar
- (function
- (lambda (scheme)
- (if (fboundp (car (cdr scheme)))
- (cons (cdr (cdr scheme))
- (funcall (car (cdr scheme)) url nil nil realm))
- (cons 0 nil))))
- url-registered-auth-schemes)
- (function
- (lambda (x y)
- (cond
- ((null (cdr x)) nil)
- ((and (cdr x) (null (cdr y))) t)
- ((and (cdr x) (cdr y))
- (>= (car x) (car y)))
- (t nil)))))))
- (if (symbolp type) (setq type (symbol-name type)))
- (let* ((scheme (car-safe
- (cdr-safe (assoc (downcase type)
- url-registered-auth-schemes)))))
- ;; on some systems, we have to wait in order to avoid drawing a blank page
- (and url-slow-proxy-requires-waiting-for
- (sleep-for url-slow-proxy-requires-waiting-for))
- (if (and scheme (fboundp scheme))
- (funcall scheme url prompt
- ;;;(and prompt
- ;;; (funcall scheme url nil nil realm args))
- ;; specify `nil' instead, otherwise authentication
- ;; gets repeated over and over again ...
- nil
- realm args)))))
-
-;;;###autoload
-(defun url-register-auth-scheme (type &optional function rating)
- "Register an HTTP authentication method.
-
-TYPE is a string or symbol specifying the name of the method. This
- should be the same thing you expect to get returned in an Authenticate
- header in HTTP/1.0 - it will be downcased.
-FUNCTION is the function to call to get the authorization information. This
- defaults to `url-?-auth', where ? is TYPE
-RATING a rating between 1 and 10 of the strength of the authentication.
- This is used when asking for the best authentication for a specific
- URL. The item with the highest rating is returned."
- (let* ((type (cond
- ((stringp type) (downcase type))
- ((symbolp type) (downcase (symbol-name type)))
- (t (error "Bad call to `url-register-auth-scheme'"))))
- (function (or function (intern (concat "url-" type "-auth"))))
- (rating (cond
- ((null rating) 2)
- ((stringp rating) (string-to-int rating))
- (t rating)))
- (node (assoc type url-registered-auth-schemes)))
- (if (not (fboundp function))
- (url-warn 'security
- (format (eval-when-compile
- "Tried to register `%s' as an auth scheme"
- ", but it is not a function!") function)))
-
- (if node
- (setcdr node (cons function rating))
- (setq url-registered-auth-schemes
- (cons (cons type (cons function rating))
- url-registered-auth-schemes)))))
-
-(defun url-auth-registered (scheme)
- ;; Return non-nil iff SCHEME is registered as an auth type
- (assoc scheme url-registered-auth-schemes))
-
-(provide 'url-auth)
+++ /dev/null
-\f
-;;;### (autoloads (url-register-auth-scheme url-get-authentication)
-;;;;;; "url-auth" "url-auth.el" (19270 18926))
-;;; Generated autoloads from url-auth.el
-
-(autoload 'url-get-authentication "url-auth" "\
-Return an authorization string suitable for use in the WWW-Authenticate
-header in an HTTP/1.0 request.
-
-URL is the url you are requesting authorization to. This can be either a
- string representing the URL, or the parsed representation returned by
- `url-generic-parse-url'
-REALM is the realm at a specific site we are looking for. This should be a
- string specifying the exact realm, or nil or the symbol 'any' to
- specify that the filename portion of the URL should be used as the
- realm
-TYPE is the type of authentication to be returned. This is either a string
- representing the type (basic, digest, etc), or nil or the symbol 'any'
- to specify that any authentication is acceptable. If requesting 'any'
- the strongest matching authentication will be returned. If this is
- wrong, its no big deal, the error from the server will specify exactly
- what type of auth to use
-PROMPT is boolean - specifies whether to ask the user for a username/password
- if one cannot be found in the cache
-
-\(fn URL REALM TYPE PROMPT &optional ARGS)" nil nil)
-
-(autoload 'url-register-auth-scheme "url-auth" "\
-Register an HTTP authentication method.
-
-TYPE is a string or symbol specifying the name of the method. This
- should be the same thing you expect to get returned in an Authenticate
- header in HTTP/1.0 - it will be downcased.
-FUNCTION is the function to call to get the authorization information. This
- defaults to `url-?-auth', where ? is TYPE
-RATING a rating between 1 and 10 of the strength of the authentication.
- This is used when asking for the best authentication for a specific
- URL. The item with the highest rating is returned.
-
-\(fn TYPE &optional FUNCTION RATING)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-cache-expired url-cache-extract url-is-cached
-;;;;;; url-store-in-cache) "url-cache" "url-cache.el" (15437 42793))
-;;; Generated autoloads from url-cache.el
-
-(autoload 'url-store-in-cache "url-cache" "\
-Store buffer BUFF in the cache.
-
-\(fn &optional BUFF)" nil nil)
-
-(autoload 'url-is-cached "url-cache" "\
-Return non-nil if the URL is cached.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-cache-extract "url-cache" "\
-Extract FNAM from the local disk cache
-
-\(fn FNAM)" nil nil)
-
-(autoload 'url-cache-expired "url-cache" "\
-Return t iff a cached file has expired.
-
-\(fn URL MOD)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-cid) "url-cid" "url-cid.el" (15092 11246))
-;;; Generated autoloads from url-cid.el
-
-(autoload 'url-cid "url-cid" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-cookie-setup-save-timer url-cookie-handle-set-cookie
-;;;;;; url-cookie-retrieve url-cookie-write-file url-cookie-parse-file)
-;;;;;; "url-cookie" "url-cookie.el" (15806 40683))
-;;; Generated autoloads from url-cookie.el
-
-(autoload 'url-cookie-parse-file "url-cookie" "\
-Not documented
-
-\(fn &optional FNAME)" nil nil)
-
-(autoload 'url-cookie-write-file "url-cookie" "\
-Not documented
-
-\(fn &optional FNAME)" nil nil)
-
-(autoload 'url-cookie-retrieve "url-cookie" "\
-Retrieves all the netscape-style cookies for a specified HOST and PATH
-
-\(fn HOST PATH &optional SECURE)" nil nil)
-
-(autoload 'url-cookie-handle-set-cookie "url-cookie" "\
-Not documented
-
-\(fn STR)" nil nil)
-
-(autoload 'url-cookie-setup-save-timer "url-cookie" "\
-Reset the cookie saver timer.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads (url-dav-vc-registered url-dav-file-name-completion
-;;;;;; url-dav-file-name-all-completions url-dav-rename-file url-dav-make-directory
-;;;;;; url-dav-file-directory-p url-dav-directory-files url-dav-delete-file
-;;;;;; url-dav-delete-directory url-dav-save-resource url-dav-file-attributes
-;;;;;; url-dav-unlock-resource url-dav-active-locks url-dav-lock-resource
-;;;;;; url-dav-get-properties url-dav-supported-p) "url-dav" "url-dav.el"
-;;;;;; (15450 54377))
-;;; Generated autoloads from url-dav.el
-
-(autoload 'url-dav-supported-p "url-dav" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(autoload 'url-dav-get-properties "url-dav" "\
-Return properties for URL, up to DEPTH levels deep.
-
-Returns an assoc list, where the key is the filename (possibly a full
-URI), and the value is a standard property list of DAV property
-names (ie: DAV:resourcetype).
-
-\(fn URL &optional ATTRIBUTES DEPTH NAMESPACES)" nil nil)
-
-(autoload 'url-dav-lock-resource "url-dav" "\
-Request a lock on URL. If EXCLUSIVE is non-nil, get an exclusive lock.
-Optional 3rd argument DEPTH says how deep the lock should go, default is 0
-\(lock only the resource and none of its children).
-
-Returns a cons-cell of (SUCCESSFUL-RESULTS . FAILURE-RESULTS).
-SUCCESSFUL-RESULTS is a list of (URL STATUS locktoken).
-FAILURE-RESULTS is a list of (URL STATUS).
-
-\(fn URL EXCLUSIVE &optional DEPTH)" nil nil)
-
-(autoload 'url-dav-active-locks "url-dav" "\
-Return an assoc list of all active locks on URL.
-
-\(fn URL &optional DEPTH)" nil nil)
-
-(autoload 'url-dav-unlock-resource "url-dav" "\
-Release the lock on URL represented by LOCK-TOKEN.
-Returns `t' iff the lock was successfully released.
-
-\(fn URL LOCK-TOKEN)" nil nil)
-
-(autoload 'url-dav-file-attributes "url-dav" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(autoload 'url-dav-save-resource "url-dav" "\
-Save OBJ as URL using WebDAV.
-URL must be a fully qualified URL.
-OBJ may be a buffer or a string.
-
-\(fn URL OBJ &optional CONTENT-TYPE LOCK-TOKEN)" nil nil)
-
-(autoload 'url-dav-delete-directory "url-dav" "\
-Delete the WebDAV collection URL.
-If optional second argument RECURSIVE is non-nil, then delete all
-files in the collection as well.
-
-\(fn URL &optional RECURSIVE LOCK-TOKEN)" nil nil)
-
-(autoload 'url-dav-delete-file "url-dav" "\
-Delete file named URL.
-
-\(fn URL &optional LOCK-TOKEN)" nil nil)
-
-(autoload 'url-dav-directory-files "url-dav" "\
-Return a list of names of files in DIRECTORY.
-There are three optional arguments:
-If FULL is non-nil, return absolute file names. Otherwise return names
- that are relative to the specified directory.
-If MATCH is non-nil, mention only file names that match the regexp MATCH.
-If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
- NOSORT is useful if you plan to sort the result yourself.
-
-\(fn URL &optional FULL MATCH NOSORT FILES-ONLY)" nil nil)
-
-(autoload 'url-dav-file-directory-p "url-dav" "\
-Return t if URL names an existing DAV collection.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-dav-make-directory "url-dav" "\
-Create the directory DIR and any nonexistent parent dirs.
-
-\(fn URL &optional PARENTS)" nil nil)
-
-(autoload 'url-dav-rename-file "url-dav" "\
-Not documented
-
-\(fn OLDNAME NEWNAME &optional OVERWRITE)" nil nil)
-
-(autoload 'url-dav-file-name-all-completions "url-dav" "\
-Return a list of all completions of file name FILE in directory DIRECTORY.
-These are all file names in directory DIRECTORY which begin with FILE.
-
-\(fn FILE URL)" nil nil)
-
-(autoload 'url-dav-file-name-completion "url-dav" "\
-Complete file name FILE in directory DIRECTORY.
-Returns the longest string
-common to all file names in DIRECTORY that start with FILE.
-If there is only one and FILE matches it exactly, returns t.
-Returns nil if DIR contains no name starting with FILE.
-
-\(fn FILE URL)" nil nil)
-
-(autoload 'url-dav-vc-registered "url-dav" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-file) "url-file" "url-file.el" (15555 54384))
-;;; Generated autoloads from url-file.el
-
-(autoload 'url-file "url-file" "\
-Handle file: and ftp: URLs.
-
-\(fn URL CALLBACK CBARGS)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-open-stream url-gateway-nslookup-host) "url-gw"
-;;;;;; "url-gw.el" (15555 55126))
-;;; Generated autoloads from url-gw.el
-
-(autoload 'url-gateway-nslookup-host "url-gw" "\
-Attempt to resolve the given HOST using nslookup if possible.
-
-\(fn HOST)" t nil)
-
-(autoload 'url-open-stream "url-gw" "\
-Open a stream to HOST, possibly via a gateway.
-Args per `open-network-stream'.
-Will not make a connexion if `url-gateway-unplugged' is non-nil.
-
-\(fn NAME BUFFER HOST SERVICE)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-insert-file-contents url-file-local-copy url-copy-file
-;;;;;; url-setup-file-name-handlers) "url-handlers" "url-handlers.el"
-;;;;;; (16123 16217))
-;;; Generated autoloads from url-handlers.el
-
-(autoload 'url-setup-file-name-handlers "url-handlers" "\
-Setup file-name handlers.
-
-\(fn)" nil nil)
-
-(autoload 'url-copy-file "url-handlers" "\
-Copy URL to NEWNAME. Both args must be strings.
-Signals a `file-already-exists' error if file NEWNAME already exists,
-unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.
-A number as third arg means request confirmation if NEWNAME already exists.
-This is what happens in interactive use with M-x.
-Fourth arg KEEP-TIME non-nil means give the new file the same
-last-modified time as the old one. (This works on only some systems.)
-A prefix arg makes KEEP-TIME non-nil.
-
-\(fn URL NEWNAME &optional OK-IF-ALREADY-EXISTS KEEP-TIME)" nil nil)
-
-(autoload 'url-file-local-copy "url-handlers" "\
-Copy URL into a temporary file on this machine.
-Returns the name of the local copy, or nil, if FILE is directly
-accessible.
-
-\(fn URL &rest IGNORED)" nil nil)
-
-(autoload 'url-insert-file-contents "url-handlers" "\
-Not documented
-
-\(fn URL &optional VISIT BEG END REPLACE)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-history-save-history url-history-parse-history
-;;;;;; url-history-setup-save-timer) "url-history" "url-history.el"
-;;;;;; (15092 12080))
-;;; Generated autoloads from url-history.el
-
-(autoload 'url-history-setup-save-timer "url-history" "\
-Reset the history list timer.
-
-\(fn)" t nil)
-
-(autoload 'url-history-parse-history "url-history" "\
-Parse a history file stored in FNAME.
-
-\(fn &optional FNAME)" nil nil)
-
-(autoload 'url-history-save-history "url-history" "\
-Write the global history file into `url-history-file'.
-The type of data written is determined by what is in the file to begin
-with. If the type of storage cannot be determined, then prompt the
-user for what type to save as.
-
-\(fn &optional FNAME)" t nil)
-
-;;;***
-\f
-;;;### (autoloads (url-http-options url-http-file-attributes url-http-file-exists-p
-;;;;;; url-http) "url-http" "url-http.el" (19270 18926))
-;;; Generated autoloads from url-http.el
-
-(autoload 'url-http "url-http" "\
-Retrieve URL via HTTP asynchronously.
-URL must be a parsed URL. See `url-generic-parse-url' for details.
-When retrieval is completed, the function CALLBACK is executed with
-CBARGS as the arguments.
-
-\(fn URL CALLBACK CBARGS)" nil nil)
-
-(autoload 'url-http-file-exists-p "url-http" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(defalias 'url-http-file-readable-p 'url-http-file-exists-p)
-
-(autoload 'url-http-file-attributes "url-http" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(autoload 'url-http-options "url-http" "\
-Returns a property list describing options available for URL.
-This list is retrieved using the `OPTIONS' HTTP method.
-
-Property list members:
-
-methods
- A list of symbols specifying what HTTP methods the resource
- supports.
-
-dav
- A list of numbers specifying what DAV protocol/schema versions are
- supported.
-
-dasl
- A list of supported DASL search types supported (string form)
-
-ranges
- A list of the units available for use in partial document fetches.
-
-p3p
- The `Platform For Privacy Protection' description for the resource.
- Currently this is just the raw header contents. This is likely to
- change once P3P is formally supported by the URL package or
- Emacs/W3.
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-irc) "url-irc" "url-irc.el" (14435 25453))
-;;; Generated autoloads from url-irc.el
-
-(autoload 'url-irc "url-irc" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-ldap) "url-ldap" "url-ldap.el" (14398 30982))
-;;; Generated autoloads from url-ldap.el
-
-(autoload 'url-ldap "url-ldap" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-mailto url-mail) "url-mailto" "url-mailto.el"
-;;;;;; (15293 59398))
-;;; Generated autoloads from url-mailto.el
-
-(autoload 'url-mail "url-mailto" "\
-Not documented
-
-\(fn &rest ARGS)" t nil)
-
-(autoload 'url-mailto "url-mailto" "\
-Handle the mailto: URL syntax.
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-data url-generic-emulator-loader url-info
-;;;;;; url-man) "url-misc" "url-misc.el" (15556 36223))
-;;; Generated autoloads from url-misc.el
-
-(autoload 'url-man "url-misc" "\
-Fetch a Unix manual page URL.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-info "url-misc" "\
-Fetch a GNU Info URL.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-generic-emulator-loader "url-misc" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(defalias 'url-rlogin 'url-generic-emulator-loader)
-
-(defalias 'url-telnet 'url-generic-emulator-loader)
-
-(defalias 'url-tn3270 'url-generic-emulator-loader)
-
-(autoload 'url-data "url-misc" "\
-Fetch a data URL (RFC 2397).
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-snews url-news) "url-news" "url-news.el" (15114
-;;;;;; 36876))
-;;; Generated autoloads from url-news.el
-
-(autoload 'url-news "url-news" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-(autoload 'url-snews "url-news" "\
-Not documented
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-ns-user-pref url-ns-prefs isInNet isResolvable
-;;;;;; dnsResolve dnsDomainIs isPlainHostName) "url-ns" "url-ns.el"
-;;;;;; (14913 8114))
-;;; Generated autoloads from url-ns.el
-
-(autoload 'isPlainHostName "url-ns" "\
-Not documented
-
-\(fn HOST)" nil nil)
-
-(autoload 'dnsDomainIs "url-ns" "\
-Not documented
-
-\(fn HOST DOM)" nil nil)
-
-(autoload 'dnsResolve "url-ns" "\
-Not documented
-
-\(fn HOST)" nil nil)
-
-(autoload 'isResolvable "url-ns" "\
-Not documented
-
-\(fn HOST)" nil nil)
-
-(autoload 'isInNet "url-ns" "\
-Not documented
-
-\(fn IP NET MASK)" nil nil)
-
-(autoload 'url-ns-prefs "url-ns" "\
-Not documented
-
-\(fn &optional FILE)" nil nil)
-
-(autoload 'url-ns-user-pref "url-ns" "\
-Not documented
-
-\(fn KEY &optional DEFAULT)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-generic-parse-url url-recreate-url) "url-parse"
-;;;;;; "url-parse.el" (15288 22758))
-;;; Generated autoloads from url-parse.el
-
-(autoload 'url-recreate-url "url-parse" "\
-Not documented
-
-\(fn URLOBJ)" nil nil)
-
-(autoload 'url-generic-parse-url "url-parse" "\
-Return a vector of the parts of URL.
-Format is:
-\[proto username password hostname portnumber file reference attributes fullp]
-
-\(fn URL)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads (url-setup-privacy-info) "url-privacy" "url-privacy.el"
-;;;;;; (15293 59778))
-;;; Generated autoloads from url-privacy.el
-
-(autoload 'url-setup-privacy-info "url-privacy" "\
-Not documented
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads (url-view-url url-truncate-url-for-viewing url-file-extension
-;;;;;; url-hexify-string url-unhex-string url-parse-query-string
-;;;;;; url-basepath url-percentage url-display-percentage url-pretty-length
-;;;;;; url-strip-leading-spaces url-eat-trailing-space url-get-normalized-date
-;;;;;; url-lazy-message url-normalize-url url-insert-entities-in-string
-;;;;;; url-parse-args url-debug url-debug) "url-util" "url-util.el"
-;;;;;; (19270 18926))
-;;; Generated autoloads from url-util.el
-
-(defvar url-debug nil "\
-*What types of debug messages from the URL library to show.
-Debug messages are logged to the *URL-DEBUG* buffer.
-
-If t, all messages will be logged.
-If a number, all messages will be logged, as well shown via `message'.
-If a list, it is a list of the types of messages to be logged.")
-
-(autoload 'url-debug "url-util")
-
-(autoload 'url-debug "url-util" "\
-Not documented
-
-\(fn TAG &rest ARGS)" nil nil)
-
-(autoload 'url-parse-args "url-util" "\
-Not documented
-
-\(fn STR &optional NODOWNCASE)" nil nil)
-
-(autoload 'url-insert-entities-in-string "url-util" "\
-Convert HTML markup-start characters to entity references in STRING.
-Also replaces the \" character, so that the result may be safely used as
- an attribute value in a tag. Returns a new string with the result of the
- conversion. Replaces these characters as follows:
- & ==> &
- < ==> <
- > ==> >
- \" ==> "
-
-\(fn STRING)" nil nil)
-
-(autoload 'url-normalize-url "url-util" "\
-Return a 'normalized' version of URL.
-Strips out default port numbers, etc.
-
-\(fn URL)" nil nil)
-
-(autoload 'url-lazy-message "url-util" "\
-Just like `message', but is a no-op if called more than once a second.
-Will not do anything if url-show-status is nil.
-
-\(fn &rest ARGS)" nil nil)
-
-(autoload 'url-get-normalized-date "url-util" "\
-Return a 'real' date string that most HTTP servers can understand.
-
-\(fn &optional SPECIFIED-TIME)" nil nil)
-
-(autoload 'url-eat-trailing-space "url-util" "\
-Remove spaces/tabs at the end of a string.
-
-\(fn X)" nil nil)
-
-(autoload 'url-strip-leading-spaces "url-util" "\
-Remove spaces at the front of a string.
-
-\(fn X)" nil nil)
-
-(autoload 'url-pretty-length "url-util" "\
-Not documented
-
-\(fn N)" nil nil)
-
-(autoload 'url-display-percentage "url-util" "\
-Not documented
-
-\(fn FMT PERC &rest ARGS)" nil nil)
-
-(autoload 'url-percentage "url-util" "\
-Not documented
-
-\(fn X Y)" nil nil)
-
-(autoload 'url-basepath "url-util" "\
-Return the base pathname of FILE, or the actual filename if X is true.
-
-\(fn FILE &optional X)" nil nil)
-
-(autoload 'url-parse-query-string "url-util" "\
-Not documented
-
-\(fn QUERY &optional DOWNCASE)" nil nil)
-
-(autoload 'url-unhex-string "url-util" "\
-Remove %XXX embedded spaces, etc in a url.
-If optional second argument ALLOW-NEWLINES is non-nil, then allow the
-decoding of carriage returns and line feeds in the string, which is normally
-forbidden in URL encoding.
-
-\(fn STR &optional ALLOW-NEWLINES)" nil nil)
-
-(autoload 'url-hexify-string "url-util" "\
-Escape characters in a string.
-
-\(fn STR)" nil nil)
-
-(autoload 'url-file-extension "url-util" "\
-Return the filename extension of FNAME.
-If optional variable X is t,
-then return the basename of the file with the extension stripped off.
-
-\(fn FNAME &optional X)" nil nil)
-
-(autoload 'url-truncate-url-for-viewing "url-util" "\
-Return a shortened version of URL that is WIDTH characters or less wide.
-WIDTH defaults to the current frame width.
-
-\(fn URL &optional WIDTH)" nil nil)
-
-(autoload 'url-view-url "url-util" "\
-View the current document's URL.
-Optional argument NO-SHOW means just return the URL, don't show it in
-the minibuffer.
-
-This uses `url-current-object', set locally to the buffer.
-
-\(fn &optional NO-SHOW)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "url" "url.el" (19270 18926))
-;;; Generated autoloads from url.el
-
-(defvar url-configuration-directory "~/.url")
-
-;;;***
-
-(provide 'url-auto)
+++ /dev/null
-;;; url-buffer.el --- URLs for Emacs buffers
-;; Created: 5 Feb 2003
-;; Version: 0.9
-;; Keywords: data, buffers
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 2001 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(eval-when-compile
- (require 'cl))
-(require 'url-util)
-(require 'url-parse)
-
-(defun url-buffer (url)
- "Handle buffer: URLs that refer to Emacs buffers."
- (let* ((buffer (get-buffer (url-filename url))))
- (if buffer
- (progn
- (set-buffer (generate-new-buffer " *buffer-data*"))
- (insert "Content-type: text/html\n\n")
- (insert-buffer-substring buffer)
- (current-buffer))
- (error "No buffer named `%s'" item))))
-
-(provide 'url-buffer)
+++ /dev/null
-;;; url-cache.el --- Uniform Resource Locator retrieval tool
-;; Author: $Author: fx $
-;; Created: $Date: 2002/01/22 17:53:45 $
-;; Version: $Revision: 1.4 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(require 'url-parse)
-
-(defcustom url-cache-directory
- (expand-file-name "cache" url-configuration-directory)
- "*The directory where cache files should be stored."
- :type 'directory
- :group 'url-file)
-
-;; Cache manager
-(defun url-cache-file-writable-p (file)
- "Follows the documentation of `file-writable-p', unlike `file-writable-p'."
- (and (file-writable-p file)
- (if (file-exists-p file)
- (not (file-directory-p file))
- (file-directory-p (file-name-directory file)))))
-
-(defun url-cache-prepare (file)
- "Makes it possible to cache data in FILE.
-Creates any necessary parent directories, deleting any non-directory files
-that would stop this. Returns nil if parent directories can not be
-created. If FILE already exists as a non-directory, it changes
-permissions of FILE or deletes FILE to make it possible to write a new
-version of FILE. Returns nil if this can not be done. Returns nil if
-FILE already exists as a directory. Otherwise, returns t, indicating that
-FILE can be created or overwritten."
- (cond
- ((url-cache-file-writable-p file)
- t)
- ((file-directory-p file)
- nil)
- (t
- (condition-case ()
- (or (make-directory (file-name-directory file) t) t)
- (error nil)))))
-
-;;;###autoload
-(defun url-store-in-cache (&optional buff)
- "Store buffer BUFF in the cache."
- (if (not (and buff (get-buffer buff)))
- nil
- (save-excursion
- (and buff (set-buffer buff))
- (let* ((fname (url-cache-create-filename (url-view-url t))))
- (if (url-cache-prepare fname)
- (let ((coding-system-for-write 'binary))
- (write-region (point-min) (point-max) fname nil 5)))))))
-
-;;;###autoload
-(defun url-is-cached (url)
- "Return non-nil if the URL is cached."
- (let* ((fname (url-cache-create-filename url))
- (attribs (file-attributes fname)))
- (and fname ; got a filename
- (file-exists-p fname) ; file exists
- (not (eq (nth 0 attribs) t)) ; Its not a directory
- (nth 5 attribs)))) ; Can get last mod-time
-
-(defun url-cache-create-filename-human-readable (url)
- "Return a filename in the local cache for URL"
- (if url
- (let* ((url (if (vectorp url) (url-recreate-url url) url))
- (urlobj (url-generic-parse-url url))
- (protocol (url-type urlobj))
- (hostname (url-host urlobj))
- (host-components
- (cons
- (user-real-login-name)
- (cons (or protocol "file")
- (reverse (split-string (or hostname "localhost")
- (eval-when-compile
- (regexp-quote ".")))))))
- (fname (url-filename urlobj)))
- (if (and fname (/= (length fname) 0) (= (aref fname 0) ?/))
- (setq fname (substring fname 1 nil)))
- (if fname
- (let ((slash nil))
- (setq fname
- (mapconcat
- (function
- (lambda (x)
- (cond
- ((and (= ?/ x) slash)
- (setq slash nil)
- "%2F")
- ((= ?/ x)
- (setq slash t)
- "/")
- (t
- (setq slash nil)
- (char-to-string x))))) fname ""))))
-
- (setq fname (and fname
- (mapconcat
- (function (lambda (x)
- (if (= x ?~) "" (char-to-string x))))
- fname ""))
- fname (cond
- ((null fname) nil)
- ((or (string= "" fname) (string= "/" fname))
- url-directory-index-file)
- ((= (string-to-char fname) ?/)
- (if (string= (substring fname -1 nil) "/")
- (concat fname url-directory-index-file)
- (substring fname 1 nil)))
- (t
- (if (string= (substring fname -1 nil) "/")
- (concat fname url-directory-index-file)
- fname))))
- (and fname
- (expand-file-name fname
- (expand-file-name
- (mapconcat 'identity host-components "/")
- url-cache-directory))))))
-
-(defun url-cache-create-filename-using-md5 (url)
- "Create a cached filename using MD5.
- Very fast if you are in XEmacs, suitably fast otherwise."
- (require 'md5)
- (if url
- (let* ((url (if (vectorp url) (url-recreate-url url) url))
- (checksum (md5 url))
- (urlobj (url-generic-parse-url url))
- (protocol (url-type urlobj))
- (hostname (url-host urlobj))
- (host-components
- (cons
- (user-real-login-name)
- (cons (or protocol "file")
- (nreverse
- (delq nil
- (split-string (or hostname "localhost")
- (eval-when-compile
- (regexp-quote "."))))))))
- (fname (url-filename urlobj)))
- (and fname
- (expand-file-name checksum
- (expand-file-name
- (mapconcat 'identity host-components "/")
- url-cache-directory))))))
-
-(defcustom url-cache-creation-function 'url-cache-create-filename-using-md5
- "*What function to use to create a cached filename."
- :type '(choice (const :tag "MD5 of filename (low collision rate)"
- :value url-cache-create-filename-using-md5)
- (const :tag "Human readable filenames (higher collision rate)"
- :value url-cache-create-filename-human-readable)
- (function :tag "Other"))
- :group 'url-cache)
-
-(defun url-cache-create-filename (url)
- (funcall url-cache-creation-function url))
-
-;;;###autoload
-(defun url-cache-extract (fnam)
- "Extract FNAM from the local disk cache"
- (erase-buffer)
- (insert-file-contents-literally fnam))
-
-;;;###autoload
-(defun url-cache-expired (url mod)
- "Return t iff a cached file has expired."
- (let* ((urlobj (if (vectorp url) url (url-generic-parse-url url)))
- (type (url-type urlobj)))
- (cond
- (url-standalone-mode
- (not (file-exists-p (url-cache-create-filename url))))
- ((string= type "http")
- t)
- ((member type '("file" "ftp"))
- (if (or (equal mod '(0 0)) (not mod))
- t
- (or (> (nth 0 mod) (nth 0 (current-time)))
- (> (nth 1 mod) (nth 1 (current-time))))))
- (t nil))))
-
-(provide 'url-cache)
+++ /dev/null
-;;; url-cid.el --- Content-ID URL loader
-;; Author: $Author: fx $
-;; Created: $Date: 2001/05/05 16:35:58 $
-;; Version: $Revision: 1.3 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1998 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url-vars)
-(require 'url-parse)
-
-(require 'mm-decode)
-
-(defun url-cid-gnus (cid)
- (let ((content-type nil)
- (encoding nil)
- (part nil)
- (data nil))
- (setq part (mm-get-content-id cid))
- (if (not part)
- (message "Unknown CID encountered: %s" cid)
- (setq data (save-excursion
- (set-buffer (mm-handle-buffer part))
- (buffer-string))
- content-type (mm-handle-type part)
- encoding (symbol-name (mm-handle-encoding part)))
- (if (= 0 (length content-type)) (setq content-type "text/plain"))
- (if (= 0 (length encoding)) (setq encoding "8bit"))
- (if (listp content-type)
- (setq content-type (car content-type)))
- (insert (format "Content-type: %d\r\n" (length data))
- "Content-type: " content-type "\r\n"
- "Content-transfer-encoding: " encoding "\r\n"
- "\r\n"
- (or data "")))))
-
-;;;###autoload
-(defun url-cid (url)
- (cond
- ((fboundp 'mm-get-content-id)
- ;; Using Pterodactyl Gnus or later
- (save-excursion
- (set-buffer (generate-new-buffer " *url-cid*"))
- (url-cid-gnus (url-filename url))))
- (t
- (message "Unable to handle CID URL: %s" url))))
+++ /dev/null
-;;; url-cookie.el --- Netscape Cookie support
-;; Author: $Author: wmperry $
-;; Created: $Date: 2002/10/29 14:44:59 $
-;; Version: $Revision: 1.7 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'timezone)
-(require 'url-util)
-(require 'url-parse)
-(eval-when-compile (require 'cl))
-
-;; See http://home.netscape.com/newsref/std/cookie_spec.html for the
-;; 'open standard' defining this crap.
-;;
-;; A cookie is stored internally as a vector of 7 slots
-;; [ 'cookie name value expires path domain secure ]
-
-(defsubst url-cookie-name (cookie) (aref cookie 1))
-(defsubst url-cookie-value (cookie) (aref cookie 2))
-(defsubst url-cookie-expires (cookie) (aref cookie 3))
-(defsubst url-cookie-path (cookie) (aref cookie 4))
-(defsubst url-cookie-domain (cookie) (aref cookie 5))
-(defsubst url-cookie-secure (cookie) (aref cookie 6))
-
-(defsubst url-cookie-set-name (cookie val) (aset cookie 1 val))
-(defsubst url-cookie-set-value (cookie val) (aset cookie 2 val))
-(defsubst url-cookie-set-expires (cookie val) (aset cookie 3 val))
-(defsubst url-cookie-set-path (cookie val) (aset cookie 4 val))
-(defsubst url-cookie-set-domain (cookie val) (aset cookie 5 val))
-(defsubst url-cookie-set-secure (cookie val) (aset cookie 6 val))
-(defsubst url-cookie-retrieve-arg (key args) (nth 1 (memq key args)))
-
-(defsubst url-cookie-create (&rest args)
- (let ((retval (make-vector 7 nil)))
- (aset retval 0 'cookie)
- (url-cookie-set-name retval (url-cookie-retrieve-arg :name args))
- (url-cookie-set-value retval (url-cookie-retrieve-arg :value args))
- (url-cookie-set-expires retval (url-cookie-retrieve-arg :expires args))
- (url-cookie-set-path retval (url-cookie-retrieve-arg :path args))
- (url-cookie-set-domain retval (url-cookie-retrieve-arg :domain args))
- (url-cookie-set-secure retval (url-cookie-retrieve-arg :secure args))
- retval))
-
-(defun url-cookie-p (obj)
- (and (vectorp obj) (= (length obj) 7) (eq (aref obj 0) 'cookie)))
-
-(defgroup url-cookie nil
- "URL cookies"
- :prefix "url-"
- :prefix "url-cookie-"
- :group 'url)
-
-(defvar url-cookie-storage nil "Where cookies are stored.")
-(defvar url-cookie-secure-storage nil "Where secure cookies are stored.")
-(defcustom url-cookie-file nil "*Where cookies are stored on disk."
- :type '(choice (const :tag "Default" :value nil) file)
- :group 'url-file
- :group 'url-cookie)
-
-(defcustom url-cookie-confirmation nil
- "*If non-nil, confirmation by the user is required to accept HTTP cookies."
- :type 'boolean
- :group 'url-cookie)
-
-(defcustom url-cookie-multiple-line nil
- "*If nil, HTTP requests put all cookies for the server on one line.
-Some web servers, such as http://www.hotmail.com/, only accept cookies
-when they are on one line. This is broken behaviour, but just try
-telling Microsoft that.")
-
-(defvar url-cookies-changed-since-last-save nil
- "Whether the cookies list has changed since the last save operation.")
-
-;;;###autoload
-(defun url-cookie-parse-file (&optional fname)
- (setq fname (or fname url-cookie-file))
- (condition-case ()
- (load fname nil t)
- (error (message "Could not load cookie file %s" fname))))
-
-(defun url-cookie-clean-up (&optional secure)
- (let* (
- (var (if secure 'url-cookie-secure-storage 'url-cookie-storage))
- (val (symbol-value var))
- (cur nil)
- (new nil)
- (cookies nil)
- (cur-cookie nil)
- (new-cookies nil)
- )
- (while val
- (setq cur (car val)
- val (cdr val)
- new-cookies nil
- cookies (cdr cur))
- (while cookies
- (setq cur-cookie (car cookies)
- cookies (cdr cookies))
- (if (or (not (url-cookie-p cur-cookie))
- (url-cookie-expired-p cur-cookie)
- (null (url-cookie-expires cur-cookie)))
- nil
- (setq new-cookies (cons cur-cookie new-cookies))))
- (if (not new-cookies)
- nil
- (setcdr cur new-cookies)
- (setq new (cons cur new))))
- (set var new)))
-
-;;;###autoload
-(defun url-cookie-write-file (&optional fname)
- (setq fname (or fname url-cookie-file))
- (cond
- ((not url-cookies-changed-since-last-save) nil)
- ((not (file-writable-p fname))
- (message "Cookies file %s (see variable `url-cookie-file') is unwritable." fname))
- (t
- (url-cookie-clean-up)
- (url-cookie-clean-up t)
- (save-excursion
- (set-buffer (get-buffer-create " *cookies*"))
- (erase-buffer)
- (fundamental-mode)
- (insert ";; Emacs-W3 HTTP cookies file\n"
- ";; Automatically generated file!!! DO NOT EDIT!!!\n\n"
- "(setq url-cookie-storage\n '")
- (pp url-cookie-storage (current-buffer))
- (insert ")\n(setq url-cookie-secure-storage\n '")
- (pp url-cookie-secure-storage (current-buffer))
- (insert ")\n")
- (write-file fname)
- (kill-buffer (current-buffer))))))
-
-(defun url-cookie-store (name value &optional expires domain path secure)
- "Stores a netscape-style cookie"
- (let* ((storage (if secure url-cookie-secure-storage url-cookie-storage))
- (tmp storage)
- (cur nil)
- (found-domain nil))
-
- ;; First, look for a matching domain
- (setq found-domain (assoc domain storage))
-
- (if found-domain
- ;; Need to either stick the new cookie in existing domain storage
- ;; or possibly replace an existing cookie if the names match.
- (progn
- (setq storage (cdr found-domain)
- tmp nil)
- (while storage
- (setq cur (car storage)
- storage (cdr storage))
- (if (and (equal path (url-cookie-path cur))
- (equal name (url-cookie-name cur)))
- (progn
- (url-cookie-set-expires cur expires)
- (url-cookie-set-value cur value)
- (setq tmp t))))
- (if (not tmp)
- ;; New cookie
- (setcdr found-domain (cons
- (url-cookie-create :name name
- :value value
- :expires expires
- :domain domain
- :path path
- :secure secure)
- (cdr found-domain)))))
- ;; Need to add a new top-level domain
- (setq tmp (url-cookie-create :name name
- :value value
- :expires expires
- :domain domain
- :path path
- :secure secure))
- (cond
- (storage
- (setcdr storage (cons (list domain tmp) (cdr storage))))
- (secure
- (setq url-cookie-secure-storage (list (list domain tmp))))
- (t
- (setq url-cookie-storage (list (list domain tmp))))))))
-
-(defun url-cookie-expired-p (cookie)
- (let* (
- (exp (url-cookie-expires cookie))
- (cur-date (and exp (timezone-parse-date (current-time-string))))
- (exp-date (and exp (timezone-parse-date exp)))
- (cur-greg (and cur-date (timezone-absolute-from-gregorian
- (string-to-int (aref cur-date 1))
- (string-to-int (aref cur-date 2))
- (string-to-int (aref cur-date 0)))))
- (exp-greg (and exp (timezone-absolute-from-gregorian
- (string-to-int (aref exp-date 1))
- (string-to-int (aref exp-date 2))
- (string-to-int (aref exp-date 0)))))
- (diff-in-days (and exp (- cur-greg exp-greg)))
- )
- (cond
- ((not exp) nil) ; No expiry == expires at browser quit
- ((< diff-in-days 0) nil) ; Expires sometime after today
- ((> diff-in-days 0) t) ; Expired before today
- (t ; Expires sometime today, check times
- (let* ((cur-time (timezone-parse-time (aref cur-date 3)))
- (exp-time (timezone-parse-time (aref exp-date 3)))
- (cur-norm (+ (* 360 (string-to-int (aref cur-time 2)))
- (* 60 (string-to-int (aref cur-time 1)))
- (* 1 (string-to-int (aref cur-time 0)))))
- (exp-norm (+ (* 360 (string-to-int (aref exp-time 2)))
- (* 60 (string-to-int (aref exp-time 1)))
- (* 1 (string-to-int (aref exp-time 0))))))
- (> (- cur-norm exp-norm) 1))))))
-
-;;;###autoload
-(defun url-cookie-retrieve (host path &optional secure)
- "Retrieves all the netscape-style cookies for a specified HOST and PATH"
- (let ((storage (if secure
- (append url-cookie-secure-storage url-cookie-storage)
- url-cookie-storage))
- (case-fold-search t)
- (cookies nil)
- (cur nil)
- (retval nil)
- (path-regexp nil))
- (while storage
- (setq cur (car storage)
- storage (cdr storage)
- cookies (cdr cur))
- (if (and (car cur)
- (string-match (concat "^.*" (regexp-quote (car cur)) "$") host))
- ;; The domains match - a possible hit!
- (while cookies
- (setq cur (car cookies)
- cookies (cdr cookies)
- path-regexp (concat "^" (regexp-quote
- (url-cookie-path cur))))
- (if (and (string-match path-regexp path)
- (not (url-cookie-expired-p cur)))
- (setq retval (cons cur retval))))))
- retval))
-
-;;;###autolaod
-(defun url-cookie-generate-header-lines (host path secure)
- (let* ((cookies (url-cookie-retrieve host path secure))
- (retval nil)
- (cur nil)
- (chunk nil))
- ;; Have to sort this for sending most specific cookies first
- (setq cookies (and cookies
- (sort cookies
- (function
- (lambda (x y)
- (> (length (url-cookie-path x))
- (length (url-cookie-path y))))))))
- (while cookies
- (setq cur (car cookies)
- cookies (cdr cookies)
- chunk (format "%s=%s" (url-cookie-name cur) (url-cookie-value cur))
- retval (if (and url-cookie-multiple-line
- (< 80 (+ (length retval) (length chunk) 4)))
- (concat retval "\r\nCookie: " chunk)
- (if retval
- (concat retval "; " chunk)
- (concat "Cookie: " chunk)))))
- (if retval
- (concat retval "\r\n")
- "")))
-
-(defvar url-cookie-two-dot-domains
- (concat "\\.\\("
- (mapconcat 'identity (list "com" "edu" "net" "org" "gov" "mil" "int")
- "\\|")
- "\\)$")
- "A regular expression of top-level domains that only require two matching
-'.'s in the domain name in order to set a cookie.")
-
-(defcustom url-cookie-trusted-urls nil
- "*A list of regular expressions matching URLs to always accept cookies from."
- :type '(repeat regexp)
- :group 'url-cookie)
-
-(defcustom url-cookie-untrusted-urls nil
- "*A list of regular expressions matching URLs to never accept cookies from."
- :type '(repeat regexp)
- :group 'url-cookie)
-
-(defun url-cookie-host-can-set-p (host domain)
- (let ((numdots 0)
- (tmp domain)
- (last nil)
- (case-fold-search t)
- (mindots 3))
- (while (setq last (string-match "\\." domain last))
- (setq numdots (1+ numdots)
- last (1+ last)))
- (if (string-match url-cookie-two-dot-domains domain)
- (setq mindots 2))
- (cond
- ((string= host domain) ; Apparently netscape lets you do this
- t)
- ((>= numdots mindots) ; We have enough dots in domain name
- ;; Need to check and make sure the host is actually _in_ the
- ;; domain it wants to set a cookie for though.
- (string-match (concat (regexp-quote domain) "$") host))
- (t
- nil))))
-
-;;;###autoload
-(defun url-cookie-handle-set-cookie (str)
- (setq url-cookies-changed-since-last-save t)
- (let* ((args (url-parse-args str t))
- (case-fold-search t)
- (secure (and (assoc-ignore-case "secure" args) t))
- (domain (or (cdr-safe (assoc-ignore-case "domain" args))
- (url-host url-current-object)))
- (current-url (url-view-url t))
- (trusted url-cookie-trusted-urls)
- (untrusted url-cookie-untrusted-urls)
- (expires (cdr-safe (assoc-ignore-case "expires" args)))
- (path (or (cdr-safe (assoc-ignore-case "path" args))
- (file-name-directory
- (url-filename url-current-object))))
- (rest nil))
- (while args
- (if (not (member (downcase (car (car args)))
- '("secure" "domain" "expires" "path")))
- (setq rest (cons (car args) rest)))
- (setq args (cdr args)))
-
- ;; Sometimes we get dates that the timezone package cannot handle very
- ;; gracefully - take care of this here, instead of in url-cookie-expired-p
- ;; to speed things up.
- (if (and expires
- (string-match
- (concat "^[^,]+, +\\(..\\)-\\(...\\)-\\(..\\) +"
- "\\(..:..:..\\) +\\[*\\([^\]]+\\)\\]*$")
- expires))
- (setq expires (concat (match-string 1 expires) " "
- (match-string 2 expires) " "
- (match-string 3 expires) " "
- (match-string 4 expires) " ["
- (match-string 5 expires) "]")))
-
- ;; This one is for older Emacs/XEmacs variants that don't
- ;; understand this format without tenths of a second in it.
- ;; Wednesday, 30-Dec-2037 16:00:00 GMT
- ;; - vs -
- ;; Wednesday, 30-Dec-2037 16:00:00.00 GMT
- (if (and expires
- (string-match
- "\\([0-9]+\\)-\\([A-Za-z]+\\)-\\([0-9]+\\)[ \t]+\\([0-9]+:[0-9]+:[0-9]+\\)\\(\\.[0-9]+\\)*[ \t]+\\([-+a-zA-Z0-9]+\\)"
- expires))
- (setq expires (concat (match-string 1 expires) "-" ; day
- (match-string 2 expires) "-" ; month
- (match-string 3 expires) " " ; year
- (match-string 4 expires) ".00 " ; hour:minutes:seconds
- (match-string 6 expires)))) ":" ; timezone
-
- (while (consp trusted)
- (if (string-match (car trusted) current-url)
- (setq trusted (- (match-end 0) (match-beginning 0)))
- (pop trusted)))
- (while (consp untrusted)
- (if (string-match (car untrusted) current-url)
- (setq untrusted (- (match-end 0) (match-beginning 0)))
- (pop untrusted)))
- (if (and trusted untrusted)
- ;; Choose the more specific match
- (if (> trusted untrusted)
- (setq untrusted nil)
- (setq trusted nil)))
- (cond
- (untrusted
- ;; The site was explicity marked as untrusted by the user
- nil)
- ((or (eq url-privacy-level 'paranoid)
- (and (listp url-privacy-level) (memq 'cookies url-privacy-level)))
- ;; user never wants cookies
- nil)
- ((and url-cookie-confirmation
- (not trusted)
- (save-window-excursion
- (with-output-to-temp-buffer "*Cookie Warning*"
- (mapcar
- (function
- (lambda (x)
- (princ (format "%s - %s" (car x) (cdr x))))) rest))
- (prog1
- (not (funcall url-confirmation-func
- (format "Allow %s to set these cookies? "
- (url-host url-current-object))))
- (if (get-buffer "*Cookie Warning*")
- (kill-buffer "*Cookie Warning*")))))
- ;; user wants to be asked, and declined.
- nil)
- ((url-cookie-host-can-set-p (url-host url-current-object) domain)
- ;; Cookie is accepted by the user, and passes our security checks
- (let ((cur nil))
- (while rest
- (setq cur (pop rest))
- (url-cookie-store (car cur) (cdr cur)
- expires domain path secure))))
- (t
- (message "%s tried to set a cookie for domain %s - rejected."
- (url-host url-current-object) domain)))))
-
-(defvar url-cookie-timer nil)
-
-(defcustom url-cookie-save-interval 3600
- "*The number of seconds between automatic saves of cookies.
-Default is 1 hour. Note that if you change this variable outside of
-the `customize' interface after `url-do-setup' has been run, you need
-to run the `url-cookie-setup-save-timer' function manually."
- :set (function (lambda (var val)
- (set-default var val)
- (and (featurep 'url)
- (fboundp 'url-cookie-setup-save-timer)
- (url-cookie-setup-save-timer))))
- :type 'integer
- :group 'url)
-
-;;;###autoload
-(defun url-cookie-setup-save-timer ()
- "Reset the cookie saver timer."
- (interactive)
- (cond
- ((featurep 'itimer)
- (ignore-errors (delete-itimer url-cookie-timer))
- (setq url-cookie-timer nil)
- (if url-cookie-save-interval
- (setq url-cookie-timer
- (start-itimer "url-cookie-saver" 'url-cookie-write-file
- url-cookie-save-interval
- url-cookie-save-interval))))
- ((fboundp 'run-at-time)
- (ignore-errors (cancel-timer url-cookie-timer))
- (setq url-cookie-timer nil)
- (if url-cookie-save-interval
- (setq url-cookie-timer
- (run-at-time url-cookie-save-interval
- url-cookie-save-interval
- 'url-cookie-write-file))))
- (t nil)))
-
-(provide 'url-cookie)
-
+++ /dev/null
-;;; url-dav.el --- WebDAV support
-
-;; Copyright (C) 2001 Free Software Foundation, Inc.
-
-;; Author: Bill Perry <wmperryNOSPAMgnu.org>
-;; Maintainer: Bill Perry <wmperryNOSPAMgnu.org>
-;; Version: $Revision: 1.6 $
-;; Keywords: url, vc
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-(eval-when-compile
- (require 'cl))
-
-(require 'xml)
-(require 'url-util)
-(require 'url-handlers)
-
-(defvar url-dav-supported-protocols '(1 2)
- "List of supported DAV versions.")
-
-;;;###autoload
-(defun url-dav-supported-p (url)
- (and (featurep 'xml)
- (fboundp 'xml-expand-namespace)
- (intersection url-dav-supported-protocols
- (plist-get (url-http-options url) 'dav))))
-
-(defun url-dav-node-text (node)
- "Return the text data from the XML node NODE."
- (mapconcat (lambda (txt)
- (if (stringp txt)
- txt
- "")) (xml-node-children node) " "))
-
-\f
-;;; Parsing routines for the actual node contents.
-;;;
-;;; I am not incredibly happy with how this code looks/works right
-;;; now, but it DOES work, and if we get the API right, our callers
-;;; won't have to worry about the internal representation.
-
-(defconst url-dav-datatype-attribute
- 'urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/dt)
-
-(defun url-dav-process-integer-property (node)
- (truncate (string-to-number (url-dav-node-text node))))
-
-(defun url-dav-process-number-property (node)
- (string-to-number (url-dav-node-text node)))
-
-(defconst url-dav-iso8601-regexp
- (let* ((dash "-?")
- (colon ":?")
- (4digit "\\([0-9][0-9][0-9][0-9]\\)")
- (2digit "\\([0-9][0-9]\\)")
- (date-fullyear 4digit)
- (date-month 2digit)
- (date-mday 2digit)
- (time-hour 2digit)
- (time-minute 2digit)
- (time-second 2digit)
- (time-secfrac "\\(\\.[0-9]+\\)?")
- (time-numoffset (concat "[-+]\\(" time-hour "\\):" time-minute))
- (time-offset (concat "Z" time-numoffset))
- (partial-time (concat time-hour colon time-minute colon time-second
- time-secfrac))
- (full-date (concat date-fullyear dash date-month dash date-mday))
- (full-time (concat partial-time time-offset))
- (date-time (concat full-date "T" full-time)))
- (list (concat "^" full-date)
- (concat "T" partial-time)
- (concat "Z" time-numoffset)))
- "List of regular expressions matching iso8601 dates.
-1st regular expression matches the date.
-2nd regular expression matches the time.
-3rd regular expression matches the (optional) timezone specification.
-")
-
-(defun url-dav-process-date-property (node)
- (require 'parse-time)
- (let* ((date-re (nth 0 url-dav-iso8601-regexp))
- (time-re (nth 1 url-dav-iso8601-regexp))
- (tz-re (nth 2 url-dav-iso8601-regexp))
- (date-string (url-dav-node-text node))
- re-start
- time seconds minute hour fractional-seconds
- day month year day-of-week dst tz)
- ;; We need to populate 'time' with
- ;; (SEC MIN HOUR DAY MON YEAR DOW DST TZ)
-
- ;; Nobody else handles iso8601 correctly, lets do it ourselves.
- (when (string-match date-re date-string re-start)
- (setq year (string-to-int (match-string 1 date-string))
- month (string-to-int (match-string 2 date-string))
- day (string-to-int (match-string 3 date-string))
- re-start (match-end 0))
- (when (string-match time-re date-string re-start)
- (setq hour (string-to-int (match-string 1 date-string))
- minute (string-to-int (match-string 2 date-string))
- seconds (string-to-int (match-string 3 date-string))
- fractional-seconds (string-to-int (or
- (match-string 4 date-string)
- "0"))
- re-start (match-end 0))
- (when (string-match tz-re date-string re-start)
- (setq tz (match-string 1 date-string)))
- (url-debug 'dav "Parsed iso8601%s date" (if tz "tz" ""))
- (setq time (list seconds minute hour day month year day-of-week dst tz))))
-
- ;; Fall back to having Gnus do fancy things for us.
- (when (not time)
- (setq time (parse-time-string date-string)))
-
- (if time
- (setq time (apply 'encode-time time))
- (url-debug 'dav "Unable to decode date (%S) (%s)"
- (xml-node-name node) date-string))
- time))
-
-(defun url-dav-process-boolean-property (node)
- (/= 0 (string-to-int (url-dav-node-text node))))
-
-(defun url-dav-process-uri-property (node)
- ;; Returns a parsed representation of the URL...
- (url-generic-parse-url (url-dav-node-text node)))
-
-(defun url-dav-find-parser (node)
- "Find a function to parse the XML node NODE."
- (or (get (xml-node-name node) 'dav-parser)
- (let ((fn (intern (format "url-dav-process-%s" (xml-node-name node)))))
- (if (not (fboundp fn))
- (setq fn 'url-dav-node-text)
- (put (xml-node-name node) 'dav-parser fn))
- fn)))
-
-(defmacro url-dav-dispatch-node (node)
- `(funcall (url-dav-find-parser ,node) ,node))
-
-(defun url-dav-process-DAV:prop (node)
- ;; A prop node has content model of ANY
- ;;
- ;; Some predefined nodes have special meanings though.
- ;;
- ;; DAV:supportedlock - list of DAV:lockentry
- ;; DAV:source
- ;; DAV:iscollection - boolean
- ;; DAV:getcontentlength - integer
- ;; DAV:ishidden - boolean
- ;; DAV:getcontenttype - string
- ;; DAV:resourcetype - node who's name is the resource type
- ;; DAV:getlastmodified - date
- ;; DAV:creationdate - date
- ;; DAV:displayname - string
- ;; DAV:getetag - unknown
- (let ((children (xml-node-children node))
- (node-type nil)
- (props nil)
- (value nil)
- (handler-func nil))
- (when (not children)
- (error "No child nodes in DAV:prop"))
-
- (while children
- (setq node (car children)
- node-type (intern
- (or
- (cdr-safe (assq url-dav-datatype-attribute
- (xml-node-attributes node)))
- "unknown"))
- value nil)
-
- (case node-type
- ((dateTime.iso8601tz
- dateTime.iso8601
- dateTime.tz
- dateTime.rfc1123
- dateTime
- date) ; date is our 'special' one...
- ;; Some type of date/time string.
- (setq value (url-dav-process-date-property node)))
- (int
- ;; Integer type...
- (setq value (url-dav-process-integer-property node)))
- ((number float)
- (setq value (url-dav-process-number-property node)))
- (boolean
- (setq value (url-dav-process-boolean-property node)))
- (uri
- (setq value (url-dav-process-uri-property node)))
- (otherwise
- (if (not (eq node-type 'unknown))
- (url-debug 'dav "Unknown data type in url-dav-process-prop: %s"
- node-type))
- (setq value (url-dav-dispatch-node node))))
-
- (setq props (plist-put props (xml-node-name node) value)
- children (cdr children)))
- props))
-
-(defun url-dav-process-DAV:supportedlock (node)
- ;; DAV:supportedlock is a list of DAV:lockentry items.
- ;; DAV:lockentry in turn contains a DAV:lockscope and DAV:locktype.
- ;; The DAV:lockscope must have a single node beneath it, ditto for
- ;; DAV:locktype.
- (let ((children (xml-node-children node))
- (results nil)
- scope type)
- (while children
- (when (and (not (stringp (car children)))
- (eq (xml-node-name (car children)) 'DAV:lockentry))
- (setq scope (assq 'DAV:lockscope (xml-node-children (car children)))
- type (assq 'DAV:locktype (xml-node-children (car children))))
- (when (and scope type)
- (setq scope (xml-node-name (car (xml-node-children scope)))
- type (xml-node-name (car (xml-node-children type))))
- (push (cons type scope) results)))
- (setq children (cdr children)))
- results))
-
-(defun url-dav-process-subnode-property (node)
- ;; Returns a list of child node names.
- (delq nil (mapcar 'car-safe (xml-node-children node))))
-
-(defalias 'url-dav-process-DAV:depth 'url-dav-process-integer-property)
-(defalias 'url-dav-process-DAV:resourcetype 'url-dav-process-subnode-property)
-(defalias 'url-dav-process-DAV:locktype 'url-dav-process-subnode-property)
-(defalias 'url-dav-process-DAV:lockscope 'url-dav-process-subnode-property)
-(defalias 'url-dav-process-DAV:getcontentlength 'url-dav-process-integer-property)
-(defalias 'url-dav-process-DAV:getlastmodified 'url-dav-process-date-property)
-(defalias 'url-dav-process-DAV:creationdate 'url-dav-process-date-property)
-(defalias 'url-dav-process-DAV:iscollection 'url-dav-process-boolean-property)
-(defalias 'url-dav-process-DAV:ishidden 'url-dav-process-boolean-property)
-
-(defun url-dav-process-DAV:locktoken (node)
- ;; DAV:locktoken can have one or more DAV:href children.
- (delq nil (mapcar (lambda (n)
- (if (stringp n)
- n
- (url-dav-dispatch-node n)))
- (xml-node-children node))))
-
-(defun url-dav-process-DAV:owner (node)
- ;; DAV:owner can contain anything.
- (delq nil (mapcar (lambda (n)
- (if (stringp n)
- n
- (url-dav-dispatch-node n)))
- (xml-node-children node))))
-
-(defun url-dav-process-DAV:activelock (node)
- ;; DAV:activelock can contain:
- ;; DAV:lockscope
- ;; DAV:locktype
- ;; DAV:depth
- ;; DAV:owner (optional)
- ;; DAV:timeout (optional)
- ;; DAV:locktoken (optional)
- (let ((children (xml-node-children node))
- (results nil))
- (while children
- (if (listp (car children))
- (push (cons (xml-node-name (car children))
- (url-dav-dispatch-node (car children)))
- results))
- (setq children (cdr children)))
- results))
-
-(defun url-dav-process-DAV:lockdiscovery (node)
- ;; Can only contain a list of DAV:activelock objects.
- (let ((children (xml-node-children node))
- (results nil))
- (while children
- (cond
- ((stringp (car children))
- ;; text node? why?
- nil)
- ((eq (xml-node-name (car children)) 'DAV:activelock)
- (push (url-dav-dispatch-node (car children)) results))
- (t
- ;; Ignore unknown nodes...
- nil))
- (setq children (cdr children)))
- results))
-
-(defun url-dav-process-DAV:status (node)
- ;; The node contains a standard HTTP/1.1 response line... we really
- ;; only care about the numeric status code.
- (let ((status (url-dav-node-text node)))
- (if (string-match "\\`[ \r\t\n]*HTTP/[0-9.]+ \\([0-9]+\\)" status)
- (string-to-int (match-string 1 status))
- 500)))
-
-(defun url-dav-process-DAV:propstat (node)
- ;; A propstate node can have the following children...
- ;;
- ;; DAV:prop - a list of properties and values
- ;; DAV:status - An HTTP/1.1 status line
- (let ((children (xml-node-children node))
- (props nil)
- (status nil))
- (when (not children)
- (error "No child nodes in DAV:propstat"))
-
- (setq props (url-dav-dispatch-node (assq 'DAV:prop children))
- status (url-dav-dispatch-node (assq 'DAV:status children)))
-
- ;; Need to parse out the HTTP status
- (setq props (plist-put props 'DAV:status status))
- props))
-
-(defun url-dav-process-DAV:response (node)
- (let ((children (xml-node-children node))
- (propstat nil)
- (href))
- (when (not children)
- (error "No child nodes in DAV:response"))
-
- ;; A response node can have the following children...
- ;;
- ;; DAV:href - URL the response is for.
- ;; DAV:propstat - see url-dav-process-propstat
- ;; DAV:responsedescription - text description of the response
- (setq propstat (assq 'DAV:propstat children)
- href (assq 'DAV:href children))
-
- (when (not href)
- (error "No href in DAV:response"))
-
- (when (not propstat)
- (error "No propstat in DAV:response"))
-
- (setq propstat (url-dav-dispatch-node propstat)
- href (url-dav-dispatch-node href))
- (cons href propstat)))
-
-(defun url-dav-process-DAV:multistatus (node)
- (let ((children (xml-node-children node))
- (results nil))
- (while children
- (push (url-dav-dispatch-node (car children)) results)
- (setq children (cdr children)))
- results))
-
-\f
-;;; DAV request/response generation/processing
-(defun url-dav-process-response (buffer url)
- "Parses a WebDAV response from BUFFER, interpreting it relative to URL.
-
-The buffer must have been retrieved by HTTP or HTTPS and contain an
-XML document.
-"
- (declare (special url-http-content-type
- url-http-response-status
- url-http-end-of-headers))
- (let ((tree nil)
- (overall-status nil))
- (when buffer
- (unwind-protect
- (save-excursion
- (set-buffer buffer)
- (goto-char url-http-end-of-headers)
- (setq overall-status url-http-response-status)
-
- ;; XML documents can be transferred as either text/xml or
- ;; application/xml, and we are required to accept both of
- ;; them.
- (if (and
- url-http-content-type
- (or (string-match "^text/xml" url-http-content-type)
- (string-match "^application/xml" url-http-content-type)))
- (setq tree (xml-parse-region (point) (point-max)))))
- ;; Clean up after ourselves.
- '(kill-buffer buffer)))
-
- ;; We should now be
- (if (eq (xml-node-name (car tree)) 'DAV:multistatus)
- (url-dav-dispatch-node (car tree))
- (url-debug 'dav "Got back singleton response for URL(%S)" url)
- (let ((properties (url-dav-dispatch-node (car tree))))
- ;; We need to make sure we have a DAV:status node in there for
- ;; higher-level code;
- (setq properties (plist-put properties 'DAV:status overall-status))
- ;; Make this look like a DAV:multistatus parse tree so that
- ;; nobody but us needs to know the difference.
- (list (cons url properties))))))
-
-(defun url-dav-request (url method tag body
- &optional depth headers namespaces)
- "Performs WebDAV operation METHOD on URL. Returns the parsed responses.
-Automatically creates an XML request body if TAG is non-nil.
-BODY is the XML document fragment to be enclosed by <TAG></TAG>.
-
-DEPTH is how deep the request should propogate. Default is 0, meaning
-it should apply only to URL. A negative number means to use
-`Infinity' for the depth. Not all WebDAV servers support this depth
-though.
-
-HEADERS is an assoc list of extra headers to send in the request.
-
-NAMESPACES is an assoc list of (NAMESPACE . EXPANSION), and these are
-added to the <TAG> element. The DAV=DAV: namespace is automatically
-added to this list, so most requests can just pass in nil.
-"
- ;; Take care of the default value for depth...
- (setq depth (or depth 0))
-
- ;; Now lets translate it into something webdav can understand.
- (if (< depth 0)
- (setq depth "Infinity")
- (setq depth (int-to-string depth)))
- (if (not (assoc "DAV" namespaces))
- (setq namespaces (cons '("DAV" . "DAV:") namespaces)))
-
- (let* ((url-request-extra-headers `(("Depth" . ,depth)
- ("Content-type" . "text/xml")
- ,@headers))
- (url-request-method method)
- (url-request-data
- (if tag
- (concat
- "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
- "<" (symbol-name tag) " "
- ;; add in the appropriate namespaces...
- (mapconcat (lambda (ns)
- (concat "xmlns:" (car ns) "='" (cdr ns) "'"))
- namespaces "\n ")
- ">\n"
- body
- "</" (symbol-name tag) ">\n"))))
- (url-dav-process-response (url-retrieve-synchronously url) url)))
-
-;;;###autoload
-(defun url-dav-get-properties (url &optional attributes depth namespaces)
- "Return properties for URL, up to DEPTH levels deep.
-
-Returns an assoc list, where the key is the filename (possibly a full
-URI), and the value is a standard property list of DAV property
-names (ie: DAV:resourcetype).
-"
- (url-dav-request url "PROPFIND" 'DAV:propfind
- (if attributes
- (mapconcat (lambda (attr)
- (concat "<DAV:prop><"
- (symbol-name attr)
- "/></DAV:prop>"))
- attributes "\n ")
- " <DAV:allprop/>")
- depth nil namespaces))
-
-(defmacro url-dav-http-success-p (status)
- "Return whether PROPERTIES was the result of a successful DAV request."
- `(= (/ (or ,status 500) 100) 2))
-
-\f
-;;; Locking support
-(defvar url-dav-lock-identifier (concat "mailto:" user-mail-address)
- "*URL used as contact information when creating locks in DAV.
-This will be used as the contents of the DAV:owner/DAV:href tag to
-identify the owner of a LOCK when requesting it. This will be shown
-to other users when the DAV:lockdiscovery property is requested, so
-make sure you are comfortable with it leaking to the outside world.
-")
-
-;;;###autoload
-(defun url-dav-lock-resource (url exclusive &optional depth)
- "Request a lock on URL. If EXCLUSIVE is non-nil, get an exclusive lock.
-Optional 3rd argument DEPTH says how deep the lock should go, default is 0
-\(lock only the resource and none of its children\).
-
-Returns a cons-cell of (SUCCESSFUL-RESULTS . FAILURE-RESULTS).
-SUCCESSFUL-RESULTS is a list of (URL STATUS locktoken).
-FAILURE-RESULTS is a list of (URL STATUS).
-"
- (setq exclusive (if exclusive "<DAV:exclusive/>" "<DAV:shared/>"))
- (let* ((body
- (concat
- " <DAV:lockscope>" exclusive "</DAV:lockscope>\n"
- " <DAV:locktype> <DAV:write/> </DAV:locktype>\n"
- " <DAV:owner>\n"
- " <DAV:href>" url-dav-lock-identifier "</DAV:href>\n"
- " </DAV:owner>\n"))
- (response nil) ; Responses to the LOCK request
- (result nil) ; For walking thru the response list
- (child-url nil)
- (child-status nil)
- (failures nil) ; List of failure cases (URL . STATUS)
- (successes nil)) ; List of success cases (URL . STATUS)
- (setq response (url-dav-request url "LOCK" 'DAV:lockinfo body
- depth '(("Timeout" . "Infinite"))))
-
- ;; Get the parent URL ready for expand-file-name
- (if (not (vectorp url))
- (setq url (url-generic-parse-url url)))
-
- ;; Walk thru the response list, fully expand the URL, and grab the
- ;; status code.
- (while response
- (setq result (pop response)
- child-url (url-expand-file-name (pop result) url)
- child-status (or (plist-get result 'DAV:status) 500))
- (if (url-dav-http-success-p child-status)
- (push (list url child-status "huh") successes)
- (push (list url child-status) failures)))
- (cons successes failures)))
-
-;;;###autoload
-(defun url-dav-active-locks (url &optional depth)
- "Return an assoc list of all active locks on URL."
- (let ((response (url-dav-get-properties url '(DAV:lockdiscovery) depth))
- (properties nil)
- (child nil)
- (child-url nil)
- (child-results nil)
- (results nil))
- (if (not (vectorp url))
- (setq url (url-generic-parse-url url)))
-
- (while response
- (setq child (pop response)
- child-url (pop child)
- child-results nil)
- (when (and (url-dav-http-success-p (plist-get child 'DAV:status))
- (setq child (plist-get child 'DAV:lockdiscovery)))
- ;; After our parser has had its way with it, The
- ;; DAV:lockdiscovery property is a list of DAV:activelock
- ;; objects, which are comprised of DAV:activelocks, which
- ;; assoc lists of properties and values.
- (while child
- (if (assq 'DAV:locktoken (car child))
- (let ((tokens (cdr (assq 'DAV:locktoken (car child))))
- (owners (cdr (assq 'DAV:owner (car child)))))
- (dolist (token tokens)
- (dolist (owner owners)
- (push (cons token owner) child-results)))))
- (pop child)))
- (if child-results
- (push (cons (url-expand-file-name child-url url) child-results)
- results)))
- results))
-
-;;;###autoload
-(defun url-dav-unlock-resource (url lock-token)
- "Release the lock on URL represented by LOCK-TOKEN.
-Returns `t' iff the lock was successfully released.
-"
- (declare (special url-http-response-status))
- (let* ((url-request-extra-headers (list (cons "Lock-Token"
- (concat "<" lock-token ">"))))
- (url-request-method "UNLOCK")
- (url-request-data nil)
- (buffer (url-retrieve-synchronously url))
- (result nil))
- (when buffer
- (unwind-protect
- (save-excursion
- (set-buffer buffer)
- (setq result (url-dav-http-success-p url-http-response-status)))
- (kill-buffer buffer)))
- result))
-
-\f
-;;; file-name-handler stuff
-(defun url-dav-file-attributes-mode-string (properties)
- (let ((modes (make-string 10 ?-))
- (supported-locks (plist-get properties 'DAV:supportedlock))
- (executable-p (equal (plist-get properties 'http://apache.org/dav/props/executable)
- "T"))
- (directory-p (memq 'DAV:collection (plist-get properties 'DAV:resourcetype)))
- (readable t)
- (lock nil))
- ;; Assume we can read this, otherwise the PROPFIND would have
- ;; failed.
- (when readable
- (aset modes 1 ?r)
- (aset modes 4 ?r)
- (aset modes 7 ?r))
-
- (when directory-p
- (aset modes 0 ?d))
-
- (when executable-p
- (aset modes 3 ?x)
- (aset modes 6 ?x)
- (aset modes 9 ?x))
-
- (while supported-locks
- (setq lock (car supported-locks)
- supported-locks (cdr supported-locks))
- (case (car lock)
- (DAV:write
- (case (cdr lock)
- (DAV:shared ; group permissions (possibly world)
- (aset modes 5 ?w))
- (DAV:exclusive
- (aset modes 2 ?w)) ; owner permissions?
- (otherwise
- (url-debug 'dav "Unrecognized DAV:lockscope (%S)" (cdr lock)))))
- (otherwise
- (url-debug 'dav "Unrecognized DAV:locktype (%S)" (car lock)))))
- modes))
-
-;;;###autoload
-(defun url-dav-file-attributes (url)
- (let ((properties (cdar (url-dav-get-properties url)))
- (attributes nil))
- (if (and properties
- (url-dav-http-success-p (plist-get properties 'DAV:status)))
- ;; We got a good DAV response back..
- (setq attributes
- (list
- ;; t for directory, string for symbolic link, or nil
- ;; Need to support DAV Bindings to figure out the
- ;; symbolic link issues.
- (if (memq 'DAV:collection (plist-get properties 'DAV:resourcetype)) t nil)
-
- ;; Number of links to file... Needs DAV Bindings.
- 1
-
- ;; File uid - no way to figure out?
- 0
-
- ;; File gid - no way to figure out?
- 0
-
- ;; Last access time - ???
- nil
-
- ;; Last modification time
- (plist-get properties 'DAV:getlastmodified)
-
- ;; Last status change time... just reuse last-modified
- ;; for now.
- (plist-get properties 'DAV:getlastmodified)
-
- ;; size in bytes
- (or (plist-get properties 'DAV:getcontentlength) 0)
-
- ;; file modes as a string like `ls -l'
- ;;
- ;; Should be able to build this up from the
- ;; DAV:supportedlock attribute pretty easily. Getting
- ;; the group info could be impossible though.
- (url-dav-file-attributes-mode-string properties)
-
- ;; t iff file's gid would change if it were deleted &
- ;; recreated. No way for us to know that thru DAV.
- nil
-
- ;; inode number - meaningless
- nil
-
- ;; device number - meaningless
- nil))
- ;; Fall back to just the normal http way of doing things.
- (setq attributes (url-http-head-file-attributes url)))
- attributes))
-
-;;;###autoload
-(defun url-dav-save-resource (url obj &optional content-type lock-token)
- "Save OBJ as URL using WebDAV.
-URL must be a fully qualified URL.
-OBJ may be a buffer or a string."
- (let ((buffer nil)
- (result nil)
- (url-request-extra-headers nil)
- (url-request-method "PUT")
- (url-request-data
- (cond
- ((bufferp obj)
- (save-excursion
- (set-buffer obj)
- (buffer-string)))
- ((stringp obj)
- obj)
- (t
- (error "Invalid object to url-dav-save-resource")))))
-
- (if lock-token
- (push
- (cons "If" (concat "(<" lock-token ">)"))
- url-request-extra-headers))
-
- ;; Everything must always have a content-type when we submit it.
- (push
- (cons "Content-type" (or content-type "application/octet-stream"))
- url-request-extra-headers)
-
- ;; Do the save...
- (setq buffer (url-retrieve-synchronously url))
-
- ;; Sanity checking
- (when buffer
- (unwind-protect
- (save-excursion
- (set-buffer buffer)
- (setq result (url-dav-http-success-p url-http-response-status)))
- (kill-buffer buffer)))
- result))
-
-(eval-when-compile
- (defmacro url-dav-delete-something (url lock-token &rest error-checking)
- "Delete URL completely, with no sanity checking whatsoever. DO NOT USE.
-This is defined as a macro that will not be visible from compiled files.
-Use with care, and even then think three times.
-"
- `(progn
- ,@error-checking
- (url-dav-request ,url "DELETE" nil nil -1
- (if ,lock-token
- (list
- (cons "If"
- (concat "(<" ,lock-token ">)"))))))))
-
-
-;;;###autoload
-(defun url-dav-delete-directory (url &optional recursive lock-token)
- "Delete the WebDAV collection URL.
-If optional second argument RECURSIVE is non-nil, then delete all
-files in the collection as well.
-"
- (let ((status nil)
- (props nil)
- (props nil))
- (setq props (url-dav-delete-something
- url lock-token
- (setq props (url-dav-get-properties url '(DAV:getcontenttype) 1))
- (if (and (not recursive)
- (/= (length props) 1))
- (signal 'file-error (list "Removing directory"
- "directory not empty" url)))))
-
- (mapc (lambda (result)
- (setq status (plist-get (cdr result) 'DAV:status))
- (if (not (url-dav-http-success-p status))
- (signal 'file-error (list "Removing directory"
- "Errror removing"
- (car result) status))))
- props))
- nil)
-
-;;;###autoload
-(defun url-dav-delete-file (url &optional lock-token)
- "Delete file named URL."
- (let ((props nil)
- (status nil))
- (setq props (url-dav-delete-something
- url lock-token
- (setq props (url-dav-get-properties url))
- (if (eq (plist-get (cdar props) 'DAV:resourcetype) 'DAV:collection)
- (signal 'file-error (list "Removing old name" "is a collection" url)))))
-
- (mapc (lambda (result)
- (setq status (plist-get (cdr result) 'DAV:status))
- (if (not (url-dav-http-success-p status))
- (signal 'file-error (list "Removing old name"
- "Errror removing"
- (car result) status))))
- props))
- nil)
-
-;;;###autoload
-(defun url-dav-directory-files (url &optional full match nosort files-only)
- "Return a list of names of files in DIRECTORY.
-There are three optional arguments:
-If FULL is non-nil, return absolute file names. Otherwise return names
- that are relative to the specified directory.
-If MATCH is non-nil, mention only file names that match the regexp MATCH.
-If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
- NOSORT is useful if you plan to sort the result yourself.
-"
- (let ((properties (url-dav-get-properties url '(DAV:resourcetype) 1))
- (child-url nil)
- (child-props nil)
- (files nil)
- (parsed-url (url-generic-parse-url url)))
-
- (if (= (length properties) 1)
- (signal 'file-error (list "Opening directory" "not a directory" url)))
-
- (while properties
- (setq child-props (pop properties)
- child-url (pop child-props))
- (if (and (eq (plist-get child-props 'DAV:resourcetype) 'DAV:collection)
- files-only)
- ;; It is a directory, and we were told to return just files.
- nil
-
- ;; Fully expand the URL and then rip off the beginning if we
- ;; are not supposed to return fully-qualified names.
- (setq child-url (url-expand-file-name child-url parsed-url))
- (if (not full)
- (setq child-url (substring child-url (length url))))
-
- ;; We don't want '/' as the last character in filenames...
- (if (string-match "/$" child-url)
- (setq child-url (substring child-url 0 -1)))
-
- ;; If we have a match criteria, then apply it.
- (if (or (and match (not (string-match match child-url)))
- (string= child-url "")
- (string= child-url url))
- nil
- (push child-url files))))
-
- (if nosort
- files
- (sort files 'string-lessp))))
-
-;;;###autoload
-(defun url-dav-file-directory-p (url)
- "Return t if URL names an existing DAV collection."
- (let ((properties (cdar (url-dav-get-properties url '(DAV:resourcetype)))))
- (eq (plist-get properties 'DAV:resourcetype) 'DAV:collection)))
-
-;;;###autoload
-(defun url-dav-make-directory (url &optional parents)
- "Create the directory DIR and any nonexistent parent dirs."
- (declare (special url-http-response-status))
- (let* ((url-request-extra-headers nil)
- (url-request-method "MKCOL")
- (url-request-data nil)
- (buffer (url-retrieve-synchronously url))
- (result nil))
- (when buffer
- (unwind-protect
- (save-excursion
- (set-buffer buffer)
- (case url-http-response-status
- (201 ; Collection created in its entirety
- (setq result t))
- (403 ; Forbidden
- nil)
- (405 ; Method not allowed
- nil)
- (409 ; Conflict
- nil)
- (415 ; Unsupported media type (WTF?)
- nil)
- (507 ; Insufficient storage
- nil)
- (otherwise
- nil)))
- (kill-buffer buffer)))
- result))
-
-;;;###autoload
-(defun url-dav-rename-file (oldname newname &optional overwrite)
- (if (not (and (string-match url-handler-regexp oldname)
- (string-match url-handler-regexp newname)))
- (signal 'file-error "Cannot rename between different URL backends" oldname newname))
-
- (let* ((headers nil)
- (props nil)
- (status nil)
- (directory-p (url-dav-file-directory-p oldname))
- (exists-p (url-http-file-exists-p newname)))
-
- (if (and exists-p
- (or
- (null overwrite)
- (and (numberp overwrite)
- (not (yes-or-no-p
- (format "File %s already exists; rename to it anyway? "
- newname))))))
- (signal 'file-already-exists (list "File already exists" newname)))
-
- ;; Honor the overwrite flag...
- (if overwrite (push '("Overwrite" . "T") headers))
-
- ;; Have to tell them where to copy it to!
- (push (cons "Destination" newname) headers)
-
- ;; Always send a depth of -1 in case we are moving a collection.
- (setq props (url-dav-request oldname "MOVE" nil nil (if directory-p -1 0)
- headers))
-
- (mapc (lambda (result)
- (setq status (plist-get (cdr result) 'DAV:status))
-
- (if (not (url-dav-http-success-p status))
- (signal 'file-error (list "Renaming" oldname newname status))))
- props)
- t))
-
-;;;###autoload
-(defun url-dav-file-name-all-completions (file url)
- "Return a list of all completions of file name FILE in directory DIRECTORY.
-These are all file names in directory DIRECTORY which begin with FILE.
-"
- (url-dav-directory-files url nil (concat "^" file ".*")))
-
-;;;###autoload
-(defun url-dav-file-name-completion (file url)
- "Complete file name FILE in directory DIRECTORY.
-Returns the longest string
-common to all file names in DIRECTORY that start with FILE.
-If there is only one and FILE matches it exactly, returns t.
-Returns nil if DIR contains no name starting with FILE.
-"
- (let ((matches (url-dav-file-name-all-completions file url))
- (result nil))
- (cond
- ((null matches)
- ;; No matches
- nil)
- ((and (= (length matches) 1)
- (string= file (car matches)))
- ;; Only one file and FILE matches it exactly...
- t)
- (t
- ;; Need to figure out the longest string that they have in commmon
- (setq matches (sort matches (lambda (a b) (> (length a) (length b)))))
- (let ((n (length file))
- (searching t)
- (regexp nil)
- (failed nil))
- (while (and searching
- (< n (length (car matches))))
- (setq regexp (concat "^" (substring (car matches) 0 (1+ n)))
- failed nil)
- (dolist (potential matches)
- (if (not (string-match regexp potential))
- (setq failed t)))
- (if failed
- (setq searching nil)
- (incf n)))
- (substring (car matches) 0 n))))))
-
-(defun url-dav-register-handler (op)
- (put op 'url-file-handlers (intern-soft (format "url-dav-%s" op))))
-
-(mapcar 'url-dav-register-handler
- '(file-name-all-completions
- file-name-completion
- rename-file
- make-directory
- file-directory-p
- directory-files
- delete-file
- delete-directory
- file-attributes))
-
-\f
-;;; Version Control backend cruft
-
-;(put 'vc-registered 'url-file-handlers 'url-dav-vc-registered)
-
-;;;###autoload
-(defun url-dav-vc-registered (url)
- (if (and (string-match "\\`https?" url)
- (plist-get (url-http-options url) 'dav))
- (progn
- (vc-file-setprop url 'vc-backend 'dav)
- t)))
-
-\f
-;;; Miscellaneous stuff.
-
-(provide 'url-dav)
+++ /dev/null
-;;; url-dired.el --- URL Dired minor mode
-;; Author: $Author: fx $
-;; Created: $Date: 2001/05/05 16:44:20 $
-;; Version: $Revision: 1.3 $
-;; Keywords: comm, files
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(autoload 'w3-fetch "w3")
-(autoload 'w3-open-local "w3")
-(autoload 'dired-get-filename "dired")
-
-(defvar url-dired-minor-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-m" 'url-dired-find-file)
- (if (featurep 'xemacs)
- (define-key map [button2] 'url-dired-find-file-mouse)
- (define-key map [mouse-2] 'url-dired-find-file-mouse))
- map)
- "Keymap used when browsing directories.")
-
-(defvar url-dired-minor-mode nil
- "Whether we are in url-dired-minor-mode")
-
-(make-variable-buffer-local 'url-dired-minor-mode)
-
-(defun url-dired-find-file ()
- "In dired, visit the file or directory named on this line, using Emacs-W3."
- (interactive)
- (let ((filename (dired-get-filename)))
- (cond ((string-match "/\\(.*@.*\\):\\(/.*\\)" filename)
- (w3-fetch (concat "file://" (match-string 1 filename) (match-string 2 filename))))
- (t
- (w3-open-local filename)))))
-
-(defun url-dired-find-file-mouse (event)
- "In dired, visit the file or directory name you click on, using Emacs-W3."
- (interactive "@e")
- (mouse-set-point event)
- (url-dired-find-file))
-
-(defun url-dired-minor-mode (&optional arg)
- "Minor mode for directory browsing with Emacs-W3."
- (interactive "P")
- (cond
- ((null arg)
- (setq url-dired-minor-mode (not url-dired-minor-mode)))
- ((equal 0 arg)
- (setq url-dired-minor-mode nil))
- (t
- (setq url-dired-minor-mode t))))
-
-(if (not (fboundp 'add-minor-mode))
- (defun add-minor-mode (toggle name &optional keymap after toggle-fun)
- "Add a minor mode to `minor-mode-alist' and `minor-mode-map-alist'.
-TOGGLE is a symbol which is used as the variable which toggle the minor mode,
-NAME is the name that should appear in the modeline (it should be a string
-beginning with a space), KEYMAP is a keymap to make active when the minor
-mode is active, and AFTER is the toggling symbol used for another minor
-mode. If AFTER is non-nil, then it is used to position the new mode in the
-minor-mode alists. TOGGLE-FUN specifies an interactive function that
-is called to toggle the mode on and off; this affects what appens when
-button2 is pressed on the mode, and when button3 is pressed somewhere
-in the list of modes. If TOGGLE-FUN is nil and TOGGLE names an
-interactive function, TOGGLE is used as the toggle function.
-
-Example: (add-minor-mode 'view-minor-mode \" View\" view-mode-map)"
- (if (not (assq toggle minor-mode-alist))
- (setq minor-mode-alist (cons (list toggle name) minor-mode-alist)))
- (if (and keymap (not (assq toggle minor-mode-map-alist)))
- (setq minor-mode-map-alist (cons (cons toggle keymap)
- minor-mode-map-alist)))))
-
-(add-minor-mode 'url-dired-minor-mode " URL" url-dired-minor-mode-map)
-
-(defun url-find-file-dired (dir)
- "\"Edit\" directory DIR, but with additional URL-friendly bindings."
- (interactive "DURL Dired (directory): ")
- (find-file dir)
- (url-dired-minor-mode t))
-
-(provide 'url-dired)
+++ /dev/null
-;;; url-expand.el --- expand-file-name for URLs
-;; Author: $Author: wmperry $
-;; Created: $Date: 1999/12/05 08:09:15 $
-;; Version: $Revision: 1.3 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url-methods)
-(require 'url-util)
-(require 'url-parse)
-
-(defun url-expander-remove-relative-links (name)
- ;; Strip . and .. from pathnames
- (let ((new (if (not (string-match "^/" name))
- (concat "/" name)
- name)))
-
- ;; If it ends with a '/.' or '/..', tack on a trailing '/' sot hat
- ;; the tests that follow are not too complicated in terms of
- ;; looking for '..' or '../', etc.
- (if (string-match "/\\.+$" new)
- (setq new (concat new "/")))
-
- ;; Remove '/./' first
- (while (string-match "/\\(\\./\\)" new)
- (setq new (concat (substring new 0 (match-beginning 1))
- (substring new (match-end 1)))))
-
- ;; Then remove '/../'
- (while (string-match "/\\([^/]*/\\.\\./\\)" new)
- (setq new (concat (substring new 0 (match-beginning 1))
- (substring new (match-end 1)))))
-
- ;; Remove cruft at the beginning of the string, so people that put
- ;; in extraneous '..' because they are morons won't lose.
- (while (string-match "^/\\.\\.\\(/\\)" new)
- (setq new (substring new (match-beginning 1) nil)))
- new))
-
-(defun url-expand-file-name (url &optional default)
- "Convert URL to a fully specified URL, and canonicalize it.
-Second arg DEFAULT is a URL to start with if URL is relative.
-If DEFAULT is nil or missing, the current buffer's URL is used.
-Path components that are `.' are removed, and
-path components followed by `..' are removed, along with the `..' itself."
- (if (and url (not (string-match "^#" url)))
- ;; Need to nuke newlines and spaces in the URL, or we open
- ;; ourselves up to potential security holes.
- (setq url (mapconcat (function (lambda (x)
- (if (memq x '(? ?\n ?\r))
- ""
- (char-to-string x))))
- url "")))
-
- ;; Need to figure out how/where to expand the fragment relative to
- (setq default (cond
- ((vectorp default)
- ;; Default URL has already been parsed
- default)
- (default
- ;; They gave us a default URL in non-parsed format
- (url-generic-parse-url default))
- (url-current-object
- ;; We are in a URL-based buffer, use the pre-parsed object
- url-current-object)
- ((string-match url-nonrelative-link url)
- ;; The URL they gave us is absolute, go for it.
- nil)
- (t
- ;; Hmmm - this shouldn't ever happen.
- (error "url-expand-file-name confused - no default?"))))
-
- (cond
- ((= (length url) 0) ; nil or empty string
- (url-recreate-url default))
- ((string-match "^#" url) ; Offset link, use it raw
- url)
- ((string-match url-nonrelative-link url) ; Fully-qualified URL, return it immediately
- url)
- (t
- (let* ((urlobj (url-generic-parse-url url))
- (inhibit-file-name-handlers t)
- (expander (url-scheme-get-property (url-type default) 'expand-file-name)))
- (if (string-match "^//" url)
- (setq urlobj (url-generic-parse-url (concat (url-type default) ":"
- url))))
- (funcall expander urlobj default)
- (url-recreate-url urlobj)))))
-
-(defun url-identity-expander (urlobj defobj)
- (url-set-type urlobj (or (url-type urlobj) (url-type defobj))))
-
-(defun url-default-expander (urlobj defobj)
- ;; The default expansion routine - urlobj is modified by side effect!
- (if (url-type urlobj)
- ;; Well, they told us the scheme, let's just go with it.
- nil
- (url-set-type urlobj (or (url-type urlobj) (url-type defobj)))
- (url-set-port urlobj (or (url-port urlobj)
- (and (string= (url-type urlobj)
- (url-type defobj))
- (url-port defobj))))
- (if (not (string= "file" (url-type urlobj)))
- (url-set-host urlobj (or (url-host urlobj) (url-host defobj))))
- (if (string= "ftp" (url-type urlobj))
- (url-set-user urlobj (or (url-user urlobj) (url-user defobj))))
- (if (string= (url-filename urlobj) "")
- (url-set-filename urlobj "/"))
- (if (string-match "^/" (url-filename urlobj))
- nil
- (let ((query nil)
- (file nil)
- (sepchar nil))
- (if (string-match "[?#]" (url-filename urlobj))
- (setq query (substring (url-filename urlobj) (match-end 0))
- file (substring (url-filename urlobj) 0 (match-beginning 0))
- sepchar (substring (url-filename urlobj) (match-beginning 0) (match-end 0)))
- (setq file (url-filename urlobj)))
- (setq file (url-expander-remove-relative-links
- (concat (url-basepath (url-filename defobj)) file)))
- (url-set-filename urlobj (if query (concat file sepchar query) file))))))
-
-(provide 'url-expand)
+++ /dev/null
-;;; url-file.el --- File retrieval code
-;; Author: $Author: fx $
-;; Created: $Date: 2002/04/22 09:14:24 $
-;; Version: $Revision: 1.11 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(eval-when-compile (require 'cl))
-(require 'mailcap)
-(require 'url-vars)
-(require 'url-parse)
-(require 'url-dired)
-
-(defconst url-file-default-port 21 "Default FTP port.")
-(defconst url-file-asynchronous-p t "FTP transfers are asynchronous.")
-(defalias 'url-file-expand-file-name 'url-default-expander)
-
-(defun url-file-find-possibly-compressed-file (fname &rest args)
- "Find the exact file referenced by `fname'.
-This tries the common compression extensions, because things like
-ange-ftp and efs are not quite smart enough to realize when a server
-can do automatic decompression for them, and won't find 'foo' if
-'foo.gz' exists, even though the ftp server would happily serve it up
-to them."
- (let ((scratch nil)
- (compressed-extensions '("" ".gz" ".z" ".Z" ".bz2"))
- (found nil))
- (while (and compressed-extensions (not found))
- (if (file-exists-p (setq scratch (concat fname (pop compressed-extensions))))
- (setq found scratch)))
- found))
-
-(defun url-file-host-is-local-p (host)
- "Return t iff HOST references our local machine."
- (let ((case-fold-search t))
- (or
- (null host)
- (string= "" host)
- (equal (downcase host) (downcase (system-name)))
- (and (string-match "^localhost$" host) t)
- (and (not (string-match (regexp-quote ".") host))
- (equal (downcase host) (if (string-match (regexp-quote ".")
- (system-name))
- (substring (system-name) 0
- (match-beginning 0))
- (system-name)))))))
-
-(defun url-file-asynch-callback (x y name buff func args &optional efs)
- (if (not (featurep 'ange-ftp))
- ;; EFS passes us an extra argument
- (setq name buff
- buff func
- func args
- args efs))
- (let ((size (nth 7 (file-attributes name))))
- (save-excursion
- (set-buffer buff)
- (goto-char (point-max))
- (if (/= -1 size)
- (insert (format "Content-length: %d\n" size)))
- (insert "\n")
- (insert-file-contents-literally name)
- (if (not (url-file-host-is-local-p (url-host url-current-object)))
- (condition-case ()
- (delete-file name)
- (error nil)))
- (apply func args))))
-
-(defun url-file-build-filename (url)
- (if (not (vectorp url))
- (setq url (url-generic-parse-url url)))
- (let* ((user (url-user url))
- (pass (url-password url))
- (port (url-port url))
- (host (url-host url))
- (site (if (and port (/= port 21))
- (if (featurep 'ange-ftp)
- (format "%s %d" host port)
- ;; This works in Emacs 21's ange-ftp too.
- (format "%s#%d" host port))
- host))
- (file (url-unhex-string (url-filename url)))
- (filename (if (or user (not (url-file-host-is-local-p host)))
- (concat "/" (or user "anonymous") "@" site ":" file)
- (if (and (memq system-type
- '(emx ms-dos windows-nt ms-windows))
- (string-match "^/[a-zA-Z]:/" file))
- (substring file 1)
- file)))
- pos-index)
-
- (and user pass
- (cond
- ((featurep 'ange-ftp)
- (ange-ftp-set-passwd host user pass))
- ((or (featurep 'efs) (featurep 'efs-auto))
- (efs-set-passwd host user pass))
- (t
- nil)))
-
- ;; This makes sure that directories have a trailing directory
- ;; separator on them so URL expansion works right.
- ;;
- ;; FIXME? What happens if the remote system doesn't use our local
- ;; directory-sep-char as its separator? Would it be safer to just
- ;; use '/' unconditionally and rely on the FTP server to
- ;; straighten it out for us?
- (if (and (file-directory-p filename)
- (not (string-match (format "%c$" directory-sep-char) filename)))
- (url-set-filename url
- (format "%s%c" filename directory-sep-char)))
-
- ;; If it is a directory, look for an index file first.
- (if (and (file-directory-p filename)
- url-directory-index-file
- (setq pos-index (expand-file-name url-directory-index-file filename))
- (file-exists-p pos-index)
- (file-readable-p pos-index))
- (setq filename pos-index))
-
- ;; Find the (possibly compressed) file
- (setq filename (url-file-find-possibly-compressed-file filename))
- filename))
-
-;;;###autoload
-(defun url-file (url callback cbargs)
- "Handle file: and ftp: URLs."
- (let* ((buffer nil)
- (uncompressed-filename nil)
- (content-type nil)
- (content-encoding nil)
- (coding-system-for-read 'binary))
-
- (setq filename (url-file-build-filename url))
-
- (if (not filename)
- (error "File does not exist: %s" (url-recreate-url url)))
-
- ;; Need to figure out the content-type from the real extension,
- ;; not the compressed one.
- (setq uncompressed-filename (if (string-match "\\.\\(gz\\|Z\\|z\\)$" filename)
- (substring filename 0 (match-beginning 0))
- filename))
- (setq content-type (mailcap-extension-to-mime
- (url-file-extension uncompressed-filename))
- content-encoding (case (intern (url-file-extension filename))
- ((\.z \.gz) "gzip")
- (\.Z "compress")
- (\.uue "x-uuencoded")
- (\.hqx "x-hqx")
- (\.bz2 "x-bzip2")
- (otherwise nil)))
-
- (if (file-directory-p filename)
- ;; A directory is done the same whether we are local or remote
- (url-find-file-dired filename)
- (save-excursion
- (setq buffer (generate-new-buffer " *url-file*"))
- (set-buffer buffer)
- (mm-disable-multibyte)
- (setq url-current-object url)
- (insert "Content-type: " (or content-type "application/octet-stream") "\n")
- (if content-encoding
- (insert "Content-transfer-encoding: " content-encoding "\n"))
- (if (url-file-host-is-local-p (url-host url))
- ;; Local files are handled slightly oddly
- (if (featurep 'ange-ftp)
- (url-file-asynch-callback nil nil
- filename
- (current-buffer)
- callback cbargs)
- (url-file-asynch-callback nil nil nil
- filename
- (current-buffer)
- callback cbargs))
- ;; FTP handling
- (let* ((extension (url-file-extension filename))
- (new (url-generate-unique-filename
- (and (> (length extension) 0)
- (concat "%s." extension)))))
- (if (featurep 'ange-ftp)
- (ange-ftp-copy-file-internal filename (expand-file-name new) t
- nil t
- (list 'url-file-asynch-callback
- new (current-buffer)
- callback cbargs)
- t)
- (autoload 'efs-copy-file-internal "efs")
- (efs-copy-file-internal filename (efs-ftp-path filename)
- new (efs-ftp-path new)
- t nil 0
- (list 'url-file-asynch-callback
- new (current-buffer)
- callback cbargs)
- 0 nil))))))
- buffer))
-
-(defmacro url-file-create-wrapper (method args)
- (` (defalias (quote (, (intern (format "url-ftp-%s" method))))
- (defun (, (intern (format "url-file-%s" method))) (, args)
- (, (format "FTP/FILE URL wrapper around `%s' call." method))
- (setq url (url-file-build-filename url))
- (and url ((, method) (,@ (remove '&rest (remove '&optional args)))))))))
-
-(url-file-create-wrapper file-exists-p (url))
-(url-file-create-wrapper file-attributes (url))
-(url-file-create-wrapper file-symlink-p (url))
-(url-file-create-wrapper file-readable-p (url))
-(url-file-create-wrapper file-writable-p (url))
-(url-file-create-wrapper file-executable-p (url))
-(if (featurep 'xemacs)
- (progn
- (url-file-create-wrapper directory-files (url &optional full match nosort files-only))
- (url-file-create-wrapper file-truename (url &optional default)))
- (url-file-create-wrapper directory-files (url &optional full match nosort))
- (url-file-create-wrapper file-truename (url &optional counter prev-dirs)))
-
-(provide 'url-file)
+++ /dev/null
-;;; url-ftp.el --- FTP wrapper
-;; Author: $Author: wmperry $
-;; Created: $Date: 1999/11/30 12:47:21 $
-;; Version: $Revision: 1.1 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; We knew not what we did when we overloaded 'file' to mean 'file'
-;; and 'ftp' back in the dark ages of the web.
-;;
-;; This stub file is just here to please the auto-scheme-loading code
-;; in url-methods.el and just maps everything onto the code in
-;; url-file.
-
-(require 'url-parse)
-(require 'url-file)
-
-(defconst url-ftp-default-port 21 "Default FTP port.")
-(defconst url-ftp-asynchronous-p t "FTP transfers are asynchronous.")
-(defalias 'url-ftp-expand-file-name 'url-default-expander)
-(defalias 'url-ftp 'url-file)
-
-(provide 'url-ftp)
+++ /dev/null
-;;; url-gw.el --- Gateway munging for URL loading
-;; Author: Bill Perry <wmperryNOSPAMgnu.org>
-;; Created: $Date: 2002/04/22 09:26:46 $
-;; $Revision: 1.8 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1997, 1998 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(eval-when-compile (require 'cl))
-(require 'url-vars)
-
-;; Fixme: support SSH explicitly or via a url-gateway-rlogin-program?
-
-(autoload 'socks-open-network-stream "socks")
-(autoload 'open-ssl-stream "ssl")
-
-(defgroup url-gateway nil
- "URL gateway variables"
- :group 'url)
-
-(defcustom url-gateway-local-host-regexp nil
- "*A regular expression specifying local hostnames/machines."
- :type '(choice (const nil) regexp)
- :group 'url-gateway)
-
-(defcustom url-gateway-prompt-pattern
- "^[^#$%>;]*[#$%>;] *" ;; "bash\\|\$ *\r?$\\|> *\r?"
- "*A regular expression matching a shell prompt."
- :type 'regexp
- :group 'url-gateway)
-
-(defcustom url-gateway-rlogin-host nil
- "*What hostname to actually rlog into before doing a telnet."
- :type '(choice (const nil) string)
- :group 'url-gateway)
-
-(defcustom url-gateway-rlogin-user-name nil
- "*Username to log into the remote machine with when using rlogin."
- :type '(choice (const nil) string)
- :group 'url-gateway)
-
-(defcustom url-gateway-rlogin-parameters '("telnet" "-8")
- "*Parameters to `url-open-rlogin'.
-This list will be used as the parameter list given to rsh."
- :type '(repeat string)
- :group 'url-gateway)
-
-(defcustom url-gateway-telnet-host nil
- "*What hostname to actually login to before doing a telnet."
- :type '(choice (const nil) string)
- :group 'url-gateway)
-
-(defcustom url-gateway-telnet-parameters '("exec" "telnet" "-8")
- "*Parameters to `url-open-telnet'.
-This list will be executed as a command after logging in via telnet."
- :type '(repeat string)
- :group 'url-gateway)
-
-(defcustom url-gateway-telnet-login-prompt "^\r*.?login:"
- "*Prompt that tells us we should send our username when loggin in w/telnet."
- :type 'regexp
- :group 'url-gateway)
-
-(defcustom url-gateway-telnet-password-prompt "^\r*.?password:"
- "*Prompt that tells us we should send our password when loggin in w/telnet."
- :type 'regexp
- :group 'url-gateway)
-
-(defcustom url-gateway-telnet-user-name nil
- "User name to log in via telnet with."
- :type '(choice (const nil) string)
- :group 'url-gateway)
-
-(defcustom url-gateway-telnet-password nil
- "Password to use to log in via telnet with."
- :type '(choice (const nil) string)
- :group 'url-gateway)
-
-(defcustom url-gateway-broken-resolution nil
- "*Whether to use nslookup to resolve hostnames.
-This should be used when your version of Emacs cannot correctly use DNS,
-but your machine can. This usually happens if you are running a statically
-linked Emacs under SunOS 4.x"
- :type 'boolean
- :group 'url-gateway)
-
-(defcustom url-gateway-nslookup-program "nslookup"
- "*If non-NIL then a string naming nslookup program."
- :type '(choice (const :tag "None" :value nil) string)
- :group 'url-gateway)
-
-;; Stolen from ange-ftp
-;;;###autoload
-(defun url-gateway-nslookup-host (host)
- "Attempt to resolve the given HOST using nslookup if possible."
- (interactive "sHost: ")
- (if url-gateway-nslookup-program
- (let ((proc (start-process " *nslookup*" " *nslookup*"
- url-gateway-nslookup-program host))
- (res host))
- (process-kill-without-query proc)
- (save-excursion
- (set-buffer (process-buffer proc))
- (while (memq (process-status proc) '(run open))
- (accept-process-output proc))
- (goto-char (point-min))
- (if (re-search-forward "Name:.*\nAddress: *\\(.*\\)$" nil t)
- (setq res (buffer-substring (match-beginning 1)
- (match-end 1))))
- (kill-buffer (current-buffer)))
- res)
- host))
-
-;; Stolen from red gnus nntp.el
-(defun url-wait-for-string (regexp proc)
- "Wait until string matching REGEXP arrives in process PROC's buffer."
- (let ((buf (current-buffer)))
- (goto-char (point-min))
- (while (not (re-search-forward regexp nil t))
- (accept-process-output proc)
- (set-buffer buf)
- (goto-char (point-min)))))
-
-;; Stolen from red gnus nntp.el
-(defun url-open-rlogin (name buffer host service)
- "Open a connection using rsh."
- (if (not (stringp service))
- (setq service (int-to-string service)))
- (let ((proc (if url-gateway-rlogin-user-name
- (start-process
- name buffer "rsh"
- url-gateway-rlogin-host "-l" url-gateway-rlogin-user-name
- (mapconcat 'identity
- (append url-gateway-rlogin-parameters
- (list host service)) " "))
- (start-process
- name buffer "rsh" url-gateway-rlogin-host
- (mapconcat 'identity
- (append url-gateway-rlogin-parameters
- (list host service))
- " ")))))
- (set-buffer buffer)
- (url-wait-for-string "^\r*200" proc)
- (beginning-of-line)
- (delete-region (point-min) (point))
- proc))
-
-;; Stolen from red gnus nntp.el
-(defun url-open-telnet (name buffer host service)
- (if (not (stringp service))
- (setq service (int-to-string service)))
- (save-excursion
- (set-buffer (get-buffer-create buffer))
- (erase-buffer)
- (let ((proc (start-process name buffer "telnet" "-8"))
- (case-fold-search t))
- (when (memq (process-status proc) '(open run))
- (process-send-string proc "set escape \^X\n")
- (process-send-string proc (concat
- "open " url-gateway-telnet-host "\n"))
- (url-wait-for-string url-gateway-telnet-login-prompt proc)
- (process-send-string
- proc (concat
- (or url-gateway-telnet-user-name
- (setq url-gateway-telnet-user-name (read-string "login: ")))
- "\n"))
- (url-wait-for-string url-gateway-telnet-password-prompt proc)
- (process-send-string
- proc (concat
- (or url-gateway-telnet-password
- (setq url-gateway-telnet-password
- (funcall url-passwd-entry-func "Password: ")))
- "\n"))
- (erase-buffer)
- (url-wait-for-string url-gateway-prompt-pattern proc)
- (process-send-string
- proc (concat (mapconcat 'identity
- (append url-gateway-telnet-parameters
- (list host service)) " ") "\n"))
- (url-wait-for-string "^\r*Escape character.*\r*\n+" proc)
- (delete-region (point-min) (match-end 0))
- (process-send-string proc "\^]\n")
- (url-wait-for-string "^telnet" proc)
- (process-send-string proc "mode character\n")
- (accept-process-output proc 1)
- (sit-for 1)
- (goto-char (point-min))
- (forward-line 1)
- (delete-region (point) (point-max)))
- proc)))
-
-;;;###autoload
-(defun url-open-stream (name buffer host service)
- "Open a stream to HOST, possibly via a gateway.
-Args per `open-network-stream'.
-Will not make a connexion if `url-gateway-unplugged' is non-nil."
- (unless url-gateway-unplugged
- (let ((gw-method (if (and url-gateway-local-host-regexp
- (not (eq 'ssl url-gateway-method))
- (string-match
- url-gateway-local-host-regexp
- host))
- 'native
- url-gateway-method))
-;;; ;; This hack is for OS/2 Emacs so that it will not do bogus CRLF
-;;; ;; conversions while trying to be 'helpful'
-;;; (tcp-binary-process-output-services (if (stringp service)
-;;; (list service)
-;;; (list service
-;;; (int-to-string service))))
-
- ;; An attempt to deal with denied connections, and attempt
- ;; to reconnect
- (cur-retries 0)
- (retry t)
- (errobj nil)
- (conn nil))
-
- ;; If the user told us to do DNS for them, do it.
- (if url-gateway-broken-resolution
- (setq host (url-gateway-nslookup-host host)))
-
- (condition-case errobj
- ;; This is a clean way to ensure the new process inherits the
- ;; right coding systems in both Emacs and XEmacs.
- (let ((coding-system-for-read 'binary)
- (coding-system-for-write 'binary))
- (setq conn (case gw-method
- (ssl
- (open-ssl-stream name buffer host service))
- ((native)
- (open-network-stream name buffer host service))
- (socks
- (socks-open-network-stream name buffer host service))
- (telnet
- (url-open-telnet name buffer host service))
- (rlogin
- (url-open-rlogin name buffer host service))
- (otherwise
- (error "Bad setting of url-gateway-method: %s"
- url-gateway-method)))))
- (error
- (setq conn nil)))
- conn)))
-
-(provide 'url-gw)
+++ /dev/null
-;;; url-handlers.el --- file-name-handler stuff for URL loading
-;; Author: $Author: sds $
-;; Created: $Date: 2003/06/26 18:45:45 $
-;; Version: $Revision: 1.10 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url)
-(require 'url-parse)
-(require 'url-util)
-(require 'mm-decode)
-(require 'mailcap)
-
-(eval-when-compile
- (require 'cl))
-
-;; Implementation status
-;; ---------------------
-;; Function Status
-;; ------------------------------------------------------------
-;; add-name-to-file Needs DAV Bindings
-;; copy-file Broken (assumes 1st item is URL)
-;; delete-directory Finished (DAV)
-;; delete-file Finished (DAV)
-;; diff-latest-backup-file
-;; directory-file-name unnecessary (what about VMS)?
-;; directory-files Finished (DAV)
-;; dired-call-process
-;; dired-compress-file
-;; dired-uncache
-;; expand-file-name Finished
-;; file-accessible-directory-p
-;; file-attributes Finished, better with DAV
-;; file-directory-p Needs DAV, finished
-;; file-executable-p Finished
-;; file-exists-p Finished
-;; file-local-copy
-;; file-modes
-;; file-name-all-completions Finished (DAV)
-;; file-name-as-directory
-;; file-name-completion Finished (DAV)
-;; file-name-directory
-;; file-name-nondirectory
-;; file-name-sans-versions why?
-;; file-newer-than-file-p
-;; file-ownership-preserved-p No way to know
-;; file-readable-p Finished
-;; file-regular-p !directory_p
-;; file-symlink-p Needs DAV bindings
-;; file-truename Needs DAV bindings
-;; file-writable-p Check for LOCK?
-;; find-backup-file-name why?
-;; get-file-buffer why?
-;; insert-directory Use DAV
-;; insert-file-contents Finished
-;; load
-;; make-directory Finished (DAV)
-;; make-symbolic-link Needs DAV bindings
-;; rename-file Finished (DAV)
-;; set-file-modes Use mod_dav specific executable flag?
-;; set-visited-file-modtime Impossible?
-;; shell-command Impossible?
-;; unhandled-file-name-directory
-;; vc-registered Finished (DAV)
-;; verify-visited-file-modtime
-;; write-region
-
-(defvar url-handler-regexp
- "\\`\\(https?\\|ftp\\|file\\|nfs\\)://"
- "*A regular expression for matching URLs handled by file-name-handler-alist.
-Some valid URL protocols just do not make sense to visit interactively
-\(about, data, info, irc, mailto, etc\). This regular expression
-avoids conflicts with local files that look like URLs \(Gnus is
-particularly bad at this\).")
-
-;;;###autoload
-(defun url-setup-file-name-handlers ()
- "Setup file-name handlers."
- (cond
- ((not (boundp 'file-name-handler-alist))
- nil) ; Don't load if no alist
- ((rassq 'url-file-handler file-name-handler-alist)
- nil) ; Don't load twice
- (t
- (push (cons url-handler-regexp 'url-file-handler)
- file-name-handler-alist))))
-
-(defun url-run-real-handler (operation args)
- (let ((inhibit-file-name-handlers (cons 'url-file-handler
- (if (eq operation inhibit-file-name-operation)
- inhibit-file-name-handlers)))
- (inhibit-file-name-operation operation))
- (apply operation args)))
-
-(defun url-file-handler (operation &rest args)
- "Function called from the `file-name-handler-alist' routines.
-OPERATION is what needs to be done (`file-exists-p', etc). ARGS are
-the arguments that would have been passed to OPERATION."
- (let ((fn (or (get operation 'url-file-handlers)
- (intern-soft (format "url-%s" operation))))
- (val nil)
- (hooked nil))
- (if (and fn (fboundp fn))
- (setq hooked t
- val (apply fn args))
- (setq hooked nil
- val (url-run-real-handler operation args)))
- (url-debug 'handlers "%s %S%S => %S" (if hooked "Hooked" "Real")
- operation args val)
- val))
-
-(defun url-file-handler-identity (&rest args)
- ;; Identity function
- (car args))
-
-;; These are operations that we can fully support
-(put 'file-readable-p 'url-file-handlers 'url-file-exists-p)
-(put 'substitute-in-file-name 'url-file-handlers 'url-file-handler-identity)
-(put 'file-name-absolute-p 'url-file-handlers (lambda (&rest ignored) t))
-(put 'expand-file-name 'url-file-handlers 'url-handler-expand-file-name)
-
-;; These are operations that we do not support yet (DAV!!!)
-(put 'file-writable-p 'url-file-handlers 'ignore)
-(put 'file-symlink-p 'url-file-handlers 'ignore)
-
-(defun url-handler-expand-file-name (file &optional base)
- (if (file-name-absolute-p file)
- (expand-file-name file "/")
- (url-expand-file-name file base)))
-
-;; The actual implementation
-;;;###autoload
-(defun url-copy-file (url newname &optional ok-if-already-exists keep-time)
- "Copy URL to NEWNAME. Both args must be strings.
-Signals a `file-already-exists' error if file NEWNAME already exists,
-unless a third argument OK-IF-ALREADY-EXISTS is supplied and non-nil.
-A number as third arg means request confirmation if NEWNAME already exists.
-This is what happens in interactive use with M-x.
-Fourth arg KEEP-TIME non-nil means give the new file the same
-last-modified time as the old one. (This works on only some systems.)
-A prefix arg makes KEEP-TIME non-nil."
- (if (and (file-exists-p newname)
- (not ok-if-already-exists))
- (error "Opening output file: File already exists, %s" newname))
- (let ((buffer (url-retrieve-synchronously url))
- (handle nil))
- (if (not buffer)
- (error "Opening input file: No such file or directory, %s" url))
- (save-excursion
- (set-buffer buffer)
- (setq handle (mm-dissect-buffer t)))
- (mm-save-part-to-file handle newname)
- (kill-buffer buffer)
- (mm-destroy-parts handle)))
-
-;;;###autoload
-(defun url-file-local-copy (url &rest ignored)
- "Copy URL into a temporary file on this machine.
-Returns the name of the local copy, or nil, if FILE is directly
-accessible."
- (let ((filename (make-temp-name "url")))
- (url-copy-file url filename)
- filename))
-
-;;;###autoload
-(defun url-insert-file-contents (url &optional visit beg end replace)
- (let ((buffer (url-retrieve-synchronously url))
- (handle nil)
- (data nil))
- (if (not buffer)
- (error "Opening input file: No such file or directory, %s" url))
- (if visit (setq buffer-file-name url))
- (save-excursion
- (set-buffer buffer)
- (setq handle (mm-dissect-buffer t))
- (set-buffer (mm-handle-buffer handle))
- (if beg
- (setq data (buffer-substring beg end))
- (setq data (buffer-string))))
- (kill-buffer buffer)
- (mm-destroy-parts handle)
- (if replace (delete-region (point-min) (point-max)))
- (save-excursion
- (insert data))
- (list url (length data))))
-
-(defun url-file-name-completion (url directory)
- (error "Unimplemented"))
-
-(defun url-file-name-all-completions (file directory)
- (error "Unimplemented"))
-
-;; All other handlers map onto their respective backends.
-(defmacro url-handlers-create-wrapper (method args)
- `(defun ,(intern (format "url-%s" method)) ,args
- ,(format "URL file-name-handler wrapper for `%s' call.\n---\n%s" method
- (or (documentation method t) "No original documentation."))
- (setq url (url-generic-parse-url url))
- (when (url-type url)
- (funcall (url-scheme-get-property (url-type url) (quote ,method))
- ,@(remove '&rest (remove '&optional args))))))
-
-(url-handlers-create-wrapper file-exists-p (url))
-(url-handlers-create-wrapper file-attributes (url))
-(url-handlers-create-wrapper file-symlink-p (url))
-(url-handlers-create-wrapper file-writable-p (url))
-(url-handlers-create-wrapper file-directory-p (url))
-(url-handlers-create-wrapper file-executable-p (url))
-
-(if (featurep 'xemacs)
- (progn
- ;; XEmacs specific prototypes
- (url-handlers-create-wrapper
- directory-files (url &optional full match nosort files-only))
- (url-handlers-create-wrapper
- file-truename (url &optional default)))
- ;; Emacs specific prototypes
- (url-handlers-create-wrapper
- directory-files (url &optional full match nosort))
- (url-handlers-create-wrapper
- file-truename (url &optional counter prev-dirs)))
-
-(add-hook 'find-file-hooks 'url-handlers-set-buffer-mode)
-
-(defun url-handlers-set-buffer-mode ()
- "Set correct modes for the current buffer if visiting a remote file."
- (and (stringp buffer-file-name)
- (string-match url-handler-regexp buffer-file-name)
- (auto-save-mode 0)))
-
-(provide 'url-handlers)
+++ /dev/null
-;;; url-history.el --- Global history tracking for URL package
-;; Author: $Author: fx $
-;; Created: $Date: 2001/05/05 16:49:52 $
-;; Version: $Revision: 1.6 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; This can get a recursive require.
-;;(require 'url)
-(eval-when-compile (require 'cl))
-(require 'url-parse)
-(autoload 'url-do-setup "url")
-
-(defgroup url-history nil
- "History variables in the URL package"
- :prefix "url-history"
- :group 'url)
-
-(defcustom url-history-track nil
- "*Controls whether to keep a list of all the URLS being visited.
-If non-nil, url will keep track of all the URLS visited.
-If eq to `t', then the list is saved to disk at the end of each emacs
-session."
- :type 'boolean
- :group 'url-history)
-
-(defcustom url-history-file nil
- "*The global history file for the URL package.
-This file contains a list of all the URLs you have visited. This file
-is parsed at startup and used to provide URL completion."
- :type '(choice (const :tag "Default" :value nil) file)
- :group 'url-history)
-
-(defcustom url-history-save-interval 3600
- "*The number of seconds between automatic saves of the history list.
-Default is 1 hour. Note that if you change this variable outside of
-the `customize' interface after `url-do-setup' has been run, you need
-to run the `url-history-setup-save-timer' function manually."
- :set (function (lambda (var val)
- (set-default var val)
- (and (featurep 'url)
- (fboundp 'url-history-setup-save-timer)
- (let ((def (symbol-function
- 'url-history-setup-save-timer)))
- (not (and (listp def) (eq 'autoload (car def)))))
- (url-history-setup-save-timer))))
- :type 'integer
- :group 'url-history)
-
-(defvar url-history-timer nil)
-
-(defvar url-history-list nil
- "List of urls visited this session.")
-
-(defvar url-history-changed-since-last-save nil
- "Whether the history list has changed since the last save operation.")
-
-(defvar url-history-hash-table nil
- "Hash table for global history completion.")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;;###autoload
-(defun url-history-setup-save-timer ()
- "Reset the history list timer."
- (interactive)
- (cond
- ((featurep 'itimer)
- (ignore-errors (delete-itimer url-history-timer))
- (setq url-history-timer nil)
- (if url-history-save-interval
- (setq url-history-timer
- (start-itimer "url-history-saver" 'url-history-save-history
- url-history-save-interval
- url-history-save-interval))))
- ((fboundp 'run-at-time)
- (ignore-errors (cancel-timer url-history-timer))
- (setq url-history-timer nil)
- (if url-history-save-interval
- (setq url-history-timer
- (run-at-time url-history-save-interval
- url-history-save-interval
- 'url-history-save-history))))
- (t nil)))
-
-;;;###autoload
-(defun url-history-parse-history (&optional fname)
- "Parse a history file stored in FNAME."
- ;; Parse out the mosaic global history file for completions, etc.
- (or fname (setq fname (expand-file-name url-history-file)))
- (cond
- ((not (file-exists-p fname))
- (message "%s does not exist." fname))
- ((not (file-readable-p fname))
- (message "%s is unreadable." fname))
- (t
- (condition-case nil
- (load fname nil t)
- (error (message "Could not load %s" fname)))))
- (if (not url-history-hash-table)
- (setq url-history-hash-table (make-hash-table :size 31 :test 'equal))))
-
-(defun url-history-update-url (url time)
- (setq url-history-changed-since-last-save t)
- (puthash (if (vectorp url) (url-recreate-url url) url) time url-history-hash-table))
-
-;;;###autoload
-(defun url-history-save-history (&optional fname)
- "Write the global history file into `url-history-file'.
-The type of data written is determined by what is in the file to begin
-with. If the type of storage cannot be determined, then prompt the
-user for what type to save as."
- (interactive)
- (or fname (setq fname (expand-file-name url-history-file)))
- (cond
- ((not url-history-changed-since-last-save) nil)
- ((not (file-writable-p fname))
- (message "%s is unwritable." fname))
- (t
- (let ((make-backup-files nil)
- (version-control nil)
- (require-final-newline t))
- (save-excursion
- (set-buffer (get-buffer-create " *url-tmp*"))
- (erase-buffer)
- (let ((count 0))
- (maphash (function
- (lambda (key value)
- (while (string-match "[\r\n]+" key)
- (setq key (concat (substring key 0 (match-beginning 0))
- (substring key (match-end 0) nil))))
- (setq count (1+ count))
- (insert "(puthash \"" key "\""
- (if (not (stringp value)) " '" "")
- (prin1-to-string value)
- " url-history-hash-table)\n")))
- url-history-hash-table)
- (goto-char (point-min))
- (insert (format
- "(setq url-history-hash-table (make-hash-table :size %d :test 'equal))\n"
- (/ count 4)))
- (goto-char (point-max))
- (insert "\n")
- (write-file fname))
- (kill-buffer (current-buffer))))))
- (setq url-history-changed-since-last-save nil))
-
-(defun url-have-visited-url (url)
- (url-do-setup)
- (gethash url url-history-hash-table nil))
-
-(defun url-completion-function (string predicate function)
- (url-do-setup)
- (cond
- ((eq function nil)
- (let ((list nil))
- (maphash (function (lambda (key val)
- (setq list (cons (cons key val)
- list))))
- url-history-hash-table)
- (try-completion string (nreverse list) predicate)))
- ((eq function t)
- (let ((stub (concat "^" (regexp-quote string)))
- (retval nil))
- (maphash
- (function
- (lambda (url time)
- (if (string-match stub url)
- (setq retval (cons url retval)))))
- url-history-hash-table)
- retval))
- ((eq function 'lambda)
- (and url-history-hash-table
- (gethash string url-history-hash-table)
- t))
- (t
- (error "url-completion-function very confused."))))
-
-(provide 'url-history)
+++ /dev/null
-;;; url-http.el --- HTTP retrieval routines
-;; Author: Bill Perry <wmperryNOSPAMgnu.org>
-;; Version: $Revision: 1.39 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1999, 2001 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(eval-when-compile
- (require 'cl)
- (defvar url-http-extra-headers))
-(require 'url-gw)
-(require 'url-util)
-(require 'url-parse)
-(require 'url-cookie)
-(require 'mail-parse)
-(require 'url-auth)
-(autoload 'url-retrieve-synchronously "url")
-(autoload 'url-retrieve "url")
-(autoload 'url-cache-create-filename "url-cache")
-(autoload 'url-mark-buffer-as-dead "url")
-
-(defconst url-http-default-port 80 "Default HTTP port.")
-(defconst url-http-asynchronous-p t "HTTP retrievals are asynchronous.")
-(defalias 'url-http-expand-file-name 'url-default-expander)
-
-(defvar url-http-real-basic-auth-storage nil)
-(defvar url-http-proxy-basic-auth-storage nil)
-
-(defvar url-http-open-connections (make-hash-table :test 'equal
- :size 17)
- "A hash table of all open network connections.")
-
-(defvar url-http-version "1.1"
- "What version of HTTP we advertise, as a string.
-Valid values are 1.1 and 1.0.
-This is only useful when debugging the HTTP subsystem.
-
-Setting this to 1.0 will tell servers not to send chunked encoding,
-and other HTTP/1.1 specific features.
-")
-
-(defvar url-http-attempt-keepalives t
- "Whether to use a single TCP connection multiple times in HTTP.
-This is only useful when debugging the HTTP subsystem. Setting to
-`nil' will explicitly close the connection to the server after every
-request.
-")
-
-;(eval-when-compile
-;; These are all macros so that they are hidden from external sight
-;; when the file is byte-compiled.
-;;
-;; This allows us to expose just the entry points we want.
-
-;; These routines will allow us to implement persistent HTTP
-;; connections.
-(defsubst url-http-debug (&rest args)
- (if quit-flag
- (let ((proc (get-buffer-process (current-buffer))))
- ;; The user hit C-g, honor it! Some things can get in an
- ;; incredibly tight loop (chunked encoding)
- (if proc
- (progn
- (set-process-sentinel proc nil)
- (set-process-filter proc nil)))
- (error "Transfer interrupted!")))
- (apply 'url-debug 'http args))
-
-(defun url-http-mark-connection-as-busy (host port proc)
- (url-http-debug "Marking connection as busy: %s:%d %S" host port proc)
- (puthash (cons host port)
- (delq proc (gethash (cons host port) url-http-open-connections))
- url-http-open-connections)
- proc)
-
-(defun url-http-mark-connection-as-free (host port proc)
- (url-http-debug "Marking connection as free: %s:%d %S" host port proc)
- (set-process-buffer proc nil)
- (set-process-sentinel proc 'url-http-idle-sentinel)
- (puthash (cons host port)
- (cons proc (gethash (cons host port) url-http-open-connections))
- url-http-open-connections)
- nil)
-
-(defun url-http-find-free-connection (host port)
- (let ((conns (gethash (cons host port) url-http-open-connections))
- (found nil))
- (while (and conns (not found))
- (if (not (memq (process-status (car conns)) '(run open)))
- (progn
- (url-http-debug "Cleaning up dead process: %s:%d %S"
- host port (car conns))
- (url-http-idle-sentinel (car conns) nil))
- (setq found (car conns))
- (url-http-debug "Found existing connection: %s:%d %S" host port found))
- (pop conns))
- (if found
- (url-http-debug "Reusing existing connection: %s:%d" host port)
- (url-http-debug "Contacting host: %s:%d" host port))
- (url-lazy-message "Contacting host: %s:%d" host port)
- (url-http-mark-connection-as-busy host port
- (or found
- (url-open-stream host nil host
- port)))))
-
-;; Building an HTTP request
-(defun url-http-user-agent-string ()
- (if (or (eq url-privacy-level 'paranoid)
- (and (listp url-privacy-level)
- (memq 'agent url-privacy-level)))
- ""
- (format "User-Agent: %sURL/%s%s\r\n"
- (if url-package-name
- (concat url-package-name "/" url-package-version " ")
- "")
- url-version
- (cond
- ((and url-os-type url-system-type)
- (concat " (" url-os-type "; " url-system-type ")"))
- ((or url-os-type url-system-type)
- (concat " (" (or url-system-type url-os-type) ")"))
- (t "")))))
-
-(defun url-http-create-request (url &optional ref-url)
- "Create an HTTP request for URL, referred to by REF-URL."
- (declare (special proxy-object proxy-info))
- (let* ((extra-headers)
- (request nil)
- (no-cache (cdr-safe (assoc "Pragma" url-request-extra-headers)))
- (proxy-obj (and (boundp 'proxy-object) proxy-object))
- (proxy-auth (if (or (cdr-safe (assoc "Proxy-Authorization"
- url-request-extra-headers))
- (not proxy-obj))
- nil
- (let ((url-basic-auth-storage
- 'url-http-proxy-basic-auth-storage))
- (url-get-authentication url nil 'any nil))))
- (real-fname (if proxy-obj (url-recreate-url proxy-obj)
- (url-filename url)))
- (host (url-host (or proxy-obj url)))
- (auth (if (cdr-safe (assoc "Authorization" url-request-extra-headers))
- nil
- (url-get-authentication (or
- (and (boundp 'proxy-info)
- proxy-info)
- url) nil 'any nil))))
- (if (equal "" real-fname)
- (setq real-fname "/"))
- (setq no-cache (and no-cache (string-match "no-cache" no-cache)))
- (if auth
- (setq auth (concat "Authorization: " auth "\r\n")))
- (if proxy-auth
- (setq proxy-auth (concat "Proxy-Authorization: " proxy-auth "\r\n")))
-
- ;; Protection against stupid values in the referer
- (if (and ref-url (stringp ref-url) (or (string= ref-url "file:nil")
- (string= ref-url "")))
- (setq ref-url nil))
-
- ;; We do not want to expose the referer if the user is paranoid.
- (if (or (memq url-privacy-level '(low high paranoid))
- (and (listp url-privacy-level)
- (memq 'lastloc url-privacy-level)))
- (setq ref-url nil))
-
- ;; url-request-extra-headers contains an assoc-list of
- ;; header/value pairs that we need to put into the request.
- (setq extra-headers (mapconcat
- (lambda (x)
- (concat (car x) ": " (cdr x)))
- url-request-extra-headers "\r\n"))
- (if (not (equal extra-headers ""))
- (setq extra-headers (concat extra-headers "\r\n")))
-
- ;; This was done with a call to `format'. Concatting parts has
- ;; the advantage of keeping the parts of each header togther and
- ;; allows us to elide null lines directly, at the cost of making
- ;; the layout less clear.
- (setq request
- (concat
- ;; The request
- (or url-request-method "GET") " " real-fname " HTTP/" url-http-version "\r\n"
- ;; Version of MIME we speak
- "MIME-Version: 1.0\r\n"
- ;; (maybe) Try to keep the connection open
- "Connection: " (if (or proxy-obj
- (not url-http-attempt-keepalives))
- "close" "keep-alive") "\r\n"
- ;; HTTP extensions we support
- (if url-extensions-header
- (format
- "Extension: %s\r\n" url-extensions-header))
- ;; Who we want to talk to
- (if (/= (url-port (or proxy-obj url))
- (url-scheme-get-property
- (url-type (or proxy-obj url)) 'default-port))
- (format
- "Host: %s:%d\r\n" host (url-port (or proxy-obj url)))
- (format "Host: %s\r\n" host))
- ;; Who its from
- (if url-personal-mail-address
- (concat
- "From: " url-personal-mail-address "\r\n"))
- ;; Encodings we understand
- (if url-mime-encoding-string
- (concat
- "Accept-encoding: " url-mime-encoding-string "\r\n"))
- (if url-mime-charset-string
- (concat
- "Accept-charset: " url-mime-charset-string "\r\n"))
- ;; Languages we understand
- (if url-mime-language-string
- (concat
- "Accept-language: " url-mime-language-string "\r\n"))
- ;; Types we understand
- "Accept: " (or url-mime-accept-string "*/*") "\r\n"
- ;; User agent
- (url-http-user-agent-string)
- ;; Proxy Authorization
- proxy-auth
- ;; Authorization
- auth
- ;; Cookies
- (url-cookie-generate-header-lines host real-fname
- (equal "https" (url-type url)))
- ;; If-modified-since
- (if (and (not no-cache)
- (member url-request-method '("GET" nil)))
- (let ((tm (url-is-cached (or proxy-obj url))))
- (if tm
- (concat "If-modified-since: "
- (url-get-normalized-date tm) "\r\n"))))
- ;; Whence we came
- (if ref-url (concat
- "Referer: " ref-url "\r\n"))
- extra-headers
- ;; Any data
- (if url-request-data
- (concat
- "Content-length: " (number-to-string
- (length url-request-data))
- "\r\n\r\n"
- url-request-data))
- ;; End request
- "\r\n"))
- (url-http-debug "Request is: \n%s" request)
- request))
-
-;; Parsing routines
-(defun url-http-clean-headers ()
- "Remove trailing \r from header lines.
-This allows us to use `mail-fetch-field', etc."
- (declare (special url-http-end-of-headers))
- (goto-char (point-min))
- (while (re-search-forward "\r$" url-http-end-of-headers t)
- (replace-match "")))
-
-(defun url-http-handle-authentication (proxy)
- (declare (special status success url-http-method url-http-data
- url-callback-function url-callback-arguments))
- (url-http-debug "Handling %s authentication" (if proxy "proxy" "normal"))
- (let ((auth (or (mail-fetch-field (if proxy "proxy-authenticate" "www-authenticate"))
- "basic"))
- (type nil)
- ;; in case there is a proxy, `url-current-object' points at this proxy
- ;; => retrieve URL from `url-callback-arguments'
- (url (car url-callback-arguments))
- (url-basic-auth-storage 'url-http-real-basic-auth-storage)
- )
-
- ;; Cheating, but who cares? :)
- (if proxy
- (setq url-basic-auth-storage 'url-http-proxy-basic-auth-storage))
-
- (setq auth (url-eat-trailing-space (url-strip-leading-spaces auth)))
- (if (string-match "[ \t]" auth)
- (setq type (downcase (substring auth 0 (match-beginning 0))))
- (setq type (downcase auth)))
-
- (if (not (url-auth-registered type))
- (progn
- (widen)
- (goto-char (point-max))
- (insert "<hr>Sorry, but I do not know how to handle " type
- " authentication. If you'd like to write it,"
- " send it to " url-bug-address ".<hr>")
- (setq status t))
- (let* ((args auth)
- (ctr (1- (length args)))
- auth)
- (while (/= 0 ctr)
- (if (char-equal ?, (aref args ctr))
- (aset args ctr ?\;))
- (setq ctr (1- ctr)))
- (setq args (url-parse-args args)
- auth (url-get-authentication url (cdr-safe (assoc "realm" args))
- type t args))
- (if (not auth)
- (setq success t)
- (push (cons (if proxy "Proxy-Authorization" "Authorization") auth)
- url-http-extra-headers)
- (let ((url-request-method url-http-method)
- (url-request-data url-http-data)
- (url-request-extra-headers url-http-extra-headers))
- (url-retrieve url url-callback-function url-callback-arguments))))
- (kill-buffer (current-buffer)))))
-
-(defun url-http-parse-response ()
- "Parse just the response code."
- (declare (special url-http-end-of-headers url-http-response-status))
- (if (not url-http-end-of-headers)
- (error "Trying to parse HTTP response code in odd buffer: %s" (buffer-name)))
- (url-http-debug "url-http-parse-response called in (%s)" (buffer-name))
- (goto-char (point-min))
- (while (and
- (not (looking-at "^HTTP"))
- (not (forward-line 1))))
- (skip-chars-forward " \t\n") ; Skip any blank crap
- (skip-chars-forward "HTTP/") ; Skip HTTP Version
- (read (current-buffer))
- (setq url-http-response-status (read (current-buffer))))
-
-(defun url-http-handle-cookies ()
- "Handle all set-cookie / set-cookie2 headers in an HTTP response.
-The buffer must already be narrowed to the headers, so mail-fetch-field will
-work correctly."
- (let ((cookies (mail-fetch-field "Set-Cookie" nil nil t))
- (cookies2 (mail-fetch-field "Set-Cookie2" nil nil t)))
- (and cookies (url-http-debug "Found %d Set-Cookie headers" (length cookies)))
- (and cookies2 (url-http-debug "Found %d Set-Cookie2 headers" (length cookies2)))
- (while cookies
- (url-cookie-handle-set-cookie (pop cookies)))
-;;; (while cookies2
-;;; (url-cookie-handle-set-cookie2 (pop cookies)))
- )
- )
-
-(defun url-http-parse-headers ()
- "Parse and handle HTTP specific headers.
-Return t if and only if the current buffer is still active and
-should be shown to the user."
- ;; The comments after each status code handled are taken from RFC
- ;; 2616 (HTTP/1.1)
- (declare (special url-http-end-of-headers url-http-response-status
- url-http-method url-http-data url-http-process
- url-callback-function url-callback-arguments))
-
- (url-http-mark-connection-as-free (url-host url-current-object)
- (url-port url-current-object)
- url-http-process)
-
- (if (or (not (boundp 'url-http-end-of-headers))
- (not url-http-end-of-headers))
- (error "Trying to parse headers in odd buffer: %s" (buffer-name)))
- (goto-char (point-min))
- (url-http-debug "url-http-parse-headers called in (%s)" (buffer-name))
- (url-http-parse-response)
- (mail-narrow-to-head)
- ;;(narrow-to-region (point-min) url-http-end-of-headers)
- (let ((parse-buffer (current-buffer))
- (version nil)
- (class nil)
- (success nil))
- (setq class (/ url-http-response-status 100))
- (url-http-debug "Parsed HTTP headers: class=%d status=%d" class url-http-response-status)
- (url-http-handle-cookies)
-
- (case class
- ;; Classes of response codes
- ;;
- ;; 5xx = Server Error
- ;; 4xx = Client Error
- ;; 3xx = Redirection
- ;; 2xx = Successful
- ;; 1xx = Informational
- (1 ; Information messages
- ;; 100 = Continue with request
- ;; 101 = Switching protocols
- ;; 102 = Processing (Added by DAV)
- (url-mark-buffer-as-dead parse-buffer)
- (error "HTTP responses in class 1xx not supported (%d)" url-http-response-status))
- (2 ; Success
- ;; 200 Ok
- ;; 201 Created
- ;; 202 Accepted
- ;; 203 Non-authoritative information
- ;; 204 No content
- ;; 205 Reset content
- ;; 206 Partial content
- ;; 207 Multi-status (Added by DAV)
- (case url-http-response-status
- ((204 205)
- ;; No new data, just stay at the same document
- (url-mark-buffer-as-dead parse-buffer)
- (setq success t))
- (otherwise
- ;; Generic success for all others. Store in the cache, and
- ;; mark it as successful.
- (widen)
- (if (equal url-http-method "GET")
- (url-store-in-cache parse-buffer))
- (setq success t))))
- (3 ; Redirection
- ;; 300 Multiple choices
- ;; 301 Moved permanently
- ;; 302 Found
- ;; 303 See other
- ;; 304 Not modified
- ;; 305 Use proxy
- ;; 307 Temporary redirect
- (let ((redirect-uri (or (mail-fetch-field "Location")
- (mail-fetch-field "URI"))))
- (case url-http-response-status
- (300
- ;; Quoth the spec (section 10.3.1)
- ;; -------------------------------
- ;; The requested resource corresponds to any one of a set of
- ;; representations, each with its own specific location and
- ;; agent-driven negotiation information is being provided so
- ;; that the user can select a preferred representation and
- ;; redirect its request to that location.
- ;; [...]
- ;; If the server has a preferred choice of representation, it
- ;; SHOULD include the specific URI for that representation in
- ;; the Location field; user agents MAY use the Location field
- ;; value for automatic redirection.
- ;; -------------------------------
- ;; We do not support agent-driven negotiation, so we just
- ;; redirect to the preferred URI if one is provided.
- nil)
- ((301 302 307)
- ;; If the 301|302 status code is received in response to a
- ;; request other than GET or HEAD, the user agent MUST NOT
- ;; automatically redirect the request unless it can be
- ;; confirmed by the user, since this might change the
- ;; conditions under which the request was issued.
- (if (member url-http-method '("HEAD" "GET"))
- ;; Automatic redirection is ok
- nil
- ;; It is just too big of a pain in the ass to get this
- ;; prompt all the time. We will just silently lose our
- ;; data and convert to a GET method.
- (url-http-debug "Converting `%s' request to `GET' because of REDIRECT(%d)"
- url-http-method url-http-response-status)
- (setq url-http-method "GET"
- url-request-data nil)))
- (303
- ;; The response to the request can be found under a different
- ;; URI and SHOULD be retrieved using a GET method on that
- ;; resource.
- (setq url-http-method "GET"
- url-http-data nil))
- (304
- ;; The 304 response MUST NOT contain a message-body.
- (url-http-debug "Extracting document from cache... (%s)"
- (url-cache-create-filename (url-view-url t)))
- (url-cache-extract (url-cache-create-filename (url-view-url t)))
- (setq redirect-uri nil
- success t))
- (305
- ;; The requested resource MUST be accessed through the
- ;; proxy given by the Location field. The Location field
- ;; gives the URI of the proxy. The recipient is expected
- ;; to repeat this single request via the proxy. 305
- ;; responses MUST only be generated by origin servers.
- (error "Redirection thru a proxy server not supported: %s"
- redirect-uri))
- (otherwise
- ;; Treat everything like '300'
- nil))
- (when redirect-uri
- ;; Clean off any whitespace and/or <...> cruft.
- (if (string-match "\\([^ \t]+\\)[ \t]" redirect-uri)
- (setq redirect-uri (match-string 1 redirect-uri)))
- (if (string-match "^<\\(.*\\)>$" redirect-uri)
- (setq redirect-uri (match-string 1 redirect-uri)))
-
- ;; Some stupid sites (like sourceforge) send a
- ;; non-fully-qualified URL (ie: /), which royally confuses
- ;; the URL library.
- (if (not (string-match url-nonrelative-link redirect-uri))
- (setq redirect-uri (url-expand-file-name redirect-uri)))
- (let ((url-request-method url-http-method)
- (url-request-data url-http-data)
- (url-request-extra-headers url-http-extra-headers))
- ;; on some systems, we have to wait in order to avoid drawing a blank page
- (and url-slow-proxy-requires-waiting-for
- (sleep-for url-slow-proxy-requires-waiting-for))
- (url-retrieve redirect-uri url-callback-function
- (cons redirect-uri
- (and url-callback-arguments
- (cdr url-callback-arguments))))
- (url-mark-buffer-as-dead parse-buffer)))))
- (4 ; Client error
- ;; 400 Bad Request
- ;; 401 Unauthorized
- ;; 402 Payment required
- ;; 403 Forbidden
- ;; 404 Not found
- ;; 405 Method not allowed
- ;; 406 Not acceptable
- ;; 407 Proxy authentication required
- ;; 408 Request time-out
- ;; 409 Conflict
- ;; 410 Gone
- ;; 411 Length required
- ;; 412 Precondition failed
- ;; 413 Request entity too large
- ;; 414 Request-URI too large
- ;; 415 Unsupported media type
- ;; 416 Requested range not satisfiable
- ;; 417 Expectation failed
- ;; 422 Unprocessable Entity (Added by DAV)
- ;; 423 Locked
- ;; 424 Failed Dependency
- (case url-http-response-status
- (401
- ;; The request requires user authentication. The response
- ;; MUST include a WWW-Authenticate header field containing a
- ;; challenge applicable to the requested resource. The
- ;; client MAY repeat the request with a suitable
- ;; Authorization header field.
- (url-http-handle-authentication nil))
- (402
- ;; This code is reserved for future use
- (url-mark-buffer-as-dead parse-buffer)
- (error "Somebody wants you to give them money"))
- (403
- ;; The server understood the request, but is refusing to
- ;; fulfill it. Authorization will not help and the request
- ;; SHOULD NOT be repeated.
- (setq success t))
- (404
- ;; Not found
- (setq success t))
- (405
- ;; The method specified in the Request-Line is not allowed
- ;; for the resource identified by the Request-URI. The
- ;; response MUST include an Allow header containing a list of
- ;; valid methods for the requested resource.
- (setq success t))
- (406
- ;; The resource identified by the request is only capable of
- ;; generating response entities which have content
- ;; characteristics nota cceptable according to the accept
- ;; headers sent in the request.
- (setq success t))
- (407
- ;; This code is similar to 401 (Unauthorized), but indicates
- ;; that the client must first authenticate itself with the
- ;; proxy. The proxy MUST return a Proxy-Authenticate header
- ;; field containing a challenge applicable to the proxy for
- ;; the requested resource.
- (url-http-handle-authentication t))
- (408
- ;; The client did not produce a request within the time that
- ;; the server was prepared to wait. The client MAY repeat
- ;; the request without modifications at any later time.
- (setq success t))
- (409
- ;; The request could not be completed due to a conflict with
- ;; the current state of the resource. This code is only
- ;; allowed in situations where it is expected that the user
- ;; mioght be able to resolve the conflict and resubmit the
- ;; request. The response body SHOULD include enough
- ;; information for the user to recognize the source of the
- ;; conflict.
- (setq success t))
- (410
- ;; The requested resource is no longer available at the
- ;; server and no forwarding address is known.
- (setq success t))
- (411
- ;; The server refuses to accept the request without a defined
- ;; Content-Length. The client MAY repeat the request if it
- ;; adds a valid Content-Length header field containing the
- ;; length of the message-body in the request message.
- ;;
- ;; NOTE - this will never happen because
- ;; `url-http-create-request' automatically calculates the
- ;; content-length.
- (setq success t))
- (412
- ;; The precondition given in one or more of the
- ;; request-header fields evaluated to false when it was
- ;; tested on the server.
- (setq success t))
- ((413 414)
- ;; The server is refusing to process a request because the
- ;; request entity|URI is larger than the server is willing or
- ;; able to process.
- (setq success t))
- (415
- ;; The server is refusing to service the request because the
- ;; entity of the request is in a format not supported by the
- ;; requested resource for the requested method.
- (setq success t))
- (416
- ;; A server SHOULD return a response with this status code if
- ;; a request included a Range request-header field, and none
- ;; of the range-specifier values in this field overlap the
- ;; current extent of the selected resource, and the request
- ;; did not include an If-Range request-header field.
- (setq success t))
- (417
- ;; The expectation given in an Expect request-header field
- ;; could not be met by this server, or, if the server is a
- ;; proxy, the server has unambiguous evidence that the
- ;; request could not be met by the next-hop server.
- (setq success t))
- (otherwise
- ;; The request could not be understood by the server due to
- ;; malformed syntax. The client SHOULD NOT repeat the
- ;; request without modifications.
- (setq success t))))
- (5
- ;; 500 Internal server error
- ;; 501 Not implemented
- ;; 502 Bad gateway
- ;; 503 Service unavailable
- ;; 504 Gateway time-out
- ;; 505 HTTP version not supported
- ;; 507 Insufficient storage
- (setq success t)
- (case url-http-response-status
- (501
- ;; The server does not support the functionality required to
- ;; fulfill the request.
- nil)
- (502
- ;; The server, while acting as a gateway or proxy, received
- ;; an invalid response from the upstream server it accessed
- ;; in attempting to fulfill the request.
- nil)
- (503
- ;; The server is currently unable to handle the request due
- ;; to a temporary overloading or maintenance of the server.
- ;; The implication is that this is a temporary condition
- ;; which will be alleviated after some delay. If known, the
- ;; length of the delay MAY be indicated in a Retry-After
- ;; header. If no Retry-After is given, the client SHOULD
- ;; handle the response as it would for a 500 response.
- nil)
- (504
- ;; The server, while acting as a gateway or proxy, did not
- ;; receive a timely response from the upstream server
- ;; specified by the URI (e.g. HTTP, FTP, LDAP) or some other
- ;; auxiliary server (e.g. DNS) it needed to access in
- ;; attempting to complete the request.
- nil)
- (505
- ;; The server does not support, or refuses to support, the
- ;; HTTP protocol version that was used in the request
- ;; message.
- nil)
- (507 ; DAV
- ;; The method could not be performed on the resource
- ;; because the server is unable to store the representation
- ;; needed to successfully complete the request. This
- ;; condition is considered to be temporary. If the request
- ;; which received this status code was the result of a user
- ;; action, the request MUST NOT be repeated until it is
- ;; requested by a separate user action.
- nil)))
- (otherwise
- (error "Unknown class of HTTP response code: %d (%d)"
- class url-http-response-status)))
- (if (not success)
- (url-mark-buffer-as-dead parse-buffer))
- (url-http-debug "Finished parsing HTTP headers: %S" success)
- (widen)
- success))
-
-;; Miscellaneous
-(defun url-http-activate-callback ()
- "Activate callback specified when this buffer was created."
- (declare (special url-http-process
- url-callback-function
- url-callback-arguments))
- (url-http-mark-connection-as-free (url-host url-current-object)
- (url-port url-current-object)
- url-http-process)
- (url-http-debug "Activating callback in buffer (%s)" (buffer-name))
- (apply url-callback-function url-callback-arguments))
-
-;; )
-
-;; These unfortunately cannot be macros... please ignore them!
-(defun url-http-idle-sentinel (proc why)
- "Remove this (now defunct) process PROC from the list of open connections."
- (maphash (lambda (key val)
- (if (memq proc val)
- (puthash key (delq proc val) url-http-open-connections)))
- url-http-open-connections))
-
-(defun url-http-end-of-document-sentinel (proc why)
- ;; Sentinel used for old HTTP/0.9 or connections we know are going
- ;; to die as the 'end of document' notifier.
- (url-http-debug "url-http-end-of-document-sentinel in buffer (%s)"
- (process-buffer proc))
- (url-http-idle-sentinel proc why)
- (save-excursion
- (set-buffer (process-buffer proc))
- (goto-char (point-min))
- (if (not (looking-at "HTTP/"))
- ;; HTTP/0.9 just gets passed back no matter what
- (url-http-activate-callback)
- (if (url-http-parse-headers)
- (url-http-activate-callback)))))
-
-(defun url-http-simple-after-change-function (st nd length)
- ;; Function used when we do NOT know how long the document is going to be
- ;; Just _very_ simple 'downloaded %d' type of info.
- (declare (special url-http-end-of-headers))
- (url-lazy-message "Reading %s..." (url-pretty-length nd)))
-
-(defun url-http-content-length-after-change-function (st nd length)
- "Function used when we DO know how long the document is going to be.
-More sophisticated percentage downloaded, etc.
-Also does minimal parsing of HTTP headers and will actually cause
-the callback to be triggered."
- (declare (special url-current-object
- url-http-end-of-headers
- url-http-content-length
- url-http-content-type
- url-http-process))
- (if url-http-content-type
- (url-display-percentage
- "Reading [%s]... %s of %s (%d%%)"
- (url-percentage (- nd url-http-end-of-headers)
- url-http-content-length)
- url-http-content-type
- (url-pretty-length (- nd url-http-end-of-headers))
- (url-pretty-length url-http-content-length)
- (url-percentage (- nd url-http-end-of-headers)
- url-http-content-length))
- (url-display-percentage
- "Reading... %s of %s (%d%%)"
- (url-percentage (- nd url-http-end-of-headers)
- url-http-content-length)
- (url-pretty-length (- nd url-http-end-of-headers))
- (url-pretty-length url-http-content-length)
- (url-percentage (- nd url-http-end-of-headers)
- url-http-content-length)))
-
- (if (> (- nd url-http-end-of-headers) url-http-content-length)
- (progn
- ;; Found the end of the document! Wheee!
- (url-display-percentage nil nil)
- (message "Reading... done.")
- (if (url-http-parse-headers)
- (url-http-activate-callback)))))
-
-(defun url-http-chunked-encoding-after-change-function (st nd length)
- "Function used when dealing with 'chunked' encoding.
-Cannot give a sophisticated percentage, but we need a different
-function to look for the special 0-length chunk that signifies
-the end of the document."
- (declare (special url-current-object
- url-http-end-of-headers
- url-http-content-type
- url-http-chunked-length
- url-http-chunked-counter
- url-http-process url-http-chunked-start))
- (save-excursion
- (goto-char st)
- (let ((read-next-chunk t)
- (case-fold-search t)
- (regexp nil)
- (no-initial-crlf nil))
- ;; We need to loop thru looking for more chunks even within
- ;; one after-change-function call.
- (while read-next-chunk
- (setq no-initial-crlf (= 0 url-http-chunked-counter))
- (if url-http-content-type
- (url-display-percentage nil
- "Reading [%s]... chunk #%d"
- url-http-content-type url-http-chunked-counter)
- (url-display-percentage nil
- "Reading... chunk #%d"
- url-http-chunked-counter))
- (url-http-debug "Reading chunk %d (%d %d %d)"
- url-http-chunked-counter st nd length)
- (setq regexp (if no-initial-crlf
- "\\([0-9a-z]+\\).*\r?\n"
- "\r?\n\\([0-9a-z]+\\).*\r?\n"))
-
- (if url-http-chunked-start
- ;; We know how long the chunk is supposed to be, skip over
- ;; leading crap if possible.
- (if (> nd (+ url-http-chunked-start url-http-chunked-length))
- (progn
- (url-http-debug "Got to the end of chunk #%d!"
- url-http-chunked-counter)
- (goto-char (+ url-http-chunked-start
- url-http-chunked-length)))
- (url-http-debug "Still need %d bytes to hit end of chunk"
- (- (+ url-http-chunked-start
- url-http-chunked-length)
- nd))
- (setq read-next-chunk nil)))
- (if (not read-next-chunk)
- (url-http-debug "Still spinning for next chunk...")
- (if no-initial-crlf (skip-chars-forward "\r\n"))
- (if (not (looking-at regexp))
- (progn
- ;; Must not have received the entirety of the chunk header,
- ;; need to spin some more.
- (url-http-debug "Did not see start of chunk @ %d!" (point))
- (setq read-next-chunk nil))
- (add-text-properties (match-beginning 0) (match-end 0)
- (list 'start-open t
- 'end-open t
- 'chunked-encoding t
- 'face (if (featurep 'xemacs)
- 'text-cursor
- 'cursor)
- 'invisible t))
- (setq url-http-chunked-length (string-to-int (buffer-substring
- (match-beginning 1)
- (match-end 1))
- 16)
- url-http-chunked-counter (1+ url-http-chunked-counter)
- url-http-chunked-start (set-marker
- (or url-http-chunked-start
- (make-marker))
- (match-end 0)))
-; (if (not url-http-debug)
- (delete-region (match-beginning 0) (match-end 0));)
- (url-http-debug "Saw start of chunk %d (length=%d, start=%d"
- url-http-chunked-counter url-http-chunked-length
- (marker-position url-http-chunked-start))
- (if (= 0 url-http-chunked-length)
- (progn
- ;; Found the end of the document! Wheee!
- (url-http-debug "Saw end of stream chunk!")
- (setq read-next-chunk nil)
- (url-display-percentage nil nil)
- (goto-char (match-end 1))
- (if (re-search-forward "^\r*$" nil t)
- (message "Saw end of trailers..."))
- (if (url-http-parse-headers)
- (url-http-activate-callback))))))))))
-
-(defun url-http-wait-for-headers-change-function (st nd length)
- ;; This will wait for the headers to arrive and then splice in the
- ;; next appropriate after-change-function, etc.
- (declare (special url-current-object
- url-http-end-of-headers
- url-http-content-type
- url-http-content-length
- url-http-transfer-encoding
- url-callback-function
- url-callback-arguments
- url-http-process
- url-http-method
- url-http-after-change-function
- url-http-response-status))
- (url-http-debug "url-http-wait-for-headers-change-function (%s)"
- (buffer-name))
- (if (not (bobp))
- (let ((end-of-headers nil)
- (old-http nil)
- (content-length nil))
- (goto-char (point-min))
- (if (not (looking-at "^HTTP/[1-9]\\.[0-9]"))
- ;; Not HTTP/x.y data, must be 0.9
- ;; God, I wish this could die.
- (setq end-of-headers t
- url-http-end-of-headers 0
- old-http t)
- (if (re-search-forward "^\r*$" nil t)
- ;; Saw the end of the headers
- (progn
- (url-http-debug "Saw end of headers... (%s)" (buffer-name))
- (setq url-http-end-of-headers (set-marker (make-marker)
- (point))
- end-of-headers t)
- (url-http-clean-headers))))
-
- (if (not end-of-headers)
- ;; Haven't seen the end of the headers yet, need to wait
- ;; for more data to arrive.
- nil
- (if old-http
- (message "HTTP/0.9 How I hate thee!")
- (progn
- (url-http-parse-response)
- (mail-narrow-to-head)
- ;;(narrow-to-region (point-min) url-http-end-of-headers)
- (setq url-http-transfer-encoding (mail-fetch-field
- "transfer-encoding")
- url-http-content-type (mail-fetch-field "content-type"))
- (if (mail-fetch-field "content-length")
- (setq url-http-content-length
- (string-to-int (mail-fetch-field "content-length"))))
- (widen)))
- (if url-http-transfer-encoding
- (setq url-http-transfer-encoding
- (downcase url-http-transfer-encoding)))
-
- (cond
- ((or (= url-http-response-status 204)
- (= url-http-response-status 205))
- (url-http-debug "%d response must have headers only (%s)."
- url-http-response-status (buffer-name))
- (if (url-http-parse-headers)
- (url-http-activate-callback)))
- ((string= "HEAD" url-http-method)
- ;; A HEAD request is _ALWAYS_ terminated by the header
- ;; information, regardless of any entity headers,
- ;; according to section 4.4 of the HTTP/1.1 draft.
- (url-http-debug "HEAD request must have headers only (%s)."
- (buffer-name))
- (if (url-http-parse-headers)
- (url-http-activate-callback)))
- ((string= "CONNECT" url-http-method)
- ;; A CONNECT request is finished, but we cannot stick this
- ;; back on the free connectin list
- (url-http-debug "CONNECT request must have headers only.")
- (if (url-http-parse-headers)
- (url-http-activate-callback)))
- ((equal url-http-response-status 304)
- ;; Only allowed to have a header section. We have to handle
- ;; this here instead of in url-http-parse-headers because if
- ;; you have a cached copy of something without a known
- ;; content-length, and try to retrieve it from the cache, we'd
- ;; fall into the 'being dumb' section and wait for the
- ;; connection to terminate, which means we'd wait for 10
- ;; seconds for the keep-alives to time out on some servers.
- (if (url-http-parse-headers)
- (url-http-activate-callback)))
- (old-http
- ;; HTTP/0.9 always signaled end-of-connection by closing the
- ;; connection.
- (url-http-debug
- "Saw HTTP/0.9 response, connection closed means end of document.")
- (setq url-http-after-change-function
- 'url-http-simple-after-change-function))
- ((equal url-http-transfer-encoding "chunked")
- (url-http-debug "Saw chunked encoding.")
- (setq url-http-after-change-function
- 'url-http-chunked-encoding-after-change-function)
- (if (> nd url-http-end-of-headers)
- (progn
- (url-http-debug
- "Calling initial chunked-encoding for extra data at end of headers")
- (url-http-chunked-encoding-after-change-function
- (marker-position url-http-end-of-headers) nd
- (- nd url-http-end-of-headers)))))
- ((integerp url-http-content-length)
- (url-http-debug
- "Got a content-length, being smart about document end.")
- (setq url-http-after-change-function
- 'url-http-content-length-after-change-function)
- (cond
- ((= 0 url-http-content-length)
- ;; We got a NULL body! Activate the callback
- ;; immediately!
- (url-http-debug
- "Got 0-length content-length, activating callback immediately.")
- (if (url-http-parse-headers)
- (url-http-activate-callback)))
- ((> nd url-http-end-of-headers)
- ;; Have some leftover data
- (url-http-debug "Calling initial content-length for extra data at end of headers")
- (url-http-content-length-after-change-function
- (marker-position url-http-end-of-headers)
- nd
- (- nd url-http-end-of-headers)))
- (t
- nil)))
- (t
- (url-http-debug "No content-length, being dumb.")
- (setq url-http-after-change-function
- 'url-http-simple-after-change-function)))))
- ;; We are still at the beginning of the buffer... must just be
- ;; waiting for a response.
- (url-http-debug "Spinning waiting for headers..."))
- (goto-char (point-max)))
-
-;;;###autoload
-(defun url-http (url callback cbargs)
- "Retrieve URL via HTTP asynchronously.
-URL must be a parsed URL. See `url-generic-parse-url' for details.
-When retrieval is completed, the function CALLBACK is executed with
-CBARGS as the arguments."
- (check-type url vector "Need a pre-parsed URL.")
- (declare (special url-current-object
- url-http-end-of-headers
- url-http-content-type
- url-http-content-length
- url-http-transfer-encoding
- url-http-after-change-function
- url-callback-function
- url-callback-arguments
- url-http-method
- url-http-extra-headers
- url-http-data
- url-http-chunked-length
- url-http-chunked-start
- url-http-chunked-counter
- url-http-process))
- (let ((connection (url-http-find-free-connection (url-host url)
- (url-port url)))
- (buffer (generate-new-buffer (format " *http %s:%d*"
- (url-host url)
- (url-port url)))))
- (if (not connection)
- ;; Failed to open the connection for some reason
- (progn
- (kill-buffer buffer)
- (setq buffer nil)
- (error "Could not create connection to %s:%d" (url-host url)
- (url-port url)))
- (save-excursion
- (set-buffer buffer)
- (mm-disable-multibyte)
- (setq url-current-object url
- mode-line-format "%b [%s]")
-
- (dolist (var '(url-http-end-of-headers
- url-http-content-type
- url-http-content-length
- url-http-transfer-encoding
- url-http-after-change-function
- url-http-response-status
- url-http-chunked-length
- url-http-chunked-counter
- url-http-chunked-start
- url-callback-function
- url-callback-arguments
- url-http-process
- url-http-method
- url-http-extra-headers
- url-http-data))
- (set (make-local-variable var) nil))
-
- (setq url-http-method (or url-request-method "GET")
- url-http-extra-headers url-request-extra-headers
- url-http-data url-request-data
- url-http-process connection
- url-http-chunked-length nil
- url-http-chunked-start nil
- url-http-chunked-counter 0
- url-callback-function callback
- url-callback-arguments cbargs
- url-http-after-change-function 'url-http-wait-for-headers-change-function)
-
- (set-process-buffer connection buffer)
- (set-process-sentinel connection 'url-http-end-of-document-sentinel)
- (set-process-filter connection 'url-http-generic-filter)
- (process-send-string connection (url-http-create-request url))))
- buffer))
-
-;; Since Emacs 19/20 does not allow you to change the
-;; `after-change-functions' hook in the midst of running them, we fake
-;; an after change by hooking into the process filter and inserting
-;; the data ourselves. This is slightly less efficient, but there
-;; were tons of weird ways the after-change code was biting us in the
-;; shorts.
-(defun url-http-generic-filter (proc data)
- ;; Sometimes we get a zero-length data chunk after the process has
- ;; been changed to 'free', which means it has no buffer associated
- ;; with it. Do nothing if there is no buffer, or 0 length data.
- (declare (special url-http-after-change-function))
- (and (process-buffer proc)
- (/= (length data) 0)
- (save-excursion
- (set-buffer (process-buffer proc))
- (url-http-debug "Calling after change function `%s' for `%S'" url-http-after-change-function proc)
- (funcall url-http-after-change-function
- (point-max)
- (progn
- (goto-char (point-max))
- (insert data)
- (point-max))
- (length data)))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; file-name-handler stuff from here on out
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(if (not (fboundp 'symbol-value-in-buffer))
- (defun url-http-symbol-value-in-buffer (symbol buffer
- &optional unbound-value)
- "Return the value of SYMBOL in BUFFER, or UNBOUND-VALUE if it is unbound."
- (save-excursion
- (set-buffer buffer)
- (if (not (boundp symbol))
- unbound-value
- (symbol-value symbol))))
- (defalias 'url-http-symbol-value-in-buffer 'symbol-value-in-buffer))
-
-(defun url-http-head (url)
- (let ((url-request-method "HEAD")
- (url-request-data nil))
- (url-retrieve-synchronously url)))
-
-;;;###autoload
-(defun url-http-file-exists-p (url)
- (let ((version nil)
- (status nil)
- (exists nil)
- (buffer (url-http-head url)))
- (if (not buffer)
- (setq exists nil)
- (setq status (url-http-symbol-value-in-buffer 'url-http-response-status
- buffer 500)
- exists (and (>= status 200) (< status 300)))
- (kill-buffer buffer))
- exists))
-
-;;;###autoload
-(defalias 'url-http-file-readable-p 'url-http-file-exists-p)
-
-(defun url-http-head-file-attributes (url)
- (let ((buffer (url-http-head url))
- (attributes nil))
- (when buffer
- (setq attributes (make-list 11 nil))
- (setf (nth 1 attributes) 1) ; Number of links to file
- (setf (nth 2 attributes) 0) ; file uid
- (setf (nth 3 attributes) 0) ; file gid
- (setf (nth 7 attributes) ; file size
- (url-http-symbol-value-in-buffer 'url-http-content-length
- buffer -1))
- (setf (nth 8 attributes) (eval-when-compile (make-string 10 ?-)))
- (kill-buffer buffer))
- attributes))
-
-;;;###autoload
-(defun url-http-file-attributes (url)
- (if (url-dav-supported-p url)
- (url-dav-file-attributes url)
- (url-http-head-file-attributes url)))
-
-;;;###autoload
-(defun url-http-options (url)
- "Returns a property list describing options available for URL.
-This list is retrieved using the `OPTIONS' HTTP method.
-
-Property list members:
-
-methods
- A list of symbols specifying what HTTP methods the resource
- supports.
-
-dav
- A list of numbers specifying what DAV protocol/schema versions are
- supported.
-
-dasl
- A list of supported DASL search types supported (string form)
-
-ranges
- A list of the units available for use in partial document fetches.
-
-p3p
- The `Platform For Privacy Protection' description for the resource.
- Currently this is just the raw header contents. This is likely to
- change once P3P is formally supported by the URL package or
- Emacs/W3.
-"
- (let* ((url-request-method "OPTIONS")
- (url-request-data nil)
- (buffer (url-retrieve-synchronously url))
- (header nil)
- (options nil))
- (when (and buffer (= 2 (/ (url-http-symbol-value-in-buffer
- 'url-http-response-status buffer 0) 100)))
- ;; Only parse the options if we got a 2xx response code!
- (save-excursion
- (save-restriction
- (save-match-data
- (set-buffer buffer)
- (mail-narrow-to-head)
-
- ;; Figure out what methods are supported.
- (when (setq header (mail-fetch-field "allow"))
- (setq options (plist-put
- options 'methods
- (mapcar 'intern (split-string header "[ ,]+")))))
-
- ;; Check for DAV
- (when (setq header (mail-fetch-field "dav"))
- (setq options (plist-put
- options 'dav
- (delq 0
- (mapcar 'string-to-number
- (split-string header "[, ]+"))))))
-
- ;; Now for DASL
- (when (setq header (mail-fetch-field "dasl"))
- (setq options (plist-put
- options 'dasl
- (split-string header "[, ]+"))))
-
- ;; P3P - should get more detailed here. FIXME
- (when (setq header (mail-fetch-field "p3p"))
- (setq options (plist-put options 'p3p header)))
-
- ;; Check for whether they accept byte-range requests.
- (when (setq header (mail-fetch-field "accept-ranges"))
- (setq options (plist-put
- options 'ranges
- (delq 'none
- (mapcar 'intern
- (split-string header "[, ]+"))))))
- ))))
- (if buffer (kill-buffer buffer))
- options))
-
-(provide 'url-http)
-
-;;; url-http.el ends here
+++ /dev/null
-;;; url-https.el --- HTTP over SSL routines
-;; Author: $Author: wmperry $
-;; Created: $Date: 2001/11/22 14:32:13 $
-;; Version: $Revision: 1.3 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url-gw)
-(require 'url-util)
-(require 'url-parse)
-(require 'url-cookie)
-(require 'url-http)
-
-(defconst url-https-default-port 443 "Default HTTPS port.")
-(defconst url-https-asynchronous-p t "HTTPS retrievals are asynchronous.")
-(defalias 'url-https-expand-file-name 'url-http-expand-file-name)
-
-(defmacro url-https-create-secure-wrapper (method args)
- (` (defun (, (intern (format (if method "url-https-%s" "url-https") method))) (, args)
- (, (format "HTTPS wrapper around `%s' call." (or method "url-http")))
- (condition-case ()
- (require 'ssl)
- (error
- (error "HTTPS support could not find `ssl' library.")))
- (let ((url-gateway-method 'ssl))
- ((, (intern (format (if method "url-http-%s" "url-http") method))) (,@ (remove '&rest (remove '&optional args))))))))
-
-(url-https-create-secure-wrapper nil (url callback cbargs))
-(url-https-create-secure-wrapper file-exists-p (url))
-(url-https-create-secure-wrapper file-readable-p (url))
-(url-https-create-secure-wrapper file-attributes (url))
-
-(provide 'url-https)
+++ /dev/null
-;;; url-imap.el --- IMAP retrieval routines
-;; Author: Simon Josefsson <jasNOSPAMpdc.kth.se>
-;; Created: $Date: 2002/01/22 17:52:16 $
-;; Version: $Revision: 1.4 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-; Anyway, here's a teaser. It's quite broken in lots of regards, but at
-; least it seem to work. At least a little. At least when called
-; manually like this (I've no idea how it's supposed to be called):
-
-; (url-imap (url-generic-parse-url "imap://cyrus.andrew.cmu.edu/archive.c-client;UID=1021"))
-
-(eval-when-compile (require 'cl))
-(require 'url-util)
-(require 'url-parse)
-(require 'nnimap)
-(require 'mm-util)
-
-(defconst url-imap-default-port 143 "Default IMAP port")
-
-(defun url-imap-open-host (host port user pass)
- ;; xxx use user and password
- (if (fboundp 'nnheader-init-server-buffer)
- (nnheader-init-server-buffer))
- (let ((imap-username user)
- (imap-password pass)
- (authenticator (if user 'login 'anonymous)))
- (if (stringp port)
- (setq port (string-to-int port)))
- (nnimap-open-server host
- `((nnimap-server-port ,port)
- (nnimap-stream 'network)
- (nnimap-authenticator ,authenticator)))))
-
-(defun url-imap (url)
- (check-type url vector "Need a pre-parsed URL.")
- (save-excursion
- (set-buffer (generate-new-buffer " *url-imap*"))
- (mm-disable-multibyte)
- (let* ((host (url-host url))
- (port (url-port url))
- ;; xxx decode mailbox (see rfc2192)
- (mailbox (url-filename url))
- (coding-system-for-read 'binary))
- (and (eq (string-to-char mailbox) ?/)
- (setq mailbox (substring mailbox 1)))
- (url-imap-open-host host port (url-user url) (url-password url))
- (cond ((assoc "TYPE" (url-attributes url))
- ;; xxx list mailboxes (start gnus?)
- )
- ((assoc "UID" (url-attributes url))
- ;; fetch message part
- ;; xxx handle partial fetches
- (insert "Content-type: message/rfc822\n\n")
- (nnimap-request-article (cdr (assoc "UID" (url-attributes url)))
- mailbox host (current-buffer)))
- (t
- ;; xxx list messages in mailbox (start gnus?)
- )))
- (current-buffer)))
+++ /dev/null
-;;; url-irc.el --- IRC URL interface
-;; Author: $Author: wmperry $
-;; Created: $Date: 1999/12/24 12:13:33 $
-;; Version: $Revision: 1.2 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; IRC URLs are defined in http://www.w3.org/Addressing/draft-mirashi-url-irc-01.txt
-
-(require 'url-vars)
-(require 'url-parse)
-
-(defconst url-irc-default-port 6667 "Default port for IRC connections")
-
-(defcustom url-irc-function 'url-irc-zenirc
- "*Function to actually open an IRC connection.
-Should be a function that takes several argument:
- HOST - the hostname of the IRC server to contact
- PORT - the port number of the IRC server to contact
- CHANNEL - What channel on the server to visit right away (can be nil)
- USER - What username to use
-PASSWORD - What password to use"
- :type '(choice (const :tag "ZEN IRC" :value 'url-irc-zenirc)
- (function :tag "Other"))
- :group 'url)
-
-(defun url-irc-zenirc (host port channel user password)
- (let ((zenirc-buffer-name (if (and user host port)
- (format "%s@%s:%d" user host port)
- (format "%s:%d" host port)))
- (zenirc-server-alist
- (list
- (list host port password nil user))))
- (zenirc)
- (goto-char (point-max))
- (if (not channel)
- nil
- (insert "/join " channel)
- (zenirc-send-line))))
-
-;;;###autoload
-(defun url-irc (url)
- (let* ((host (url-host url))
- (port (string-to-int (url-port url)))
- (pass (url-password url))
- (user (url-user url))
- (chan (url-filename url)))
- (if (url-target url)
- (setq chan (concat chan "#" (url-target url))))
- (if (string-match "^/" chan)
- (setq chan (substring chan 1 nil)))
- (if (= (length chan) 0)
- (setq chan nil))
- (funcall url-irc-function host port chan user pass)
- nil))
-
-(provide 'url-irc)
+++ /dev/null
-;;; url-ldap.el --- LDAP Uniform Resource Locator retrieval code
-;; Author: $Author: wmperry $
-;; Created: $Date: 1999/11/26 12:11:50 $
-;; Version: $Revision: 1.1.1.1 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1998 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url-vars)
-(require 'url-parse)
-(require 'url-util)
-
-;; This has been implemented from RFC2255 'The LDAP URL Format' (Dec 1997)
-;;
-;; basic format is: ldap://host:port/dn?attributes?scope?filter?extensions
-;;
-;; Test URLs:
-;; ldap://ldap.itd.umich.edu/cn%3Dumbflabmanager%2C%20ou%3DUser%20Groups%2C%20ou%3DGroups%2C%20o%3DUniversity%20of%20Michigan%2C%20c%3DUS
-;; ldap://ldap.itd.umich.edu/o=University%20of%20Michigan,c=US
-;;
-;; For simple queries, I have verified compatibility with Netscape
-;; Communicator v4.5 under linux.
-;;
-;; For anything _useful_ though, like specifying the attributes,
-;; scope, filter, or extensions, netscape claims the URL format is
-;; unrecognized. So I don't think it supports anything other than the
-;; defaults (scope=base,attributes=*,filter=(objectClass=*)
-
-(defconst url-ldap-default-port 389 "Default LDAP port.")
-(defalias 'url-ldap-expand-file-name 'url-default-expander)
-
-(defvar url-ldap-pretty-names
- '(("l" . "City")
- ("objectclass" . "Object Class")
- ("o" . "Organization")
- ("ou" . "Organizational Unit")
- ("cn" . "Name")
- ("sn" . "Last Name")
- ("givenname" . "First Name")
- ("mail" . "Email")
- ("title" . "Title")
- ("c" . "Country")
- ("postalcode" . "ZIP Code")
- ("telephonenumber" . "Phone Number")
- ("facsimiletelephonenumber" . "Fax")
- ("postaladdress" . "Mailing Address")
- ("description" . "Notes"))
- "*An assoc list mapping LDAP attribute names to pretty descriptions of them.")
-
-(defvar url-ldap-attribute-formatters
- '(("mail" . (lambda (x) (format "<a href='mailto:%s'>%s</a>" x x)))
- ("owner" . url-ldap-dn-formatter)
- ("creatorsname" . url-ldap-dn-formatter)
- ("jpegphoto" . url-ldap-image-formatter)
- ("usercertificate" . url-ldap-certificate-formatter)
- ("modifiersname" . url-ldap-dn-formatter)
- ("namingcontexts" . url-ldap-dn-formatter)
- ("defaultnamingcontext" . url-ldap-dn-formatter)
- ("member" . url-ldap-dn-formatter))
- "*An assoc list mapping LDAP attribute names to pretty formatters for them.")
-
-(defsubst url-ldap-attribute-pretty-name (n)
- (or (cdr-safe (assoc (downcase n) url-ldap-pretty-names)) n))
-
-(defsubst url-ldap-attribute-pretty-desc (n v)
- (if (string-match "^\\([^;]+\\);" n)
- (setq n (match-string 1 n)))
- (funcall (or (cdr-safe (assoc (downcase n) url-ldap-attribute-formatters)) 'identity) v))
-
-(defun url-ldap-dn-formatter (dn)
- (concat "<a href='/"
- (url-hexify-string dn)
- "'>" dn "</a>"))
-
-(defun url-ldap-certificate-formatter (data)
- (condition-case ()
- (require 'ssl)
- (error nil))
- (let ((vals (and (fboundp 'ssl-certificate-information)
- (ssl-certificate-information data))))
- (if (not vals)
- "<b>Unable to parse certificate</b>"
- (concat "<table border=0>\n"
- (mapconcat
- (lambda (ava)
- (format "<tr><td>%s</td><td>%s</td></tr>\n" (car ava) (cdr ava)))
- vals "\n")
- "</table>\n"))))
-
-(defun url-ldap-image-formatter (data)
- (format "<img alt='JPEG Photo' src='data:image/jpeg;base64,%s'>"
- (url-hexify-string (base64-encode-string data))))
-
-;;;###autoload
-(defun url-ldap (url)
- (save-excursion
- (set-buffer (generate-new-buffer " *url-ldap*"))
- (setq url-current-object url)
- (insert "Content-type: text/html\r\n\r\n")
- (if (not (fboundp 'ldap-search-internal))
- (insert "<html>\n"
- " <head>\n"
- " <title>LDAP Not Supported</title>\n"
- " <base href='" (url-recreate-url url) "'>\n"
- " </head>\n"
- " <body>\n"
- " <h1>LDAP Not Supported</h1>\n"
- " <p>\n"
- " This version of Emacs does not support LDAP.\n"
- " </p>\n"
- " </body>\n"
- "</html>\n")
- (let* ((binddn nil)
- (data (url-filename url))
- (host (url-host url))
- (port (url-port url))
- (base-object nil)
- (attributes nil)
- (scope nil)
- (filter nil)
- (extensions nil)
- (connection nil)
- (results nil)
- (extract-dn (and (fboundp 'function-max-args)
- (= (function-max-args 'ldap-search-internal) 7))))
-
- ;; Get rid of leading /
- (if (string-match "^/" data)
- (setq data (substring data 1)))
-
- (setq data (mapcar (lambda (x) (if (/= (length x) 0) x nil)) (split-string data "\\?"))
- base-object (nth 0 data)
- attributes (nth 1 data)
- scope (nth 2 data)
- filter (nth 3 data)
- extensions (nth 4 data))
-
- ;; fill in the defaults
- (setq base-object (url-unhex-string (or base-object ""))
- scope (intern (url-unhex-string (or scope "base")))
- filter (url-unhex-string (or filter "(objectClass=*)")))
-
- (if (not (memq scope '(base one tree)))
- (error "Malformed LDAP URL: Unknown scope: %S" scope))
-
- ;; Convert to the internal LDAP support scoping names.
- (setq scope (cdr (assq scope '((base . base) (one . onelevel) (sub . subtree)))))
-
- (if attributes
- (setq attributes (mapcar 'url-unhex-string (split-string attributes ","))))
-
- ;; Parse out the exentions
- (if extensions
- (setq extensions (mapcar (lambda (ext)
- (if (string-match "\\([^=]*\\)=\\(.*\\)" ext)
- (cons (match-string 1 ext) (match-string 2 ext))
- (cons ext ext)))
- (split-string extensions ","))
- extensions (mapcar (lambda (ext)
- (cons (url-unhex-string (car ext))
- (url-unhex-string (cdr ext))))
- extensions)))
-
- (setq binddn (cdr-safe (or (assoc "bindname" extensions)
- (assoc "!bindname" extensions))))
-
- ;; Now, let's actually do something with it.
- (setq connection (ldap-open host (if binddn (list 'binddn binddn)))
- results (if extract-dn
- (ldap-search-internal connection filter base-object scope attributes nil t)
- (ldap-search-internal connection filter base-object scope attributes nil)))
-
- (ldap-close connection)
- (insert "<html>\n"
- " <head>\n"
- " <title>LDAP Search Results</title>\n"
- " <base href='" (url-recreate-url url) "'>\n"
- " </head>\n"
- " <body>\n"
- " <h1>" (int-to-string (length results)) " matches</h1>\n")
-
- (mapc (lambda (obj)
- (insert " <hr>\n"
- " <table border=1>\n")
- (if extract-dn
- (insert " <tr><th colspan=2>" (car obj) "</th></tr>\n"))
- (mapc (lambda (attr)
- (if (= (length (cdr attr)) 1)
- ;; single match, easy
- (insert " <tr><td>"
- (url-ldap-attribute-pretty-name (car attr))
- "</td><td>"
- (url-ldap-attribute-pretty-desc (car attr) (car (cdr attr)))
- "</td></tr>\n")
- ;; Multiple matches, slightly uglier
- (insert " <tr>\n"
- (format " <td valign=top>" (length (cdr attr)))
- (url-ldap-attribute-pretty-name (car attr)) "</td><td>"
- (mapconcat (lambda (x)
- (url-ldap-attribute-pretty-desc (car attr) x))
- (cdr attr)
- "<br>\n")
- "</td>"
- " </tr>\n")))
- (if extract-dn (cdr obj) obj))
- (insert " </table>\n"))
- results)
-
- (insert " <hr>\n"
- " </body>\n"
- "</html>\n")))
- (current-buffer)))
-
-(provide 'url-ldap)
+++ /dev/null
-;;; url-mail.el --- Mail Uniform Resource Locator retrieval code
-;; Author: $Author: fx $
-;; Created: $Date: 2001/10/05 17:04:06 $
-;; Version: $Revision: 1.4 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(eval-when-compile (require 'cl))
-(require 'url-vars)
-(require 'url-parse)
-(require 'url-util)
-
-;;;###autoload
-(defun url-mail (&rest args)
- (interactive "P")
- (if (fboundp 'message-mail)
- (apply 'message-mail args)
- (or (apply 'mail args)
- (error "Mail aborted"))))
-
-(defun url-mail-goto-field (field)
- (if (not field)
- (goto-char (point-max))
- (let ((dest nil)
- (lim nil)
- (case-fold-search t))
- (save-excursion
- (goto-char (point-min))
- (if (re-search-forward (regexp-quote mail-header-separator) nil t)
- (setq lim (match-beginning 0)))
- (goto-char (point-min))
- (if (re-search-forward (concat "^" (regexp-quote field) ":") lim t)
- (setq dest (match-beginning 0))))
- (if dest
- (progn
- (goto-char dest)
- (end-of-line))
- (goto-char lim)
- (insert (capitalize field) ": ")
- (save-excursion
- (insert "\n"))))))
-
-;;;###autoload
-(defun url-mailto (url)
- "Handle the mailto: URL syntax."
- (if (url-user url)
- ;; malformed mailto URL (mailto://wmperryNOSPAMgnu.org instead of
- ;; mailto:wmperryNOSPAMgnu.org
- (url-set-filename url (concat (url-user url) "@" (url-filename url))))
- (setq url (url-filename url))
- (let (to args source-url subject func headers-start)
- (if (string-match (regexp-quote "?") url)
- (setq headers-start (match-end 0)
- to (url-unhex-string (substring url 0 (match-beginning 0)))
- args (url-parse-query-string
- (substring url headers-start nil) t))
- (setq to (url-unhex-string url)))
- (setq source-url (url-view-url t))
- (if (and url-request-data (not (assoc "subject" args)))
- (setq args (cons (list "subject"
- (concat "Automatic submission from "
- url-package-name "/"
- url-package-version)) args)))
- (if (and source-url (not (assoc "x-url-from" args)))
- (setq args (cons (list "x-url-from" source-url) args)))
-
- (if (assoc "to" args)
- (push to (cdr (assoc "to" args)))
- (setq args (cons (list "to" to) args)))
- (setq subject (cdr-safe (assoc "subject" args)))
- (if (fboundp url-mail-command) (funcall url-mail-command) (mail))
- (while args
- (if (string= (caar args) "body")
- (progn
- (goto-char (point-max))
- (insert (mapconcat 'identity (cdar args) "\n")))
- (url-mail-goto-field (caar args))
- (setq func (intern-soft (concat "mail-" (caar args))))
- (insert (mapconcat 'identity (cdar args) ", ")))
- (setq args (cdr args)))
- ;; (url-mail-goto-field "User-Agent")
-;; (insert url-package-name "/" url-package-version " URL/" url-version)
- (if (not url-request-data)
- (progn
- (set-buffer-modified-p nil)
- (if subject
- (url-mail-goto-field nil)
- (url-mail-goto-field "subject")))
- (if url-request-extra-headers
- (mapconcat
- (lambda (x)
- (url-mail-goto-field (car x))
- (insert (cdr x)))
- url-request-extra-headers ""))
- (goto-char (point-max))
- (insert url-request-data)
- ;; It seems Microsoft-ish to send without warning.
- ;; Fixme: presumably this should depend on a privacy setting.
- (if (y-or-n-p "Send this auto-generated mail? ")
- (cond ((eq url-mail-command 'compose-mail)
- (funcall (get mail-user-agent 'sendfunc) nil))
- ;; otherwise, we can't be sure
- ((fboundp 'message-mail)
- (message-send-and-exit))
- (t (mail-send-and-exit nil)))))
- nil))
-
-(provide 'url-mailto)
+++ /dev/null
-;;; url-methods.el --- Load URL schemes as needed
-;; Author: $Author: wmperry $
-;; Created: $Date: 2002/11/04 14:40:32 $
-;; Version: $Revision: 1.14 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(eval-when-compile
- (require 'cl))
-
-;; This loads up some of the small, silly URLs that I really don't
-;; want to bother putting in their own separate files.
-(require 'url-auto)
-(require 'url-parse)
-
-(defvar url-scheme-registry (make-hash-table :size 7 :test 'equal))
-
-(defconst url-scheme-methods
- '((default-port . variable)
- (asynchronous-p . variable)
- (expand-file-name . function)
- (file-exists-p . function)
- (file-attributes . function)
- (parse-url . function)
- (file-symlink-p . function)
- (file-writable-p . function)
- (file-directory-p . function)
- (file-executable-p . function)
- (directory-files . function)
- (file-truename . function))
- "Assoc-list of methods that each URL loader can provide.")
-
-(defconst url-scheme-default-properties
- (list 'name "unknown"
- 'loader 'url-scheme-default-loader
- 'default-port 0
- 'expand-file-name 'url-identity-expander
- 'parse-url 'url-generic-parse-url
- 'asynchronous-p nil
- 'file-directory-p 'ignore
- 'file-truename (lambda (&rest args)
- (url-recreate-url (car args)))
- 'file-exists-p 'ignore
- 'file-attributes 'ignore))
-
-(defun url-scheme-default-loader (url &optional callback cbargs)
- "Signal an error for an unknown URL scheme."
- (error "Unkown URL scheme: %s" (url-type url)))
-
-(defun url-scheme-register-proxy (scheme)
- "Automatically find a proxy for SCHEME and put it in `url-proxy-services'."
- (let* ((env-var (concat scheme "_proxy"))
- (env-proxy (or (getenv (upcase env-var))
- (getenv (downcase env-var))))
- (cur-proxy (assoc scheme url-proxy-services))
- (urlobj nil))
-
- ;; Store any proxying information - this will not overwrite an old
- ;; entry, so that people can still set this information in their
- ;; .emacs file
- (cond
- (cur-proxy nil) ; Keep their old settings
- ((null env-proxy) nil) ; No proxy setup
- ;; First check if its something like hostname:port
- ((string-match "^\\([^:]+\\):\\([0-9]+\\)$" env-proxy)
- (setq urlobj (url-generic-parse-url nil)) ; Get a blank object
- (url-set-type urlobj "http")
- (url-set-host urlobj (match-string 1 env-proxy))
- (url-set-port urlobj (string-to-number (match-string 2 env-proxy))))
- ;; Then check if its a fully specified URL
- ((string-match url-nonrelative-link env-proxy)
- (setq urlobj (url-generic-parse-url env-proxy))
- (url-set-type urlobj "http")
- (url-set-target urlobj nil))
- ;; Finally, fall back on the assumption that its just a hostname
- (t
- (setq urlobj (url-generic-parse-url nil)) ; Get a blank object
- (url-set-type urlobj "http")
- (url-set-host urlobj env-proxy)))
-
- (if (and (not cur-proxy) urlobj)
- (progn
- (setq url-proxy-services
- (cons (cons scheme (format "%s:%d" (url-host urlobj)
- (url-port urlobj)))
- url-proxy-services))
- (message "Using a proxy for %s..." scheme)))))
-
-(defun url-scheme-get-property (scheme property)
- "Get property of a URL SCHEME.
-Will automatically try to load a backend from url-SCHEME.el if
-it has not already been loaded."
- (setq scheme (downcase scheme))
- (let ((desc (gethash scheme url-scheme-registry)))
- (if (not desc)
- (let* ((stub (concat "url-" scheme))
- (loader (intern stub)))
- (condition-case ()
- (require loader)
- (error nil))
- (if (fboundp loader)
- (progn
- ;; Found the module to handle <scheme> URLs
- (url-scheme-register-proxy scheme)
- (setq desc (list 'name scheme
- 'loader loader))
- (dolist (cell url-scheme-methods)
- (let ((symbol (intern-soft (format "%s-%s" stub (car cell))))
- (type (cdr cell)))
- (if symbol
- (case type
- (function
- ;; Store the symbol name of a function
- (if (fboundp symbol)
- (setq desc (plist-put desc (car cell) symbol))))
- (variable
- ;; Store the VALUE of a variable
- (if (boundp symbol)
- (setq desc (plist-put desc (car cell)
- (symbol-value symbol)))))
- (otherwise
- (error "Malformed url-scheme-methods entry: %S"
- cell))))))
- (puthash scheme desc url-scheme-registry)))))
- (or (plist-get desc property)
- (plist-get url-scheme-default-properties property))))
-
-(provide 'url-methods)
+++ /dev/null
-;;; url-misc.el --- Misc Uniform Resource Locator retrieval code
-;; Author: $Author: fx $
-;; Created: $Date: 2002/04/22 22:23:59 $
-;; Version: $Revision: 1.5 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996, 97, 98, 99, 2002 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url-vars)
-(require 'url-parse)
-(autoload 'Info-goto-node "info" "" t)
-(autoload 'man "man" nil t)
-
-;;;###autoload
-(defun url-man (url)
- "Fetch a Unix manual page URL."
- (man (url-filename url))
- nil)
-
-;;;###autoload
-(defun url-info (url)
- "Fetch a GNU Info URL."
- ;; Fetch an info node
- (let* ((fname (url-filename url))
- (node (url-unhex-string (or (url-target url) "Top"))))
- (if (and fname node)
- (Info-goto-node (concat "(" fname ")" node))
- (error "Malformed url: %s" (url-recreate-url url)))
- nil))
-
-(defun url-do-terminal-emulator (type server port user)
- (terminal-emulator
- (generate-new-buffer (format "%s%s" (if user (concat user "@") "") server))
- (case type
- (rlogin "rlogin")
- (telnet "telnet")
- (tn3270 "tn3270")
- (otherwise
- (error "Unknown terminal emulator required: %s" type)))
- (case type
- (rlogin
- (if user
- (list server "-l" user)
- (list server)))
- (telnet
- (if user (message "Please log in as user: %s" user))
- (if port
- (list server port)
- (list server)))
- (tn3270
- (if user (message "Please log in as user: %s" user))
- (list server)))))
-
-;;;###autoload
-(defun url-generic-emulator-loader (url)
- (let* ((type (intern (downcase (url-type url))))
- (server (url-host url))
- (name (url-user url))
- (port (url-port url)))
- (url-do-terminal-emulator type server port name))
- nil)
-
-;;;###autoload
-(defalias 'url-rlogin 'url-generic-emulator-loader)
-;;;###autoload
-(defalias 'url-telnet 'url-generic-emulator-loader)
-;;;###autoload
-(defalias 'url-tn3270 'url-generic-emulator-loader)
-
-;; RFC 2397
-;;;###autoload
-(defun url-data (url)
- "Fetch a data URL (RFC 2397)."
- (let ((mediatype nil)
- ;; The mediatype may need to be hex-encoded too -- see the RFC.
- (desc (url-unhex-string (url-filename url)))
- (encoding "8bit")
- (data nil))
- (save-excursion
- (if (not (string-match "\\([^,]*\\)?," desc))
- (error "Malformed data URL: %s" desc)
- (setq mediatype (match-string 1 desc))
- (if (and mediatype (string-match ";base64\\'" mediatype))
- (setq mediatype (substring mediatype 0 (match-beginning 0))
- encoding "base64"))
- (if (or (null mediatype)
- (eq ?\; (aref mediatype 0)))
- (setq mediatype (concat "text/plain" mediatype)))
- (setq data (url-unhex-string (substring desc (match-end 0)))))
- (set-buffer (generate-new-buffer " *url-data*"))
- (mm-disable-multibyte)
- (insert (format "Content-Length: %d\n" (length data))
- "Content-Type: " mediatype "\n"
- "Content-Encoding: " encoding "\n"
- "\n")
- (if data (insert data))
- (current-buffer))))
-
-(provide 'url-misc)
+++ /dev/null
-;;; url-news.el --- News Uniform Resource Locator retrieval code
-;; Author: $Author: fx $
-;; Created: $Date: 2001/05/22 16:13:00 $
-;; Version: $Revision: 1.3 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(require 'url-vars)
-(require 'url-util)
-(require 'url-parse)
-(require 'nntp)
-(autoload 'url-warn "url")
-(autoload 'gnus-group-read-ephemeral-group "gnus-group")
-(eval-when-compile (require 'cl))
-
-(defgroup url-news nil
- "News related options"
- :group 'url)
-
-(defun url-news-open-host (host port user pass)
- (if (fboundp 'nnheader-init-server-buffer)
- (nnheader-init-server-buffer))
- (nntp-open-server host (list (string-to-int port)))
- (if (and user pass)
- (progn
- (nntp-send-command "^.*\r?\n" "AUTHINFO USER" user)
- (nntp-send-command "^.*\r?\n" "AUTHINFO PASS" pass)
- (if (not (nntp-server-opened host))
- (url-warn 'url (format "NNTP authentication to `%s' as `%s' failed"
- host user))))))
-
-(defun url-news-fetch-message-id (host message-id)
- (let ((buf (generate-new-buffer " *url-news*")))
- (if (eq ?> (aref message-id (1- (length message-id))))
- nil
- (setq message-id (concat "<" message-id ">")))
- (if (cdr-safe (nntp-request-article message-id nil host buf))
- ;; Successfully retrieved the article
- nil
- (save-excursion
- (set-buffer buf)
- (insert "Content-type: text/html\n\n"
- "<html>\n"
- " <head>\n"
- " <title>Error</title>\n"
- " </head>\n"
- " <body>\n"
- " <div>\n"
- " <h1>Error requesting article...</h1>\n"
- " <p>\n"
- " The status message returned by the NNTP server was:"
- "<br><hr>\n"
- " <xmp>\n"
- (nntp-status-message)
- " </xmp>\n"
- " </p>\n"
- " <p>\n"
- " If you If you feel this is an error, <a href=\""
- "mailto:" url-bug-address "\">send me mail</a>\n"
- " </p>\n"
- " </div>\n"
- " </body>\n"
- "</html>\n"
- "<!-- Automatically generated by URL v" url-version " -->\n"
- )))
- buf))
-
-(defun url-news-fetch-newsgroup (newsgroup host)
- (declare (special gnus-group-buffer))
- (if (string-match "^/+" newsgroup)
- (setq newsgroup (substring newsgroup (match-end 0))))
- (if (string-match "/+$" newsgroup)
- (setq newsgroup (substring newsgroup 0 (match-beginning 0))))
-
- ;; This saves us from checking new news if GNUS is already running
- ;; FIXME - is it relatively safe to use gnus-alive-p here? FIXME
- (if (or (not (get-buffer gnus-group-buffer))
- (save-excursion
- (set-buffer gnus-group-buffer)
- (not (eq major-mode 'gnus-group-mode))))
- (gnus))
- (set-buffer gnus-group-buffer)
- (goto-char (point-min))
- (gnus-group-read-ephemeral-group newsgroup
- (list 'nntp host
- 'nntp-open-connection-function
- nntp-open-connection-function)
- nil
- (cons (current-buffer) 'browse)))
-
-;;;###autoload
-(defun url-news (url)
- ;; Find a news reference
- (let* ((host (or (url-host url) url-news-server))
- (port (url-port url))
- (article-brackets nil)
- (buf nil)
- (article (url-filename url)))
- (url-news-open-host host port (url-user url) (url-password url))
- (setq article (url-unhex-string article))
- (cond
- ((string-match "@" article) ; Its a specific article
- (setq buf (url-news-fetch-message-id host article)))
- ((string= article "") ; List all newsgroups
- (gnus))
- (t ; Whole newsgroup
- (url-news-fetch-newsgroup article host)))
- buf))
-
-;;;###autoload
-(defun url-snews (url)
- (let ((nntp-open-connection-function 'nntp-open-ssl-stream))
- (url-news url)))
-
-(provide 'url-news)
+++ /dev/null
-;;; url-nfs.el --- NFS URL interface
-;; Author: $Author: fx $
-;; Created: $Date: 2001/05/22 16:10:50 $
-;; Version: $Revision: 1.3 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(eval-when-compile (require 'cl))
-(require 'url-parse)
-(require 'url-file)
-
-(defvar url-nfs-automounter-directory-spec
- "file:/net/%h%f"
- "*How to invoke the NFS automounter. Certain % sequences are recognized.
-
-%h -- the hostname of the NFS server
-%n -- the port # of the NFS server
-%u -- the username to use to authenticate
-%p -- the password to use to authenticate
-%f -- the filename on the remote server
-%% -- a literal %
-
-Each can be used any number of times.")
-
-(defun url-nfs-unescape (format host port user pass file)
- (save-excursion
- (set-buffer (get-buffer-create " *nfs-parse*"))
- (erase-buffer)
- (insert format)
- (goto-char (point-min))
- (while (re-search-forward "%\\(.\\)" nil t)
- (let ((escape (aref (match-string 1) 0)))
- (replace-match "" t t)
- (case escape
- (?% (insert "%"))
- (?h (insert host))
- (?n (insert (or port "")))
- (?u (insert (or user "")))
- (?p (insert (or pass "")))
- (?f (insert (or file "/"))))))
- (buffer-string)))
-
-(defun url-nfs-build-filename (url)
- (let* ((host (url-host url))
- (port (string-to-int (url-port url)))
- (pass (url-password url))
- (user (url-user url))
- (file (url-filename url)))
- (url-generic-parse-url
- (url-nfs-unescape url-nfs-automounter-directory-spec
- host port user pass file))))
-
-(defun url-nfs (url callback cbargs)
- (url-file (url-nfs-build-filename url) callback cbargs))
-
-(defmacro url-nfs-create-wrapper (method args)
- (` (defun (, (intern (format "url-nfs-%s" method))) (, args)
- (, (format "NFS URL wrapper around `%s' call." method))
- (setq url (url-nfs-build-filename url))
- (and url ((, (intern (format "url-file-%s" method)))
- (,@ (remove '&rest (remove '&optional args))))))))
-
-(url-nfs-create-wrapper file-exists-p (url))
-(url-nfs-create-wrapper file-attributes (url))
-(url-nfs-create-wrapper file-symlink-p (url))
-(url-nfs-create-wrapper file-readable-p (url))
-(url-nfs-create-wrapper file-writable-p (url))
-(url-nfs-create-wrapper file-executable-p (url))
-(if (featurep 'xemacs)
- (progn
- (url-nfs-create-wrapper directory-files (url &optional full match nosort files-only))
- (url-nfs-create-wrapper file-truename (url &optional default)))
- (url-nfs-create-wrapper directory-files (url &optional full match nosort))
- (url-nfs-create-wrapper file-truename (url &optional counter prev-dirs)))
-
-(provide 'url-nfs)
+++ /dev/null
-;;; url-ns.el --- Various netscape-ish functions for proxy definitions
-;; Author: $Author: fx $
-;; Created: $Date: 2000/12/20 21:08:02 $
-;; Version: $Revision: 1.2 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1997 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url-gw)
-
-;;;###autoload
-(defun isPlainHostName (host)
- (not (string-match "\\." host)))
-
-;;;###autoload
-(defun dnsDomainIs (host dom)
- (string-match (concat (regexp-quote dom) "$") host))
-
-;;;###autoload
-(defun dnsResolve (host)
- (url-gateway-nslookup-host host))
-
-;;;###autoload
-(defun isResolvable (host)
- (if (string-match "^[0-9.]+$" host)
- t
- (not (string= host (url-gateway-nslookup-host host)))))
-
-;;;###autoload
-(defun isInNet (ip net mask)
- (let ((netc (split-string ip "\\."))
- (ipc (split-string net "\\."))
- (maskc (split-string mask "\\.")))
- (if (or (/= (length netc) (length ipc))
- (/= (length ipc) (length maskc)))
- nil
- (setq netc (mapcar 'string-to-int netc)
- ipc (mapcar 'string-to-int ipc)
- maskc (mapcar 'string-to-int maskc))
- (and
- (= (logand (nth 0 netc) (nth 0 maskc))
- (logand (nth 0 ipc) (nth 0 maskc)))
- (= (logand (nth 1 netc) (nth 1 maskc))
- (logand (nth 1 ipc) (nth 1 maskc)))
- (= (logand (nth 2 netc) (nth 2 maskc))
- (logand (nth 2 ipc) (nth 2 maskc)))
- (= (logand (nth 3 netc) (nth 3 maskc))
- (logand (nth 3 ipc) (nth 3 maskc)))))))
-
-;; Netscape configuration file parsing
-(defvar url-ns-user-prefs nil
- "Internal, do not use.")
-
-;;;###autoload
-(defun url-ns-prefs (&optional file)
- (if (not file)
- (setq file (expand-file-name "~/.netscape/preferences.js")))
- (if (not (and (file-exists-p file)
- (file-readable-p file)))
- (message "Could not open %s for reading" file)
- (save-excursion
- (let ((false nil)
- (true t))
- (setq url-ns-user-prefs (make-hash-table :size 13 :test 'equal))
- (set-buffer (get-buffer-create " *ns-parse*"))
- (erase-buffer)
- (insert-file-contents file)
- (goto-char (point-min))
- (while (re-search-forward "^//" nil t)
- (replace-match ";;"))
- (goto-char (point-min))
- (while (re-search-forward "^user_pref(" nil t)
- (replace-match "(url-ns-set-user-pref "))
- (goto-char (point-min))
- (while (re-search-forward "\"," nil t)
- (replace-match "\""))
- (goto-char (point-min))
- (eval-buffer)))))
-
-(defun url-ns-set-user-pref (key val)
- (puthash key val url-ns-user-prefs))
-
-;;;###autoload
-(defun url-ns-user-pref (key &optional default)
- (gethash key url-ns-user-prefs default))
-
-(provide 'url-ns)
+++ /dev/null
-;;; url-parse.el --- Uniform Resource Locator parser
-;; Author: $Author: fx $
-;; Created: $Date: 2001/10/01 11:52:06 $
-;; Version: $Revision: 1.4 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(require 'url-auto)
-(require 'url-vars)
-
-(autoload 'url-scheme-get-property "url-methods")
-
-(defmacro url-type (urlobj)
- `(aref ,urlobj 0))
-
-(defmacro url-user (urlobj)
- `(aref ,urlobj 1))
-
-(defmacro url-password (urlobj)
- `(aref ,urlobj 2))
-
-(defmacro url-host (urlobj)
- `(aref ,urlobj 3))
-
-(defmacro url-port (urlobj)
- `(or (aref ,urlobj 4)
- (if (url-fullness ,urlobj)
- (url-scheme-get-property (url-type ,urlobj) 'default-port))))
-
-(defmacro url-filename (urlobj)
- `(aref ,urlobj 5))
-
-(defmacro url-target (urlobj)
- `(aref ,urlobj 6))
-
-(defmacro url-attributes (urlobj)
- `(aref ,urlobj 7))
-
-(defmacro url-fullness (urlobj)
- `(aref ,urlobj 8))
-
-(defmacro url-set-type (urlobj type)
- `(aset ,urlobj 0 ,type))
-
-(defmacro url-set-user (urlobj user)
- `(aset ,urlobj 1 ,user))
-
-(defmacro url-set-password (urlobj pass)
- `(aset ,urlobj 2 ,pass))
-
-(defmacro url-set-host (urlobj host)
- `(aset ,urlobj 3 ,host))
-
-(defmacro url-set-port (urlobj port)
- `(aset ,urlobj 4 ,port))
-
-(defmacro url-set-filename (urlobj file)
- `(aset ,urlobj 5 ,file))
-
-(defmacro url-set-target (urlobj targ)
- `(aset ,urlobj 6 ,targ))
-
-(defmacro url-set-attributes (urlobj targ)
- `(aset ,urlobj 7 ,targ))
-
-(defmacro url-set-full (urlobj val)
- `(aset ,urlobj 8 ,val))
-
-;;;###autoload
-(defun url-recreate-url (urlobj)
- (concat (url-type urlobj) ":" (if (url-host urlobj) "//" "")
- (if (url-user urlobj)
- (concat (url-user urlobj)
- (if (url-password urlobj)
- (concat ":" (url-password urlobj)))
- "@"))
- (url-host urlobj)
- (if (and (url-port urlobj)
- (not (equal (url-port urlobj)
- (url-scheme-get-property (url-type urlobj) 'default-port))))
- (format ":%d" (url-port urlobj)))
- (or (url-filename urlobj) "/")
- (if (url-target urlobj)
- (concat "#" (url-target urlobj)))
- (if (url-attributes urlobj)
- (concat ";"
- (mapconcat
- (function
- (lambda (x)
- (if (cdr x)
- (concat (car x) "=" (cdr x))
- (car x)))) (url-attributes urlobj) ";")))))
-
-;;;###autoload
-(defun url-generic-parse-url (url)
- "Return a vector of the parts of URL.
-Format is:
-\[proto username password hostname portnumber file reference attributes fullp\]"
- (cond
- ((null url)
- (make-vector 9 nil))
- ((or (not (string-match url-nonrelative-link url))
- (= ?/ (string-to-char url)))
- (let ((retval (make-vector 9 nil)))
- (url-set-filename retval url)
- (url-set-full retval nil)
- retval))
- (t
- (save-excursion
- (set-buffer (get-buffer-create " *urlparse*"))
- (set-syntax-table url-parse-syntax-table)
- (let ((save-pos nil)
- (prot nil)
- (user nil)
- (pass nil)
- (host nil)
- (port nil)
- (file nil)
- (refs nil)
- (attr nil)
- (full nil)
- (inhibit-read-only t))
- (erase-buffer)
- (insert url)
- (goto-char (point-min))
- (setq save-pos (point))
- (if (not (looking-at "//"))
- (progn
- (skip-chars-forward "a-zA-Z+.\\-")
- (downcase-region save-pos (point))
- (setq prot (buffer-substring save-pos (point)))
- (skip-chars-forward ":")
- (setq save-pos (point))))
-
- ;; We are doing a fully specified URL, with hostname and all
- (if (looking-at "//")
- (progn
- (setq full t)
- (forward-char 2)
- (setq save-pos (point))
- (skip-chars-forward "^/")
- (setq host (buffer-substring save-pos (point)))
- (if (string-match "^\\([^@]+\\)@" host)
- (setq user (match-string 1 host)
- host (substring host (match-end 0) nil)))
- (if (and user (string-match "\\([^:]+\\):\\(.*\\)" user))
- (setq pass (match-string 2 user)
- user (match-string 1 user)))
- (if (string-match ":\\([0-9+]+\\)" host)
- (setq port (string-to-int (match-string 1 host))
- host (substring host 0 (match-beginning 0))))
- (if (string-match ":$" host)
- (setq host (substring host 0 (match-beginning 0))))
- (setq host (downcase host)
- save-pos (point))))
-
- (if (not port)
- (setq port (url-scheme-get-property prot 'default-port)))
-
- ;; Gross hack to preserve ';' in data URLs
-
- (setq save-pos (point))
-
- (if (string= "data" prot)
- (goto-char (point-max))
- ;; Now check for references
- (skip-chars-forward "^#")
- (if (eobp)
- nil
- (delete-region
- (point)
- (progn
- (skip-chars-forward "#")
- (setq refs (buffer-substring (point) (point-max)))
- (point-max))))
- (goto-char save-pos)
- (skip-chars-forward "^;")
- (if (not (eobp))
- (setq attr (url-parse-args (buffer-substring (point) (point-max)) t)
- attr (nreverse attr))))
-
- (setq file (buffer-substring save-pos (point)))
- (if (and host (string-match "%[0-9][0-9]" host))
- (setq host (url-unhex-string host)))
- (vector prot user pass host port file refs attr full))))))
-
-(provide 'url-parse)
+++ /dev/null
-;;; url-privacy.el --- Global history tracking for URL package
-;; Author: $Author: fx $
-;; Created: $Date: 2001/10/05 17:10:26 $
-;; Version: $Revision: 1.4 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996 - 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(eval-when-compile (require 'cl))
-(require 'url-vars)
-
-(if (fboundp 'device-type)
- (defalias 'url-device-type 'device-type)
- (defun url-device-type (&optional device) (or window-system 'tty)))
-
-;;;###autoload
-(defun url-setup-privacy-info ()
- (interactive)
- (setq url-system-type
- (cond
- ((or (eq url-privacy-level 'paranoid)
- (and (listp url-privacy-level)
- (memq 'os url-privacy-level)))
- nil)
- ;; First, we handle the inseparable OS/Windowing system
- ;; combinations
- ((eq system-type 'Apple-Macintosh) "Macintosh")
- ((eq system-type 'next-mach) "NeXT")
- ((eq system-type 'windows-nt) "Windows-NT; 32bit")
- ((eq system-type 'ms-windows) "Windows; 16bit")
- ((eq system-type 'ms-dos) "MS-DOS; 32bit")
- ((memq (url-device-type) '(win32 w32)) "Windows; 32bit")
- ((eq (url-device-type) 'pm) "OS/2; 32bit")
- (t
- (case (url-device-type)
- (x "X11")
- (ns "OpenStep")
- (tty "TTY")
- (otherwise nil)))))
-
- (setq url-personal-mail-address (or url-personal-mail-address
- user-mail-address
- (format "%s@%s" (user-real-login-name)
- (system-name))))
-
- (if (or (memq url-privacy-level '(paranoid high))
- (and (listp url-privacy-level)
- (memq 'email url-privacy-level)))
- (setq url-personal-mail-address nil))
-
- (setq url-os-type
- (cond
- ((or (eq url-privacy-level 'paranoid)
- (and (listp url-privacy-level)
- (memq 'os url-privacy-level)))
- nil)
- ((boundp 'system-configuration)
- system-configuration)
- ((boundp 'system-type)
- (symbol-name system-type))
- (t nil))))
-
-(provide 'url-privacy)
+++ /dev/null
-;;; url-proxy.el --- Proxy server support
-;; Author: $Author: fx $
-;; Created: $Date: 2001/10/11 21:09:35 $
-;; Version: $Revision: 1.5 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1999 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url-parse)
-(autoload 'url-warn "url")
-
-(defun url-default-find-proxy-for-url (urlobj host)
- (cond
- ((or (and (assoc "no_proxy" url-proxy-services)
- (string-match
- (cdr
- (assoc "no_proxy" url-proxy-services))
- host))
- (equal "www" (url-type urlobj)))
- "DIRECT")
- ((cdr (assoc (url-type urlobj) url-proxy-services))
- (concat "PROXY " (cdr (assoc (url-type urlobj) url-proxy-services))))
- ;;
- ;; Should check for socks
- ;;
- (t
- "DIRECT")))
-
-(defvar url-proxy-locator 'url-default-find-proxy-for-url)
-
-(defun url-find-proxy-for-url (url host)
- (let ((proxies (split-string (funcall url-proxy-locator url host) " *; *"))
- (proxy nil)
- (case-fold-search t))
- ;; Not sure how I should handle gracefully degrading from one proxy to
- ;; another, so for now just deal with the first one
- ;; (while proxies
- (if (listp proxies)
- (setq proxy (car proxies))
- (setq proxy proxies))
- (cond
- ((string-match "^direct" proxy) nil)
- ((string-match "^proxy +" proxy)
- (concat "http://" (substring proxy (match-end 0)) "/"))
- ((string-match "^socks +" proxy)
- (concat "socks://" (substring proxy (match-end 0))))
- (t
- (url-warn 'url (format "Unknown proxy directive: %s" proxy) 'critical)
- nil))))
-
-(defun url-proxy (url callback &optional cbargs)
- ;; Retrieve URL from a proxy.
- ;; Expects `url-using-proxy' to be bound to the specific proxy to use."
- (setq url-using-proxy (url-generic-parse-url url-using-proxy))
- (let ((proxy-object (copy-sequence url)))
- (url-set-target proxy-object nil)
- (url-http url-using-proxy callback cbargs)))
-
-(provide 'url-proxy)
+++ /dev/null
-;;; url-util.el --- Miscellaneous helper routines for URL library
-;; Author: Bill Perry <wmperryNOSPAMgnu.org>
-;; Created: $Date: 2002/04/22 09:16:11 $
-;; Version: $Revision: 1.14 $
-;; Keywords: comm, data, processes
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996, 97, 98, 99, 2001 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'url-parse)
-(autoload 'timezone-parse-date "timezone")
-(autoload 'timezone-make-date-arpa-standard "timezone")
-
-(defvar url-parse-args-syntax-table
- (copy-syntax-table emacs-lisp-mode-syntax-table)
- "A syntax table for parsing sgml attributes.")
-
-(modify-syntax-entry ?' "\"" url-parse-args-syntax-table)
-(modify-syntax-entry ?` "\"" url-parse-args-syntax-table)
-(modify-syntax-entry ?{ "(" url-parse-args-syntax-table)
-(modify-syntax-entry ?} ")" url-parse-args-syntax-table)
-
-;;;###autoload
-(defcustom url-debug nil
- "*What types of debug messages from the URL library to show.
-Debug messages are logged to the *URL-DEBUG* buffer.
-
-If t, all messages will be logged.
-If a number, all messages will be logged, as well shown via `message'.
-If a list, it is a list of the types of messages to be logged."
- :type '(choice (const :tag "none" nil)
- (const :tag "all" t)
- (checklist :tag "custom"
- (const :tag "HTTP" :value http)
- (const :tag "DAV" :value dav)
- (const :tag "General" :value retrieval)
- (const :tag "Filename handlers" :value handlers)
- (symbol :tag "Other")))
- :group 'url-hairy)
-
-;;;###autoload
-(defun url-debug (tag &rest args)
- (if quit-flag
- (error "Interrupted!"))
- (if (or (eq url-debug t)
- (numberp url-debug)
- (and (listp url-debug) (memq tag url-debug)))
- (save-excursion
- (set-buffer (get-buffer-create "*URL-DEBUG*"))
- (goto-char (point-max))
- (insert (symbol-name tag) " -> " (apply 'format args) "\n")
- (if (numberp url-debug)
- (apply 'message args)))))
-
-;;;###autoload
-(defun url-parse-args (str &optional nodowncase)
- ;; Return an assoc list of attribute/value pairs from an RFC822-type string
- (let (
- name ; From name=
- value ; its value
- results ; Assoc list of results
- name-pos ; Start of XXXX= position
- val-pos ; Start of value position
- st
- nd
- )
- (save-excursion
- (save-restriction
- (set-buffer (get-buffer-create " *urlparse-temp*"))
- (set-syntax-table url-parse-args-syntax-table)
- (erase-buffer)
- (insert str)
- (setq st (point-min)
- nd (point-max))
- (set-syntax-table url-parse-args-syntax-table)
- (narrow-to-region st nd)
- (goto-char (point-min))
- (while (not (eobp))
- (skip-chars-forward "; \n\t")
- (setq name-pos (point))
- (skip-chars-forward "^ \n\t=;")
- (if (not nodowncase)
- (downcase-region name-pos (point)))
- (setq name (buffer-substring name-pos (point)))
- (skip-chars-forward " \t\n")
- (if (/= (or (char-after (point)) 0) ?=) ; There is no value
- (setq value nil)
- (skip-chars-forward " \t\n=")
- (setq val-pos (point)
- value
- (cond
- ((or (= (or (char-after val-pos) 0) ?\")
- (= (or (char-after val-pos) 0) ?'))
- (buffer-substring (1+ val-pos)
- (condition-case ()
- (prog2
- (forward-sexp 1)
- (1- (point))
- (skip-chars-forward "\""))
- (error
- (skip-chars-forward "^ \t\n")
- (point)))))
- (t
- (buffer-substring val-pos
- (progn
- (skip-chars-forward "^;")
- (skip-chars-backward " \t")
- (point)))))))
- (setq results (cons (cons name value) results))
- (skip-chars-forward "; \n\t"))
- results))))
-
-;;;###autoload
-(defun url-insert-entities-in-string (string)
- "Convert HTML markup-start characters to entity references in STRING.
-Also replaces the \" character, so that the result may be safely used as
- an attribute value in a tag. Returns a new string with the result of the
- conversion. Replaces these characters as follows:
- & ==> &
- < ==> <
- > ==> >
- \" ==> ""
- (if (string-match "[&<>\"]" string)
- (save-excursion
- (set-buffer (get-buffer-create " *entity*"))
- (erase-buffer)
- (buffer-disable-undo (current-buffer))
- (insert string)
- (goto-char (point-min))
- (while (progn
- (skip-chars-forward "^&<>\"")
- (not (eobp)))
- (insert (cdr (assq (char-after (point))
- '((?\" . """)
- (?& . "&")
- (?< . "<")
- (?> . ">")))))
- (delete-char 1))
- (buffer-string))
- string))
-
-;;;###autoload
-(defun url-normalize-url (url)
- "Return a 'normalized' version of URL.
-Strips out default port numbers, etc."
- (let (type data grok retval)
- (setq data (url-generic-parse-url url)
- type (url-type data))
- (if (member type '("www" "about" "mailto" "info"))
- (setq retval url)
- (url-set-target data nil)
- (setq retval (url-recreate-url data)))
- retval))
-
-;;;###autoload
-(defun url-lazy-message (&rest args)
- "Just like `message', but is a no-op if called more than once a second.
-Will not do anything if url-show-status is nil."
- (if (or (null url-show-status)
- (active-minibuffer-window)
- (= url-lazy-message-time
- (setq url-lazy-message-time (nth 1 (current-time)))))
- nil
- (apply 'message args)))
-
-;;;###autoload
-(defun url-get-normalized-date (&optional specified-time)
- "Return a 'real' date string that most HTTP servers can understand."
- (require 'timezone)
- (let* ((raw (if specified-time (current-time-string specified-time)
- (current-time-string)))
- (gmt (timezone-make-date-arpa-standard raw
- (nth 1 (current-time-zone))
- "GMT"))
- (parsed (timezone-parse-date gmt))
- (day (cdr-safe (assoc (substring raw 0 3) weekday-alist)))
- (year nil)
- (month (car
- (rassoc
- (string-to-int (aref parsed 1)) monthabbrev-alist)))
- )
- (setq day (or (car-safe (rassoc day weekday-alist))
- (substring raw 0 3))
- year (aref parsed 0))
- ;; This is needed for plexus servers, or the server will hang trying to
- ;; parse the if-modified-since header. Hopefully, I can take this out
- ;; soon.
- (if (and year (> (length year) 2))
- (setq year (substring year -2 nil)))
-
- (concat day ", " (aref parsed 2) "-" month "-" year " "
- (aref parsed 3) " " (or (aref parsed 4)
- (concat "[" (nth 1 (current-time-zone))
- "]")))))
-
-;;;###autoload
-(defun url-eat-trailing-space (x)
- "Remove spaces/tabs at the end of a string."
- (let ((y (1- (length x)))
- (skip-chars (list ? ?\t ?\n)))
- (while (and (>= y 0) (memq (aref x y) skip-chars))
- (setq y (1- y)))
- (substring x 0 (1+ y))))
-
-;;;###autoload
-(defun url-strip-leading-spaces (x)
- "Remove spaces at the front of a string."
- (let ((y (1- (length x)))
- (z 0)
- (skip-chars (list ? ?\t ?\n)))
- (while (and (<= z y) (memq (aref x z) skip-chars))
- (setq z (1+ z)))
- (substring x z nil)))
-
-;;;###autoload
-(defun url-pretty-length (n)
- (cond
- ((< n 1024)
- (format "%d bytes" n))
- ((< n (* 1024 1024))
- (format "%dk" (/ n 1024.0)))
- (t
- (format "%2.2fM" (/ n (* 1024 1024.0))))))
-
-;;;###autoload
-(defun url-display-percentage (fmt perc &rest args)
- (if (null fmt)
- (if (fboundp 'clear-progress-display)
- (clear-progress-display))
- (if (and (fboundp 'progress-display) perc)
- (apply 'progress-display fmt perc args)
- (apply 'message fmt args))))
-
-;;;###autoload
-(defun url-percentage (x y)
- (if (fboundp 'float)
- (round (* 100 (/ x (float y))))
- (/ (* x 100) y)))
-
-;;;###autoload
-(defun url-basepath (file &optional x)
- "Return the base pathname of FILE, or the actual filename if X is true."
- (cond
- ((null file) "")
- ((string-match (eval-when-compile (regexp-quote "?")) file)
- (if x
- (file-name-nondirectory (substring file 0 (match-beginning 0)))
- (file-name-directory (substring file 0 (match-beginning 0)))))
- (x (file-name-nondirectory file))
- (t (file-name-directory file))))
-
-;;;###autoload
-(defun url-parse-query-string (query &optional downcase)
- (let (retval pairs cur key val)
- (setq pairs (split-string query "&"))
- (while pairs
- (setq cur (car pairs)
- pairs (cdr pairs))
- (if (not (string-match "=" cur))
- nil ; Grace
- (setq key (url-unhex-string (substring cur 0 (match-beginning 0)))
- val (url-unhex-string (substring cur (match-end 0) nil)))
- (if downcase
- (setq key (downcase key)))
- (setq cur (assoc key retval))
- (if cur
- (setcdr cur (cons val (cdr cur)))
- (setq retval (cons (list key val) retval)))))
- retval))
-
-(defun url-unhex (x)
- (if (> x ?9)
- (if (>= x ?a)
- (+ 10 (- x ?a))
- (+ 10 (- x ?A)))
- (- x ?0)))
-
-;;;###autoload
-(defun url-unhex-string (str &optional allow-newlines)
- "Remove %XXX embedded spaces, etc in a url.
-If optional second argument ALLOW-NEWLINES is non-nil, then allow the
-decoding of carriage returns and line feeds in the string, which is normally
-forbidden in URL encoding."
- (setq str (or str ""))
- (let ((tmp "")
- (case-fold-search t))
- (while (string-match "%[0-9a-f][0-9a-f]" str)
- (let* ((start (match-beginning 0))
- (ch1 (url-unhex (elt str (+ start 1))))
- (code (+ (* 16 ch1)
- (url-unhex (elt str (+ start 2))))))
- (setq tmp (concat
- tmp (substring str 0 start)
- (cond
- (allow-newlines
- (char-to-string code))
- ((or (= code ?\n) (= code ?\r))
- " ")
- (t (char-to-string code))))
- str (substring str (match-end 0)))))
- (setq tmp (concat tmp str))
- tmp))
-
-(defconst url-unreserved-chars
- '(
- ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z
- ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z
- ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9
- ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\))
- "A list of characters that are _NOT_ reserved in the URL spec.
-This is taken from RFC 2396.")
-
-;;;###autoload
-(defun url-hexify-string (str)
- "Escape characters in a string."
- (mapconcat
- (lambda (char)
- ;; Fixme: use a char table instead.
- (if (not (memq char url-unreserved-chars))
- (if (< char 16)
- (format "%%0%X" char)
- (format "%%%X" char))
- (char-to-string char)))
- str ""))
-
-;;;###autoload
-(defun url-file-extension (fname &optional x)
- "Return the filename extension of FNAME.
-If optional variable X is t,
-then return the basename of the file with the extension stripped off."
- (if (and fname
- (setq fname (url-basepath fname t))
- (string-match "\\.[^./]+$" fname))
- (if x (substring fname 0 (match-beginning 0))
- (substring fname (match-beginning 0) nil))
- ;;
- ;; If fname has no extension, and x then return fname itself instead of
- ;; nothing. When caching it allows the correct .hdr file to be produced
- ;; for filenames without extension.
- ;;
- (if x
- fname
- "")))
-
-;;;###autoload
-(defun url-truncate-url-for-viewing (url &optional width)
- "Return a shortened version of URL that is WIDTH characters or less wide.
-WIDTH defaults to the current frame width."
- (let* ((fr-width (or width (frame-width)))
- (str-width (length url))
- (tail (file-name-nondirectory url))
- (fname nil)
- (modified 0)
- (urlobj nil))
- ;; The first thing that can go are the search strings
- (if (and (>= str-width fr-width)
- (string-match "?" url))
- (setq url (concat (substring url 0 (match-beginning 0)) "?...")
- str-width (length url)
- tail (file-name-nondirectory url)))
- (if (< str-width fr-width)
- nil ; Hey, we are done!
- (setq urlobj (url-generic-parse-url url)
- fname (url-filename urlobj)
- fr-width (- fr-width 4))
- (while (and (>= str-width fr-width)
- (string-match "/" fname))
- (setq fname (substring fname (match-end 0) nil)
- modified (1+ modified))
- (url-set-filename urlobj fname)
- (setq url (url-recreate-url urlobj)
- str-width (length url)))
- (if (> modified 1)
- (setq fname (concat "/.../" fname))
- (setq fname (concat "/" fname)))
- (url-set-filename urlobj fname)
- (setq url (url-recreate-url urlobj)))
- url))
-
-;;;###autoload
-(defun url-view-url (&optional no-show)
- "View the current document's URL.
-Optional argument NO-SHOW means just return the URL, don't show it in
-the minibuffer.
-
-This uses `url-current-object', set locally to the buffer."
- (interactive)
- (if (not url-current-object)
- nil
- (if no-show
- (url-recreate-url url-current-object)
- (message "%s" (url-recreate-url url-current-object)))))
-
-(eval-and-compile
- (defvar url-get-url-filename-chars "-%.?@a-zA-Z0-9()_/:~=&"
- "Valid characters in a URL")
- )
-
-(defun url-get-url-at-point (&optional pt)
- "Get the URL closest to point, but don't change position.
-Has a preference for looking backward when not directly on a symbol."
- ;; Not at all perfect - point must be right in the name.
- (save-excursion
- (if pt (goto-char pt))
- (let (start url)
- (save-excursion
- ;; first see if you're just past a filename
- (if (not (eobp))
- (if (looking-at "[] \t\n[{}()]") ; whitespace or some parens
- (progn
- (skip-chars-backward " \n\t\r({[]})")
- (if (not (bobp))
- (backward-char 1)))))
- (if (and (char-after (point))
- (string-match (eval-when-compile
- (concat "[" url-get-url-filename-chars "]"))
- (char-to-string (char-after (point)))))
- (progn
- (skip-chars-backward url-get-url-filename-chars)
- (setq start (point))
- (skip-chars-forward url-get-url-filename-chars))
- (setq start (point)))
- (setq url (buffer-substring-no-properties start (point))))
- (if (and url (string-match "^(.*)\\.?$" url))
- (setq url (match-string 1 url)))
- (if (and url (string-match "^URL:" url))
- (setq url (substring url 4 nil)))
- (if (and url (string-match "\\.$" url))
- (setq url (substring url 0 -1)))
- (if (and url (string-match "^www\\." url))
- (setq url (concat "http://" url)))
- (if (and url (not (string-match url-nonrelative-link url)))
- (setq url nil))
- url)))
-
-(defun url-generate-unique-filename (&optional fmt)
- "Generate a unique filename in `url-temporary-directory'."
- (if (not fmt)
- (let ((base (format "url-tmp.%d" (user-real-uid)))
- (fname "")
- (x 0))
- (setq fname (format "%s%d" base x))
- (while (file-exists-p
- (expand-file-name fname url-temporary-directory))
- (setq x (1+ x)
- fname (concat base (int-to-string x))))
- (expand-file-name fname url-temporary-directory))
- (let ((base (concat "url" (int-to-string (user-real-uid))))
- (fname "")
- (x 0))
- (setq fname (format fmt (concat base (int-to-string x))))
- (while (file-exists-p
- (expand-file-name fname url-temporary-directory))
- (setq x (1+ x)
- fname (format fmt (concat base (int-to-string x)))))
- (expand-file-name fname url-temporary-directory))))
-
-(defun url-extract-mime-headers ()
- "Set `url-current-mime-headers' in current buffer."
- (save-excursion
- (goto-char (point-min))
- (unless url-current-mime-headers
- (set (make-local-variable 'url-current-mime-headers)
- (mail-header-extract)))))
-
-(provide 'url-util)
+++ /dev/null
-;;; url-vars.el --- Variables for Uniform Resource Locator tool
-;; Author: $Author: fx $
-;; Created: $Date: 2002/04/22 09:25:02 $
-;; Version: $Revision: 1.14 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996, 97, 98, 99, 2001 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(require 'mm-util)
-(eval-when-compile (require 'cl))
-
-(defconst url-version (let ((x "$State: Exp $"))
- (if (string-match "State: \\([^ \t\n]+\\)" x)
- (substring x (match-beginning 1) (match-end 1))
- x))
- "Version number of URL package.")
-
-(defgroup url nil
- "Uniform Resource Locator tool"
- :group 'hypermedia)
-
-(defgroup url-file nil
- "URL storage"
- :prefix "url-"
- :group 'url)
-
-(defgroup url-cache nil
- "URL cache"
- :prefix "url-"
- :prefix "url-cache-"
- :group 'url)
-
-(defgroup url-mime nil
- "MIME options of URL"
- :prefix "url-"
- :group 'url)
-
-(defgroup url-hairy nil
- "Hairy options of URL"
- :prefix "url-"
- :group 'url)
-
-
-(defvar url-current-object nil
- "A parsed representation of the current url.")
-
-(defvar url-current-mime-headers nil
- "A parsed representation of the MIME headers for the current url.")
-
-(mapcar 'make-variable-buffer-local
- '(
- url-current-object
- url-current-referer
- url-current-mime-headers
- ))
-
-(defcustom url-honor-refresh-requests t
- "*Whether to do automatic page reloads.
-These are done at the request of the document author or the server via
-the `Refresh' header in an HTTP response. If nil, no refresh
-requests will be honored. If t, all refresh requests will be honored.
-If non-nil and not t, the user will be asked for each refresh
-request."
- :type '(choice (const :tag "off" nil)
- (const :tag "on" t)
- (const :tag "ask" 'ask))
- :group 'url-hairy)
-
-(defcustom url-automatic-caching nil
- "*If non-nil, all documents will be automatically cached to the local disk."
- :type 'boolean
- :group 'url-cache)
-
-;; Fixme: sanitize this.
-(defcustom url-cache-expired
- (lambda (t1 t2) (>= (- (car t2) (car t1)) 5))
- "*A function determining if a cached item has expired.
-It takes two times (numbers) as its arguments, and returns non-nil if
-the second time is 'too old' when compared to the first time."
- :type 'function
- :group 'url-cache)
-
-(defvar url-bug-address "w3-bugsNOSPAMxemacs.org"
- "Where to send bug reports.")
-
-(defcustom url-personal-mail-address nil
- "*Your full email address.
-This is what is sent to HTTP servers as the FROM field in an HTTP
-request."
- :type '(choice (const :tag "Unspecified" nil) string)
- :group 'url)
-
-(defcustom url-directory-index-file "index.html"
- "*The filename to look for when indexing a directory.
-If this file exists, and is readable, then it will be viewed instead of
-using `dired' to view the directory."
- :type 'string
- :group 'url-file)
-
-;; Fixme: this should have a setter which calls url-setup-privacy-info.
-(defcustom url-privacy-level '(email)
- "*How private you want your requests to be.
-HTTP has header fields for various information about the user, including
-operating system information, email addresses, the last page you visited, etc.
-This variable controls how much of this information is sent.
-
-This should a symbol or a list.
-Valid values if a symbol are:
-none -- Send all information
-low -- Don't send the last location
-high -- Don't send the email address or last location
-paranoid -- Don't send anything
-
-If a list, this should be a list of symbols of what NOT to send.
-Valid symbols are:
-email -- the email address
-os -- the operating system info
-lastloc -- the last location
-agent -- Do not send the User-Agent string
-cookie -- never accept HTTP cookies
-
-Samples:
-
- (setq url-privacy-level 'high)
- (setq url-privacy-level '(email lastloc)) ;; equivalent to 'high
- (setq url-privacy-level '(os))
-
-::NOTE::
-This variable controls several other variables and is _NOT_ automatically
-updated. Call the function `url-setup-privacy-info' after modifying this
-variable."
- :type '(radio (const :tag "None (you believe in the basic goodness of humanity)"
- :value none)
- (const :tag "Low (do not reveal last location)"
- :value low)
- (const :tag "High (no email address or last location)"
- :value high)
- (const :tag "Paranoid (reveal nothing!)"
- :value paranoid)
- (checklist :tag "Custom"
- (const :tag "Email address" :value email)
- (const :tag "Operating system" :value os)
- (const :tag "Last location" :value lastloc)
- (const :tag "Browser identification" :value agent)
- (const :tag "No cookies" :value cookie)))
- :group 'url)
-
-(defvar url-inhibit-uncompression nil "Do not do decompression if non-nil.")
-
-(defcustom url-uncompressor-alist '((".z" . "x-gzip")
- (".gz" . "x-gzip")
- (".uue" . "x-uuencoded")
- (".hqx" . "x-hqx")
- (".Z" . "x-compress")
- (".bz2" . "x-bzip2"))
- "*An alist of file extensions and appropriate content-transfer-encodings."
- :type '(repeat (cons :format "%v"
- (string :tag "Extension")
- (string :tag "Encoding")))
- :group 'url-mime)
-
-(defcustom url-mail-command (if (fboundp 'compose-mail)
- 'compose-mail
- 'url-mail)
- "*This function will be called whenever url needs to send mail.
-It should enter a mail-mode-like buffer in the current window.
-The commands `mail-to' and `mail-subject' should still work in this
-buffer, and it should use `mail-header-separator' if possible."
- :type 'function
- :group 'url)
-
-(defcustom url-proxy-services nil
- "*An alist of schemes and proxy servers that gateway them.
-Looks like ((\"http\" . \"hostname:portnumber\") ...). This is set up
-from the ACCESS_proxy environment variables."
- :type '(repeat (cons :format "%v"
- (string :tag "Protocol")
- (string :tag "Proxy")))
- :group 'url)
-
-(defcustom url-passwd-entry-func nil
- "*Symbol indicating which function to call to read in a password.
-It will be set up depending on whether you are running EFS or ange-ftp
-at startup if it is nil. This function should accept the prompt
-string as its first argument, and the default value as its second
-argument."
- :type '(choice (const :tag "Guess" :value nil)
- (const :tag "Use Ange-FTP" :value ange-ftp-read-passwd)
- (const :tag "Use EFS" :value efs-read-passwd)
- (const :tag "Use Password Package" :value read-passwd)
- (function :tag "Other"))
- :group 'url-hairy)
-
-(defcustom url-standalone-mode nil
- "*Rely solely on the cache?"
- :type 'boolean
- :group 'url-cache)
-
-(defvar url-mime-separator-chars (mapcar 'identity
- (concat "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789'()+_,-./=?"))
- "Characters allowable in a MIME multipart separator.")
-
-(defcustom url-bad-port-list
- '("25" "119" "19")
- "*List of ports to warn the user about connecting to.
-Defaults to just the mail, chargen, and NNTP ports so you cannot be
-tricked into sending fake mail or forging messages by a malicious HTML
-document."
- :type '(repeat (string :tag "Port"))
- :group 'url-hairy)
-
-(defvar url-mime-content-type-charset-regexp
- ";[ \t]*charset=\"?\\([^\"]+\\)\"?"
- "Regexp used in parsing `Content-Type' for a charset indication.")
-
-(defvar url-request-data nil "Any data to send with the next request.")
-
-(defvar url-request-extra-headers nil
- "A list of extra headers to send with the next request.
-Should be an assoc list of headers/contents.")
-
-(defvar url-request-method nil "The method to use for the next request.")
-
-;; FIXME!! (RFC 2616 gives examples like `compress, gzip'.)
-(defvar url-mime-encoding-string nil
- "*String to send in the Accept-encoding: field in HTTP requests.")
-
-;; `mm-mime-mule-charset-alist' in Gnus 5.8/9 contains elements whose
-;; cars aren't valid MIME charsets/coding systems, at least in Emacs.
-;; This gets it correct by construction in Emacs. Fixme: DTRT for
-;; XEmacs -- its `coding-system-list' doesn't have the BASE-ONLY arg.
-(when (and (not (featurep 'xemacs))
- (fboundp 'coding-system-list))
- (setq mm-mime-mule-charset-alist
- (apply
- 'nconc
- (mapcar
- (lambda (cs)
- (when (and (coding-system-get cs 'mime-charset)
- (not (eq t (coding-system-get cs 'safe-charsets))))
- (list (cons (coding-system-get cs 'mime-charset)
- (delq 'ascii
- (coding-system-get cs 'safe-charsets))))))
- (coding-system-list 'base-only)))))
-
-;; Perhaps the first few should actually be given decreasing `q's and
-;; the list should be trimmed significantly.
-;; Fixme: do something sane if we don't have `sort-coding-systems'
-;; (Emacs 20, XEmacs).
-(defun url-mime-charset-string ()
- "Generate a list of preferred MIME charsets for HTTP requests.
-Generated according to current coding system priorities."
- (if (fboundp 'sort-coding-systems)
- (let ((ordered (sort-coding-systems
- (let (accum)
- (dolist (elt mm-mime-mule-charset-alist)
- (if (mm-coding-system-p (car elt))
- (push (car elt) accum)))
- (nreverse accum)))))
- (concat (format "%s;q=1, " (pop ordered))
- (mapconcat 'symbol-name ordered ";q=0.5, ")
- ";q=0.5"))))
-
-(defvar url-mime-charset-string (url-mime-charset-string)
- "*String to send in the Accept-charset: field in HTTP requests.
-The MIME charset corresponding to the most preferred coding system is
-given priority 1 and the rest are given priority 0.5.")
-
-(defun url-set-mime-charset-string ()
- (setq url-mime-charset-string (url-mime-charset-string)))
-;; Regenerate if the language environment changes.
-(add-hook 'set-language-environment-hook 'url-set-mime-charset-string)
-
-;; Fixme: set from the locale.
-(defcustom url-mime-language-string nil
- "*String to send in the Accept-language: field in HTTP requests.
-
-Specifies the preferred language when servers can serve documents in
-several languages. Use RFC 1766 abbreviations, e.g.@: `en' for
-English, `de' for German. A comma-separated specifies descending
-order of preference. The ordering can be made explicit using `q'
-factors defined by HTTP, e.g. `de,en-gb;q=0.8,en;q=0.7'. `*' means
-get the first available language (as opposed to the default)."
- :type '(radio
- (const :tag "None (get default language version)" :value nil)
- (const :tag "Any (get first available language version)" :value "*")
- (string :tag "Other"))
- :group 'url-mime
- :group 'i18n)
-
-(defvar url-mime-accept-string nil
- "String to send to the server in the Accept: field in HTTP requests.")
-
-(defvar url-package-version nil
- "Version number of package using URL.")
-
-(defvar url-package-name nil "Version number of package using URL.")
-
-(defvar url-system-type nil
- "What type of system we are on.")
-(defvar url-os-type nil
- "What OS we are on.")
-
-(defcustom url-max-password-attempts 5
- "*Maximum number of times a password will be prompted for.
-Applies when a protected document is denied by the server."
- :type 'integer
- :group 'url)
-
-(defcustom url-temporary-directory (or (getenv "TMPDIR") "/tmp")
- "*Where temporary files go."
- :type 'directory
- :group 'url-file)
-
-(defcustom url-show-status t
- "*Whether to show a running total of bytes transferred.
-Can cause a large hit if using a remote X display over a slow link, or
-a terminal with a slow modem."
- :type 'boolean
- :group 'url)
-
-(defvar url-using-proxy nil
- "Either nil or the fully qualified proxy URL in use, e.g.
-http://www.domain.com/")
-
-(defvar url-slow-proxy-requires-waiting-for nil
- "Either nil or a number of seconds to wait before authentication or redirection")
-
-(defcustom url-news-server nil
- "*The default news server from which to get newsgroups/articles.
-Applies if no server is specified in the URL. Defaults to the
-environment variable NNTPSERVER or \"news\" if NNTPSERVER is
-undefined."
- :type '(choice (const :tag "None" :value nil) string)
- :group 'url)
-
-(defvar url-nonrelative-link
- "\\`\\([-a-zA-Z0-9+.]+:\\)"
- "A regular expression that will match an absolute URL.")
-
-(defcustom url-confirmation-func 'y-or-n-p
- "*What function to use for asking yes or no functions.
-Possible values are `yes-or-no-p' or `y-or-n-p', or any function that
-takes a single argument (the prompt), and returns t only if a positive
-answer is given."
- :type '(choice (const :tag "Short (y or n)" :value y-or-n-p)
- (const :tag "Long (yes or no)" :value yes-or-no-p)
- (function :tag "Other"))
- :group 'url-hairy)
-
-(defcustom url-gateway-method 'native
- "*The type of gateway support to use.
-Should be a symbol specifying how to get a connection from the local machine.
-
-Currently supported methods:
-`telnet': Run telnet in a subprocess to connect;
-`rlogin': Rlogin to another machine to connect;
-`socks': Connect through a socks server;
-`ssl': Connect with SSL;
-`native': Connect directy."
- :type '(radio (const :tag "Telnet to gateway host" :value telnet)
- (const :tag "Rlogin to gateway host" :value rlogin)
- (const :tag "Use SOCKS proxy" :value socks)
- (const :tag "Use SSL for all connections" :value ssl)
- (const :tag "Direct connection" :value native))
- :group 'url-hairy)
-
-(defvar url-setup-done nil "Has setup configuration been done?")
-
-(defconst weekday-alist
- '(("Sunday" . 0) ("Monday" . 1) ("Tuesday" . 2) ("Wednesday" . 3)
- ("Thursday" . 4) ("Friday" . 5) ("Saturday" . 6)
- ("Tues" . 2) ("Thurs" . 4)
- ("Sun" . 0) ("Mon" . 1) ("Tue" . 2) ("Wed" . 3)
- ("Thu" . 4) ("Fri" . 5) ("Sat" . 6)))
-
-(defconst monthabbrev-alist
- '(("Jan" . 1) ("Feb" . 2) ("Mar" . 3) ("Apr" . 4) ("May" . 5) ("Jun" . 6)
- ("Jul" . 7) ("Aug" . 8) ("Sep" . 9) ("Oct" . 10) ("Nov" . 11)
- ("Dec" . 12)))
-
-(defvar url-lazy-message-time 0)
-
-;; Fixme: We may not be able to run SSL.
-(defvar url-extensions-header "Security/Digest Security/SSL")
-
-(defvar url-parse-syntax-table
- (copy-syntax-table emacs-lisp-mode-syntax-table)
- "*A syntax table for parsing URLs.")
-
-(modify-syntax-entry ?' "\"" url-parse-syntax-table)
-(modify-syntax-entry ?` "\"" url-parse-syntax-table)
-(modify-syntax-entry ?< "(>" url-parse-syntax-table)
-(modify-syntax-entry ?> ")<" url-parse-syntax-table)
-(modify-syntax-entry ?/ " " url-parse-syntax-table)
-
-(defvar url-load-hook nil
- "*Hooks to be run after initalizing the URL library.")
-
-;;; Make OS/2 happy - yeeks
-;; (defvar tcp-binary-process-input-services nil
-;; "*Make OS/2 happy with our CRLF pairs...")
-
-(defconst url-working-buffer " *url-work")
-
-(defvar url-gateway-unplugged nil
- "Non-nil means don't open new network connexions.
-This should be set, e.g. by mail user agents rendering HTML to avoid
-`bugs' which call home.")
-
-(defun url-vars-unload-hook ()
- (remove-hook 'set-language-environment-hook 'url-set-mime-charset-string))
-
-(provide 'url-vars)
-
-;;; url-vars.el ends here
+++ /dev/null
-;;; url.el --- Uniform Resource Locator retrieval tool
-;; Author: Bill Perry <wmperryNOSPAMgnu.org>
-;; Version: $Revision: 1.15 $
-;; Keywords: comm, data, processes, hypermedia
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Copyright (c) 1993 - 1996 by William M. Perry <wmperryNOSPAMcs.indiana.edu>
-;;; Copyright (c) 1996, 97, 98, 99, 2001 Free Software Foundation, Inc.
-;;;
-;;; This file is part of GNU Emacs.
-;;;
-;;; GNU Emacs is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;;; Boston, MA 02111-1307, USA.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Registered URI schemes: http://www.iana.org/assignments/uri-schemes
-
-(eval-when-compile (require 'cl))
-;; Don't require CL at runtime if we can avoid it (Emacs 21).
-;; Otherwise we need it for hashing functions. `puthash' was never
-;; defined in the Emacs 20 cl.el for some reason.
-(if (fboundp 'puthash)
- nil ; internal or CL is loaded
- (defalias 'puthash 'cl-puthash)
- (autoload 'cl-puthash "cl")
- (autoload 'gethash "cl")
- (autoload 'maphash "cl")
- (autoload 'make-hash-table "cl"))
-
-(eval-when-compile
- (require 'mm-decode)
- (require 'mm-view))
-
-(require 'mailcap)
-(require 'url-vars)
-(require 'url-cookie)
-(require 'url-history)
-(require 'url-expand)
-(require 'url-privacy)
-(require 'url-methods)
-(require 'url-proxy)
-(require 'url-parse)
-(require 'url-util)
-
-;; Fixme: customize? convert-standard-filename?
-;;;###autoload
-(defvar url-configuration-directory "~/.url")
-
-(defun url-do-setup ()
- "Setup the url package.
-This is to avoid conflict with user settings if URL is dumped with
-Emacs."
- (unless url-setup-done
-
- ;; Make OS/2 happy
- ;;(push '("http" "80") tcp-binary-process-input-services)
-
- (mailcap-parse-mailcaps)
- (mailcap-parse-mimetypes)
-
- ;; Register all the authentication schemes we can handle
- (url-register-auth-scheme "basic" nil 4)
- (url-register-auth-scheme "digest" nil 7)
-
- (setq url-cookie-file
- (or url-cookie-file
- (expand-file-name "cookies" url-configuration-directory)))
-
- (setq url-history-file
- (or url-history-file
- (expand-file-name "history" url-configuration-directory)))
-
- ;; Parse the global history file if it exists, so that it can be used
- ;; for URL completion, etc.
- (url-history-parse-history)
- (url-history-setup-save-timer)
-
- ;; Ditto for cookies
- (url-cookie-setup-save-timer)
- (url-cookie-parse-file url-cookie-file)
-
- ;; Read in proxy gateways
- (let ((noproxy (and (not (assoc "no_proxy" url-proxy-services))
- (or (getenv "NO_PROXY")
- (getenv "no_PROXY")
- (getenv "no_proxy")))))
- (if noproxy
- (setq url-proxy-services
- (cons (cons "no_proxy"
- (concat "\\("
- (mapconcat
- (lambda (x)
- (cond
- ((= x ?,) "\\|")
- ((= x ? ) "")
- ((= x ?.) (regexp-quote "."))
- ((= x ?*) ".*")
- ((= x ??) ".")
- (t (char-to-string x))))
- noproxy "") "\\)"))
- url-proxy-services))))
-
- ;; Set the password entry funtion based on user defaults or guess
- ;; based on which remote-file-access package they are using.
- (cond
- (url-passwd-entry-func nil) ; Already been set
- ((fboundp 'read-passwd) ; Use secure password if available
- (setq url-passwd-entry-func 'read-passwd))
- ((or (featurep 'efs) ; Using EFS
- (featurep 'efs-auto)) ; or autoloading efs
- (if (not (fboundp 'read-passwd))
- (autoload 'read-passwd "passwd" "Read in a password" nil))
- (setq url-passwd-entry-func 'read-passwd))
- ((or (featurep 'ange-ftp) ; Using ange-ftp
- (and (boundp 'file-name-handler-alist)
- (not (featurep 'xemacs)))) ; ??
- (setq url-passwd-entry-func 'ange-ftp-read-passwd))
- (t
- (url-warn
- 'security
- "(url-setup): Can't determine how to read passwords, winging it.")))
-
- (url-setup-privacy-info)
- (run-hooks 'url-load-hook)
- (setq url-setup-done t)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Retrieval functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun url-retrieve (url callback &optional cbargs)
- "Retrieve URL asynchronously and call CALLBACK with CBARGS when finished.
-The callback is called when the object has been completely retrieved, with
-the current buffer containing the object, and any MIME headers associated
-with it. URL is either a string or a parsed URL.
-
-Return the buffer URL will load into, or nil if the process has
-already completed."
- (url-do-setup)
- (url-gc-dead-buffers)
- (if (stringp url)
- (set-text-properties 0 (length url) nil url))
- (if (not (vectorp url))
- (setq url (url-generic-parse-url url)))
- (if (not (functionp callback))
- (error "Must provide a callback function to url-retrieve"))
- (unless (url-type url)
- (error "Bad url: %s" (url-recreate-url url)))
- (let ((loader (url-scheme-get-property (url-type url) 'loader))
- (url-using-proxy (if (url-host url)
- (url-find-proxy-for-url url (url-host url))))
- (buffer nil)
- (asynch (url-scheme-get-property (url-type url) 'asynchronous-p)))
- (if url-using-proxy
- (setq asynch t
- loader 'url-proxy))
- (if asynch
- (setq buffer (funcall loader url callback cbargs))
- (setq buffer (funcall loader url))
- (if buffer
- (save-excursion
- (set-buffer buffer)
- (apply callback cbargs))))
- (url-history-update-url url (current-time))
- buffer))
-
-(defun url-retrieve-synchronously (url)
- "Retrieve URL synchronously.
-Return the buffer containing the data, or nil if there are no data
-associated with it (the case for dired, info, or mailto URLs that need
-no further processing). URL is either a string or a parsed URL."
- (url-do-setup)
-
- (lexical-let ((retrieval-done nil)
- (asynch-buffer nil))
- (setq asynch-buffer
- (url-retrieve url (lambda (&rest ignored)
- (url-debug 'retrieval "Synchronous fetching done (%S)" (current-buffer))
- (setq retrieval-done t
- asynch-buffer (current-buffer)))))
- (let ((proc (and asynch-buffer (get-buffer-process asynch-buffer))))
- (if (null proc)
- ;; We do not need to do anything, it was a mailto or something
- ;; similar that takes processing completely outside of the URL
- ;; package.
- nil
- (while (not retrieval-done)
- (if (memq (process-status proc) '(closed exit signal failed))
- ;; FIXME: It's not clear whether url-retrieve's callback is
- ;; guaranteed to be called or not. It seems that url-http
- ;; decides sometimes consciously not to call it, so it's not
- ;; clear that it's a bug, but even if we need to decide how
- ;; url-http can then warn us that the download has completed.
- ;; In the mean time, we use this here workaround.
- (setq retrieval-done t)
- ;; We used to use `sit-for' here, but in some cases it wouldn't
- ;; work because apparently pending keyboard input would always
- ;; interrupt it before it got a chance to handle process input.
- ;; `sleep-for' was tried but it lead to other forms of
- ;; hanging. --Stef
- (unless (accept-process-output proc)
- ;; accept-process-output returned nil, maybe because the process
- ;; exited (and may have been replaced with another).
- (setq proc (get-buffer-process asynch-buffer))))))
- asynch-buffer)))
-
-(defun url-mm-callback (&rest ignored)
- (let ((handle (mm-dissect-buffer t)))
- (save-excursion
- (url-mark-buffer-as-dead (current-buffer))
- (set-buffer (generate-new-buffer (url-recreate-url url-current-object)))
- (if (eq (mm-display-part handle) 'external)
- (progn
- (set-process-sentinel
- ;; Fixme: this shouldn't have to know the form of the
- ;; undisplayer produced by `mm-display-part'.
- (get-buffer-process (cdr (mm-handle-undisplayer handle)))
- `(lambda (proc event)
- (mm-destroy-parts (quote ,handle))))
- (message "Viewing externally")
- (kill-buffer (current-buffer)))
- (display-buffer (current-buffer))
- (mm-destroy-parts handle)))))
-
-(defun url-mm-url (url)
- "Retrieve URL and pass to the appropriate viewing application."
- (require 'mm-decode)
- (require 'mm-view)
- (url-retrieve url 'url-mm-callback nil))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Miscellaneous
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar url-dead-buffer-list nil)
-
-(defun url-mark-buffer-as-dead (buff)
- (push buff url-dead-buffer-list))
-
-(defun url-gc-dead-buffers ()
- (let ((buff))
- (while (setq buff (pop url-dead-buffer-list))
- (if (buffer-live-p buff)
- (kill-buffer buff)))))
-
-(cond
- ((fboundp 'display-warning)
- (defalias 'url-warn 'display-warning))
- ((fboundp 'warn)
- (defun url-warn (class message &optional level)
- (warn "(%s/%s) %s" class (or level 'warning) message)))
- (t
- (defun url-warn (class message &optional level)
- (save-excursion
- (set-buffer (get-buffer-create "*URL-WARNINGS*"))
- (goto-char (point-max))
- (save-excursion
- (insert (format "(%s/%s) %s\n" class (or level 'warning) message)))
- (display-buffer (current-buffer))))))
-
-(provide 'url)
-
-;;; url.el ends here
+++ /dev/null
-;;; vc-dav.el --- vc.el support for WebDAV
-
-;; Copyright (C) 2001 Free Software Foundation, Inc.
-
-;; Author: Bill Perry <wmperryNOSPAMgnu.org>
-;; Maintainer: Bill Perry <wmperryNOSPAMgnu.org>
-;; Version: $Revision: 1.3 $
-;; Keywords: url, vc
-
-;; GNU Emacs is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-(require 'url)
-(require 'url-dav)
-
-;;; Required functions for a vc backend
-(defun vc-dav-registered (url)
- "Return t iff URL is registered with a DAV aware server."
- (url-dav-vc-registered url))
-
-(defun vc-dav-state (url)
- "Return the current version control state of URL.
-For a list of possible values, see `vc-state'."
- ;; Things we can support for WebDAV
- ;;
- ;; up-to-date - use lockdiscovery
- ;; edited - check for an active lock by us
- ;; USER - use lockdiscovery + owner
- ;;
- ;; These don't make sense for WebDAV
- ;; needs-patch
- ;; needs-merge
- ;; unlocked-changes
- (let ((locks (url-dav-active-locks url)))
- (cond
- ((null locks) 'up-to-date)
- ((assoc url locks)
- ;; SOMEBODY has a lock... let's find out who.
- (setq locks (cdr (assoc url locks)))
- (if (rassoc url-dav-lock-identifier locks)
- ;; _WE_ have a lock
- 'edited
- (cdr (car locks)))))))
-
-(defun vc-dav-checkout-model (url)
- "Indicate whether URL needs to be \"checked out\" before it can be edited.
-See `vc-checkout-model' for a list of possible values."
- ;; The only thing we can support with webdav is 'locking
- 'locking)
-
-;; This should figure out the version # of the file somehow. What is
-;; the most appropriate property in WebDAV to look at for this?
-(defun vc-dav-workfile-version (url)
- "Return the current workfile version of URL."
- "Unknown")
-
-(defun vc-dav-register (url &optional rev comment)
- "Register URL in the DAV backend."
- ;; Do we need to do anything here? FIXME?
- )
-
-(defun vc-dav-checkin (url rev comment)
- "Commit changes in URL to WebDAV.
-If REV is non-nil, that should become the new revision number.
-COMMENT is used as a check-in comment."
- ;; This should PUT the resource and release any locks that we hold.
- )
-
-(defun vc-dav-checkout (url &optional editable rev destfile)
- "Check out revision REV of URL into the working area.
-
-If EDITABLE is non-nil URL should be writable by the user and if
-locking is used for URL, a lock should also be set.
-
-If REV is non-nil, that is the revision to check out. If REV is the
-empty string, that means to check ou tht ehead of the trunk.
-
-If optional arg DESTFILE is given, it is an alternate filename to
-write the contents to.
-"
- ;; This should LOCK the resource.
- )
-
-(defun vc-dav-revert (url &optional contents-done)
- "Revert URL back to the current workfile version.
-
-If optional arg CONTENTS-DONE is non-nil, then the contents of FILE
-have already been reverted from a version backup, and this function
-only needs to update the status of URL within the backend.
-"
- ;; Should do a GET if !contents_done
- ;; Should UNLOCK the file.
- )
-
-(defun vc-dav-print-log (url)
- "Insert the revision log of URL into the *vc* buffer."
- )
-
-(defun vc-dav-diff (url &optional rev1 rev2)
- "Insert the diff for URL into the *vc-diff* buffer.
-If REV1 and REV2 are non-nil report differences from REV1 to REV2.
-If REV1 is nil, use the current workfile version as the older version.
-If REV2 is nil, use the current workfile contents as the nwer version.
-
-It should return a status of either 0 (no differences found), or
-1 (either non-empty diff or the diff is run asynchronously).
-"
- ;; We should do this asynchronously...
- ;; How would we do it at all, that is the question!
- )
-
-
-
-;;; Optional functions
-;; Should be faster than vc-dav-state - but how?
-(defun vc-dav-state-heuristic (url)
- "Estimate the version control state of URL at visiting time."
- (vc-dav-state url))
-
-;; This should use url-dav-get-properties with a depth of `1' to get
-;; all the properties.
-(defun vc-dav-dir-state (url)
- "find the version control state of all files in DIR in a fast way."
- )
-
-(defun vc-dav-workfile-unchanged-p (url)
- "Return non-nil if URL is unchanged from its current workfile version."
- ;; Probably impossible with webdav
- )
-
-(defun vc-dav-responsible-p (url)
- "Return non-nil if DAV considers itself `responsible' for URL."
- ;; Check for DAV support on the web server.
- t)
-
-(defun vc-dav-could-register (url)
- "Return non-nil if URL could be registered under this backend."
- ;; Check for DAV support on the web server.
- t)
-
-;;; Unimplemented functions
-;;
-;; vc-dav-latest-on-branch-p(URL)
-;; Return non-nil if the current workfile version of FILE is the
-;; latest on its branch. There are no branches in webdav yet.
-;;
-;; vc-dav-mode-line-string(url)
-;; Return a dav-specific mode line string for URL. Are there any
-;; specific states that we want exposed?
-;;
-;; vc-dav-dired-state-info(url)
-;; Translate the `vc-state' property of URL into a string that can
-;; be used in a vc-dired buffer. Are there any extra states that
-;; we want exposed?
-;;
-;; vc-dav-receive-file(url rev)
-;; Let this backend `receive' a file that is already registered
-;; under another backend. The default just calls `register', which
-;; should be sufficient for WebDAV.
-;;
-;; vc-dav-unregister(url)
-;; Unregister URL. Not possible with WebDAV, other than by
-;; deleting the resource.
-
-(provide 'vc-dav)
+++ /dev/null
-cURL + OpenSSL for Windows \83}\83j\83\85\83A\83\8b\r
- Since: 27-Feb-2002\r
- Version: 1.1\r
- Author: MURAOKA Taro (KoRoN)\r
- Last Change: 04-Nov-2003.\r
-\90à\96¾\r
- cURL\82Í\83R\83}\83\93\83h\83\89\83C\83\93\82Å URI/URL \82ð\8ew\92è\82µ\82Ä\81A\83t\83@\83C\83\8b\82ð\83_\83E\83\93\83\8d\81[\83h\82·\82é\83\\83t\83g\r
- \83E\83F\83A\82Å\82·\81B\83A\81[\83J\83C\83u\82É\8eû\98^\82³\82ê\82Ä\82¢\82é\8eÀ\8ds\83t\83@\83C\83\8b(curl.exe)\82Í\81A\83\\81[\83X\83R\81[\83h\r
- \82©\82ç SSL \82ð\97L\8cø\82É\82µ\82Ä Visual C++ 6.0 \82ð\97p\82¢\82Ä\83R\83\93\83p\83C\83\8b\82µ\82½\82à\82Ì\82Å\82·\81B SSL \82Í\r
- OpenSSL\82Ì\82à\82Ì\82ðVC6\82ÆNASM 0.98\82ð\97p\82¢\82ÄDLL\82Æ\82µ\82Ä\83R\83\93\83p\83C\83\8b\82µ\82Ü\82µ\82½\81B\r
- \r
- \8eg\82¢\95û\81A\8by\82Ñ\83\89\83C\83Z\83\93\83X\82É\82Â\82¢\82Ä\82Ì\8fÚ\8d×\82Í\88È\89º\82ÌURI\82Æ\94z\95z\83A\81[\83J\83C\83u\93à\82Ìdocs/*\82ð\r
- \8eQ\8fÆ\82µ\82Ä\82\82¾\82³\82¢\81B\r
-\r
- - cURL (7.10.8)\r
- http://curl.haxx.se/\r
- - OpenSSL (0.9.7c)\r
- http://www.openssl.org/\r
-\r
- \96{\83A\81[\83J\83C\83u\82Í\88È\89º\82ÌURI\82É\82Ä\94z\95z\82³\82ê\82Ü\82µ\82½\81B\r
-\r
- - \8d\81\82è\89®\r
- http://www.kaoriya.net/\r
- - \94z\95z\8eÒ\83\81\81[\83\8b\83A\83h\83\8c\83X\r
- koronNOSPAMtka.att.ne.jp\r
-\r
-\r
-\8b\8c\94Å\82ð\82¨\8eg\82¢\82Ì\95û\82Ö\r
- \8d¡\94Å\82æ\82èDLL\82ð\8eg\97p\82¹\82¸\92P\91Ì\82ÌEXE\82Æ\82µ\82Ä\83r\83\8b\83h\82·\82é\82æ\82¤\82É\82µ\82Ü\82µ\82½\81B\82»\82Ì\82½\82ß\8b\8c\94Å\82É\r
- \8aÜ\82Ü\82ê\82Ä\82¢\82½ libcurl.dll, libeay32.dll, ssleay32.dll\82Ì3\82Â\82Ì\83t\83@\83C\83\8b\82Í\95s\97v\82É\r
- \82È\82è\82Ü\82µ\82½\81B\82±\82ê\82ç\82Ì\83t\83@\83C\83\8b\82Í\91¶\8dÝ\82µ\82Ä\82¢\82Ä\82à\89½\82Ì\8aQ\82É\82à\82È\82è\82Ü\82¹\82ñ\82ª\93¾\82É\82à\82È\82ç\r
- \82¸\81A\82Ü\82½\96³\82\82Ä\82àcURL\82Ì\93®\8dì\82É\8ex\8fá\82ð\82«\82½\82·\8e\96\82Í\82 \82è\82Ü\82¹\82ñ\81B\82æ\82Á\82Ä\8ae\8e©\82Ì\94»\92f\82Å\8fÁ\r
- \82µ\82Ä\82¢\82½\82¾\82¢\82Ä\8d\\82¢\82Ü\82¹\82ñ\81B\r
-\r
-\r
-\8dX\90V\97\9a\97ð\r
- 04-Nov-2003\r
- curl\82ð7.10.8\82É\83A\83b\83v\83f\81[\83g\r
- OpenSSH\82ð0.9.7c\82É\83A\83b\83v\83f\81[\83g\r
- CA\82ð\94z\95z\95¨\82É\92Ç\89Á\r
- 08-Apr-2003\r
- curl\82ð7.10.4\82É\83A\83b\83v\83f\81[\83g\r
- OpenSSH\82ð0.9.6i\82É\83A\83b\83v\83f\81[\83g\r
- 23-Jan-2003\r
- curl\82ð7.10.3\82É\83A\83b\83v\83f\81[\83g\r
- OpenSSH\82ð0.9.6h\82É\83A\83b\83v\83f\81[\83g\r
- DLL\82Å\82Í\82È\82\92P\91Ì\82ÌEXE\82Æ\82µ\82Ä\83\8a\83r\83\8b\83h\r
- \94z\95z\83A\81[\83J\83C\83u\93à\82Édocs/FAQ\82ð\92Ç\89Á\r
- 05-Oct-2002\r
- curl\82ð7.10\82É\83A\83b\83v\83f\81[\83g\r
- OpenSSH\82ð0.9.6g\82É\95Ï\8dX\r
- 06-Aug-2002\r
- OpenSSH\82ð0.9.6e\82É\95Ï\8dX\r
-\r
-------------------------------------------------------------------------------\r
- \90¶\82«\82é\8e\96\82Ö\82Ì\8b\82¢\88Ó\8eu\82ª\93¯\8e\9e\82É\8e©\95ª\82Æ\88Ù\82È\82é\90¶\96½\82ð\82à\91¸\82Ô\90S\82Æ\82È\82é\r
- MURAOKA Taro/KoRoN <koronNOSPAMtka.att.ne.jp>\r
- vim:set ts=8 sts=2 sw=2 tw=78 et ft=memo:\r
+++ /dev/null
-##
-## $Id: ca-bundle.crt,v 1.2 2003/03/24 11:06:57 bagder Exp $
-##
-## ca-bundle.crt -- Bundle of CA Root Certificates
-## Last Modified: Thu Mar 2 09:32:46 CET 2000
-##
-## This is a bundle of X.509 certificates of public
-## Certificate Authorities (CA). These were automatically
-## extracted from Netscape Communicator 4.72's certificate database
-## (the file `cert7.db'). It contains the certificates in both
-## plain text and PEM format and therefore can be directly used
-## with an Apache+mod_ssl webserver for SSL client authentication.
-## Just configure this file as the SSLCACertificateFile.
-##
-## (SKIPME)
-##
-
-ABAecom (sub., Am. Bankers Assn.) Root CA
-=========================================
-MD5 Fingerprint: 82:12:F7:89:E1:0B:91:60:A4:B6:22:9F:94:68:11:92
-PEM Data:
------BEGIN CERTIFICATE-----
-MIID+DCCAuCgAwIBAgIRANAeQJAAACdLAAAAAQAAAAQwDQYJKoZIhvcNAQEFBQAw
-gYwxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIEwRVdGFoMRcwFQYDVQQHEw5TYWx0IExh
-a2UgQ2l0eTEYMBYGA1UEChMPWGNlcnQgRVogYnkgRFNUMRgwFgYDVQQDEw9YY2Vy
-dCBFWiBieSBEU1QxITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAe
-Fw05OTA3MTQxNjE0MThaFw0wOTA3MTExNjE0MThaMIGMMQswCQYDVQQGEwJVUzEN
-MAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxGDAWBgNVBAoT
-D1hjZXJ0IEVaIGJ5IERTVDEYMBYGA1UEAxMPWGNlcnQgRVogYnkgRFNUMSEwHwYJ
-KoZIhvcNAQkBFhJjYUBkaWdzaWd0cnVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUA
-A4IBDwAwggEKAoIBAQCtVBjetL/3reh0qu2LfI/C1HUa1YS5tmL8ie/kl2GS+x24
-4VpHNJ6eBiL70+o4y7iLB/caoBd3B1owHNQpOCDXJ0DYUJNDv9IYoil2BXKqa7Zp
-mKt5Hhxl9WqL/MUWqqJy2mDtTm4ZJXoKHTDjUJtCPETrobAgHtsCfv49H7/QAIrb
-QHamGKUVp1e2UsIBF5h3j4qBxhq0airmr6nWAKzP2BVJfNsbof6B+of505DBAsD5
-0ELpkWglX8a/hznplQBgKL+DLMDnXrbXNhbnYId26OcnsiUNi3rlqh3lWc3OCw5v
-xsic4xDZhTnTt5v6xrp8dNJddVardKSiUb9SfO5xAgMBAAGjUzBRMA8GA1UdEwEB
-/wQFMAMBAf8wHwYDVR0jBBgwFoAUCCBsZuuBCmxc1bWmPEHdHJaRJ3cwHQYDVR0O
-BBYEFAggbGbrgQpsXNW1pjxB3RyWkSd3MA0GCSqGSIb3DQEBBQUAA4IBAQBah1iP
-Lat2IWtUDNnxQfZOzSue4x+boy1/2St9WMhnpCn16ezVvZY/o3P4xFs2fNBjLDQ5
-m0i4PW/2FMWeY+anNG7T6DOzxzwYbiOuQ5KZP5jFaTDxNjutuTCC1rZZFpYCCykS
-YbQRifcML5SQhZgonFNsfmPdc/QZ/0qB0bJSI/08SjTOWhvgUIrtT4GV2GDn5MQN
-u1g+WPdOaG8+Z8nLepcWJ+xCYRR2uwDF6wg9FX9LtiJdhzuQ9PPA/jez6dliDMDD
-Wa9gvR8N26E0HzDEPYutsB0Ek+1f1eS/IDAE9EjpMwHRLpAnUrOb3jocq6mXf5vr
-wo3CbezcE9NGxXl8
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number:
- d0:1e:40:90:00:00:27:4b:00:00:00:01:00:00:00:04
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, ST=Utah, L=Salt Lake City, O=Xcert EZ by DST, CN=Xcert EZ by DST/Email=caNOSPAMdigsigtrust.com
- Validity
- Not Before: Jul 14 16:14:18 1999 GMT
- Not After : Jul 11 16:14:18 2009 GMT
- Subject: C=US, ST=Utah, L=Salt Lake City, O=Xcert EZ by DST, CN=Xcert EZ by DST/Email=caNOSPAMdigsigtrust.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:ad:54:18:de:b4:bf:f7:ad:e8:74:aa:ed:8b:7c:
- 8f:c2:d4:75:1a:d5:84:b9:b6:62:fc:89:ef:e4:97:
- 61:92:fb:1d:b8:e1:5a:47:34:9e:9e:06:22:fb:d3:
- ea:38:cb:b8:8b:07:f7:1a:a0:17:77:07:5a:30:1c:
- d4:29:38:20:d7:27:40:d8:50:93:43:bf:d2:18:a2:
- 29:76:05:72:aa:6b:b6:69:98:ab:79:1e:1c:65:f5:
- 6a:8b:fc:c5:16:aa:a2:72:da:60:ed:4e:6e:19:25:
- 7a:0a:1d:30:e3:50:9b:42:3c:44:eb:a1:b0:20:1e:
- db:02:7e:fe:3d:1f:bf:d0:00:8a:db:40:76:a6:18:
- a5:15:a7:57:b6:52:c2:01:17:98:77:8f:8a:81:c6:
- 1a:b4:6a:2a:e6:af:a9:d6:00:ac:cf:d8:15:49:7c:
- db:1b:a1:fe:81:fa:87:f9:d3:90:c1:02:c0:f9:d0:
- 42:e9:91:68:25:5f:c6:bf:87:39:e9:95:00:60:28:
- bf:83:2c:c0:e7:5e:b6:d7:36:16:e7:60:87:76:e8:
- e7:27:b2:25:0d:8b:7a:e5:aa:1d:e5:59:cd:ce:0b:
- 0e:6f:c6:c8:9c:e3:10:d9:85:39:d3:b7:9b:fa:c6:
- ba:7c:74:d2:5d:75:56:ab:74:a4:a2:51:bf:52:7c:
- ee:71
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints: critical
- CA:TRUE
- X509v3 Authority Key Identifier:
- keyid:08:20:6C:66:EB:81:0A:6C:5C:D5:B5:A6:3C:41:DD:1C:96:91:27:77
-
- X509v3 Subject Key Identifier:
- 08:20:6C:66:EB:81:0A:6C:5C:D5:B5:A6:3C:41:DD:1C:96:91:27:77
- Signature Algorithm: sha1WithRSAEncryption
- 5a:87:58:8f:2d:ab:76:21:6b:54:0c:d9:f1:41:f6:4e:cd:2b:
- 9e:e3:1f:9b:a3:2d:7f:d9:2b:7d:58:c8:67:a4:29:f5:e9:ec:
- d5:bd:96:3f:a3:73:f8:c4:5b:36:7c:d0:63:2c:34:39:9b:48:
- b8:3d:6f:f6:14:c5:9e:63:e6:a7:34:6e:d3:e8:33:b3:c7:3c:
- 18:6e:23:ae:43:92:99:3f:98:c5:69:30:f1:36:3b:ad:b9:30:
- 82:d6:b6:59:16:96:02:0b:29:12:61:b4:11:89:f7:0c:2f:94:
- 90:85:98:28:9c:53:6c:7e:63:dd:73:f4:19:ff:4a:81:d1:b2:
- 52:23:fd:3c:4a:34:ce:5a:1b:e0:50:8a:ed:4f:81:95:d8:60:
- e7:e4:c4:0d:bb:58:3e:58:f7:4e:68:6f:3e:67:c9:cb:7a:97:
- 16:27:ec:42:61:14:76:bb:00:c5:eb:08:3d:15:7f:4b:b6:22:
- 5d:87:3b:90:f4:f3:c0:fe:37:b3:e9:d9:62:0c:c0:c3:59:af:
- 60:bd:1f:0d:db:a1:34:1f:30:c4:3d:8b:ad:b0:1d:04:93:ed:
- 5f:d5:e4:bf:20:30:04:f4:48:e9:33:01:d1:2e:90:27:52:b3:
- 9b:de:3a:1c:ab:a9:97:7f:9b:eb:c2:8d:c2:6d:ec:dc:13:d3:
- 46:c5:79:7c
-
-ANX Network CA by DST
-=====================
-MD5 Fingerprint: A8:ED:DE:EB:93:88:66:D8:2F:C3:BD:1D:BE:45:BE:4D
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDTTCCAragAwIBAgIENm6ibzANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJV
-UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMR0wGwYDVQQL
-ExREU1QgKEFOWCBOZXR3b3JrKSBDQTAeFw05ODEyMDkxNTQ2NDhaFw0xODEyMDkx
-NjE2NDhaMFIxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVy
-ZSBUcnVzdCBDby4xHTAbBgNVBAsTFERTVCAoQU5YIE5ldHdvcmspIENBMIGdMA0G
-CSqGSIb3DQEBAQUAA4GLADCBhwKBgQC0SBGAWKDVpZkP9jcsRLZu0XzzKmueEbaI
-IwRccSWeahJ3EW6/aDllqPay9qIYsokVoGe3eowiSGv2hDQftsr3G3LL8ltI04ce
-InYTBLSsbJZ/5w4IyTJRMC3VgOghZ7rzXggkLAdZnZAa7kbJtaQelrRBkdR/0o04
-JrBvQ24JfQIBA6OCATAwggEsMBEGCWCGSAGG+EIBAQQEAwIABzB0BgNVHR8EbTBr
-MGmgZ6BlpGMwYTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0
-dXJlIFRydXN0IENvLjEdMBsGA1UECxMURFNUIChBTlggTmV0d29yaykgQ0ExDTAL
-BgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxNTQ2NDhagQ8yMDE4MTIw
-OTE1NDY0OFowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFIwWVXDMFgpTZMKlhKqz
-ZBdDP4I2MB0GA1UdDgQWBBSMFlVwzBYKU2TCpYSqs2QXQz+CNjAMBgNVHRMEBTAD
-AQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB
-AEklyWCxDF+pORDTxTRVfc95wynr3vnCQPnoVsXwL+z02exIUbhjOF6TbhiWhbnK
-UJykuOpmJmiThW9vTHHQvnoLPDG5975pnhDX0UDorBZxq66rOOFwscqSFuBdhaYY
-gAYAnOGmGEJRp2hoWe8mlF+tMQz+KR4XAYQ3W+gSMqNd
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 913220207 (0x366ea26f)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA
- Validity
- Not Before: Dec 9 15:46:48 1998 GMT
- Not After : Dec 9 16:16:48 2018 GMT
- Subject: C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:b4:48:11:80:58:a0:d5:a5:99:0f:f6:37:2c:44:
- b6:6e:d1:7c:f3:2a:6b:9e:11:b6:88:23:04:5c:71:
- 25:9e:6a:12:77:11:6e:bf:68:39:65:a8:f6:b2:f6:
- a2:18:b2:89:15:a0:67:b7:7a:8c:22:48:6b:f6:84:
- 34:1f:b6:ca:f7:1b:72:cb:f2:5b:48:d3:87:1e:22:
- 76:13:04:b4:ac:6c:96:7f:e7:0e:08:c9:32:51:30:
- 2d:d5:80:e8:21:67:ba:f3:5e:08:24:2c:07:59:9d:
- 90:1a:ee:46:c9:b5:a4:1e:96:b4:41:91:d4:7f:d2:
- 8d:38:26:b0:6f:43:6e:09:7d
- Exponent: 3 (0x3)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 CRL Distribution Points:
- DirName:/C=US/O=Digital Signature Trust Co./OU=DST (ANX Network) CA/CN=CRL1
-
- X509v3 Private Key Usage Period:
- Not Before: Dec 9 15:46:48 1998 GMT, Not After: Dec 9 15:46:48 2018 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:8C:16:55:70:CC:16:0A:53:64:C2:A5:84:AA:B3:64:17:43:3F:82:36
-
- X509v3 Subject Key Identifier:
- 8C:16:55:70:CC:16:0A:53:64:C2:A5:84:AA:B3:64:17:43:3F:82:36
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0
-..V4.0....
- Signature Algorithm: sha1WithRSAEncryption
- 49:25:c9:60:b1:0c:5f:a9:39:10:d3:c5:34:55:7d:cf:79:c3:
- 29:eb:de:f9:c2:40:f9:e8:56:c5:f0:2f:ec:f4:d9:ec:48:51:
- b8:63:38:5e:93:6e:18:96:85:b9:ca:50:9c:a4:b8:ea:66:26:
- 68:93:85:6f:6f:4c:71:d0:be:7a:0b:3c:31:b9:f7:be:69:9e:
- 10:d7:d1:40:e8:ac:16:71:ab:ae:ab:38:e1:70:b1:ca:92:16:
- e0:5d:85:a6:18:80:06:00:9c:e1:a6:18:42:51:a7:68:68:59:
- ef:26:94:5f:ad:31:0c:fe:29:1e:17:01:84:37:5b:e8:12:32:
- a3:5d
-
-American Express CA
-===================
-MD5 Fingerprint: 1C:D5:8E:82:BE:70:55:8E:39:61:DF:AD:51:DB:6B:A0
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICkDCCAfkCAgCNMA0GCSqGSIb3DQEBBAUAMIGPMQswCQYDVQQGEwJVUzEnMCUG
-A1UEChMeQW1lcmljYW4gRXhwcmVzcyBDb21wYW55LCBJbmMuMSYwJAYDVQQLEx1B
-bWVyaWNhbiBFeHByZXNzIFRlY2hub2xvZ2llczEvMC0GA1UEAxMmQW1lcmljYW4g
-RXhwcmVzcyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNOTgwODE0MjIwMTAwWhcN
-MDYwODE0MjM1OTAwWjCBjzELMAkGA1UEBhMCVVMxJzAlBgNVBAoTHkFtZXJpY2Fu
-IEV4cHJlc3MgQ29tcGFueSwgSW5jLjEmMCQGA1UECxMdQW1lcmljYW4gRXhwcmVz
-cyBUZWNobm9sb2dpZXMxLzAtBgNVBAMTJkFtZXJpY2FuIEV4cHJlc3MgQ2VydGlm
-aWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ8kmS
-hcr9FSm1BrZE7PyIo/KGzv8UTyQckvnCI8HOQ99dNMi4FOzVKnCRSZXXVs2U8amT
-0Ggi3E19oApyKkfqJfCFAF82VGHPC/k3Wmed6R/pZD9wlWGn0DAC3iYopGYDBOkw
-+48zB/lvYYeictvzaHhjZlmpybdm4RWySDYs+QIDAQABMA0GCSqGSIb3DQEBBAUA
-A4GBAGgXYrhzi0xs60qlPqvlnS7SzYoHV/PGWZd2Fxf4Uo4nk9hY2Chs9KIEeorC
-diSxArTfKPL386infiNIYYj0EWiuJl32oUtTJWrYKhQCDuCHIG6eGVxzkAsj4jGX
-Iz/VIqLTBnvaN/XXtUFEF3pFAtmFRWbWjsfwegyZYiJpW+3S
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 141 (0x8d)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Certificate Authority
- Validity
- Not Before: Aug 14 22:01:00 1998 GMT
- Not After : Aug 14 23:59:00 2006 GMT
- Subject: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Certificate Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:c9:f2:49:92:85:ca:fd:15:29:b5:06:b6:44:ec:
- fc:88:a3:f2:86:ce:ff:14:4f:24:1c:92:f9:c2:23:
- c1:ce:43:df:5d:34:c8:b8:14:ec:d5:2a:70:91:49:
- 95:d7:56:cd:94:f1:a9:93:d0:68:22:dc:4d:7d:a0:
- 0a:72:2a:47:ea:25:f0:85:00:5f:36:54:61:cf:0b:
- f9:37:5a:67:9d:e9:1f:e9:64:3f:70:95:61:a7:d0:
- 30:02:de:26:28:a4:66:03:04:e9:30:fb:8f:33:07:
- f9:6f:61:87:a2:72:db:f3:68:78:63:66:59:a9:c9:
- b7:66:e1:15:b2:48:36:2c:f9
- Exponent: 65537 (0x10001)
- Signature Algorithm: md5WithRSAEncryption
- 68:17:62:b8:73:8b:4c:6c:eb:4a:a5:3e:ab:e5:9d:2e:d2:cd:
- 8a:07:57:f3:c6:59:97:76:17:17:f8:52:8e:27:93:d8:58:d8:
- 28:6c:f4:a2:04:7a:8a:c2:76:24:b1:02:b4:df:28:f2:f7:f3:
- a8:a7:7e:23:48:61:88:f4:11:68:ae:26:5d:f6:a1:4b:53:25:
- 6a:d8:2a:14:02:0e:e0:87:20:6e:9e:19:5c:73:90:0b:23:e2:
- 31:97:23:3f:d5:22:a2:d3:06:7b:da:37:f5:d7:b5:41:44:17:
- 7a:45:02:d9:85:45:66:d6:8e:c7:f0:7a:0c:99:62:22:69:5b:
- ed:d2
-
-American Express Global CA
-==========================
-MD5 Fingerprint: 63:1B:66:93:8C:F3:66:CB:3C:79:57:DC:05:49:EA:DB
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIEBDCCAuygAwIBAgICAIUwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNVBAYTAlVT
-MScwJQYDVQQKEx5BbWVyaWNhbiBFeHByZXNzIENvbXBhbnksIEluYy4xJjAkBgNV
-BAsTHUFtZXJpY2FuIEV4cHJlc3MgVGVjaG5vbG9naWVzMTYwNAYDVQQDEy1BbWVy
-aWNhbiBFeHByZXNzIEdsb2JhbCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNOTgw
-ODE0MTkwNjAwWhcNMTMwODE0MjM1OTAwWjCBljELMAkGA1UEBhMCVVMxJzAlBgNV
-BAoTHkFtZXJpY2FuIEV4cHJlc3MgQ29tcGFueSwgSW5jLjEmMCQGA1UECxMdQW1l
-cmljYW4gRXhwcmVzcyBUZWNobm9sb2dpZXMxNjA0BgNVBAMTLUFtZXJpY2FuIEV4
-cHJlc3MgR2xvYmFsIENlcnRpZmljYXRlIEF1dGhvcml0eTCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBAPAkJmYu++tKc3FTiUfLJjxTkpRMysKFtQ34w1e9
-Lyofahi3V68MABb6oLaQpvcaoS5mJsdoo4qTaWa1RlYtHYLqkAwKIsKJUI0F89Sr
-c0HwzxKsKLRvFJSWWUuekHWG3+JH6+HpT0N+h8onGGaetcFAZX38YW+tm3LPqV7Y
-8/nabpEQ+ky16n4g3qk5L/WI5IpvNcYgnCuGRjMK/DFVpWusFkDpzTVZbzIEw3u1
-D3t3cPNIuypSgs6vKW3xEW9t5gcAAe+a8yYNpnkTZ6/4qxx1rJG1a75AsN6cDLFp
-hRlxkRNFyt/R/eayypaDedvFuKpbepALeFY+xteflEgR9a0CAwEAAaNaMFgwEgYD
-VR0TAQH/BAgwBgEB/wIBBTAOBgNVHQ8BAf8EBAMCAQYwFwYDVR0gBBAwDjAMBgoq
-hkiG+Q8KAQUBMBkGA1UdDgQSBBBXRzV7NicRqAj8L0Yl6yRpMA0GCSqGSIb3DQEB
-BQUAA4IBAQDHYUWoinG5vjTpIXshzVYTmNUwY+kYqkuSFb8LHbvskmnFLsNhi+gw
-RcsQRsFzOFyLGdIr80DrfHKzLh4n43WVihybLsSVBYZy0FX0oZJSeVzb9Pjc5dcS
-sUDHPIbkMWVKyjfG3nZXGWlMRmn8Kq0WN3qTrPchSy3766lQy8HRQAjaA2mHpzde
-VcHF7cTjjgwml5tcV0ty4/IDBdACOyYDQJCevgtbSQx48dVMVSng9v1MA6lUAjLR
-V1qFrEPtWzsWX6C/NdtLnnvo/+cNPDuom0lBRvVzTv+SZSGDE1Vx60k8f4gawhIo
-JaFGS0E3l3/sjvHUoZbCILZerakcHhGg
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 133 (0x85)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Global Certificate Authority
- Validity
- Not Before: Aug 14 19:06:00 1998 GMT
- Not After : Aug 14 23:59:00 2013 GMT
- Subject: C=US, O=American Express Company, Inc., OU=American Express Technologies, CN=American Express Global Certificate Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:f0:24:26:66:2e:fb:eb:4a:73:71:53:89:47:cb:
- 26:3c:53:92:94:4c:ca:c2:85:b5:0d:f8:c3:57:bd:
- 2f:2a:1f:6a:18:b7:57:af:0c:00:16:fa:a0:b6:90:
- a6:f7:1a:a1:2e:66:26:c7:68:a3:8a:93:69:66:b5:
- 46:56:2d:1d:82:ea:90:0c:0a:22:c2:89:50:8d:05:
- f3:d4:ab:73:41:f0:cf:12:ac:28:b4:6f:14:94:96:
- 59:4b:9e:90:75:86:df:e2:47:eb:e1:e9:4f:43:7e:
- 87:ca:27:18:66:9e:b5:c1:40:65:7d:fc:61:6f:ad:
- 9b:72:cf:a9:5e:d8:f3:f9:da:6e:91:10:fa:4c:b5:
- ea:7e:20:de:a9:39:2f:f5:88:e4:8a:6f:35:c6:20:
- 9c:2b:86:46:33:0a:fc:31:55:a5:6b:ac:16:40:e9:
- cd:35:59:6f:32:04:c3:7b:b5:0f:7b:77:70:f3:48:
- bb:2a:52:82:ce:af:29:6d:f1:11:6f:6d:e6:07:00:
- 01:ef:9a:f3:26:0d:a6:79:13:67:af:f8:ab:1c:75:
- ac:91:b5:6b:be:40:b0:de:9c:0c:b1:69:85:19:71:
- 91:13:45:ca:df:d1:fd:e6:b2:ca:96:83:79:db:c5:
- b8:aa:5b:7a:90:0b:78:56:3e:c6:d7:9f:94:48:11:
- f5:ad
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints: critical
- CA:TRUE, pathlen:5
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Certificate Policies:
- Policy: 1.2.840.113807.10.1.5.1
-
- X509v3 Subject Key Identifier:
- 57:47:35:7B:36:27:11:A8:08:FC:2F:46:25:EB:24:69
- Signature Algorithm: sha1WithRSAEncryption
- c7:61:45:a8:8a:71:b9:be:34:e9:21:7b:21:cd:56:13:98:d5:
- 30:63:e9:18:aa:4b:92:15:bf:0b:1d:bb:ec:92:69:c5:2e:c3:
- 61:8b:e8:30:45:cb:10:46:c1:73:38:5c:8b:19:d2:2b:f3:40:
- eb:7c:72:b3:2e:1e:27:e3:75:95:8a:1c:9b:2e:c4:95:05:86:
- 72:d0:55:f4:a1:92:52:79:5c:db:f4:f8:dc:e5:d7:12:b1:40:
- c7:3c:86:e4:31:65:4a:ca:37:c6:de:76:57:19:69:4c:46:69:
- fc:2a:ad:16:37:7a:93:ac:f7:21:4b:2d:fb:eb:a9:50:cb:c1:
- d1:40:08:da:03:69:87:a7:37:5e:55:c1:c5:ed:c4:e3:8e:0c:
- 26:97:9b:5c:57:4b:72:e3:f2:03:05:d0:02:3b:26:03:40:90:
- 9e:be:0b:5b:49:0c:78:f1:d5:4c:55:29:e0:f6:fd:4c:03:a9:
- 54:02:32:d1:57:5a:85:ac:43:ed:5b:3b:16:5f:a0:bf:35:db:
- 4b:9e:7b:e8:ff:e7:0d:3c:3b:a8:9b:49:41:46:f5:73:4e:ff:
- 92:65:21:83:13:55:71:eb:49:3c:7f:88:1a:c2:12:28:25:a1:
- 46:4b:41:37:97:7f:ec:8e:f1:d4:a1:96:c2:20:b6:5e:ad:a9:
- 1c:1e:11:a0
-
-BelSign Object Publishing CA
-============================
-MD5 Fingerprint: 8A:02:F8:DF:B8:E1:84:9F:5A:C2:60:24:65:D1:73:FB
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDAzCCAmygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBuzELMAkGA1UEBhMCQkUx
-ETAPBgNVBAcTCEJydXNzZWxzMRMwEQYDVQQKEwpCZWxTaWduIE5WMTgwNgYDVQQL
-Ey9CZWxTaWduIE9iamVjdCBQdWJsaXNoaW5nIENlcnRpZmljYXRlIEF1dGhvcml0
-eTElMCMGA1UEAxMcQmVsU2lnbiBPYmplY3QgUHVibGlzaGluZyBDQTEjMCEGCSqG
-SIb3DQEJARYUd2VibWFzdGVyQGJlbHNpZ24uYmUwHhcNOTcwOTE5MjIwMzAwWhcN
-MDcwOTE5MjIwMzAwWjCBuzELMAkGA1UEBhMCQkUxETAPBgNVBAcTCEJydXNzZWxz
-MRMwEQYDVQQKEwpCZWxTaWduIE5WMTgwNgYDVQQLEy9CZWxTaWduIE9iamVjdCBQ
-dWJsaXNoaW5nIENlcnRpZmljYXRlIEF1dGhvcml0eTElMCMGA1UEAxMcQmVsU2ln
-biBPYmplY3QgUHVibGlzaGluZyBDQTEjMCEGCSqGSIb3DQEJARYUd2VibWFzdGVy
-QGJlbHNpZ24uYmUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMQuH7a/7oJA
-3fm3LkHVngWxWtAmfGJVA5v8y2HeS+/+6Jn+h7mIz5DaDwk8dt8Xl7bLPyVF/bS8
-WAC+sFq2FIeP7mdkrR2Ig7tnn2VhAFgIgFCfgMkx9iqQHC33SmwQ9iNDXTgJYIhX
-As0WbBj8zfuSKnfQnpOjXYhk0Mj4XVRRAgMBAAGjFTATMBEGCWCGSAGG+EIBAQQE
-AwIABzANBgkqhkiG9w0BAQQFAAOBgQBjdhd8lvBTpV0BHFPOKcJ+daxMDaIIc7Rq
-Mf0CBhSZ3FQEpL/IloafMUMyJVf2hfYluze+oXkjyVcGJXFrRU/49AJAFoIir1Tq
-Mij2De6ZuksIUQ9uhiMhTC0liIHELg7xEyw4ipUCJMM6lWPkk45IuwhHcl+u5jpa
-R9Zxxp6aUg==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 1 (0x1)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Object Publishing Certificate Authority, CN=BelSign Object Publishing CA/Email=webmasterNOSPAMbelsign.be
- Validity
- Not Before: Sep 19 22:03:00 1997 GMT
- Not After : Sep 19 22:03:00 2007 GMT
- Subject: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Object Publishing Certificate Authority, CN=BelSign Object Publishing CA/Email=webmaster@belsign.be
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:c4:2e:1f:b6:bf:ee:82:40:dd:f9:b7:2e:41:d5:
- 9e:05:b1:5a:d0:26:7c:62:55:03:9b:fc:cb:61:de:
- 4b:ef:fe:e8:99:fe:87:b9:88:cf:90:da:0f:09:3c:
- 76:df:17:97:b6:cb:3f:25:45:fd:b4:bc:58:00:be:
- b0:5a:b6:14:87:8f:ee:67:64:ad:1d:88:83:bb:67:
- 9f:65:61:00:58:08:80:50:9f:80:c9:31:f6:2a:90:
- 1c:2d:f7:4a:6c:10:f6:23:43:5d:38:09:60:88:57:
- 02:cd:16:6c:18:fc:cd:fb:92:2a:77:d0:9e:93:a3:
- 5d:88:64:d0:c8:f8:5d:54:51
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- Signature Algorithm: md5WithRSAEncryption
- 63:76:17:7c:96:f0:53:a5:5d:01:1c:53:ce:29:c2:7e:75:ac:
- 4c:0d:a2:08:73:b4:6a:31:fd:02:06:14:99:dc:54:04:a4:bf:
- c8:96:86:9f:31:43:32:25:57:f6:85:f6:25:bb:37:be:a1:79:
- 23:c9:57:06:25:71:6b:45:4f:f8:f4:02:40:16:82:22:af:54:
- ea:32:28:f6:0d:ee:99:ba:4b:08:51:0f:6e:86:23:21:4c:2d:
- 25:88:81:c4:2e:0e:f1:13:2c:38:8a:95:02:24:c3:3a:95:63:
- e4:93:8e:48:bb:08:47:72:5f:ae:e6:3a:5a:47:d6:71:c6:9e:
- 9a:52
-
-BelSign Secure Server CA
-========================
-MD5 Fingerprint: 3D:5E:82:C6:D9:AD:D9:8B:93:6B:0C:10:B9:49:0A:B1
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIC8zCCAlygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBszELMAkGA1UEBhMCQkUx
-ETAPBgNVBAcTCEJydXNzZWxzMRMwEQYDVQQKEwpCZWxTaWduIE5WMTQwMgYDVQQL
-EytCZWxTaWduIFNlY3VyZSBTZXJ2ZXIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSEw
-HwYDVQQDExhCZWxTaWduIFNlY3VyZSBTZXJ2ZXIgQ0ExIzAhBgkqhkiG9w0BCQEW
-FHdlYm1hc3RlckBiZWxzaWduLmJlMB4XDTk3MDcxNjIyMDA1NFoXDTA3MDcxNjIy
-MDA1NFowgbMxCzAJBgNVBAYTAkJFMREwDwYDVQQHEwhCcnVzc2VsczETMBEGA1UE
-ChMKQmVsU2lnbiBOVjE0MDIGA1UECxMrQmVsU2lnbiBTZWN1cmUgU2VydmVyIENl
-cnRpZmljYXRlIEF1dGhvcml0eTEhMB8GA1UEAxMYQmVsU2lnbiBTZWN1cmUgU2Vy
-dmVyIENBMSMwIQYJKoZIhvcNAQkBFhR3ZWJtYXN0ZXJAYmVsc2lnbi5iZTCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1gESeJL4BEJ/yccig/x8R3AwK0kLPjZA
-kCjaIXODU/LE0RZAwFP/rqbGJLMnbaWzPTl3XagG9ubpvGMRTgZlcAqdk/miQIt/
-SoQOjRax1swIZBIM4ChLyKWEkBf7EUYu1qeFGMsYrmOasFgG9ADP+MQJGjUMofnu
-Sv1t3v4mpTsCAwEAAaMVMBMwEQYJYIZIAYb4QgEBBAQDAgCgMA0GCSqGSIb3DQEB
-BAUAA4GBAGw9mcMF4h3K5S2qaIWLQDEgZhNo5lg6idCNdbLFYth9go/32TKBd/Y1
-W4UpzmeyubwrGXjP84f9RvGVdbIJVwMwwXrNckdxgMp9ncllPEcRIn36BwsoeKGT
-6AVFSOIyMko96FMcELfHc4wHUOH5yStTQfWDjeUJOUqOA2KqQGOL
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 1 (0x1)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Secure Server Certificate Authority, CN=BelSign Secure Server CA/Email=webmasterNOSPAMbelsign.be
- Validity
- Not Before: Jul 16 22:00:54 1997 GMT
- Not After : Jul 16 22:00:54 2007 GMT
- Subject: C=BE, L=Brussels, O=BelSign NV, OU=BelSign Secure Server Certificate Authority, CN=BelSign Secure Server CA/Email=webmasterNOSPAMbelsign.be
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:d6:01:12:78:92:f8:04:42:7f:c9:c7:22:83:fc:
- 7c:47:70:30:2b:49:0b:3e:36:40:90:28:da:21:73:
- 83:53:f2:c4:d1:16:40:c0:53:ff:ae:a6:c6:24:b3:
- 27:6d:a5:b3:3d:39:77:5d:a8:06:f6:e6:e9:bc:63:
- 11:4e:06:65:70:0a:9d:93:f9:a2:40:8b:7f:4a:84:
- 0e:8d:16:b1:d6:cc:08:64:12:0c:e0:28:4b:c8:a5:
- 84:90:17:fb:11:46:2e:d6:a7:85:18:cb:18:ae:63:
- 9a:b0:58:06:f4:00:cf:f8:c4:09:1a:35:0c:a1:f9:
- ee:4a:fd:6d:de:fe:26:a5:3b
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- Netscape Cert Type:
- SSL Client, S/MIME
- Signature Algorithm: md5WithRSAEncryption
- 6c:3d:99:c3:05:e2:1d:ca:e5:2d:aa:68:85:8b:40:31:20:66:
- 13:68:e6:58:3a:89:d0:8d:75:b2:c5:62:d8:7d:82:8f:f7:d9:
- 32:81:77:f6:35:5b:85:29:ce:67:b2:b9:bc:2b:19:78:cf:f3:
- 87:fd:46:f1:95:75:b2:09:57:03:30:c1:7a:cd:72:47:71:80:
- ca:7d:9d:c9:65:3c:47:11:22:7d:fa:07:0b:28:78:a1:93:e8:
- 05:45:48:e2:32:32:4a:3d:e8:53:1c:10:b7:c7:73:8c:07:50:
- e1:f9:c9:2b:53:41:f5:83:8d:e5:09:39:4a:8e:03:62:aa:40:
- 63:8b
-
-Deutsche Telekom AG Root CA
-===========================
-MD5 Fingerprint: 77:DE:04:94:77:D0:0C:5F:A7:B1:F4:30:18:87:FB:55
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICjjCCAfegAwIBAgIBBjANBgkqhkiG9w0BAQQFADBtMQswCQYDVQQGEwJERTEc
-MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEdMBsGA1UECxMUVGVsZVNlYyBU
-cnVzdCBDZW50ZXIxITAfBgNVBAMTGERldXRzY2hlIFRlbGVrb20gUm9vdCBDQTAe
-Fw05ODEyMDkwOTExMDBaFw0wNDEyMDkyMzU5MDBaMG0xCzAJBgNVBAYTAkRFMRww
-GgYDVQQKExNEZXV0c2NoZSBUZWxla29tIEFHMR0wGwYDVQQLExRUZWxlU2VjIFRy
-dXN0IENlbnRlcjEhMB8GA1UEAxMYRGV1dHNjaGUgVGVsZWtvbSBSb290IENBMIGf
-MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdBSz5BbO5EtdpcffqVjAIVxRDe7sa
-nG0vV2HX4vVEa+42QZb2ZM7hwbK5pBQEmFDocPiONZp9ScFhHVmu2gYYlX2tzuyp
-vtEYD0CRdiqj5f3+iRX0V/fgVdp1rQD0LME1zLRDJlViRC4BJZyKW/DB0AA1eP41
-3pRAZHiDocw5iQIDAQABoz4wPDAPBgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQE
-AwIBBjAZBgNVHQ4EEgQQLIdZH4sTgLL5hp0+En5YljANBgkqhkiG9w0BAQQFAAOB
-gQAP/nO1B4hvoAuJ6spQH5TelCsLJ15P9RyVJtqMllStGZE3Q12ryYuzzW+YOT3t
-3TXjcbftE5OD6IblKTMTE7w1e/0oL3BZ1dO0jSgTWTvI1XT5RcIHYKq4GFT5pWj/
-1wXVj7YFMS5BSvQQH2BHGguLGU2SVyDS71AZ6M3QcLy8Ng==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 6 (0x6)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=DE, O=Deutsche Telekom AG, OU=TeleSec Trust Center, CN=Deutsche Telekom Root CA
- Validity
- Not Before: Dec 9 09:11:00 1998 GMT
- Not After : Dec 9 23:59:00 2004 GMT
- Subject: C=DE, O=Deutsche Telekom AG, OU=TeleSec Trust Center, CN=Deutsche Telekom Root CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:dd:05:2c:f9:05:b3:b9:12:d7:69:71:f7:ea:56:
- 30:08:57:14:43:7b:bb:1a:9c:6d:2f:57:61:d7:e2:
- f5:44:6b:ee:36:41:96:f6:64:ce:e1:c1:b2:b9:a4:
- 14:04:98:50:e8:70:f8:8e:35:9a:7d:49:c1:61:1d:
- 59:ae:da:06:18:95:7d:ad:ce:ec:a9:be:d1:18:0f:
- 40:91:76:2a:a3:e5:fd:fe:89:15:f4:57:f7:e0:55:
- da:75:ad:00:f4:2c:c1:35:cc:b4:43:26:55:62:44:
- 2e:01:25:9c:8a:5b:f0:c1:d0:00:35:78:fe:35:de:
- 94:40:64:78:83:a1:cc:39:89
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints:
- CA:TRUE, pathlen:5
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Subject Key Identifier:
- 2C:87:59:1F:8B:13:80:B2:F9:86:9D:3E:12:7E:58:96
- Signature Algorithm: md5WithRSAEncryption
- 0f:fe:73:b5:07:88:6f:a0:0b:89:ea:ca:50:1f:94:de:94:2b:
- 0b:27:5e:4f:f5:1c:95:26:da:8c:96:54:ad:19:91:37:43:5d:
- ab:c9:8b:b3:cd:6f:98:39:3d:ed:dd:35:e3:71:b7:ed:13:93:
- 83:e8:86:e5:29:33:13:13:bc:35:7b:fd:28:2f:70:59:d5:d3:
- b4:8d:28:13:59:3b:c8:d5:74:f9:45:c2:07:60:aa:b8:18:54:
- f9:a5:68:ff:d7:05:d5:8f:b6:05:31:2e:41:4a:f4:10:1f:60:
- 47:1a:0b:8b:19:4d:92:57:20:d2:ef:50:19:e8:cd:d0:70:bc:
- bc:36
-
-Digital Signature Trust Co. Global CA 1
-=======================================
-MD5 Fingerprint: 25:7A:BA:83:2E:B6:A2:0B:DA:FE:F5:02:0F:08:D7:AD
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV
-UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL
-EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ
-BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x
-ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg
-bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ
-j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV
-Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG
-SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx
-JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI
-RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw
-MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5
-fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i
-+DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG
-SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN
-QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+
-gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 913315222 (0x36701596)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E1
- Validity
- Not Before: Dec 10 18:10:23 1998 GMT
- Not After : Dec 10 18:40:23 2018 GMT
- Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E1
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:a0:6c:81:a9:cf:34:1e:24:dd:fe:86:28:cc:de:
- 83:2f:f9:5e:d4:42:d2:e8:74:60:66:13:98:06:1c:
- a9:51:12:69:6f:31:55:b9:49:72:00:08:7e:d3:a5:
- 62:44:37:24:99:8f:d9:83:48:8f:99:6d:95:13:bb:
- 43:3b:2e:49:4e:88:37:c1:bb:58:7f:fe:e1:bd:f8:
- bb:61:cd:f3:47:c0:99:a6:f1:f3:91:e8:78:7c:00:
- cb:61:c9:44:27:71:69:55:4a:7e:49:4d:ed:a2:a3:
- be:02:4c:00:ca:02:a8:ee:01:02:31:64:0f:52:2d:
- 13:74:76:36:b5:7a:b4:2d:71
- Exponent: 3 (0x3)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 CRL Distribution Points:
- DirName:/C=US/O=Digital Signature Trust Co./OU=DSTCA E1/CN=CRL1
-
- X509v3 Private Key Usage Period:
- Not Before: Dec 10 18:10:23 1998 GMT, Not After: Dec 10 18:10:23 2018 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8
-
- X509v3 Subject Key Identifier:
- 6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0
-..V4.0....
- Signature Algorithm: sha1WithRSAEncryption
- 22:12:d8:7a:1d:dc:81:06:b6:09:65:b2:87:c8:1f:5e:b4:2f:
- e9:c4:1e:f2:3c:c1:bb:04:90:11:4a:83:4e:7e:93:b9:4d:42:
- c7:92:26:a0:5c:34:9a:38:72:f8:fd:6b:16:3e:20:ee:82:8b:
- 31:2a:93:36:85:23:88:8a:3c:03:68:d3:c9:09:0f:4d:fc:6c:
- a4:da:28:72:93:0e:89:80:b0:7d:fe:80:6f:65:6d:18:33:97:
- 8b:c2:6b:89:ee:60:3d:c8:9b:ef:7f:2b:32:62:73:93:cb:3c:
- e3:7b:e2:76:78:45:bc:a1:93:04:bb:86:9f:3a:5b:43:7a:c3:
- 8a:65
-
-Digital Signature Trust Co. Global CA 2
-=======================================
-MD5 Fingerprint: 6C:C9:A7:6E:47:F1:0C:E3:53:3B:78:4C:4D:C2:6A:C5
-PEM Data:
------BEGIN CERTIFICATE-----
-MIID2DCCAsACEQDQHkCLAAACfAAAAAIAAAABMA0GCSqGSIb3DQEBBQUAMIGpMQsw
-CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp
-dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE
-CxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDExITAfBgkqhkiG9w0B
-CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODEyMDExODE4NTVaFw0wODExMjgx
-ODE4NTVaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO
-U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0
-IENvLjERMA8GA1UECxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDEx
-ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBANLGJrbnpT3BxGjVUG9TxW9JEwm4ryxIjRRqoxdf
-WvnTLnUv2Chi0ZMv/E3Uq4flCMeZ55I/db3rJbQVwZsZPdJEjdd0IG03Ao9pk1uK
-xBmd9LIO/BZsubEFkoPRhSxglD5FVaDZqwgh5mDoO3TymVBRaNADLbGAvqPYUrBE
-zUNKcI5YhZXhTizWLUFv1oTnyJhEykfbLCSlaSbPa7gnYsP0yXqSI+0TZ4KuRS5F
-5X5yP4WdlGIQ5jyRoa13AOAV7POEgHJ6jm5gl8ckWRA0g1vhpaRptlc1HHhZxtMv
-OnNn7pTKBBMFYgZwI7P0fO5F2WQLW0mqpEPOJsREEmy43XkCAwEAATANBgkqhkiG
-9w0BAQUFAAOCAQEAojeyP2n714Z5VEkxlTMr89EJFEliYIalsBHiUMIdBlc+Legz
-ZL6bqq1fG03UmZWii5rJYnK1aerZWKs17RWiQ9a2vAd5ZWRzfdd5ynvVWlHG4VME
-lo04z6MXrDlxawHDi1M8Y+nuecDkvpIyZHqzH5eUYr3qsiAVlfuX8ngvYzZAOONG
-Dx3drJXK50uQe7FLqdTF65raqtWjlBRGjS0f8zrWkzr2Pnn86Oawde3uPclwx12q
-gUtGJRzHbBXjlU4PqjI3lAoXJJIThFjSY28r9+ZbYgsTF7ANUkz+/m9c4pFuHf2k
-Ytdo+o56T9II2pPc8JIRetDccpMMc5NihWjQ9A==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- d0:1e:40:8b:00:00:02:7c:00:00:00:02:00:00:00:01
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X1, CN=DST RootCA X1/Email=caNOSPAMdigsigtrust.com
- Validity
- Not Before: Dec 1 18:18:55 1998 GMT
- Not After : Nov 28 18:18:55 2008 GMT
- Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X1, CN=DST RootCA X1/Email=ca@digsigtrust.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:d2:c6:26:b6:e7:a5:3d:c1:c4:68:d5:50:6f:53:
- c5:6f:49:13:09:b8:af:2c:48:8d:14:6a:a3:17:5f:
- 5a:f9:d3:2e:75:2f:d8:28:62:d1:93:2f:fc:4d:d4:
- ab:87:e5:08:c7:99:e7:92:3f:75:bd:eb:25:b4:15:
- c1:9b:19:3d:d2:44:8d:d7:74:20:6d:37:02:8f:69:
- 93:5b:8a:c4:19:9d:f4:b2:0e:fc:16:6c:b9:b1:05:
- 92:83:d1:85:2c:60:94:3e:45:55:a0:d9:ab:08:21:
- e6:60:e8:3b:74:f2:99:50:51:68:d0:03:2d:b1:80:
- be:a3:d8:52:b0:44:cd:43:4a:70:8e:58:85:95:e1:
- 4e:2c:d6:2d:41:6f:d6:84:e7:c8:98:44:ca:47:db:
- 2c:24:a5:69:26:cf:6b:b8:27:62:c3:f4:c9:7a:92:
- 23:ed:13:67:82:ae:45:2e:45:e5:7e:72:3f:85:9d:
- 94:62:10:e6:3c:91:a1:ad:77:00:e0:15:ec:f3:84:
- 80:72:7a:8e:6e:60:97:c7:24:59:10:34:83:5b:e1:
- a5:a4:69:b6:57:35:1c:78:59:c6:d3:2f:3a:73:67:
- ee:94:ca:04:13:05:62:06:70:23:b3:f4:7c:ee:45:
- d9:64:0b:5b:49:aa:a4:43:ce:26:c4:44:12:6c:b8:
- dd:79
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- a2:37:b2:3f:69:fb:d7:86:79:54:49:31:95:33:2b:f3:d1:09:
- 14:49:62:60:86:a5:b0:11:e2:50:c2:1d:06:57:3e:2d:e8:33:
- 64:be:9b:aa:ad:5f:1b:4d:d4:99:95:a2:8b:9a:c9:62:72:b5:
- 69:ea:d9:58:ab:35:ed:15:a2:43:d6:b6:bc:07:79:65:64:73:
- 7d:d7:79:ca:7b:d5:5a:51:c6:e1:53:04:96:8d:38:cf:a3:17:
- ac:39:71:6b:01:c3:8b:53:3c:63:e9:ee:79:c0:e4:be:92:32:
- 64:7a:b3:1f:97:94:62:bd:ea:b2:20:15:95:fb:97:f2:78:2f:
- 63:36:40:38:e3:46:0f:1d:dd:ac:95:ca:e7:4b:90:7b:b1:4b:
- a9:d4:c5:eb:9a:da:aa:d5:a3:94:14:46:8d:2d:1f:f3:3a:d6:
- 93:3a:f6:3e:79:fc:e8:e6:b0:75:ed:ee:3d:c9:70:c7:5d:aa:
- 81:4b:46:25:1c:c7:6c:15:e3:95:4e:0f:aa:32:37:94:0a:17:
- 24:92:13:84:58:d2:63:6f:2b:f7:e6:5b:62:0b:13:17:b0:0d:
- 52:4c:fe:fe:6f:5c:e2:91:6e:1d:fd:a4:62:d7:68:fa:8e:7a:
- 4f:d2:08:da:93:dc:f0:92:11:7a:d0:dc:72:93:0c:73:93:62:
- 85:68:d0:f4
-
-Digital Signature Trust Co. Global CA 3
-=======================================
-MD5 Fingerprint: 93:C2:8E:11:7B:D4:F3:03:19:BD:28:75:13:4A:45:4A
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV
-UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL
-EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ
-BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x
-ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/
-k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso
-LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o
-TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG
-SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx
-JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI
-RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3
-MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C
-TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5
-WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG
-SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR
-xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL
-B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 913232846 (0x366ed3ce)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E2
- Validity
- Not Before: Dec 9 19:17:26 1998 GMT
- Not After : Dec 9 19:47:26 2018 GMT
- Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E2
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:bf:93:8f:17:92:ef:33:13:18:eb:10:7f:4e:16:
- bf:ff:06:8f:2a:85:bc:5e:f9:24:a6:24:88:b6:03:
- b7:c1:c3:5f:03:5b:d1:6f:ae:7e:42:ea:66:23:b8:
- 63:83:56:fb:28:2d:e1:38:8b:b4:ee:a8:01:e1:ce:
- 1c:b6:88:2a:22:46:85:fb:9f:a7:70:a9:47:14:3f:
- ce:de:65:f0:a8:71:f7:4f:26:6c:8c:bc:c6:b5:ef:
- de:49:27:ff:48:2a:7d:e8:4d:03:cc:c7:b2:52:c6:
- 17:31:13:3b:b5:4d:db:c8:c4:f6:c3:0f:24:2a:da:
- 0c:9d:e7:91:5b:80:cd:94:9d
- Exponent: 3 (0x3)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 CRL Distribution Points:
- DirName:/C=US/O=Digital Signature Trust Co./OU=DSTCA E2/CN=CRL1
-
- X509v3 Private Key Usage Period:
- Not Before: Dec 9 19:17:26 1998 GMT, Not After: Dec 9 19:17:26 2018 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B
-
- X509v3 Subject Key Identifier:
- 1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0
-..V4.0....
- Signature Algorithm: sha1WithRSAEncryption
- 47:8d:83:ad:62:f2:db:b0:9e:45:22:05:b9:a2:d6:03:0e:38:
- 72:e7:9e:fc:7b:e6:93:b6:9a:a5:a2:94:c8:34:1d:91:d1:c5:
- d7:f4:0a:25:0f:3d:78:81:9e:0f:b1:67:c4:90:4c:63:dd:5e:
- a7:e2:ba:9f:f5:f7:4d:a5:31:7b:9c:29:2d:4c:fe:64:3e:ec:
- b6:53:fe:ea:9b:ed:82:db:74:75:4b:07:79:6e:1e:d8:19:83:
- 73:de:f5:3e:d0:b5:de:e7:4b:68:7d:43:2e:2a:20:e1:7e:a0:
- 78:44:9e:08:f5:98:f9:c7:7f:1b:1b:d6:06:20:02:58:a1:c3:
- a2:03
-
-Digital Signature Trust Co. Global CA 4
-=======================================
-MD5 Fingerprint: CD:3B:3D:62:5B:09:B8:09:36:87:9E:12:2F:71:64:BA
-PEM Data:
------BEGIN CERTIFICATE-----
-MIID2DCCAsACEQDQHkCLAAB3bQAAAAEAAAAEMA0GCSqGSIb3DQEBBQUAMIGpMQsw
-CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp
-dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE
-CxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIxITAfBgkqhkiG9w0B
-CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODExMzAyMjQ2MTZaFw0wODExMjcy
-MjQ2MTZaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO
-U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0
-IENvLjERMA8GA1UECxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIx
-ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBANx18IzAdZaawGIfJvfE4Zrq4FZzW5nNAUSoCLbV
-p9oaBBg5kkp4o4HC9Xd6ULRw/5qrxsfKboNPQpj7Jgva3G3WqZlVUmfpKAOS3OWw
-BZoPFflrWXJW8vo5/Kpo7g8fEIMv/J36F5bdguPmRX3AS4BEH+0s4IT9kVySVGkl
-5WJp3OXuAFK9MwutdQKFp2RQLcUZGTDAJtvJ0/0uma1ZtQtN1EGuhUhDWdy3qOKi
-3sOP17ihYqZoUFLkzzGnlIXan0YyF1bl8utmPRL/Q9uY73fPy4GNNLHGUEom0eQ+
-QVCvbK4iNC7Va26Dunm4dmVI2gkpZGMiuftHdoWMhkTLCdsCAwEAATANBgkqhkiG
-9w0BAQUFAAOCAQEAtTYOXeFhKFoRZcA/gwN5Tb4opgsHAlKFzfiR0BBstWogWxyQ
-2TA8xkieil5k+aFxd+8EJx8H6+Qm93N0yUQYGmbT4EOvkTvRyyzYdFQ6HE3K1GjN
-I3wdEJ5F6fYAbqbNGf9PLCmPV03Ed5K+4EwJ+11EhmYhqLkyolbV6YyDfFk/xPEL
-553snr2cGA4+wjl5KLcDDQjLxufZATdQEOzMYRZA1K8xdHv8PzGn0EdzMzkbzE5q
-10mDEQb+64JYMzJM8FasHpwvVpp7wUocpf1VNs78lk30sPDst2yC7S8xmUJMqbIN
-uBVd8d+6ybVK1GSYsyapMMj9puyrliGtf8J4tg==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- d0:1e:40:8b:00:00:77:6d:00:00:00:01:00:00:00:04
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X2, CN=DST RootCA X2/Email=caNOSPAMdigsigtrust.com
- Validity
- Not Before: Nov 30 22:46:16 1998 GMT
- Not After : Nov 27 22:46:16 2008 GMT
- Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X2, CN=DST RootCA X2/Email=caNOSPAMdigsigtrust.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:dc:75:f0:8c:c0:75:96:9a:c0:62:1f:26:f7:c4:
- e1:9a:ea:e0:56:73:5b:99:cd:01:44:a8:08:b6:d5:
- a7:da:1a:04:18:39:92:4a:78:a3:81:c2:f5:77:7a:
- 50:b4:70:ff:9a:ab:c6:c7:ca:6e:83:4f:42:98:fb:
- 26:0b:da:dc:6d:d6:a9:99:55:52:67:e9:28:03:92:
- dc:e5:b0:05:9a:0f:15:f9:6b:59:72:56:f2:fa:39:
- fc:aa:68:ee:0f:1f:10:83:2f:fc:9d:fa:17:96:dd:
- 82:e3:e6:45:7d:c0:4b:80:44:1f:ed:2c:e0:84:fd:
- 91:5c:92:54:69:25:e5:62:69:dc:e5:ee:00:52:bd:
- 33:0b:ad:75:02:85:a7:64:50:2d:c5:19:19:30:c0:
- 26:db:c9:d3:fd:2e:99:ad:59:b5:0b:4d:d4:41:ae:
- 85:48:43:59:dc:b7:a8:e2:a2:de:c3:8f:d7:b8:a1:
- 62:a6:68:50:52:e4:cf:31:a7:94:85:da:9f:46:32:
- 17:56:e5:f2:eb:66:3d:12:ff:43:db:98:ef:77:cf:
- cb:81:8d:34:b1:c6:50:4a:26:d1:e4:3e:41:50:af:
- 6c:ae:22:34:2e:d5:6b:6e:83:ba:79:b8:76:65:48:
- da:09:29:64:63:22:b9:fb:47:76:85:8c:86:44:cb:
- 09:db
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- b5:36:0e:5d:e1:61:28:5a:11:65:c0:3f:83:03:79:4d:be:28:
- a6:0b:07:02:52:85:cd:f8:91:d0:10:6c:b5:6a:20:5b:1c:90:
- d9:30:3c:c6:48:9e:8a:5e:64:f9:a1:71:77:ef:04:27:1f:07:
- eb:e4:26:f7:73:74:c9:44:18:1a:66:d3:e0:43:af:91:3b:d1:
- cb:2c:d8:74:54:3a:1c:4d:ca:d4:68:cd:23:7c:1d:10:9e:45:
- e9:f6:00:6e:a6:cd:19:ff:4f:2c:29:8f:57:4d:c4:77:92:be:
- e0:4c:09:fb:5d:44:86:66:21:a8:b9:32:a2:56:d5:e9:8c:83:
- 7c:59:3f:c4:f1:0b:e7:9d:ec:9e:bd:9c:18:0e:3e:c2:39:79:
- 28:b7:03:0d:08:cb:c6:e7:d9:01:37:50:10:ec:cc:61:16:40:
- d4:af:31:74:7b:fc:3f:31:a7:d0:47:73:33:39:1b:cc:4e:6a:
- d7:49:83:11:06:fe:eb:82:58:33:32:4c:f0:56:ac:1e:9c:2f:
- 56:9a:7b:c1:4a:1c:a5:fd:55:36:ce:fc:96:4d:f4:b0:f0:ec:
- b7:6c:82:ed:2f:31:99:42:4c:a9:b2:0d:b8:15:5d:f1:df:ba:
- c9:b5:4a:d4:64:98:b3:26:a9:30:c8:fd:a6:ec:ab:96:21:ad:
- 7f:c2:78:b6
-
-Entrust Worldwide by DST
-========================
-MD5 Fingerprint: B4:65:22:0A:7C:AD:DF:41:B7:D5:44:D5:AD:FA:9A:75
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDRzCCArCgAwIBAgIENm3FGDANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJV
-UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRswGQYDVQQL
-ExJEU1QtRW50cnVzdCBHVEkgQ0EwHhcNOTgxMjA5MDAwMjI0WhcNMTgxMjA5MDAz
-MjI0WjBQMQswCQYDVQQGEwJVUzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUg
-VHJ1c3QgQ28uMRswGQYDVQQLExJEU1QtRW50cnVzdCBHVEkgQ0EwgZ0wDQYJKoZI
-hvcNAQEBBQADgYsAMIGHAoGBALYd90uNDxPjEvUJ/gYyDq9MQfV91Ec9KgrfgwXe
-3n3mAxb2UTrLRxpKrX7E/R20vnSKeN0Lg460hBPE+/htKa6h4Q8PQ+O1XmBp+oOU
-/Hnm3Hbt0UQrjv0Su/4XdxcMie2n71F9xO04wzujevviTaBgtfL9E2XTxuw/vjWc
-PSLvAgEDo4IBLjCCASowEQYJYIZIAYb4QgEBBAQDAgAHMHIGA1UdHwRrMGkwZ6Bl
-oGOkYTBfMQswCQYDVQQGEwJVUzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUg
-VHJ1c3QgQ28uMRswGQYDVQQLExJEU1QtRW50cnVzdCBHVEkgQ0ExDTALBgNVBAMT
-BENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkwMDAyMjRagQ8yMDE4MTIwOTAwMDIy
-NFowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFJOaRMrQeFOAKUkE38evMz+ZdV+u
-MB0GA1UdDgQWBBSTmkTK0HhTgClJBN/HrzM/mXVfrjAMBgNVHRMEBTADAQH/MBkG
-CSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GBAGSJzAOn
-3AryWCDn/RegKHLNh7DNmLUkR2MzMRAQsu+KV3KuTAPgZ5+sYEOEIsGpo+Wxp94J
-1M8NeEYjW49Je/4TIpeU6nJI4SwgeJbpZkUZywllY2E/0UmYsXYQVdVjSmZLpAdr
-3nt/ueaTWxoCW4AO3Y0Y1Iqjwmjxo+AY0U5M
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 913163544 (0x366dc518)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA
- Validity
- Not Before: Dec 9 00:02:24 1998 GMT
- Not After : Dec 9 00:32:24 2018 GMT
- Subject: C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:b6:1d:f7:4b:8d:0f:13:e3:12:f5:09:fe:06:32:
- 0e:af:4c:41:f5:7d:d4:47:3d:2a:0a:df:83:05:de:
- de:7d:e6:03:16:f6:51:3a:cb:47:1a:4a:ad:7e:c4:
- fd:1d:b4:be:74:8a:78:dd:0b:83:8e:b4:84:13:c4:
- fb:f8:6d:29:ae:a1:e1:0f:0f:43:e3:b5:5e:60:69:
- fa:83:94:fc:79:e6:dc:76:ed:d1:44:2b:8e:fd:12:
- bb:fe:17:77:17:0c:89:ed:a7:ef:51:7d:c4:ed:38:
- c3:3b:a3:7a:fb:e2:4d:a0:60:b5:f2:fd:13:65:d3:
- c6:ec:3f:be:35:9c:3d:22:ef
- Exponent: 3 (0x3)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 CRL Distribution Points:
- DirName:/C=US/O=Digital Signature Trust Co./OU=DST-Entrust GTI CA/CN=CRL1
-
- X509v3 Private Key Usage Period:
- Not Before: Dec 9 00:02:24 1998 GMT, Not After: Dec 9 00:02:24 2018 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:93:9A:44:CA:D0:78:53:80:29:49:04:DF:C7:AF:33:3F:99:75:5F:AE
-
- X509v3 Subject Key Identifier:
- 93:9A:44:CA:D0:78:53:80:29:49:04:DF:C7:AF:33:3F:99:75:5F:AE
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0
-..V4.0....
- Signature Algorithm: sha1WithRSAEncryption
- 64:89:cc:03:a7:dc:0a:f2:58:20:e7:fd:17:a0:28:72:cd:87:
- b0:cd:98:b5:24:47:63:33:31:10:10:b2:ef:8a:57:72:ae:4c:
- 03:e0:67:9f:ac:60:43:84:22:c1:a9:a3:e5:b1:a7:de:09:d4:
- cf:0d:78:46:23:5b:8f:49:7b:fe:13:22:97:94:ea:72:48:e1:
- 2c:20:78:96:e9:66:45:19:cb:09:65:63:61:3f:d1:49:98:b1:
- 76:10:55:d5:63:4a:66:4b:a4:07:6b:de:7b:7f:b9:e6:93:5b:
- 1a:02:5b:80:0e:dd:8d:18:d4:8a:a3:c2:68:f1:a3:e0:18:d1:
- 4e:4c
-
-Entrust.net Premium 2048 Secure Server CA
-=========================================
-MD5 Fingerprint: BA:21:EA:20:D6:DD:DB:8F:C1:57:8B:40:AD:A1:FC:FC
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
-RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
-bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
-IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
-ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy
-MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
-LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
-YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
-A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
-K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
-sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
-MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
-XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
-HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
-4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA
-vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G
-CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA
-WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo
-oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ
-h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18
-f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN
-B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy
-vUxFnmG6v4SBkgPR0ml8xQ==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 946059622 (0x3863b966)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048)
- Validity
- Not Before: Dec 24 17:50:51 1999 GMT
- Not After : Dec 24 18:20:51 2019 GMT
- Subject: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048)
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:ad:4d:4b:a9:12:86:b2:ea:a3:20:07:15:16:64:
- 2a:2b:4b:d1:bf:0b:4a:4d:8e:ed:80:76:a5:67:b7:
- 78:40:c0:73:42:c8:68:c0:db:53:2b:dd:5e:b8:76:
- 98:35:93:8b:1a:9d:7c:13:3a:0e:1f:5b:b7:1e:cf:
- e5:24:14:1e:b1:81:a9:8d:7d:b8:cc:6b:4b:03:f1:
- 02:0c:dc:ab:a5:40:24:00:7f:74:94:a1:9d:08:29:
- b3:88:0b:f5:87:77:9d:55:cd:e4:c3:7e:d7:6a:64:
- ab:85:14:86:95:5b:97:32:50:6f:3d:c8:ba:66:0c:
- e3:fc:bd:b8:49:c1:76:89:49:19:fd:c0:a8:bd:89:
- a3:67:2f:c6:9f:bc:71:19:60:b8:2d:e9:2c:c9:90:
- 76:66:7b:94:e2:af:78:d6:65:53:5d:3c:d6:9c:b2:
- cf:29:03:f9:2f:a4:50:b2:d4:48:ce:05:32:55:8a:
- fd:b2:64:4c:0e:e4:98:07:75:db:7f:df:b9:08:55:
- 60:85:30:29:f9:7b:48:a4:69:86:e3:35:3f:1e:86:
- 5d:7a:7a:15:bd:ef:00:8e:15:22:54:17:00:90:26:
- 93:bc:0e:49:68:91:bf:f8:47:d3:9d:95:42:c1:0e:
- 4d:df:6f:26:cf:c3:18:21:62:66:43:70:d6:d5:c0:
- 07:e1
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 Authority Key Identifier:
- keyid:55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70
-
- X509v3 Subject Key Identifier:
- 55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70
- 1.2.840.113533.7.65.0:
- 0...V5.0:4.0....
- Signature Algorithm: sha1WithRSAEncryption
- 59:47:ac:21:84:8a:17:c9:9c:89:53:1e:ba:80:85:1a:c6:3c:
- 4e:3e:b1:9c:b6:7c:c6:92:5d:18:64:02:e3:d3:06:08:11:61:
- 7c:63:e3:2b:9d:31:03:70:76:d2:a3:28:a0:f4:bb:9a:63:73:
- ed:6d:e5:2a:db:ed:14:a9:2b:c6:36:11:d0:2b:eb:07:8b:a5:
- da:9e:5c:19:9d:56:12:f5:54:29:c8:05:ed:b2:12:2a:8d:f4:
- 03:1b:ff:e7:92:10:87:b0:3a:b5:c3:9d:05:37:12:a3:c7:f4:
- 15:b9:d5:a4:39:16:9b:53:3a:23:91:f1:a8:82:a2:6a:88:68:
- c1:79:02:22:bc:aa:a6:d6:ae:df:b0:14:5f:b8:87:d0:dd:7c:
- 7f:7b:ff:af:1c:cf:e6:db:07:ad:5e:db:85:9d:d0:2b:0d:33:
- db:04:d1:e6:49:40:13:2b:76:fb:3e:e9:9c:89:0f:15:ce:18:
- b0:85:78:21:4f:6b:4f:0e:fa:36:67:cd:07:f2:ff:08:d0:e2:
- de:d9:bf:2a:af:b8:87:86:21:3c:04:ca:b7:94:68:7f:cf:3c:
- e9:98:d7:38:ff:ec:c0:d9:50:f0:2e:4b:58:ae:46:6f:d0:2e:
- c3:60:da:72:55:72:bd:4c:45:9e:61:ba:bf:84:81:92:03:d1:
- d2:69:7c:c5
-
-Entrust.net Secure Personal CA
-==============================
-MD5 Fingerprint: 0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UEBhMC
-VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50cnVzdC5u
-ZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBsaW1pdHMgbGlh
-Yi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
-BAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
-Fw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBaMIHJMQswCQYDVQQGEwJVUzEU
-MBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9D
-bGllbnRfQ0FfSW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjEl
-MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMq
-RW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0G
-CSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo
-6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux
-5zDeg7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zm
-AqTmT173iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSC
-ARkwggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50
-cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5m
-by9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMp
-IDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQg
-Q2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCyg
-KqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9DbGllbnQxLmNybDArBgNV
-HRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkxMDEyMTkyNDMwWjALBgNVHQ8E
-BAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW/O5bs8qZdIuV6kwwHQYDVR0OBBYE
-FMT7nCl7l81MlvzuW7PKmXSLlepMMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA
-BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7
-pFuPeJoSSJn59DXeDDYHAmsQOokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzz
-wy5E97BnRqqS5TvaHBkUODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/a
-EkP/TOYGJqibGapEPHayXOw=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 939758062 (0x380391ee)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=US, O=Entrust.net, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab., OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Client Certification Authority
- Validity
- Not Before: Oct 12 19:24:30 1999 GMT
- Not After : Oct 12 19:54:30 2019 GMT
- Subject: C=US, O=Entrust.net, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab., OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Client Certification Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:c8:3a:99:5e:31:17:df:ac:27:6f:90:7b:e4:19:
- ff:45:a3:34:c2:db:c1:a8:4f:f0:68:ea:84:fd:9f:
- 75:79:cf:c1:8a:51:94:af:c7:57:03:47:64:9e:ad:
- 82:1b:5a:da:7f:37:78:47:bb:37:98:12:96:ce:c6:
- 13:7d:ef:d2:0c:30:51:a9:39:9e:55:f8:fb:b1:e7:
- 30:de:83:b2:ba:3e:f1:d5:89:3b:3b:85:ba:aa:74:
- 2c:fe:3f:31:6e:af:91:95:6e:06:d4:07:4d:4b:2c:
- 56:47:18:04:52:da:0e:10:93:bf:63:90:9b:e1:df:
- 8c:e6:02:a4:e6:4f:5e:f7:8b
- Exponent: 3 (0x3)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 CRL Distribution Points:
- DirName:/C=US/O=Entrust.net/OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab./OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Client Certification Authority/CN=CRL1
- URI:http://www.entrust.net/CRL/Client1.crl
-
- X509v3 Private Key Usage Period:
- Not Before: Oct 12 19:24:30 1999 GMT, Not After: Oct 12 19:24:30 2019 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:C4:FB:9C:29:7B:97:CD:4C:96:FC:EE:5B:B3:CA:99:74:8B:95:EA:4C
-
- X509v3 Subject Key Identifier:
- C4:FB:9C:29:7B:97:CD:4C:96:FC:EE:5B:B3:CA:99:74:8B:95:EA:4C
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0
-..V4.0....
- Signature Algorithm: md5WithRSAEncryption
- 3f:ae:8a:f1:d7:66:03:05:9e:3e:fa:ea:1c:46:bb:a4:5b:8f:
- 78:9a:12:48:99:f9:f4:35:de:0c:36:07:02:6b:10:3a:89:14:
- 81:9c:31:a6:7c:b2:41:b2:6a:e7:07:01:a1:4b:f9:9f:25:3b:
- 96:ca:99:c3:3e:a1:51:1c:f3:c3:2e:44:f7:b0:67:46:aa:92:
- e5:3b:da:1c:19:14:38:30:d5:e2:a2:31:25:2e:f1:ec:45:38:
- ed:f8:06:58:03:73:62:b0:10:31:8f:40:bf:64:e0:5c:3e:c5:
- 4f:1f:da:12:43:ff:4c:e6:06:26:a8:9b:19:aa:44:3c:76:b2:
- 5c:ec
-
-Entrust.net Secure Server CA
-============================
-MD5 Fingerprint: DF:F2:80:73:CC:F1:E6:61:73:FC:F5:42:E9:C5:7C:EE
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
-VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
-ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
-KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
-ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
-MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
-ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
-b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
-bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
-U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
-A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
-I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
-wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
-AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
-oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
-BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
-dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
-MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
-b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
-dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
-MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
-E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
-MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
-hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
-95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
-2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 927650371 (0x374ad243)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
- Validity
- Not Before: May 25 16:09:40 1999 GMT
- Not After : May 25 16:39:40 2019 GMT
- Subject: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:cd:28:83:34:54:1b:89:f3:0f:af:37:91:31:ff:
- af:31:60:c9:a8:e8:b2:10:68:ed:9f:e7:93:36:f1:
- 0a:64:bb:47:f5:04:17:3f:23:47:4d:c5:27:19:81:
- 26:0c:54:72:0d:88:2d:d9:1f:9a:12:9f:bc:b3:71:
- d3:80:19:3f:47:66:7b:8c:35:28:d2:b9:0a:df:24:
- da:9c:d6:50:79:81:7a:5a:d3:37:f7:c2:4a:d8:29:
- 92:26:64:d1:e4:98:6c:3a:00:8a:f5:34:9b:65:f8:
- ed:e3:10:ff:fd:b8:49:58:dc:a0:de:82:39:6b:81:
- b1:16:19:61:b9:54:b6:e6:43
- Exponent: 3 (0x3)
- X509v3 extensions:
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- X509v3 CRL Distribution Points:
- DirName:/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority/CN=CRL1
- URI:http://www.entrust.net/CRL/net1.crl
-
- X509v3 Private Key Usage Period:
- Not Before: May 25 16:09:40 1999 GMT, Not After: May 25 16:09:40 2019 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
-
- X509v3 Subject Key Identifier:
- F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0
-..V4.0....
- Signature Algorithm: sha1WithRSAEncryption
- 90:dc:30:02:fa:64:74:c2:a7:0a:a5:7c:21:8d:34:17:a8:fb:
- 47:0e:ff:25:7c:8d:13:0a:fb:e4:98:b5:ef:8c:f8:c5:10:0d:
- f7:92:be:f1:c3:d5:d5:95:6a:04:bb:2c:ce:26:36:65:c8:31:
- c6:e7:ee:3f:e3:57:75:84:7a:11:ef:46:4f:18:f4:d3:98:bb:
- a8:87:32:ba:72:f6:3c:e2:3d:9f:d7:1d:d9:c3:60:43:8c:58:
- 0e:22:96:2f:62:a3:2c:1f:ba:ad:05:ef:ab:32:78:87:a0:54:
- 73:19:b5:5c:05:f9:52:3e:6d:2d:45:0b:f7:0a:93:ea:ed:06:
- f9:b2
-
-Equifax Premium CA
-==================
-MD5 Fingerprint: A9:E9:A8:9D:0E:73:E3:B1:2F:37:0D:E8:48:3F:86:ED
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDIzCCAoygAwIBAgIENeHvHjANBgkqhkiG9w0BAQUFADBPMQswCQYDVQQGEwJV
-UzEQMA4GA1UEChMHRXF1aWZheDEuMCwGA1UECxMlRXF1aWZheCBQcmVtaXVtIENl
-cnRpZmljYXRlIEF1dGhvcml0eTAeFw05ODA4MjQyMjU0MjNaFw0xODA4MjQyMjU0
-MjNaME8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFcXVpZmF4MS4wLAYDVQQLEyVF
-cXVpZmF4IFByZW1pdW0gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqGSIb3
-DQEBAQUAA4GNADCBiQKBgQDOoQaOBswIC8GGqN4g1Q0O0Q3En+pq2bPCMkdAb4qI
-pAm9OCwd5svmpPM269rrvPxkswf2Lbyqzp8ZSGhK/PWiRX4JEPWPs0lcIwY56hOL
-uAvNkR12X9k3oUT7X5DyZ7PNGJlDH3YSawLylYM4Q8L2YjTKyXhdX9LYupr/vhBg
-WwIDAQABo4IBCjCCAQYwcQYDVR0fBGowaDBmoGSgYqRgMF4xCzAJBgNVBAYTAlVT
-MRAwDgYDVQQKEwdFcXVpZmF4MS4wLAYDVQQLEyVFcXVpZmF4IFByZW1pdW0gQ2Vy
-dGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIw
-MTgwODI0MjI1NDIzWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUFe6yKFmrbuX4
-z4uB9CThrj91G5gwHQYDVR0OBBYEFBXusihZq27l+M+LgfQk4a4/dRuYMAwGA1Ud
-EwQFMAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEB
-BQUAA4GBAL0LnCepA9so3JipS9DRjqeoGlqR4Jzx9xh8LiKeNh/JqLXNRkpu+jUH
-G4YI65/iqPmdQS06rlxctl80BOv8KmCw+3TkhellOJbuFcfGd2MSvYpoH6tsfdrK
-XBPO6snrCVzFc+cSAdXZUwee4A+W8Iu0u0VIn4bFGVWgy5bFA/xI
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 903999262 (0x35e1ef1e)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Equifax, OU=Equifax Premium Certificate Authority
- Validity
- Not Before: Aug 24 22:54:23 1998 GMT
- Not After : Aug 24 22:54:23 2018 GMT
- Subject: C=US, O=Equifax, OU=Equifax Premium Certificate Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:ce:a1:06:8e:06:cc:08:0b:c1:86:a8:de:20:d5:
- 0d:0e:d1:0d:c4:9f:ea:6a:d9:b3:c2:32:47:40:6f:
- 8a:88:a4:09:bd:38:2c:1d:e6:cb:e6:a4:f3:36:eb:
- da:eb:bc:fc:64:b3:07:f6:2d:bc:aa:ce:9f:19:48:
- 68:4a:fc:f5:a2:45:7e:09:10:f5:8f:b3:49:5c:23:
- 06:39:ea:13:8b:b8:0b:cd:91:1d:76:5f:d9:37:a1:
- 44:fb:5f:90:f2:67:b3:cd:18:99:43:1f:76:12:6b:
- 02:f2:95:83:38:43:c2:f6:62:34:ca:c9:78:5d:5f:
- d2:d8:ba:9a:ff:be:10:60:5b
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 CRL Distribution Points:
- DirName:/C=US/O=Equifax/OU=Equifax Premium Certificate Authority/CN=CRL1
-
- X509v3 Private Key Usage Period:
- Not After: Aug 24 22:54:23 2018 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:15:EE:B2:28:59:AB:6E:E5:F8:CF:8B:81:F4:24:E1:AE:3F:75:1B:98
-
- X509v3 Subject Key Identifier:
- 15:EE:B2:28:59:AB:6E:E5:F8:CF:8B:81:F4:24:E1:AE:3F:75:1B:98
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0...V3.0c....
- Signature Algorithm: sha1WithRSAEncryption
- bd:0b:9c:27:a9:03:db:28:dc:98:a9:4b:d0:d1:8e:a7:a8:1a:
- 5a:91:e0:9c:f1:f7:18:7c:2e:22:9e:36:1f:c9:a8:b5:cd:46:
- 4a:6e:fa:35:07:1b:86:08:eb:9f:e2:a8:f9:9d:41:2d:3a:ae:
- 5c:5c:b6:5f:34:04:eb:fc:2a:60:b0:fb:74:e4:85:e9:65:38:
- 96:ee:15:c7:c6:77:63:12:bd:8a:68:1f:ab:6c:7d:da:ca:5c:
- 13:ce:ea:c9:eb:09:5c:c5:73:e7:12:01:d5:d9:53:07:9e:e0:
- 0f:96:f0:8b:b4:bb:45:48:9f:86:c5:19:55:a0:cb:96:c5:03:
- fc:48
-
-Equifax Secure CA
-=================
-MD5 Fingerprint: 67:CB:9D:C0:13:24:8A:82:9B:B2:17:1E:D1:1B:EC:D4
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
-dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
-MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
-dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
-BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
-cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
-MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
-aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
-ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
-IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
-7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
-1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 903804111 (0x35def4cf)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=Equifax, OU=Equifax Secure Certificate Authority
- Validity
- Not Before: Aug 22 16:41:51 1998 GMT
- Not After : Aug 22 16:41:51 2018 GMT
- Subject: C=US, O=Equifax, OU=Equifax Secure Certificate Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:c1:5d:b1:58:67:08:62:ee:a0:9a:2d:1f:08:6d:
- 91:14:68:98:0a:1e:fe:da:04:6f:13:84:62:21:c3:
- d1:7c:ce:9f:05:e0:b8:01:f0:4e:34:ec:e2:8a:95:
- 04:64:ac:f1:6b:53:5f:05:b3:cb:67:80:bf:42:02:
- 8e:fe:dd:01:09:ec:e1:00:14:4f:fc:fb:f0:0c:dd:
- 43:ba:5b:2b:e1:1f:80:70:99:15:57:93:16:f1:0f:
- 97:6a:b7:c2:68:23:1c:cc:4d:59:30:ac:51:1e:3b:
- af:2b:d6:ee:63:45:7b:c5:d9:5f:50:d2:e3:50:0f:
- 3a:88:e7:bf:14:fd:e0:c7:b9
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 CRL Distribution Points:
- DirName:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority/CN=CRL1
-
- X509v3 Private Key Usage Period:
- Not After: Aug 22 16:41:51 2018 GMT
- X509v3 Key Usage:
- Certificate Sign, CRL Sign
- X509v3 Authority Key Identifier:
- keyid:48:E6:68:F9:2B:D2:B2:95:D7:47:D8:23:20:10:4F:33:98:90:9F:D4
-
- X509v3 Subject Key Identifier:
- 48:E6:68:F9:2B:D2:B2:95:D7:47:D8:23:20:10:4F:33:98:90:9F:D4
- X509v3 Basic Constraints:
- CA:TRUE
- 1.2.840.113533.7.65.0:
- 0...V3.0c....
- Signature Algorithm: sha1WithRSAEncryption
- 58:ce:29:ea:fc:f7:de:b5:ce:02:b9:17:b5:85:d1:b9:e3:e0:
- 95:cc:25:31:0d:00:a6:92:6e:7f:b6:92:63:9e:50:95:d1:9a:
- 6f:e4:11:de:63:85:6e:98:ee:a8:ff:5a:c8:d3:55:b2:66:71:
- 57:de:c0:21:eb:3d:2a:a7:23:49:01:04:86:42:7b:fc:ee:7f:
- a2:16:52:b5:67:67:d3:40:db:3b:26:58:b2:28:77:3d:ae:14:
- 77:61:d6:fa:2a:66:27:a0:0d:fa:a7:73:5c:ea:70:f1:94:21:
- 65:44:5f:fa:fc:ef:29:68:a9:a2:87:79:ef:79:ef:4f:ac:07:
- 77:38
-
-GTE CyberTrust Global Root
-==========================
-MD5 Fingerprint: CA:3D:D3:68:F1:03:5C:D0:32:FA:B8:2B:59:E8:5A:DB
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD
-VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
-bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv
-b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV
-UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
-cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
-b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH
-iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS
-r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4
-04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r
-GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9
-3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P
-lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 421 (0x1a5)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root
- Validity
- Not Before: Aug 13 00:29:00 1998 GMT
- Not After : Aug 13 23:59:00 2018 GMT
- Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:95:0f:a0:b6:f0:50:9c:e8:7a:c7:88:cd:dd:17:
- 0e:2e:b0:94:d0:1b:3d:0e:f6:94:c0:8a:94:c7:06:
- c8:90:97:c8:b8:64:1a:7a:7e:6c:3c:53:e1:37:28:
- 73:60:7f:b2:97:53:07:9f:53:f9:6d:58:94:d2:af:
- 8d:6d:88:67:80:e6:ed:b2:95:cf:72:31:ca:a5:1c:
- 72:ba:5c:02:e7:64:42:e7:f9:a9:2c:d6:3a:0d:ac:
- 8d:42:aa:24:01:39:e6:9c:3f:01:85:57:0d:58:87:
- 45:f8:d3:85:aa:93:69:26:85:70:48:80:3f:12:15:
- c7:79:b4:1f:05:2f:3b:62:99
- Exponent: 65537 (0x10001)
- Signature Algorithm: md5WithRSAEncryption
- 6d:eb:1b:09:e9:5e:d9:51:db:67:22:61:a4:2a:3c:48:77:e3:
- a0:7c:a6:de:73:a2:14:03:85:3d:fb:ab:0e:30:c5:83:16:33:
- 81:13:08:9e:7b:34:4e:df:40:c8:74:d7:b9:7d:dc:f4:76:55:
- 7d:9b:63:54:18:e9:f0:ea:f3:5c:b1:d9:8b:42:1e:b9:c0:95:
- 4e:ba:fa:d5:e2:7c:f5:68:61:bf:8e:ec:05:97:5f:5b:b0:d7:
- a3:85:34:c4:24:a7:0d:0f:95:93:ef:cb:94:d8:9e:1f:9d:5c:
- 85:6d:c7:aa:ae:4f:1f:22:b5:cd:95:ad:ba:a7:cc:f9:ab:0b:
- 7a:7f
-
-GTE CyberTrust Japan Root CA
-============================
-MD5 Fingerprint: DE:AB:FF:43:2A:65:37:06:9B:28:B5:7A:E8:84:D3:8E
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICETCCAXoCAU4wDQYJKoZIhvcNAQEEBQAwUTELMAkGA1UEBhMCSlAxHzAdBgNV
-BAoTFkN5YmVyVHJ1c3QgSmFwYW4sIEluYy4xITAfBgNVBAMTGEN5YmVyVHJ1c3Qg
-SkFQQU4gUm9vdCBDQTAeFw05ODA4MDQwNzU3MDBaFw0wMzA4MDQyMzU5MDBaMFEx
-CzAJBgNVBAYTAkpQMR8wHQYDVQQKExZDeWJlclRydXN0IEphcGFuLCBJbmMuMSEw
-HwYDVQQDExhDeWJlclRydXN0IEpBUEFOIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEB
-BQADgY0AMIGJAoGBALet/MpHEHaJ/Wes5HMGfIFLHda1fA5Hr+ymVHWoxP1lr+fI
-sbFsNDWN97lkVygLIVredP7ceC6GRhJMfxEf3JO9X75mmIa4t+xtSdOQ2eF5AFZo
-uq1sHyw7H8ksjEOwBELqgXOmzjN1RQ2KRXIvqldV5AfDQ+J1Og+8PNCEzrrvAgMB
-AAEwDQYJKoZIhvcNAQEEBQADgYEAt6ZkowyAPBzE2O5BO+WGpJ5gXdYBMqhqZC0g
-cEC6ck5m+gdlTgOOC/1W4K07IKcy+rISHoDfHuN6GMxX2+bJNGDvdesQFtCkLnDY
-JCO4pXdzQvkHOt0BbAiTBzUmECVgKf8J5WSfabkWSfNc3SRjRpMNsFM2dbxIILsZ
-to/QIv0=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 78 (0x4e)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=JP, O=CyberTrust Japan, Inc., CN=CyberTrust JAPAN Root CA
- Validity
- Not Before: Aug 4 07:57:00 1998 GMT
- Not After : Aug 4 23:59:00 2003 GMT
- Subject: C=JP, O=CyberTrust Japan, Inc., CN=CyberTrust JAPAN Root CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:b7:ad:fc:ca:47:10:76:89:fd:67:ac:e4:73:06:
- 7c:81:4b:1d:d6:b5:7c:0e:47:af:ec:a6:54:75:a8:
- c4:fd:65:af:e7:c8:b1:b1:6c:34:35:8d:f7:b9:64:
- 57:28:0b:21:5a:de:74:fe:dc:78:2e:86:46:12:4c:
- 7f:11:1f:dc:93:bd:5f:be:66:98:86:b8:b7:ec:6d:
- 49:d3:90:d9:e1:79:00:56:68:ba:ad:6c:1f:2c:3b:
- 1f:c9:2c:8c:43:b0:04:42:ea:81:73:a6:ce:33:75:
- 45:0d:8a:45:72:2f:aa:57:55:e4:07:c3:43:e2:75:
- 3a:0f:bc:3c:d0:84:ce:ba:ef
- Exponent: 65537 (0x10001)
- Signature Algorithm: md5WithRSAEncryption
- b7:a6:64:a3:0c:80:3c:1c:c4:d8:ee:41:3b:e5:86:a4:9e:60:
- 5d:d6:01:32:a8:6a:64:2d:20:70:40:ba:72:4e:66:fa:07:65:
- 4e:03:8e:0b:fd:56:e0:ad:3b:20:a7:32:fa:b2:12:1e:80:df:
- 1e:e3:7a:18:cc:57:db:e6:c9:34:60:ef:75:eb:10:16:d0:a4:
- 2e:70:d8:24:23:b8:a5:77:73:42:f9:07:3a:dd:01:6c:08:93:
- 07:35:26:10:25:60:29:ff:09:e5:64:9f:69:b9:16:49:f3:5c:
- dd:24:63:46:93:0d:b0:53:36:75:bc:48:20:bb:19:b6:8f:d0:
- 22:fd
-
-GTE CyberTrust Japan Secure Server CA
-=====================================
-MD5 Fingerprint: DD:0D:0D:B4:78:4B:7D:CE:30:0A:A6:35:C6:AB:4C:88
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICIzCCAYwCAU8wDQYJKoZIhvcNAQEEBQAwWjELMAkGA1UEBhMCSlAxHzAdBgNV
-BAoTFkN5YmVyVHJ1c3QgSmFwYW4sIEluYy4xKjAoBgNVBAMTIUN5YmVyVHJ1c3Qg
-SkFQQU4gU2VjdXJlIFNlcnZlciBDQTAeFw05ODA4MDQwODA2MzJaFw0wMzA4MDQy
-MzU5MDBaMFoxCzAJBgNVBAYTAkpQMR8wHQYDVQQKExZDeWJlclRydXN0IEphcGFu
-LCBJbmMuMSowKAYDVQQDEyFDeWJlclRydXN0IEpBUEFOIFNlY3VyZSBTZXJ2ZXIg
-Q0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKwmo6G4b2rALBL52zEFkuf9
-+tSBtLjVKtWQ+vBDZfwSFcrs27lh3jNjN0+vADx/kjcbGHPlnzyI8RoTRP558sMm
-lQ8L8J4UByFsV8Jdw+JRsM2LX81fhjj4eZc57Oi/Ui6xXqqprozt7tfIty4xi7Q5
-kjt8gScHGgFEL0lzILbJAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAaB17Eu5aeSkx
-ygGsi1CpJ5ksAPw4Ghz/wtXwE/4bpzn1gBTrUfrAjXuEG1musTVRbqE+1xvsoJ7f
-4KWCluOxP9io8ct5gI738ESZfhT1I6MR42hLBTZuiOOrhqo4UwNCO9O5+eC/BenT
-X8NKp7b9t12QSfiasq1mpoIAk65g/yA=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 79 (0x4f)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=JP, O=CyberTrust Japan, Inc., CN=CyberTrust JAPAN Secure Server CA
- Validity
- Not Before: Aug 4 08:06:32 1998 GMT
- Not After : Aug 4 23:59:00 2003 GMT
- Subject: C=JP, O=CyberTrust Japan, Inc., CN=CyberTrust JAPAN Secure Server CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:ac:26:a3:a1:b8:6f:6a:c0:2c:12:f9:db:31:05:
- 92:e7:fd:fa:d4:81:b4:b8:d5:2a:d5:90:fa:f0:43:
- 65:fc:12:15:ca:ec:db:b9:61:de:33:63:37:4f:af:
- 00:3c:7f:92:37:1b:18:73:e5:9f:3c:88:f1:1a:13:
- 44:fe:79:f2:c3:26:95:0f:0b:f0:9e:14:07:21:6c:
- 57:c2:5d:c3:e2:51:b0:cd:8b:5f:cd:5f:86:38:f8:
- 79:97:39:ec:e8:bf:52:2e:b1:5e:aa:a9:ae:8c:ed:
- ee:d7:c8:b7:2e:31:8b:b4:39:92:3b:7c:81:27:07:
- 1a:01:44:2f:49:73:20:b6:c9
- Exponent: 65537 (0x10001)
- Signature Algorithm: md5WithRSAEncryption
- 68:1d:7b:12:ee:5a:79:29:31:ca:01:ac:8b:50:a9:27:99:2c:
- 00:fc:38:1a:1c:ff:c2:d5:f0:13:fe:1b:a7:39:f5:80:14:eb:
- 51:fa:c0:8d:7b:84:1b:59:ae:b1:35:51:6e:a1:3e:d7:1b:ec:
- a0:9e:df:e0:a5:82:96:e3:b1:3f:d8:a8:f1:cb:79:80:8e:f7:
- f0:44:99:7e:14:f5:23:a3:11:e3:68:4b:05:36:6e:88:e3:ab:
- 86:aa:38:53:03:42:3b:d3:b9:f9:e0:bf:05:e9:d3:5f:c3:4a:
- a7:b6:fd:b7:5d:90:49:f8:9a:b2:ad:66:a6:82:00:93:ae:60:
- ff:20
-
-GTE CyberTrust Root 2
-=====================
-MD5 Fingerprint: BA:ED:17:57:9A:4B:FF:7C:F9:C9:1F:A2:CD:1A:D6:87
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICUDCCAbkCAgGbMA0GCSqGSIb3DQEBBAUAMHAxCzAJBgNVBAYTAlVTMRgwFgYD
-VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
-bHV0aW9ucywgSW5jLjEeMBwGA1UEAxMVR1RFIEN5YmVyVHJ1c3QgUm9vdCAyMB4X
-DTk4MDgxMTExMzUwN1oXDTA4MDgxMTExMjIxNlowcDELMAkGA1UEBhMCVVMxGDAW
-BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg
-U29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290IDIw
-gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANksTE4vaRoj41a6886EwAnAefFE
-XzMfFZF/iogouCRFzI8YzR900bWPcUzWMfZzloSUQMWpg2Akfa9vNLdLTMIJgDtF
-BJ7EPMQndXsADKFkR7UUXYJLUTpYu0RMPdPlBjjoYVyYeLuAs5zacoJioN+cX+v5
-T3fCzGAYAGs0giWzAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAo2SRbxDt526iQkCU
-eM74FAjR+kOF60bNkhTQ7y4tNjkY2brJJ4gp6UgXb/jBqshhbS39QC11QzCXOfgU
-ZL1v72OoK0LfsloNJex7N9jOkSmCFvnoYqLhdsQCfd0li5jh9g1gjPZZkEBRRNHC
-+xkkHhc5a3QhFTPWVdeCHnAsJ6g=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 411 (0x19b)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 2
- Validity
- Not Before: Aug 11 11:35:07 1998 GMT
- Not After : Aug 11 11:22:16 2008 GMT
- Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 2
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:d9:2c:4c:4e:2f:69:1a:23:e3:56:ba:f3:ce:84:
- c0:09:c0:79:f1:44:5f:33:1f:15:91:7f:8a:88:28:
- b8:24:45:cc:8f:18:cd:1f:74:d1:b5:8f:71:4c:d6:
- 31:f6:73:96:84:94:40:c5:a9:83:60:24:7d:af:6f:
- 34:b7:4b:4c:c2:09:80:3b:45:04:9e:c4:3c:c4:27:
- 75:7b:00:0c:a1:64:47:b5:14:5d:82:4b:51:3a:58:
- bb:44:4c:3d:d3:e5:06:38:e8:61:5c:98:78:bb:80:
- b3:9c:da:72:82:62:a0:df:9c:5f:eb:f9:4f:77:c2:
- cc:60:18:00:6b:34:82:25:b3
- Exponent: 65537 (0x10001)
- Signature Algorithm: md5WithRSAEncryption
- a3:64:91:6f:10:ed:e7:6e:a2:42:40:94:78:ce:f8:14:08:d1:
- fa:43:85:eb:46:cd:92:14:d0:ef:2e:2d:36:39:18:d9:ba:c9:
- 27:88:29:e9:48:17:6f:f8:c1:aa:c8:61:6d:2d:fd:40:2d:75:
- 43:30:97:39:f8:14:64:bd:6f:ef:63:a8:2b:42:df:b2:5a:0d:
- 25:ec:7b:37:d8:ce:91:29:82:16:f9:e8:62:a2:e1:76:c4:02:
- 7d:dd:25:8b:98:e1:f6:0d:60:8c:f6:59:90:40:51:44:d1:c2:
- fb:19:24:1e:17:39:6b:74:21:15:33:d6:55:d7:82:1e:70:2c:
- 27:a8
-
-GTE CyberTrust Root 3
-=====================
-MD5 Fingerprint: DB:81:96:57:AE:64:61:EF:77:A7:83:C4:51:24:3C:87
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICUDCCAbkCAgGXMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNVBAYTAlVTMRgwFgYD
-VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
-bHV0aW9ucywgSW5jLjEeMBwGA1UEAxMVR1RFIEN5YmVyVHJ1c3QgUm9vdCAzMB4X
-DTk4MDgxMDE5NTkwOFoXDTA4MDgxMDE5MzYzOVowcDELMAkGA1UEBhMCVVMxGDAW
-BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg
-U29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290IDMw
-gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHzsSsLztwU2TSXYlASVmOETFP6
-wIXP+sHdD955E39T+6oOYN3iYr/G7k6ZNKpoQzWZ+KP982O9AVRqnrI6lix7eCjG
-WrWNGhUY/eOMLqJQCVtx1g21GB8ZjgQpk5N4q18U53NC8gMMV6IbUDsLu1ngoDoD
-7icbWky5sAjKuRqJAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAheutlCAG6bKiazvy
-ZuvjS7gSJgXl9JGo3IfcmPSUwfRhvdWcbFFzlV7QvdfmRdw8z0aE1ee57ORnY24A
-KHdxXUoF6bl8hszCRLveKUja6t29F58dUQGo6BResVf3/9qPzpX+Le0yEnf/fGph
-la4xcgYI8PnzDY7i76hTXZEDg94=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 407 (0x197)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 3
- Validity
- Not Before: Aug 10 19:59:08 1998 GMT
- Not After : Aug 10 19:36:39 2008 GMT
- Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 3
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:e1:f3:b1:2b:0b:ce:dc:14:d9:34:97:62:50:12:
- 56:63:84:4c:53:fa:c0:85:cf:fa:c1:dd:0f:de:79:
- 13:7f:53:fb:aa:0e:60:dd:e2:62:bf:c6:ee:4e:99:
- 34:aa:68:43:35:99:f8:a3:fd:f3:63:bd:01:54:6a:
- 9e:b2:3a:96:2c:7b:78:28:c6:5a:b5:8d:1a:15:18:
- fd:e3:8c:2e:a2:50:09:5b:71:d6:0d:b5:18:1f:19:
- 8e:04:29:93:93:78:ab:5f:14:e7:73:42:f2:03:0c:
- 57:a2:1b:50:3b:0b:bb:59:e0:a0:3a:03:ee:27:1b:
- 5a:4c:b9:b0:08:ca:b9:1a:89
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 85:eb:ad:94:20:06:e9:b2:a2:6b:3b:f2:66:eb:e3:4b:b8:12:
- 26:05:e5:f4:91:a8:dc:87:dc:98:f4:94:c1:f4:61:bd:d5:9c:
- 6c:51:73:95:5e:d0:bd:d7:e6:45:dc:3c:cf:46:84:d5:e7:b9:
- ec:e4:67:63:6e:00:28:77:71:5d:4a:05:e9:b9:7c:86:cc:c2:
- 44:bb:de:29:48:da:ea:dd:bd:17:9f:1d:51:01:a8:e8:14:5e:
- b1:57:f7:ff:da:8f:ce:95:fe:2d:ed:32:12:77:ff:7c:6a:61:
- 95:ae:31:72:06:08:f0:f9:f3:0d:8e:e2:ef:a8:53:5d:91:03:
- 83:de
-
-GTE CyberTrust Root 4
-=====================
-MD5 Fingerprint: 33:43:02:B1:B9:E0:73:B1:B1:20:CA:CB:C7:84:03:50
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDVTCCAj0CAgGoMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNVBAYTAlVTMRgwFgYD
-VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
-bHV0aW9ucywgSW5jLjEeMBwGA1UEAxMVR1RFIEN5YmVyVHJ1c3QgUm9vdCA0MB4X
-DTk4MDgxMzEzNTEwMFoXDTEzMDgxMzIzNTkwMFowcDELMAkGA1UEBhMCVVMxGDAW
-BgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3Qg
-U29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290IDQw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6nSJuf9pmPDlCsaMqb9P3
-vK6sMVrXEZBHuZ0ZLvnzGyKgw+GnusT8XgqUS5haSybkH/Tc8/6OiNxsLXx3hyZQ
-wF5OqCih6hdpT03GAQ7amg0GViYVtqRdejWvje14Uob5OKuzAdPaBZaxtlCrwKGu
-F1P6QzkgcWUj223Etu2YRYPX0vbiqWv7+XXM78WrcZY16N+OkZuoEHUft84Tjmuz
-lneXGpEvxyxpmfAPKmgAmHZEG4wo0uuO9IO0f6QlXmw72cZo1WG41F4xB7VbkDVS
-V3sXIO0tuB6OiDk+Usvf8FyxZbulErSQY79xnTLB2r9QSpW+BjrEK+vNmHZETQvl
-AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAEOvHIfJSbpliTRJPOoHO0eiedSgO5Bs
-3n+oVMPoTEAyvMjsHOXZrEC6/Iw/wnOc9GTq36ntTlvIAWDuOW1DJ/N/qgjS/k5v
-FDJNfeQ0gKU1xNZGULQ7oC1lH09lfjQoLcCndn0xyQ0zFvYgGSARULsDzHBtlrfv
-TKfaNhXPu03UltyITWyY7blz/ihXoO1k+AqBKXP29pcyhzm0ge/ZTRoHNPe6QjXe
-V9xc1vfF6wonDIGmwtBoTv2SW0iD9haKjzZb7TFsP0F6cfeSPzGkCkBM84biYcE8
-SYEtpbjvupcPvCsdm4ny0o4eTYbywqv2LZnAGyoNobZP+SxYTT19Nwo=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 424 (0x1a8)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 4
- Validity
- Not Before: Aug 13 13:51:00 1998 GMT
- Not After : Aug 13 23:59:00 2013 GMT
- Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 4
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:ba:9d:22:6e:7f:da:66:3c:39:42:b1:a3:2a:6f:
- d3:f7:bc:ae:ac:31:5a:d7:11:90:47:b9:9d:19:2e:
- f9:f3:1b:22:a0:c3:e1:a7:ba:c4:fc:5e:0a:94:4b:
- 98:5a:4b:26:e4:1f:f4:dc:f3:fe:8e:88:dc:6c:2d:
- 7c:77:87:26:50:c0:5e:4e:a8:28:a1:ea:17:69:4f:
- 4d:c6:01:0e:da:9a:0d:06:56:26:15:b6:a4:5d:7a:
- 35:af:8d:ed:78:52:86:f9:38:ab:b3:01:d3:da:05:
- 96:b1:b6:50:ab:c0:a1:ae:17:53:fa:43:39:20:71:
- 65:23:db:6d:c4:b6:ed:98:45:83:d7:d2:f6:e2:a9:
- 6b:fb:f9:75:cc:ef:c5:ab:71:96:35:e8:df:8e:91:
- 9b:a8:10:75:1f:b7:ce:13:8e:6b:b3:96:77:97:1a:
- 91:2f:c7:2c:69:99:f0:0f:2a:68:00:98:76:44:1b:
- 8c:28:d2:eb:8e:f4:83:b4:7f:a4:25:5e:6c:3b:d9:
- c6:68:d5:61:b8:d4:5e:31:07:b5:5b:90:35:52:57:
- 7b:17:20:ed:2d:b8:1e:8e:88:39:3e:52:cb:df:f0:
- 5c:b1:65:bb:a5:12:b4:90:63:bf:71:9d:32:c1:da:
- bf:50:4a:95:be:06:3a:c4:2b:eb:cd:98:76:44:4d:
- 0b:e5
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 43:af:1c:87:c9:49:ba:65:89:34:49:3c:ea:07:3b:47:a2:79:
- d4:a0:3b:90:6c:de:7f:a8:54:c3:e8:4c:40:32:bc:c8:ec:1c:
- e5:d9:ac:40:ba:fc:8c:3f:c2:73:9c:f4:64:ea:df:a9:ed:4e:
- 5b:c8:01:60:ee:39:6d:43:27:f3:7f:aa:08:d2:fe:4e:6f:14:
- 32:4d:7d:e4:34:80:a5:35:c4:d6:46:50:b4:3b:a0:2d:65:1f:
- 4f:65:7e:34:28:2d:c0:a7:76:7d:31:c9:0d:33:16:f6:20:19:
- 20:11:50:bb:03:cc:70:6d:96:b7:ef:4c:a7:da:36:15:cf:bb:
- 4d:d4:96:dc:88:4d:6c:98:ed:b9:73:fe:28:57:a0:ed:64:f8:
- 0a:81:29:73:f6:f6:97:32:87:39:b4:81:ef:d9:4d:1a:07:34:
- f7:ba:42:35:de:57:dc:5c:d6:f7:c5:eb:0a:27:0c:81:a6:c2:
- d0:68:4e:fd:92:5b:48:83:f6:16:8a:8f:36:5b:ed:31:6c:3f:
- 41:7a:71:f7:92:3f:31:a4:0a:40:4c:f3:86:e2:61:c1:3c:49:
- 81:2d:a5:b8:ef:ba:97:0f:bc:2b:1d:9b:89:f2:d2:8e:1e:4d:
- 86:f2:c2:ab:f6:2d:99:c0:1b:2a:0d:a1:b6:4f:f9:2c:58:4d:
- 3d:7d:37:0a
-
-GTE CyberTrust Root 5
-=====================
-MD5 Fingerprint: 7D:6C:86:E4:FC:4D:D1:0B:00:BA:22:BB:4E:7C:6A:8E
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDtjCCAp6gAwIBAgICAbYwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVVMx
-GDAWBgNVBAoTD0dURSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1
-c3QgU29sdXRpb25zLCBJbmMuMR4wHAYDVQQDExVHVEUgQ3liZXJUcnVzdCBSb290
-IDUwHhcNOTgwODE0MTQ1MDAwWhcNMTMwODE0MjM1OTAwWjBwMQswCQYDVQQGEwJV
-UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
-cnVzdCBTb2x1dGlvbnMsIEluYy4xHjAcBgNVBAMTFUdURSBDeWJlclRydXN0IFJv
-b3QgNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALwSbj+KfHqXAewe
-uzlaAvR4RKJIG457SVJ6uHtHs6+Um2+7lvoramVcuByUc76/iQoigO5X/IwFu3Cf
-lzkE2qOHXKjlyq/AM5rVN1xLrOSA0KYjYPv9ci6UncfOwgQy73hgXe2thw9FZR48
-mgqavl0dmezn8tHGehfZrZtUln/EfGC/haoVNR1A2hG87FQhKC0joajwzy3N3fx+
-D17hZQdWywe00lboXjHMGGPEhtIthc+Tkqtt/mg5+95zvYb45EZ66p8My/QZ/mO8
-0Sx7iDM29uThnAxTgWAc2i6rlqkWiBNQmbK9Vd8VMH7o5Zj7cH5stQf8/Ea30O03
-ln4y/iECAwEAAaNaMFgwEgYDVR0TAQH/BAgwBgEB/wIBBTAOBgNVHQ8BAf8EBAMC
-AQYwFwYDVR0gBBAwDjAMBgoqhkiG+GMBAgEDMBkGA1UdDgQSBBB2CkkhOEyf3vjE
-ScdxcZGdMA0GCSqGSIb3DQEBBQUAA4IBAQBBOtQYW9q43iEc4Y4J5fFoNP/elvQH
-9ac886xKsZv6kvqb7eYyIapKdsXcTzjl39WG5NXIdn2Y17HNj021kSNsi4rr6nzv
-FJTExvAfSi0ycWMrY5EmAgm2gB3t4sy4f9uHY8jh0GwmsTUdQGYQG82VVBgzYewT
-T9oT95mvPtDPjqZyorPDBZrJJ32SzH5SjbOrcG2eiZ9N6xp1wpiq1QIW1wyKvyXk
-6y28mOlYOBl8uTf+2+KZCHMGx5eDan0QAS8yuRcFSmXmL86+XlOmgumaUwqEdC2D
-ysiUFnZflGEo8IWnObvXi9moshMdVAk0JH0ggX1mfqKQdFwQxr3sqxvC
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 438 (0x1b6)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 5
- Validity
- Not Before: Aug 14 14:50:00 1998 GMT
- Not After : Aug 14 23:59:00 2013 GMT
- Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Root 5
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:bc:12:6e:3f:8a:7c:7a:97:01:ec:1e:bb:39:5a:
- 02:f4:78:44:a2:48:1b:8e:7b:49:52:7a:b8:7b:47:
- b3:af:94:9b:6f:bb:96:fa:2b:6a:65:5c:b8:1c:94:
- 73:be:bf:89:0a:22:80:ee:57:fc:8c:05:bb:70:9f:
- 97:39:04:da:a3:87:5c:a8:e5:ca:af:c0:33:9a:d5:
- 37:5c:4b:ac:e4:80:d0:a6:23:60:fb:fd:72:2e:94:
- 9d:c7:ce:c2:04:32:ef:78:60:5d:ed:ad:87:0f:45:
- 65:1e:3c:9a:0a:9a:be:5d:1d:99:ec:e7:f2:d1:c6:
- 7a:17:d9:ad:9b:54:96:7f:c4:7c:60:bf:85:aa:15:
- 35:1d:40:da:11:bc:ec:54:21:28:2d:23:a1:a8:f0:
- cf:2d:cd:dd:fc:7e:0f:5e:e1:65:07:56:cb:07:b4:
- d2:56:e8:5e:31:cc:18:63:c4:86:d2:2d:85:cf:93:
- 92:ab:6d:fe:68:39:fb:de:73:bd:86:f8:e4:46:7a:
- ea:9f:0c:cb:f4:19:fe:63:bc:d1:2c:7b:88:33:36:
- f6:e4:e1:9c:0c:53:81:60:1c:da:2e:ab:96:a9:16:
- 88:13:50:99:b2:bd:55:df:15:30:7e:e8:e5:98:fb:
- 70:7e:6c:b5:07:fc:fc:46:b7:d0:ed:37:96:7e:32:
- fe:21
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints: critical
- CA:TRUE, pathlen:5
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Certificate Policies:
- Policy: 1.2.840.113763.1.2.1.3
-
- X509v3 Subject Key Identifier:
- 76:0A:49:21:38:4C:9F:DE:F8:C4:49:C7:71:71:91:9D
- Signature Algorithm: sha1WithRSAEncryption
- 41:3a:d4:18:5b:da:b8:de:21:1c:e1:8e:09:e5:f1:68:34:ff:
- de:96:f4:07:f5:a7:3c:f3:ac:4a:b1:9b:fa:92:fa:9b:ed:e6:
- 32:21:aa:4a:76:c5:dc:4f:38:e5:df:d5:86:e4:d5:c8:76:7d:
- 98:d7:b1:cd:8f:4d:b5:91:23:6c:8b:8a:eb:ea:7c:ef:14:94:
- c4:c6:f0:1f:4a:2d:32:71:63:2b:63:91:26:02:09:b6:80:1d:
- ed:e2:cc:b8:7f:db:87:63:c8:e1:d0:6c:26:b1:35:1d:40:66:
- 10:1b:cd:95:54:18:33:61:ec:13:4f:da:13:f7:99:af:3e:d0:
- cf:8e:a6:72:a2:b3:c3:05:9a:c9:27:7d:92:cc:7e:52:8d:b3:
- ab:70:6d:9e:89:9f:4d:eb:1a:75:c2:98:aa:d5:02:16:d7:0c:
- 8a:bf:25:e4:eb:2d:bc:98:e9:58:38:19:7c:b9:37:fe:db:e2:
- 99:08:73:06:c7:97:83:6a:7d:10:01:2f:32:b9:17:05:4a:65:
- e6:2f:ce:be:5e:53:a6:82:e9:9a:53:0a:84:74:2d:83:ca:c8:
- 94:16:76:5f:94:61:28:f0:85:a7:39:bb:d7:8b:d9:a8:b2:13:
- 1d:54:09:34:24:7d:20:81:7d:66:7e:a2:90:74:5c:10:c6:bd:
- ec:ab:1b:c2
-
-GTE CyberTrust Root CA
-======================
-MD5 Fingerprint: C4:D7:F0:B2:A3:C5:7D:61:67:F0:04:CD:43:D3:BA:58
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIB+jCCAWMCAgGjMA0GCSqGSIb3DQEBBAUAMEUxCzAJBgNVBAYTAlVTMRgwFgYD
-VQQKEw9HVEUgQ29ycG9yYXRpb24xHDAaBgNVBAMTE0dURSBDeWJlclRydXN0IFJv
-b3QwHhcNOTYwMjIzMjMwMTAwWhcNMDYwMjIzMjM1OTAwWjBFMQswCQYDVQQGEwJV
-UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMRwwGgYDVQQDExNHVEUgQ3liZXJU
-cnVzdCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyv
-RLfTD0bZZOWTwUKOx7pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4M
-ypqfpX/1FZSj1aJGgthoTNE3FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/5
-1KiOQswkwB6RJ0q1bQaAYznEol44AwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBABKz
-dcZfHeFhVYAA1IFLezEPI2PnPfMD+fQ2qLvZ46WXTeorKeDWanOB5sCJo9Px4KWl
-IjeaY8JIILTbcuPI9tl8vrGvU9oUtCG41tWW4/5ODFlitppK+ULdjG+BqXH/9Apy
-bW1EDp3zdHSo1TRJ6V6e6bR64eVaH4QwnNOfpSXY
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 419 (0x1a3)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=US, O=GTE Corporation, CN=GTE CyberTrust Root
- Validity
- Not Before: Feb 23 23:01:00 1996 GMT
- Not After : Feb 23 23:59:00 2006 GMT
- Subject: C=US, O=GTE Corporation, CN=GTE CyberTrust Root
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:b8:e6:4f:ba:db:98:7c:71:7c:af:44:b7:d3:0f:
- 46:d9:64:e5:93:c1:42:8e:c7:ba:49:8d:35:2d:7a:
- e7:8b:bd:e5:05:31:59:c6:b1:2f:0a:0c:fb:9f:a7:
- 3f:a2:09:66:84:56:1e:37:29:1b:87:e9:7e:0c:ca:
- 9a:9f:a5:7f:f5:15:94:a3:d5:a2:46:82:d8:68:4c:
- d1:37:15:06:68:af:bd:f8:b0:b3:f0:29:f5:95:5a:
- 09:16:61:77:0a:22:25:d4:4f:45:aa:c7:bd:e5:96:
- df:f9:d4:a8:8e:42:cc:24:c0:1e:91:27:4a:b5:6d:
- 06:80:63:39:c4:a2:5e:38:03
- Exponent: 65537 (0x10001)
- Signature Algorithm: md5WithRSAEncryption
- 12:b3:75:c6:5f:1d:e1:61:55:80:00:d4:81:4b:7b:31:0f:23:
- 63:e7:3d:f3:03:f9:f4:36:a8:bb:d9:e3:a5:97:4d:ea:2b:29:
- e0:d6:6a:73:81:e6:c0:89:a3:d3:f1:e0:a5:a5:22:37:9a:63:
- c2:48:20:b4:db:72:e3:c8:f6:d9:7c:be:b1:af:53:da:14:b4:
- 21:b8:d6:d5:96:e3:fe:4e:0c:59:62:b6:9a:4a:f9:42:dd:8c:
- 6f:81:a9:71:ff:f4:0a:72:6d:6d:44:0e:9d:f3:74:74:a8:d5:
- 34:49:e9:5e:9e:e9:b4:7a:e1:e5:5a:1f:84:30:9c:d3:9f:a5:
- 25:d8
-
-GlobalSign Partners CA
-======================
-MD5 Fingerprint: 3C:75:CD:4C:BD:A9:D0:8A:79:4F:50:16:37:84:F4:2B
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDnjCCAoagAwIBAgILAgAAAAAA1ni50a8wDQYJKoZIhvcNAQEEBQAwVzELMAkG
-A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
-b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05OTAxMjgxMjAw
-MDBaFw0wOTAxMjgxMjAwMDBaMF8xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
-YWxTaWduIG52LXNhMRQwEgYDVQQLEwtQYXJ0bmVycyBDQTEfMB0GA1UEAxMWR2xv
-YmFsU2lnbiBQYXJ0bmVycyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBANIs+DKsShJ6N8gpkaWujG4eDsA0M4jlM3EWHHiEaMMYNFAuFj6xlIJPsZqf
-APjGETXGaXuYAq0ABohs50wzKACIJ0Yfh7NxdWO8MruI3mYYDlAGk7T2vBQ3MD0i
-3z3/dX7ZChrFn7P80KyzCHqJ0wHoAFznSgs9TXsmordiBovaRt2TFz8/WwJLC7aI
-IBGSAK27xy7U40Wu9YlafI2krYVkMsAnjMbyioCShiRWWY10aKKDQrOePVBBhm8g
-bvb9ztMZ4zLMj+2aXm0fKPVSrG4YXvg90ZLlumwBiEsK8i3eZTMFQqBMqjF2vv2/
-gXj5cRxGXi0VlS0wWY5MQdFiqz0CAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgAGMB0G
-A1UdDgQWBBRDJI1wFQhiVZxPDEAXXYZeD6JM+zAfBgNVHSMEGDAWgBRge2YaRQ2X
-yolQL30EzTSo//z9SzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IB
-AQBm7bSIaRGZgiGDrKFti5uErQ8tyB6Mynt+rarUjt4H1p5Fx6W4nAc5YCVVGsBP
-GeXPFylJiRg1ZuXrKEBOV8mvs+S4IAWjO5VQkUmUKX0s5YhBpUWIXp2CJ/fS71u1
-T5++/jVlLFVkn+FR2iJhd7pYTo/GeVlZbjCAok+QbiELrdBoOZAQm+0iZW8eETjm
-f4zS8zltR9Uh6Op1OkHRrfYWnV0LIb3zH2MGJR3BHzVxLOsgGdXBsOw95W/tAgc/
-E3tmktZEwZj3X1CLelvCb22w0fjldKBAN6MlD+Q9ymQxk5BcMHu5OTGaXkzNuUFP
-UOQ9OK7IZtnHO11RR6ybq/Kt
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number:
- 02:00:00:00:00:00:d6:78:b9:d1:af
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
- Validity
- Not Before: Jan 28 12:00:00 1999 GMT
- Not After : Jan 28 12:00:00 2009 GMT
- Subject: C=BE, O=GlobalSign nv-sa, OU=Partners CA, CN=GlobalSign Partners CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:d2:2c:f8:32:ac:4a:12:7a:37:c8:29:91:a5:ae:
- 8c:6e:1e:0e:c0:34:33:88:e5:33:71:16:1c:78:84:
- 68:c3:18:34:50:2e:16:3e:b1:94:82:4f:b1:9a:9f:
- 00:f8:c6:11:35:c6:69:7b:98:02:ad:00:06:88:6c:
- e7:4c:33:28:00:88:27:46:1f:87:b3:71:75:63:bc:
- 32:bb:88:de:66:18:0e:50:06:93:b4:f6:bc:14:37:
- 30:3d:22:df:3d:ff:75:7e:d9:0a:1a:c5:9f:b3:fc:
- d0:ac:b3:08:7a:89:d3:01:e8:00:5c:e7:4a:0b:3d:
- 4d:7b:26:a2:b7:62:06:8b:da:46:dd:93:17:3f:3f:
- 5b:02:4b:0b:b6:88:20:11:92:00:ad:bb:c7:2e:d4:
- e3:45:ae:f5:89:5a:7c:8d:a4:ad:85:64:32:c0:27:
- 8c:c6:f2:8a:80:92:86:24:56:59:8d:74:68:a2:83:
- 42:b3:9e:3d:50:41:86:6f:20:6e:f6:fd:ce:d3:19:
- e3:32:cc:8f:ed:9a:5e:6d:1f:28:f5:52:ac:6e:18:
- 5e:f8:3d:d1:92:e5:ba:6c:01:88:4b:0a:f2:2d:de:
- 65:33:05:42:a0:4c:aa:31:76:be:fd:bf:81:78:f9:
- 71:1c:46:5e:2d:15:95:2d:30:59:8e:4c:41:d1:62:
- ab:3d
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Subject Key Identifier:
- 43:24:8D:70:15:08:62:55:9C:4F:0C:40:17:5D:86:5E:0F:A2:4C:FB
- X509v3 Authority Key Identifier:
- keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
-
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- 66:ed:b4:88:69:11:99:82:21:83:ac:a1:6d:8b:9b:84:ad:0f:
- 2d:c8:1e:8c:ca:7b:7e:ad:aa:d4:8e:de:07:d6:9e:45:c7:a5:
- b8:9c:07:39:60:25:55:1a:c0:4f:19:e5:cf:17:29:49:89:18:
- 35:66:e5:eb:28:40:4e:57:c9:af:b3:e4:b8:20:05:a3:3b:95:
- 50:91:49:94:29:7d:2c:e5:88:41:a5:45:88:5e:9d:82:27:f7:
- d2:ef:5b:b5:4f:9f:be:fe:35:65:2c:55:64:9f:e1:51:da:22:
- 61:77:ba:58:4e:8f:c6:79:59:59:6e:30:80:a2:4f:90:6e:21:
- 0b:ad:d0:68:39:90:10:9b:ed:22:65:6f:1e:11:38:e6:7f:8c:
- d2:f3:39:6d:47:d5:21:e8:ea:75:3a:41:d1:ad:f6:16:9d:5d:
- 0b:21:bd:f3:1f:63:06:25:1d:c1:1f:35:71:2c:eb:20:19:d5:
- c1:b0:ec:3d:e5:6f:ed:02:07:3f:13:7b:66:92:d6:44:c1:98:
- f7:5f:50:8b:7a:5b:c2:6f:6d:b0:d1:f8:e5:74:a0:40:37:a3:
- 25:0f:e4:3d:ca:64:31:93:90:5c:30:7b:b9:39:31:9a:5e:4c:
- cd:b9:41:4f:50:e4:3d:38:ae:c8:66:d9:c7:3b:5d:51:47:ac:
- 9b:ab:f2:ad
-
-GlobalSign Primary Class 1 CA
-=============================
-MD5 Fingerprint: 5C:AC:59:01:A4:86:53:CB:10:66:B5:D6:D6:71:FF:01
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDrDCCApSgAwIBAgILAgAAAAAA1ni4N88wDQYJKoZIhvcNAQEEBQAwVzELMAkG
-A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
-b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MTUxMjAw
-MDBaFw0wOTAxMjgxMjAwMDBaMG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
-YWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDEgQ0ExJjAkBgNV
-BAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAxIENBMIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEAvSA1R9Eo1gijEjkjRw29cCFSDlcxlaY0V2vsfkN5
-wwZSSM28taGZvdgfMrzP125ybS53IpCCTkuPmgwBQprZcFm2nR/mY9EMrR1O+IWB
-+a7vn6ZSYUR5GnVF4GFWRW1CjD1yy6akErea9dZg0GBQs46mpuy09BLNf6jO77Ph
-hTD+csTm53eznlhB1lGDiAfGtmlPNt7RC0g/vdafIXRkbycGPkv9Dqabv6RIV4yQ
-7okYCwKBGL5n/lNgiCe6o3M0S1pWtN5zBe2Yll3sSudA/EsJYuvQ4zFPhdF6q1ln
-K/uID+uqg701/WEn7GYOQlf3acIM7/xqwm5J2o9BOK5IqQIDAQABo2MwYTAOBgNV
-HQ8BAf8EBAMCAAYwHQYDVR0OBBYEFPzgZvZaNZnrQB7SuB5DvJiOH4rDMB8GA1Ud
-IwQYMBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQEEBQADggEBAJujCETO8pCdcfMyswVqterPKZjeVT6gFn0GekTWr9L6
-E1iM+BzHqx20G+9paJhcCDmP4Pf7SMwh57gz2wWqNCRsSuXpe2Deg7MfCr5BdfzM
-MEi3wSYdBDOqtnjtKsu6VpcybvcxlS5G8hTuJ8f3Yom5XFrTOIpk9Te08bM0ctXV
-IT1L13iT1zFmNR6j2EdJbxyt4YB/+JgkbHOsDsIadwKjJge3x2tdvILVKkgdY89Q
-Mqb7HBhHFQpbDFw4JJoEmKgISF98NIdjqy2NTAB3lBt2uvUWGKMVry+U9ikAdsEV
-F9PpN0121MtLKVkkrNpKoOpj3l9Usfrz0UXLxWS0cyE=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number:
- 02:00:00:00:00:00:d6:78:b8:37:cf
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
- Validity
- Not Before: Sep 15 12:00:00 1998 GMT
- Not After : Jan 28 12:00:00 2009 GMT
- Subject: C=BE, O=GlobalSign nv-sa, OU=Primary Class 1 CA, CN=GlobalSign Primary Class 1 CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:bd:20:35:47:d1:28:d6:08:a3:12:39:23:47:0d:
- bd:70:21:52:0e:57:31:95:a6:34:57:6b:ec:7e:43:
- 79:c3:06:52:48:cd:bc:b5:a1:99:bd:d8:1f:32:bc:
- cf:d7:6e:72:6d:2e:77:22:90:82:4e:4b:8f:9a:0c:
- 01:42:9a:d9:70:59:b6:9d:1f:e6:63:d1:0c:ad:1d:
- 4e:f8:85:81:f9:ae:ef:9f:a6:52:61:44:79:1a:75:
- 45:e0:61:56:45:6d:42:8c:3d:72:cb:a6:a4:12:b7:
- 9a:f5:d6:60:d0:60:50:b3:8e:a6:a6:ec:b4:f4:12:
- cd:7f:a8:ce:ef:b3:e1:85:30:fe:72:c4:e6:e7:77:
- b3:9e:58:41:d6:51:83:88:07:c6:b6:69:4f:36:de:
- d1:0b:48:3f:bd:d6:9f:21:74:64:6f:27:06:3e:4b:
- fd:0e:a6:9b:bf:a4:48:57:8c:90:ee:89:18:0b:02:
- 81:18:be:67:fe:53:60:88:27:ba:a3:73:34:4b:5a:
- 56:b4:de:73:05:ed:98:96:5d:ec:4a:e7:40:fc:4b:
- 09:62:eb:d0:e3:31:4f:85:d1:7a:ab:59:67:2b:fb:
- 88:0f:eb:aa:83:bd:35:fd:61:27:ec:66:0e:42:57:
- f7:69:c2:0c:ef:fc:6a:c2:6e:49:da:8f:41:38:ae:
- 48:a9
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Subject Key Identifier:
- FC:E0:66:F6:5A:35:99:EB:40:1E:D2:B8:1E:43:BC:98:8E:1F:8A:C3
- X509v3 Authority Key Identifier:
- keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
-
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- 9b:a3:08:44:ce:f2:90:9d:71:f3:32:b3:05:6a:b5:ea:cf:29:
- 98:de:55:3e:a0:16:7d:06:7a:44:d6:af:d2:fa:13:58:8c:f8:
- 1c:c7:ab:1d:b4:1b:ef:69:68:98:5c:08:39:8f:e0:f7:fb:48:
- cc:21:e7:b8:33:db:05:aa:34:24:6c:4a:e5:e9:7b:60:de:83:
- b3:1f:0a:be:41:75:fc:cc:30:48:b7:c1:26:1d:04:33:aa:b6:
- 78:ed:2a:cb:ba:56:97:32:6e:f7:31:95:2e:46:f2:14:ee:27:
- c7:f7:62:89:b9:5c:5a:d3:38:8a:64:f5:37:b4:f1:b3:34:72:
- d5:d5:21:3d:4b:d7:78:93:d7:31:66:35:1e:a3:d8:47:49:6f:
- 1c:ad:e1:80:7f:f8:98:24:6c:73:ac:0e:c2:1a:77:02:a3:26:
- 07:b7:c7:6b:5d:bc:82:d5:2a:48:1d:63:cf:50:32:a6:fb:1c:
- 18:47:15:0a:5b:0c:5c:38:24:9a:04:98:a8:08:48:5f:7c:34:
- 87:63:ab:2d:8d:4c:00:77:94:1b:76:ba:f5:16:18:a3:15:af:
- 2f:94:f6:29:00:76:c1:15:17:d3:e9:37:4d:76:d4:cb:4b:29:
- 59:24:ac:da:4a:a0:ea:63:de:5f:54:b1:fa:f3:d1:45:cb:c5:
- 64:b4:73:21
-
-GlobalSign Primary Class 2 CA
-=============================
-MD5 Fingerprint: A9:A9:42:59:7E:BE:5A:94:E4:2C:C6:8B:1C:2A:44:B6
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDrDCCApSgAwIBAgILAgAAAAAA1ni4jY0wDQYJKoZIhvcNAQEEBQAwVzELMAkG
-A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
-b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05OTAxMjgxMjAw
-MDBaFw0wOTAxMjgxMjAwMDBaMG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
-YWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDIgQ0ExJjAkBgNV
-BAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAyIENBMIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEAkoz+7/RFjhdBbvzYvyFvqwadUsEsAJ0/joW4f0qP
-vaBjKspJJ65agvR04lWS/8LRqnmitvrVnYIET8ayxl5jpzq62O7rim+ftrsoQcAi
-+05IGgaS17/Xz7nZvThPOw1EblVB/vwJ29i/844h8egStfYTpdPGTJMisAL/7h0M
-xKhrT3VoVujcKBJQ96gknS4kOfsJBd7lo2RJIdBofnEwkbFg4Dn0UPh6TZgAa3x5
-uk7OSuK6Nh23xTYVlZxkQupfxLr1QAW+4TpZvYSnGbjeTVNQzgfR0lHT7w2BbObn
-bctdfD98zOxPgycl/3BQ9oNZdYQGZlgs3omNAKZJ+aVDdwIDAQABo2MwYTAOBgNV
-HQ8BAf8EBAMCAAYwHQYDVR0OBBYEFHznsrEs3rGna+l2DOGj/U5sx7n2MB8GA1Ud
-IwQYMBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQEEBQADggEBAGPdWc6KeaqYnU7FiWQ3foqTZy8Q6m8nw413bfJcVpQZ
-GmlgMEZdj/JtRTyONZd8L7hR4uiJvYjPJxwINFyIwWgk25GF5M/7+0ON6CUBG8QO
-9wBCSIYfJAhYWoyN8mtHLGiRsWlC/Q2NySbmkoamZG6Sxc4+PH1x4yOkq8fVqKnf
-gqc76IbVw08Y40TQ4NzzxWgu/qUvBYTIfkdCU2uHSv4y/14+cIy3qBXMF8L/RuzQ
-7C20bhIoqflA6evUZpdTqWlVwKmqsi7N0Wn0vvi7fGnuVKbbnvtapj7+mu+UUUt1
-7tjU4ZrxAlYTiQ6nQouWi4UMG4W+Jq6rppm8IvFz30I=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number:
- 02:00:00:00:00:00:d6:78:b8:8d:8d
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
- Validity
- Not Before: Jan 28 12:00:00 1999 GMT
- Not After : Jan 28 12:00:00 2009 GMT
- Subject: C=BE, O=GlobalSign nv-sa, OU=Primary Class 2 CA, CN=GlobalSign Primary Class 2 CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:92:8c:fe:ef:f4:45:8e:17:41:6e:fc:d8:bf:21:
- 6f:ab:06:9d:52:c1:2c:00:9d:3f:8e:85:b8:7f:4a:
- 8f:bd:a0:63:2a:ca:49:27:ae:5a:82:f4:74:e2:55:
- 92:ff:c2:d1:aa:79:a2:b6:fa:d5:9d:82:04:4f:c6:
- b2:c6:5e:63:a7:3a:ba:d8:ee:eb:8a:6f:9f:b6:bb:
- 28:41:c0:22:fb:4e:48:1a:06:92:d7:bf:d7:cf:b9:
- d9:bd:38:4f:3b:0d:44:6e:55:41:fe:fc:09:db:d8:
- bf:f3:8e:21:f1:e8:12:b5:f6:13:a5:d3:c6:4c:93:
- 22:b0:02:ff:ee:1d:0c:c4:a8:6b:4f:75:68:56:e8:
- dc:28:12:50:f7:a8:24:9d:2e:24:39:fb:09:05:de:
- e5:a3:64:49:21:d0:68:7e:71:30:91:b1:60:e0:39:
- f4:50:f8:7a:4d:98:00:6b:7c:79:ba:4e:ce:4a:e2:
- ba:36:1d:b7:c5:36:15:95:9c:64:42:ea:5f:c4:ba:
- f5:40:05:be:e1:3a:59:bd:84:a7:19:b8:de:4d:53:
- 50:ce:07:d1:d2:51:d3:ef:0d:81:6c:e6:e7:6d:cb:
- 5d:7c:3f:7c:cc:ec:4f:83:27:25:ff:70:50:f6:83:
- 59:75:84:06:66:58:2c:de:89:8d:00:a6:49:f9:a5:
- 43:77
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Subject Key Identifier:
- 7C:E7:B2:B1:2C:DE:B1:A7:6B:E9:76:0C:E1:A3:FD:4E:6C:C7:B9:F6
- X509v3 Authority Key Identifier:
- keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
-
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- 63:dd:59:ce:8a:79:aa:98:9d:4e:c5:89:64:37:7e:8a:93:67:
- 2f:10:ea:6f:27:c3:8d:77:6d:f2:5c:56:94:19:1a:69:60:30:
- 46:5d:8f:f2:6d:45:3c:8e:35:97:7c:2f:b8:51:e2:e8:89:bd:
- 88:cf:27:1c:08:34:5c:88:c1:68:24:db:91:85:e4:cf:fb:fb:
- 43:8d:e8:25:01:1b:c4:0e:f7:00:42:48:86:1f:24:08:58:5a:
- 8c:8d:f2:6b:47:2c:68:91:b1:69:42:fd:0d:8d:c9:26:e6:92:
- 86:a6:64:6e:92:c5:ce:3e:3c:7d:71:e3:23:a4:ab:c7:d5:a8:
- a9:df:82:a7:3b:e8:86:d5:c3:4f:18:e3:44:d0:e0:dc:f3:c5:
- 68:2e:fe:a5:2f:05:84:c8:7e:47:42:53:6b:87:4a:fe:32:ff:
- 5e:3e:70:8c:b7:a8:15:cc:17:c2:ff:46:ec:d0:ec:2d:b4:6e:
- 12:28:a9:f9:40:e9:eb:d4:66:97:53:a9:69:55:c0:a9:aa:b2:
- 2e:cd:d1:69:f4:be:f8:bb:7c:69:ee:54:a6:db:9e:fb:5a:a6:
- 3e:fe:9a:ef:94:51:4b:75:ee:d8:d4:e1:9a:f1:02:56:13:89:
- 0e:a7:42:8b:96:8b:85:0c:1b:85:be:26:ae:ab:a6:99:bc:22:
- f1:73:df:42
-
-GlobalSign Primary Class 3 CA
-=============================
-MD5 Fingerprint: 98:12:A3:4B:95:A9:96:64:94:E7:50:8C:3E:E1:83:5A
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDrDCCApSgAwIBAgILAgAAAAAA1ni41sMwDQYJKoZIhvcNAQEEBQAwVzELMAkG
-A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
-b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05OTAxMjgxMjAw
-MDBaFw0wOTAxMjgxMjAwMDBaMG0xCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
-YWxTaWduIG52LXNhMRswGQYDVQQLExJQcmltYXJ5IENsYXNzIDMgQ0ExJjAkBgNV
-BAMTHUdsb2JhbFNpZ24gUHJpbWFyeSBDbGFzcyAzIENBMIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEAkV5WZdbAwAScv0fEXHt6MQH5WJaZ4xyEL9xWj631
-WYHVQ2ZdWpOMdcqp5xHBURAUYMks1HuvxneGq3onrm+VuQvKtkb7fhr0DRRt0slO
-sq7wVPZcQEw2SHToVIxlZhCnvSu3II0FSa14fdIkI1Dj8LR5mwE5/6870y3u4UmN
-jS88akFFL5vjPeES5JF1ns+gPjySgW+KLhjc4PKMjP2H2Qf0QJTJTk9D32dWb70D
-UHyZZ6S5PJFsAm6E1vxG98xvGD4X8O8LZBZX5qyG8UiqQ8HJJ3hzREXihX26/7Ph
-+xsFpEs7mRIlAVAUaq9d6sgM7uTa7EuLXGgTldzDtTA61wIDAQABo2MwYTAOBgNV
-HQ8BAf8EBAMCAAYwHQYDVR0OBBYEFMw2zBe0RZEv7c87MEh3+7UUmb7jMB8GA1Ud
-IwQYMBaAFGB7ZhpFDZfKiVAvfQTNNKj//P1LMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQEEBQADggEBAFeyVMy9lRdkYIm2U5EMRZLDPahsw8yyGPV4QXTYfaMn
-r3cNWT6UHWn6idMMvRoB9D/o4Hcagiha5mLXt+M2yQ6feuPC08xZiQzvFovwNnci
-yqS2t8FCZwFAY8znOGSHWxSWZnstFO69SW3/d9DiTlvTgMJND8q4nYGXpzRux+Oc
-SOW0qkX19mVMSPISwtKTjMIVJPMrUv/jCK64btYsEs85yxIq56l7X5g9o+HMpmOJ
-XH0xdfnV1l3y0NQ9355xqA7c5CCXeOZ/U6QNUU+OOwOuow1aTcN55zVYcELJXqFe
-tNkio0RTNaTQz3OAxc+fVph2+RRMd4eCydx+XTTVNnU=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number:
- 02:00:00:00:00:00:d6:78:b8:d6:c3
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
- Validity
- Not Before: Jan 28 12:00:00 1999 GMT
- Not After : Jan 28 12:00:00 2009 GMT
- Subject: C=BE, O=GlobalSign nv-sa, OU=Primary Class 3 CA, CN=GlobalSign Primary Class 3 CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:91:5e:56:65:d6:c0:c0:04:9c:bf:47:c4:5c:7b:
- 7a:31:01:f9:58:96:99:e3:1c:84:2f:dc:56:8f:ad:
- f5:59:81:d5:43:66:5d:5a:93:8c:75:ca:a9:e7:11:
- c1:51:10:14:60:c9:2c:d4:7b:af:c6:77:86:ab:7a:
- 27:ae:6f:95:b9:0b:ca:b6:46:fb:7e:1a:f4:0d:14:
- 6d:d2:c9:4e:b2:ae:f0:54:f6:5c:40:4c:36:48:74:
- e8:54:8c:65:66:10:a7:bd:2b:b7:20:8d:05:49:ad:
- 78:7d:d2:24:23:50:e3:f0:b4:79:9b:01:39:ff:af:
- 3b:d3:2d:ee:e1:49:8d:8d:2f:3c:6a:41:45:2f:9b:
- e3:3d:e1:12:e4:91:75:9e:cf:a0:3e:3c:92:81:6f:
- 8a:2e:18:dc:e0:f2:8c:8c:fd:87:d9:07:f4:40:94:
- c9:4e:4f:43:df:67:56:6f:bd:03:50:7c:99:67:a4:
- b9:3c:91:6c:02:6e:84:d6:fc:46:f7:cc:6f:18:3e:
- 17:f0:ef:0b:64:16:57:e6:ac:86:f1:48:aa:43:c1:
- c9:27:78:73:44:45:e2:85:7d:ba:ff:b3:e1:fb:1b:
- 05:a4:4b:3b:99:12:25:01:50:14:6a:af:5d:ea:c8:
- 0c:ee:e4:da:ec:4b:8b:5c:68:13:95:dc:c3:b5:30:
- 3a:d7
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Subject Key Identifier:
- CC:36:CC:17:B4:45:91:2F:ED:CF:3B:30:48:77:FB:B5:14:99:BE:E3
- X509v3 Authority Key Identifier:
- keyid:60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
-
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- 57:b2:54:cc:bd:95:17:64:60:89:b6:53:91:0c:45:92:c3:3d:
- a8:6c:c3:cc:b2:18:f5:78:41:74:d8:7d:a3:27:af:77:0d:59:
- 3e:94:1d:69:fa:89:d3:0c:bd:1a:01:f4:3f:e8:e0:77:1a:82:
- 28:5a:e6:62:d7:b7:e3:36:c9:0e:9f:7a:e3:c2:d3:cc:59:89:
- 0c:ef:16:8b:f0:36:77:22:ca:a4:b6:b7:c1:42:67:01:40:63:
- cc:e7:38:64:87:5b:14:96:66:7b:2d:14:ee:bd:49:6d:ff:77:
- d0:e2:4e:5b:d3:80:c2:4d:0f:ca:b8:9d:81:97:a7:34:6e:c7:
- e3:9c:48:e5:b4:aa:45:f5:f6:65:4c:48:f2:12:c2:d2:93:8c:
- c2:15:24:f3:2b:52:ff:e3:08:ae:b8:6e:d6:2c:12:cf:39:cb:
- 12:2a:e7:a9:7b:5f:98:3d:a3:e1:cc:a6:63:89:5c:7d:31:75:
- f9:d5:d6:5d:f2:d0:d4:3d:df:9e:71:a8:0e:dc:e4:20:97:78:
- e6:7f:53:a4:0d:51:4f:8e:3b:03:ae:a3:0d:5a:4d:c3:79:e7:
- 35:58:70:42:c9:5e:a1:5e:b4:d9:22:a3:44:53:35:a4:d0:cf:
- 73:80:c5:cf:9f:56:98:76:f9:14:4c:77:87:82:c9:dc:7e:5d:
- 34:d5:36:75
-
-GlobalSign Root CA
-==================
-MD5 Fingerprint: AB:BF:EA:E3:6B:29:A6:CC:A6:78:35:99:EF:AD:2B:80
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDdTCCAl2gAwIBAgILAgAAAAAA1ni3lAUwDQYJKoZIhvcNAQEEBQAwVzELMAkG
-A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
-b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
-MDBaFw0xNDAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
-YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
-aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
-jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
-xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
-1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
-snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
-U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
-9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIABjAdBgNVHQ4EFgQU
-YHtmGkUNl8qJUC99BM00qP/8/UswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B
-AQQFAAOCAQEArqqf/LfSyx9fOSkoGJ40yWxPbxrwZKJwSk8ThptgKJ7ogUmYfQq7
-5bCdPTbbjwVR/wkxKh/diXeeDy5slQTthsu0AD+EAk2AaioteAuubyuig0SDH81Q
-gkwkr733pbTIWg/050deSY43lv6aiAU62cDbKYfmGZZHpzqmjIs8d/5GY6dT2iHR
-rH5Jokvmw2dZL7OKDrssvamqQnw1wdh/1acxOk5jQzmvCLBhNIzTmKlDNPYPhyk7
-ncJWWJh3w/cbrPad+D6qp1RF8PX51TFl/mtYnHGzHtdS6jIX/EBgHcl5JLL2bP2o
-Zg6C3ZjL2sJETy6ge/L3ayx2EYRGinij4w==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number:
- 02:00:00:00:00:00:d6:78:b7:94:05
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
- Validity
- Not Before: Sep 1 12:00:00 1998 GMT
- Not After : Jan 28 12:00:00 2014 GMT
- Subject: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:da:0e:e6:99:8d:ce:a3:e3:4f:8a:7e:fb:f1:8b:
- 83:25:6b:ea:48:1f:f1:2a:b0:b9:95:11:04:bd:f0:
- 63:d1:e2:67:66:cf:1c:dd:cf:1b:48:2b:ee:8d:89:
- 8e:9a:af:29:80:65:ab:e9:c7:2d:12:cb:ab:1c:4c:
- 70:07:a1:3d:0a:30:cd:15:8d:4f:f8:dd:d4:8c:50:
- 15:1c:ef:50:ee:c4:2e:f7:fc:e9:52:f2:91:7d:e0:
- 6d:d5:35:30:8e:5e:43:73:f2:41:e9:d5:6a:e3:b2:
- 89:3a:56:39:38:6f:06:3c:88:69:5b:2a:4d:c5:a7:
- 54:b8:6c:89:cc:9b:f9:3c:ca:e5:fd:89:f5:12:3c:
- 92:78:96:d6:dc:74:6e:93:44:61:d1:8d:c7:46:b2:
- 75:0e:86:e8:19:8a:d5:6d:6c:d5:78:16:95:a2:e9:
- c8:0a:38:eb:f2:24:13:4f:73:54:93:13:85:3a:1b:
- bc:1e:34:b5:8b:05:8c:b9:77:8b:b1:db:1f:20:91:
- ab:09:53:6e:90:ce:7b:37:74:b9:70:47:91:22:51:
- 63:16:79:ae:b1:ae:41:26:08:c8:19:2b:d1:46:aa:
- 48:d6:64:2a:d7:83:34:ff:2c:2a:c1:6c:19:43:4a:
- 07:85:e7:d3:7c:f6:21:68:ef:ea:f2:52:9f:7f:93:
- 90:cf
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Key Usage: critical
- Certificate Sign, CRL Sign
- X509v3 Subject Key Identifier:
- 60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- ae:aa:9f:fc:b7:d2:cb:1f:5f:39:29:28:18:9e:34:c9:6c:4f:
- 6f:1a:f0:64:a2:70:4a:4f:13:86:9b:60:28:9e:e8:81:49:98:
- 7d:0a:bb:e5:b0:9d:3d:36:db:8f:05:51:ff:09:31:2a:1f:dd:
- 89:77:9e:0f:2e:6c:95:04:ed:86:cb:b4:00:3f:84:02:4d:80:
- 6a:2a:2d:78:0b:ae:6f:2b:a2:83:44:83:1f:cd:50:82:4c:24:
- af:bd:f7:a5:b4:c8:5a:0f:f4:e7:47:5e:49:8e:37:96:fe:9a:
- 88:05:3a:d9:c0:db:29:87:e6:19:96:47:a7:3a:a6:8c:8b:3c:
- 77:fe:46:63:a7:53:da:21:d1:ac:7e:49:a2:4b:e6:c3:67:59:
- 2f:b3:8a:0e:bb:2c:bd:a9:aa:42:7c:35:c1:d8:7f:d5:a7:31:
- 3a:4e:63:43:39:af:08:b0:61:34:8c:d3:98:a9:43:34:f6:0f:
- 87:29:3b:9d:c2:56:58:98:77:c3:f7:1b:ac:f6:9d:f8:3e:aa:
- a7:54:45:f0:f5:f9:d5:31:65:fe:6b:58:9c:71:b3:1e:d7:52:
- ea:32:17:fc:40:60:1d:c9:79:24:b2:f6:6c:fd:a8:66:0e:82:
- dd:98:cb:da:c2:44:4f:2e:a0:7b:f2:f7:6b:2c:76:11:84:46:
- 8a:78:a3:e3
-
-National Retail Federation by DST
-=================================
-MD5 Fingerprint: AD:8E:0F:9E:01:6B:A0:C5:74:D5:0C:D3:68:65:4F:1E
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIEAjCCAuoCEQDQHkCKAAACfAAAAAMAAAABMA0GCSqGSIb3DQEBBQUAMIG+MQsw
-CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp
-dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEjMCEGA1UE
-CxMaTmF0aW9uYWwgUmV0YWlsIEZlZGVyYXRpb24xGTAXBgNVBAMTEERTVCAoTlJG
-KSBSb290Q0ExITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05
-ODEyMTExNjE0MTZaFw0wODEyMDgxNjE0MTZaMIG+MQswCQYDVQQGEwJ1czENMAsG
-A1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0Rp
-Z2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEjMCEGA1UECxMaTmF0aW9uYWwgUmV0
-YWlsIEZlZGVyYXRpb24xGTAXBgNVBAMTEERTVCAoTlJGKSBSb290Q0ExITAfBgkq
-hkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBANmsm3f6UNPM3LlArLlyagCHI/wPliHQJq/k4rVf+tOmfSEw
-LswXgo+YdPxnpKbfiJeiQin1p9sRk/teIzDCqrwi50Eb5e0l3sg/295XRXhARoOy
-1Ro93w9FbdVjAnXYL8Zuq5WRdDcNy00JXNHUWzra3Q7Ia5nY1TnM34VVxJJTAqPh
-94DJcKPa3DPEf6JHCBw1lh+hAxwwg/TEzP+Yw7BGRKLAv63b0oH2TJgsp14k84bK
-Y9W6ffCawErQG1ju7Klnz2kCbCLAYCws0cgg6sgt+92cu8tRTNznVwQ7VJsRpTJ0
-7HQB85AVWy98LJNluWZntIGINeWekRh/gahByMsCAwEAATANBgkqhkiG9w0BAQUF
-AAOCAQEAhF4LO+ygjRyb0DwdcWnkGn9kvoFlYcWMatd8AHTgemJV7SR84GHj8t0U
-5hFugw7h6qmegK2aIL/gV37V0LWEYy3ZGOS9GzUsXq5hdqpnhTs44TGBHzF/5tf4
-W9K7Y3mGxIzF3gqu19H8AXT/trYNYoFnHLsm+CSA4Fxe2KSKOo99y/+So/18qTJp
-B1hYYUKZUgOxOD3GcW9s8uh9BqrBfFPLGi2IT8mpp6xpb/ekH9h0gfVKv7FVt9N3
-OKdvwkrI4nOJ01dy4UMvcjz2H7f4BEpuwemUF+SXF/QOE4ZvjavoXy20/2zWorQf
-7LmUaqoSTxrd9Xe1JYzyigrx/FJbWA==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- d0:1e:40:8a:00:00:02:7c:00:00:00:03:00:00:00:01
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=National Retail Federation, CN=DST (NRF) RootCA/Email=caNOSPAMdigsigtrust.com
- Validity
- Not Before: Dec 11 16:14:16 1998 GMT
- Not After : Dec 8 16:14:16 2008 GMT
- Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=National Retail Federation, CN=DST (NRF) RootCA/Email=caNOSPAMdigsigtrust.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:d9:ac:9b:77:fa:50:d3:cc:dc:b9:40:ac:b9:72:
- 6a:00:87:23:fc:0f:96:21:d0:26:af:e4:e2:b5:5f:
- fa:d3:a6:7d:21:30:2e:cc:17:82:8f:98:74:fc:67:
- a4:a6:df:88:97:a2:42:29:f5:a7:db:11:93:fb:5e:
- 23:30:c2:aa:bc:22:e7:41:1b:e5:ed:25:de:c8:3f:
- db:de:57:45:78:40:46:83:b2:d5:1a:3d:df:0f:45:
- 6d:d5:63:02:75:d8:2f:c6:6e:ab:95:91:74:37:0d:
- cb:4d:09:5c:d1:d4:5b:3a:da:dd:0e:c8:6b:99:d8:
- d5:39:cc:df:85:55:c4:92:53:02:a3:e1:f7:80:c9:
- 70:a3:da:dc:33:c4:7f:a2:47:08:1c:35:96:1f:a1:
- 03:1c:30:83:f4:c4:cc:ff:98:c3:b0:46:44:a2:c0:
- bf:ad:db:d2:81:f6:4c:98:2c:a7:5e:24:f3:86:ca:
- 63:d5:ba:7d:f0:9a:c0:4a:d0:1b:58:ee:ec:a9:67:
- cf:69:02:6c:22:c0:60:2c:2c:d1:c8:20:ea:c8:2d:
- fb:dd:9c:bb:cb:51:4c:dc:e7:57:04:3b:54:9b:11:
- a5:32:74:ec:74:01:f3:90:15:5b:2f:7c:2c:93:65:
- b9:66:67:b4:81:88:35:e5:9e:91:18:7f:81:a8:41:
- c8:cb
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 84:5e:0b:3b:ec:a0:8d:1c:9b:d0:3c:1d:71:69:e4:1a:7f:64:
- be:81:65:61:c5:8c:6a:d7:7c:00:74:e0:7a:62:55:ed:24:7c:
- e0:61:e3:f2:dd:14:e6:11:6e:83:0e:e1:ea:a9:9e:80:ad:9a:
- 20:bf:e0:57:7e:d5:d0:b5:84:63:2d:d9:18:e4:bd:1b:35:2c:
- 5e:ae:61:76:aa:67:85:3b:38:e1:31:81:1f:31:7f:e6:d7:f8:
- 5b:d2:bb:63:79:86:c4:8c:c5:de:0a:ae:d7:d1:fc:01:74:ff:
- b6:b6:0d:62:81:67:1c:bb:26:f8:24:80:e0:5c:5e:d8:a4:8a:
- 3a:8f:7d:cb:ff:92:a3:fd:7c:a9:32:69:07:58:58:61:42:99:
- 52:03:b1:38:3d:c6:71:6f:6c:f2:e8:7d:06:aa:c1:7c:53:cb:
- 1a:2d:88:4f:c9:a9:a7:ac:69:6f:f7:a4:1f:d8:74:81:f5:4a:
- bf:b1:55:b7:d3:77:38:a7:6f:c2:4a:c8:e2:73:89:d3:57:72:
- e1:43:2f:72:3c:f6:1f:b7:f8:04:4a:6e:c1:e9:94:17:e4:97:
- 17:f4:0e:13:86:6f:8d:ab:e8:5f:2d:b4:ff:6c:d6:a2:b4:1f:
- ec:b9:94:6a:aa:12:4f:1a:dd:f5:77:b5:25:8c:f2:8a:0a:f1:
- fc:52:5b:58
-
-TC TrustCenter, Germany, Class 1 CA
-===================================
-MD5 Fingerprint: 64:3F:F8:3E:52:14:4A:59:BA:93:56:04:0B:23:02:D1
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIENTCCA56gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx
-EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD
-IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx
-IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDEgQ0ExKTAnBgkqhkiG9w0B
-CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTYzM1oX
-DTA1MTIzMTEzNTYzM1owgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn
-MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig
-U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz
-dENlbnRlciBDbGFzcyAxIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0
-cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsCnrtHaz
-rte2W7Re573jsZxJBFdboavZfxMb/bphq9jncd8tAJRdUUh9I+91YoSQPAofWRF0
-L46Apf0wAj0pUs1yGkkhnLzLUo5IoWOWyBCFMGlXdEXAWobG1T3gaFd9MWokjUWX
-PjF+aGYybiRt7DI2yUHK8DFEyKNhyhugNh8CAwEAAaOCAUMwggE/MEAGCWCGSAGG
-+EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr
-LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl
-ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw
-czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI
-AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p
-bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAx
-IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQAFQlImpAwn
-AUSsXCUowkRCVAi5HcU+bFlmxLNOUKf4+JZ1oZZ16BY4oM1dbvp5pxt7HR7DALlm
-vlrWYg/n8nu470zgwD9Zrjm3hAmeq/GpLmtp4q3M8up4CQUgOEJxGH7Hspfm1QIF
-BlajX/GqwsRP/vfvFg+d7KqFzz0pJPEEzQ==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 2 (0x2)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 1 CA/Email=certificateNOSPAMtrustcenter.de
- Validity
- Not Before: Mar 9 13:56:33 1998 GMT
- Not After : Dec 31 13:56:33 2005 GMT
- Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 1 CA/Email=certificate@trustcenter.de
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:b0:29:eb:b4:76:b3:ae:d7:b6:5b:b4:5e:e7:bd:
- e3:b1:9c:49:04:57:5b:a1:ab:d9:7f:13:1b:fd:ba:
- 61:ab:d8:e7:71:df:2d:00:94:5d:51:48:7d:23:ef:
- 75:62:84:90:3c:0a:1f:59:11:74:2f:8e:80:a5:fd:
- 30:02:3d:29:52:cd:72:1a:49:21:9c:bc:cb:52:8e:
- 48:a1:63:96:c8:10:85:30:69:57:74:45:c0:5a:86:
- c6:d5:3d:e0:68:57:7d:31:6a:24:8d:45:97:3e:31:
- 7e:68:66:32:6e:24:6d:ec:32:36:c9:41:ca:f0:31:
- 44:c8:a3:61:ca:1b:a0:36:1f
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- Netscape Revocation Url:
- https://www.trustcenter.de/cgi-bin/check-rev.cgi?
- Netscape CA Revocation Url:
- https://www.trustcenter.de/cgi-bin/check-rev.cgi?
- Netscape Renewal Url:
- https://www.trustcenter.de/cgi-bin/Renew.cgi?
- Netscape CA Policy Url:
- http://www.trustcenter.de/guidelines/index.html
- Netscape Comment:
- TC TrustCenter Class 1 CA
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- Signature Algorithm: md5WithRSAEncryption
- 05:42:52:26:a4:0c:27:01:44:ac:5c:25:28:c2:44:42:54:08:
- b9:1d:c5:3e:6c:59:66:c4:b3:4e:50:a7:f8:f8:96:75:a1:96:
- 75:e8:16:38:a0:cd:5d:6e:fa:79:a7:1b:7b:1d:1e:c3:00:b9:
- 66:be:5a:d6:62:0f:e7:f2:7b:b8:ef:4c:e0:c0:3f:59:ae:39:
- b7:84:09:9e:ab:f1:a9:2e:6b:69:e2:ad:cc:f2:ea:78:09:05:
- 20:38:42:71:18:7e:c7:b2:97:e6:d5:02:05:06:56:a3:5f:f1:
- aa:c2:c4:4f:fe:f7:ef:16:0f:9d:ec:aa:85:cf:3d:29:24:f1:
- 04:cd
-
-TC TrustCenter, Germany, Class 2 CA
-===================================
-MD5 Fingerprint: E1:E9:96:53:77:E1:F0:38:A0:02:AB:94:C6:95:7B:FC
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIENTCCA56gAwIBAgIBAzANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx
-EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD
-IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx
-IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExKTAnBgkqhkiG9w0B
-CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTc0NFoX
-DTA1MTIzMTEzNTc0NFowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn
-MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig
-U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz
-dENlbnRlciBDbGFzcyAyIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0
-cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2jjo7TIA
-KXGDAQ2/jAHc2satOaSpii/Vi1xoX1DGYvVmvcqRIuyqHVHXPbNRsoNOXctJsPBM
-VeVrLceFCzAckk6C1MoC7fdvvtzg4xS4BVPymvRWi1qehZPRtIJWrk27qEtXFrz+
-+Fie+CmNsHvNeMlPrItnDPGc+/xXm1dcTw0CAwEAAaOCAUMwggE/MEAGCWCGSAGG
-+EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr
-LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl
-ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw
-czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI
-AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p
-bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAy
-IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCJG/Tv6Tji
-bAz2zW9JzinM+6YP+Y0+lUbW/EcyibLIBmF60ucNEwKUC9mLVkf0u+fFX3v0Y0yu
-fDTqDaKpsyyF8+P+J1QQkrCPksGYQhhwSNtOLOsNJGjk0fe+Cakph7vo2tw+o4hC
-MfXR43+u2I4AWnSYsE/G/yN7XHMAeMnbTg==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 3 (0x3)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 2 CA/Email=certificateNOSPAMtrustcenter.de
- Validity
- Not Before: Mar 9 13:57:44 1998 GMT
- Not After : Dec 31 13:57:44 2005 GMT
- Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 2 CA/Email=certificateNOSPAMtrustcenter.de
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:da:38:e8:ed:32:00:29:71:83:01:0d:bf:8c:01:
- dc:da:c6:ad:39:a4:a9:8a:2f:d5:8b:5c:68:5f:50:
- c6:62:f5:66:bd:ca:91:22:ec:aa:1d:51:d7:3d:b3:
- 51:b2:83:4e:5d:cb:49:b0:f0:4c:55:e5:6b:2d:c7:
- 85:0b:30:1c:92:4e:82:d4:ca:02:ed:f7:6f:be:dc:
- e0:e3:14:b8:05:53:f2:9a:f4:56:8b:5a:9e:85:93:
- d1:b4:82:56:ae:4d:bb:a8:4b:57:16:bc:fe:f8:58:
- 9e:f8:29:8d:b0:7b:cd:78:c9:4f:ac:8b:67:0c:f1:
- 9c:fb:fc:57:9b:57:5c:4f:0d
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- Netscape Revocation Url:
- https://www.trustcenter.de/cgi-bin/check-rev.cgi?
- Netscape CA Revocation Url:
- https://www.trustcenter.de/cgi-bin/check-rev.cgi?
- Netscape Renewal Url:
- https://www.trustcenter.de/cgi-bin/Renew.cgi?
- Netscape CA Policy Url:
- http://www.trustcenter.de/guidelines/index.html
- Netscape Comment:
- TC TrustCenter Class 2 CA
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- Signature Algorithm: md5WithRSAEncryption
- 89:1b:f4:ef:e9:38:e2:6c:0c:f6:cd:6f:49:ce:29:cc:fb:a6:
- 0f:f9:8d:3e:95:46:d6:fc:47:32:89:b2:c8:06:61:7a:d2:e7:
- 0d:13:02:94:0b:d9:8b:56:47:f4:bb:e7:c5:5f:7b:f4:63:4c:
- ae:7c:34:ea:0d:a2:a9:b3:2c:85:f3:e3:fe:27:54:10:92:b0:
- 8f:92:c1:98:42:18:70:48:db:4e:2c:eb:0d:24:68:e4:d1:f7:
- be:09:a9:29:87:bb:e8:da:dc:3e:a3:88:42:31:f5:d1:e3:7f:
- ae:d8:8e:00:5a:74:98:b0:4f:c6:ff:23:7b:5c:73:00:78:c9:
- db:4e
-
-TC TrustCenter, Germany, Class 3 CA
-===================================
-MD5 Fingerprint: 62:AB:B6:15:4A:B4:B0:16:77:FF:AE:CF:16:16:2B:8C
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIENTCCA56gAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx
-EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD
-IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx
-IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExKTAnBgkqhkiG9w0B
-CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTEzNTg0OVoX
-DTA1MTIzMTEzNTg0OVowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn
-MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig
-U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz
-dENlbnRlciBDbGFzcyAzIENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0
-cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtrTBNQUu
-DY3soEBqHA4nplCSa1AbB94u53bM4Nr8hKhejGNqK03ZTgJ2EcEL8o15ygC28bAO
-1/ukFz2vq2l6lie/rzOhmipZqsS1NwjyEqUxtkP1MpZxKCirjSiG37vu4wx9MNbD
-UquPXSeca8Cj5wVrV0lEs27qZM/SjnpQd3cCAwEAAaOCAUMwggE/MEAGCWCGSAGG
-+EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr
-LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl
-ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw
-czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI
-AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p
-bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyAz
-IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCEhlBieaAn
-4SW6CbE0DxMJ7S3Ko+aV+TCszRelzj2Xnex8jyZ/wGHKIveR3Tw2WZqbdfe85Mjt
-7AK2IqfzLPHIknhttu7FKOyAIE+5awjnL6eGHn2xCJ9UuQA3PKDYGsiWHPQyFJw5
-lbfu8ENJwl7oy3lvU7/7SYos2EvZVfIScA==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 4 (0x4)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 3 CA/Email=certificateNOSPAMtrustcenter.de
- Validity
- Not Before: Mar 9 13:58:49 1998 GMT
- Not After : Dec 31 13:58:49 2005 GMT
- Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 3 CA/Email=certificateNOSPAMtrustcenter.de
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:b6:b4:c1:35:05:2e:0d:8d:ec:a0:40:6a:1c:0e:
- 27:a6:50:92:6b:50:1b:07:de:2e:e7:76:cc:e0:da:
- fc:84:a8:5e:8c:63:6a:2b:4d:d9:4e:02:76:11:c1:
- 0b:f2:8d:79:ca:00:b6:f1:b0:0e:d7:fb:a4:17:3d:
- af:ab:69:7a:96:27:bf:af:33:a1:9a:2a:59:aa:c4:
- b5:37:08:f2:12:a5:31:b6:43:f5:32:96:71:28:28:
- ab:8d:28:86:df:bb:ee:e3:0c:7d:30:d6:c3:52:ab:
- 8f:5d:27:9c:6b:c0:a3:e7:05:6b:57:49:44:b3:6e:
- ea:64:cf:d2:8e:7a:50:77:77
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- Netscape Revocation Url:
- https://www.trustcenter.de/cgi-bin/check-rev.cgi?
- Netscape CA Revocation Url:
- https://www.trustcenter.de/cgi-bin/check-rev.cgi?
- Netscape Renewal Url:
- https://www.trustcenter.de/cgi-bin/Renew.cgi?
- Netscape CA Policy Url:
- http://www.trustcenter.de/guidelines/index.html
- Netscape Comment:
- TC TrustCenter Class 3 CA
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- Signature Algorithm: md5WithRSAEncryption
- 84:86:50:62:79:a0:27:e1:25:ba:09:b1:34:0f:13:09:ed:2d:
- ca:a3:e6:95:f9:30:ac:cd:17:a5:ce:3d:97:9d:ec:7c:8f:26:
- 7f:c0:61:ca:22:f7:91:dd:3c:36:59:9a:9b:75:f7:bc:e4:c8:
- ed:ec:02:b6:22:a7:f3:2c:f1:c8:92:78:6d:b6:ee:c5:28:ec:
- 80:20:4f:b9:6b:08:e7:2f:a7:86:1e:7d:b1:08:9f:54:b9:00:
- 37:3c:a0:d8:1a:c8:96:1c:f4:32:14:9c:39:95:b7:ee:f0:43:
- 49:c2:5e:e8:cb:79:6f:53:bf:fb:49:8a:2c:d8:4b:d9:55:f2:
- 12:70
-
-TC TrustCenter, Germany, Class 4 CA
-===================================
-MD5 Fingerprint: BF:AF:EC:C4:DA:F9:30:F9:CA:35:CA:25:E4:3F:8D:89
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIENTCCA56gAwIBAgIBBTANBgkqhkiG9w0BAQQFADCBvDELMAkGA1UEBhMCREUx
-EDAOBgNVBAgTB0hhbWJ1cmcxEDAOBgNVBAcTB0hhbWJ1cmcxOjA4BgNVBAoTMVRD
-IFRydXN0Q2VudGVyIGZvciBTZWN1cml0eSBpbiBEYXRhIE5ldHdvcmtzIEdtYkgx
-IjAgBgNVBAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDQgQ0ExKTAnBgkqhkiG9w0B
-CQEWGmNlcnRpZmljYXRlQHRydXN0Y2VudGVyLmRlMB4XDTk4MDMwOTE0MDAyMFoX
-DTA1MTIzMTE0MDAyMFowgbwxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1idXJn
-MRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFUQyBUcnVzdENlbnRlciBmb3Ig
-U2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJIMSIwIAYDVQQLExlUQyBUcnVz
-dENlbnRlciBDbGFzcyA0IENBMSkwJwYJKoZIhvcNAQkBFhpjZXJ0aWZpY2F0ZUB0
-cnVzdGNlbnRlci5kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvy9j1jZ7
-sg3TVfVkbOYlXca0yBS6JTiD61ZipVWpZaP0I5nCS7nQzVRnpqOgo6kzK3bkva13
-su1cEnTDxbYPUppyk0OQYmYVD0Wl3eDduG9AblfBeXKjYKq6dh0SiVNa/AK+4QkT
-xUov3D2LGa3XiyRF+0z0zVw1HSlMUfPybFUCAwEAAaOCAUMwggE/MEAGCWCGSAGG
-+EIBAwQzFjFodHRwczovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL2NoZWNr
-LXJldi5jZ2k/MEAGCWCGSAGG+EIBBAQzFjFodHRwczovL3d3dy50cnVzdGNlbnRl
-ci5kZS9jZ2ktYmluL2NoZWNrLXJldi5jZ2k/MDwGCWCGSAGG+EIBBwQvFi1odHRw
-czovL3d3dy50cnVzdGNlbnRlci5kZS9jZ2ktYmluL1JlbmV3LmNnaT8wPgYJYIZI
-AYb4QgEIBDEWL2h0dHA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvZ3VpZGVsaW5lcy9p
-bmRleC5odG1sMCgGCWCGSAGG+EIBDQQbFhlUQyBUcnVzdENlbnRlciBDbGFzcyA0
-IENBMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQQFAAOBgQCUaBQbJZ4p
-mbGyI9JEs5Wf0Z5VBN3jL4IzVZZ3GZ0rnmUc+orjx48l/LEeVUYPj/9PNy+kdlmm
-ZOvVFnC93ZUzDKQNJOtkULRDEfJDvg1xmCLsAa/s98dcccN1kVgZ6N2g9LTxvBBK
-85O0Bkm7H2bSvXRH4Zr569erbR+64R0s2g==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 5 (0x5)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 4 CA/Email=certificateNOSPAMtrustcenter.de
- Validity
- Not Before: Mar 9 14:00:20 1998 GMT
- Not After : Dec 31 14:00:20 2005 GMT
- Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 4 CA/Email=certificateNOSPAMtrustcenter.de
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:bf:2f:63:d6:36:7b:b2:0d:d3:55:f5:64:6c:e6:
- 25:5d:c6:b4:c8:14:ba:25:38:83:eb:56:62:a5:55:
- a9:65:a3:f4:23:99:c2:4b:b9:d0:cd:54:67:a6:a3:
- a0:a3:a9:33:2b:76:e4:bd:ad:77:b2:ed:5c:12:74:
- c3:c5:b6:0f:52:9a:72:93:43:90:62:66:15:0f:45:
- a5:dd:e0:dd:b8:6f:40:6e:57:c1:79:72:a3:60:aa:
- ba:76:1d:12:89:53:5a:fc:02:be:e1:09:13:c5:4a:
- 2f:dc:3d:8b:19:ad:d7:8b:24:45:fb:4c:f4:cd:5c:
- 35:1d:29:4c:51:f3:f2:6c:55
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- Netscape Revocation Url:
- https://www.trustcenter.de/cgi-bin/check-rev.cgi?
- Netscape CA Revocation Url:
- https://www.trustcenter.de/cgi-bin/check-rev.cgi?
- Netscape Renewal Url:
- https://www.trustcenter.de/cgi-bin/Renew.cgi?
- Netscape CA Policy Url:
- http://www.trustcenter.de/guidelines/index.html
- Netscape Comment:
- TC TrustCenter Class 4 CA
- Netscape Cert Type:
- SSL CA, S/MIME CA, Object Signing CA
- Signature Algorithm: md5WithRSAEncryption
- 94:68:14:1b:25:9e:29:99:b1:b2:23:d2:44:b3:95:9f:d1:9e:
- 55:04:dd:e3:2f:82:33:55:96:77:19:9d:2b:9e:65:1c:fa:8a:
- e3:c7:8f:25:fc:b1:1e:55:46:0f:8f:ff:4f:37:2f:a4:76:59:
- a6:64:eb:d5:16:70:bd:dd:95:33:0c:a4:0d:24:eb:64:50:b4:
- 43:11:f2:43:be:0d:71:98:22:ec:01:af:ec:f7:c7:5c:71:c3:
- 75:91:58:19:e8:dd:a0:f4:b4:f1:bc:10:4a:f3:93:b4:06:49:
- bb:1f:66:d2:bd:74:47:e1:9a:f9:eb:d7:ab:6d:1f:ba:e1:1d:
- 2c:da
-
-Thawte Personal Basic CA
-========================
-MD5 Fingerprint: E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD
-VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT
-ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj
-IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X
-DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw
-EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE
-ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy
-dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD
-QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53
-dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK
-wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7
-G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF
-AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7
-c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P
-9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 0 (0x0)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Basic CA/Email=personal-basicNOSPAMthawte.com
- Validity
- Not Before: Jan 1 00:00:00 1996 GMT
- Not After : Dec 31 23:59:59 2020 GMT
- Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Basic CA/Email=personal-basicNOSPAMthawte.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:bc:bc:93:53:6d:c0:50:4f:82:15:e6:48:94:35:
- a6:5a:be:6f:42:fa:0f:47:ee:77:75:72:dd:8d:49:
- 9b:96:57:a0:78:d4:ca:3f:51:b3:69:0b:91:76:17:
- 22:07:97:6a:c4:51:93:4b:e0:8d:ef:37:95:a1:0c:
- 4d:da:34:90:1d:17:89:97:e0:35:38:57:4a:c0:f4:
- 08:70:e9:3c:44:7b:50:7e:61:9a:90:e3:23:d3:88:
- 11:46:27:f5:0b:07:0e:bb:dd:d1:7f:20:0a:88:b9:
- 56:0b:2e:1c:80:da:f1:e3:9e:29:ef:14:bd:0a:44:
- fb:1b:5b:18:d1:bf:23:93:21
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- 2d:e2:99:6b:b0:3d:7a:89:d7:59:a2:94:01:1f:2b:dd:12:4b:
- 53:c2:ad:7f:aa:a7:00:5c:91:40:57:25:4a:38:aa:84:70:b9:
- d9:80:0f:a5:7b:5c:fb:73:c6:bd:d7:8a:61:5c:03:e3:2d:27:
- a8:17:e0:84:85:42:dc:5e:9b:c6:b7:b2:6d:bb:74:af:e4:3f:
- cb:a7:b7:b0:e0:5d:be:78:83:25:94:d2:db:81:0f:79:07:6d:
- 4f:f4:39:15:5a:52:01:7b:de:32:d6:4d:38:f6:12:5c:06:50:
- df:05:5b:bd:14:4b:a1:df:29:ba:3b:41:8d:f7:63:56:a1:df:
- 22:b1
-
-Thawte Personal Freemail CA
-===========================
-MD5 Fingerprint: 1E:74:C3:86:3C:0C:35:C5:3E:C2:7F:EF:3C:AA:3C:D9
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD
-VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT
-ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt
-YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu
-Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT
-AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa
-MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp
-b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG
-cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh
-d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY
-DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E
-rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq
-uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP
-MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa
-/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei
-gQ==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 0 (0x0)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Freemail CA/Email=personal-freemailNOSPAMthawte.com
- Validity
- Not Before: Jan 1 00:00:00 1996 GMT
- Not After : Dec 31 23:59:59 2020 GMT
- Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Freemail CA/Email=personal-freemailNOSPAMthawte.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:d4:69:d7:d4:b0:94:64:5b:71:e9:47:d8:0c:51:
- b6:ea:72:91:b0:84:5e:7d:2d:0d:8f:7b:12:df:85:
- 25:75:28:74:3a:42:2c:63:27:9f:95:7b:4b:ef:7e:
- 19:87:1d:86:ea:a3:dd:b9:ce:96:64:1a:c2:14:6e:
- 44:ac:7c:e6:8f:e8:4d:0f:71:1f:40:38:a6:00:a3:
- 87:78:f6:f9:94:86:5e:ad:ea:c0:5e:76:eb:d9:14:
- a3:5d:6e:7a:7c:0c:a5:4b:55:7f:06:19:29:7f:9e:
- 9a:26:d5:6a:bb:38:24:08:6a:98:c7:b1:da:a3:98:
- 91:fd:79:db:e5:5a:c4:1c:b9
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- c7:ec:92:7e:4e:f8:f5:96:a5:67:62:2a:a4:f0:4d:11:60:d0:
- 6f:8d:60:58:61:ac:26:bb:52:35:5c:08:cf:30:fb:a8:4a:96:
- 8a:1f:62:42:23:8c:17:0f:f4:ba:64:9c:17:ac:47:29:df:9d:
- 98:5e:d2:6c:60:71:5c:a2:ac:dc:79:e3:e7:6e:00:47:1f:b5:
- 0d:28:e8:02:9d:e4:9a:fd:13:f4:a6:d9:7c:b1:f8:dc:5f:23:
- 26:09:91:80:73:d0:14:1b:de:43:a9:83:25:f2:e6:9c:2f:15:
- ca:fe:a6:ab:8a:07:75:8b:0c:dd:51:84:6b:e4:f8:d1:ce:77:
- a2:81
-
-Thawte Personal Premium CA
-==========================
-MD5 Fingerprint: 3A:B2:DE:22:9A:20:93:49:F9:ED:C8:D2:8A:E7:68:0D
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD
-VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT
-ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p
-dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv
-bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa
-QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY
-BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u
-IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl
-bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu
-Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs
-Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI
-Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD
-ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
-SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH
-b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh
-KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 0 (0x0)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA/Email=personal-premiumNOSPAMthawte.com
- Validity
- Not Before: Jan 1 00:00:00 1996 GMT
- Not After : Dec 31 23:59:59 2020 GMT
- Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA/Email=personal-premiumNOSPAMthawte.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:c9:66:d9:f8:07:44:cf:b9:8c:2e:f0:a1:ef:13:
- 45:6c:05:df:de:27:16:51:36:41:11:6c:6c:3b:ed:
- fe:10:7d:12:9e:e5:9b:42:9a:fe:60:31:c3:66:b7:
- 73:3a:48:ae:4e:d0:32:37:94:88:b5:0d:b6:d9:f3:
- f2:44:d9:d5:88:12:dd:76:4d:f2:1a:fc:6f:23:1e:
- 7a:f1:d8:98:45:4e:07:10:ef:16:42:d0:43:75:6d:
- 4a:de:e2:aa:c9:31:ff:1f:00:70:7c:66:cf:10:25:
- 08:ba:fa:ee:00:e9:46:03:66:27:11:15:3b:aa:5b:
- f2:98:dd:36:42:b2:da:88:75
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- 69:36:89:f7:34:2a:33:72:2f:6d:3b:d4:22:b2:b8:6f:9a:c5:
- 36:66:0e:1b:3c:a1:b1:75:5a:e6:fd:35:d3:f8:a8:f2:07:6f:
- 85:67:8e:de:2b:b9:e2:17:b0:3a:a0:f0:0e:a2:00:9a:df:f3:
- 14:15:6e:bb:c8:85:5a:98:80:f9:ff:be:74:1d:3d:f3:fe:30:
- 25:d1:37:34:67:fa:a5:71:79:30:61:29:72:c0:e0:2c:4c:fb:
- 56:e4:3a:a8:6f:e5:32:59:52:db:75:28:50:59:0c:f8:0b:19:
- e4:ac:d9:af:96:8d:2f:50:db:07:c3:ea:1f:ab:33:e0:f5:2b:
- 31:89
-
-Thawte Premium Server CA
-========================
-MD5 Fingerprint: 06:9F:69:79:16:66:90:02:1B:8C:8C:A2:C3:07:6F:3A
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
-VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
-biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy
-dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
-MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB
-MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG
-A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp
-b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl
-cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv
-bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE
-VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ
-ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR
-uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
-9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI
-hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM
-pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 1 (0x1)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/Email=premium-serverNOSPAMthawte.com
- Validity
- Not Before: Aug 1 00:00:00 1996 GMT
- Not After : Dec 31 23:59:59 2020 GMT
- Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/Email=premium-serverNOSPAMthawte.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:d2:36:36:6a:8b:d7:c2:5b:9e:da:81:41:62:8f:
- 38:ee:49:04:55:d6:d0:ef:1c:1b:95:16:47:ef:18:
- 48:35:3a:52:f4:2b:6a:06:8f:3b:2f:ea:56:e3:af:
- 86:8d:9e:17:f7:9e:b4:65:75:02:4d:ef:cb:09:a2:
- 21:51:d8:9b:d0:67:d0:ba:0d:92:06:14:73:d4:93:
- cb:97:2a:00:9c:5c:4e:0c:bc:fa:15:52:fc:f2:44:
- 6e:da:11:4a:6e:08:9f:2f:2d:e3:f9:aa:3a:86:73:
- b6:46:53:58:c8:89:05:bd:83:11:b8:73:3f:aa:07:
- 8d:f4:42:4d:e7:40:9d:1c:37
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- 26:48:2c:16:c2:58:fa:e8:16:74:0c:aa:aa:5f:54:3f:f2:d7:
- c9:78:60:5e:5e:6e:37:63:22:77:36:7e:b2:17:c4:34:b9:f5:
- 08:85:fc:c9:01:38:ff:4d:be:f2:16:42:43:e7:bb:5a:46:fb:
- c1:c6:11:1f:f1:4a:b0:28:46:c9:c3:c4:42:7d:bc:fa:ab:59:
- 6e:d5:b7:51:88:11:e3:a4:85:19:6b:82:4c:a4:0c:12:ad:e9:
- a4:ae:3f:f1:c3:49:65:9a:8c:c5:c8:3e:25:b7:94:99:bb:92:
- 32:71:07:f0:86:5e:ed:50:27:a6:0d:a6:23:f9:bb:cb:a6:07:
- 14:42
-
-Thawte Server CA
-================
-MD5 Fingerprint: C5:70:C4:A2:ED:53:78:0C:C8:10:53:81:64:CB:D0:1D
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
-VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
-biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm
-MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx
-MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
-DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3
-dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl
-cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3
-DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91
-yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX
-L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj
-EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG
-7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e
-QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ
-qdq5snUb9kLy78fyGPmJvKP/iiMucEc=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 3 (0x2)
- Serial Number: 1 (0x1)
- Signature Algorithm: md5WithRSAEncryption
- Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/Email=server-certsNOSPAMthawte.com
- Validity
- Not Before: Aug 1 00:00:00 1996 GMT
- Not After : Dec 31 23:59:59 2020 GMT
- Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/Email=server-certsNOSPAMthawte.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:d3:a4:50:6e:c8:ff:56:6b:e6:cf:5d:b6:ea:0c:
- 68:75:47:a2:aa:c2:da:84:25:fc:a8:f4:47:51:da:
- 85:b5:20:74:94:86:1e:0f:75:c9:e9:08:61:f5:06:
- 6d:30:6e:15:19:02:e9:52:c0:62:db:4d:99:9e:e2:
- 6a:0c:44:38:cd:fe:be:e3:64:09:70:c5:fe:b1:6b:
- 29:b6:2f:49:c8:3b:d4:27:04:25:10:97:2f:e7:90:
- 6d:c0:28:42:99:d7:4c:43:de:c3:f5:21:6d:54:9f:
- 5d:c3:58:e1:c0:e4:d9:5b:b0:b8:dc:b4:7b:df:36:
- 3a:c2:b5:66:22:12:d6:87:0d
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: md5WithRSAEncryption
- 07:fa:4c:69:5c:fb:95:cc:46:ee:85:83:4d:21:30:8e:ca:d9:
- a8:6f:49:1a:e6:da:51:e3:60:70:6c:84:61:11:a1:1a:c8:48:
- 3e:59:43:7d:4f:95:3d:a1:8b:b7:0b:62:98:7a:75:8a:dd:88:
- 4e:4e:9e:40:db:a8:cc:32:74:b9:6f:0d:c6:e3:b3:44:0b:d9:
- 8a:6f:9a:29:9b:99:18:28:3b:d1:e3:40:28:9a:5a:3c:d5:b5:
- e7:20:1b:8b:ca:a4:ab:8d:e9:51:d9:e2:4c:2c:59:a9:da:b9:
- b2:75:1b:f6:42:f2:ef:c7:f2:18:f9:89:bc:a3:ff:8a:23:2e:
- 70:47
-
-Thawte Universal CA Root
-========================
-MD5 Fingerprint: 17:AF:71:16:52:7B:73:65:22:05:29:28:84:71:9D:13
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIRIjCCCQoCAQAwDQYJKoZIhvcNAQEFBQAwVzEPMA0GA1UEChMGVGhhd3RlMSEw
-HwYDVQQLExhUaGF3dGUgVW5pdmVyc2FsIENBIFJvb3QxITAfBgNVBAMTGFRoYXd0
-ZSBVbml2ZXJzYWwgQ0EgUm9vdDAeFw05OTEyMDUxMzU2MDVaFw0zNzA0MDMxMzU2
-MDVaMFcxDzANBgNVBAoTBlRoYXd0ZTEhMB8GA1UECxMYVGhhd3RlIFVuaXZlcnNh
-bCBDQSBSb290MSEwHwYDVQQDExhUaGF3dGUgVW5pdmVyc2FsIENBIFJvb3Qwgggi
-MA0GCSqGSIb3DQEBAQUAA4IIDwAwgggKAoIIAQDiiQVtw3+tpok6/7vHzZ03seHS
-IR6bYSoV53tXT1U80Lv52T0+przstK1TmhYC6wty/Yryj0QFxevT5b22RDnm+0e/
-ap4KlRjiaOLWltYhrYj99Rf109pCpZDtKZWWdTrah6HU9dOH3gVipuNmdJLPpby7
-32j/cXVWQVk16zNaZlHy0qMKwYzOc1wRby2MlYyRsf3P5a1WlcyFkoOQVUHJwnft
-+aN0QgpoCPPQ0WX9Zyw0/yR/53nIBzslV92kDJg9vuDMGWXb8lSir0LUneKuhCMl
-CTMStWoedsSL2UkAbF66H/Ib2mfKJ6qjRCMbg4LO8qsz7VSk3MmrWWXROA7BPhtn
-j9Z1AeBVIt12d+yO3fTPeSJtuVcD9ZkIpzw+NPvEF64jWM0k8yPKagIolAGBNLRs
-a66LGsOj0gk8FlT1Nl8k459KoeJkxhbDpoF6JDZHjsFeDvv5FXgE1g5Z2Z1YZmLS
-lCkyMsh4uWb2tVbhbMYUS5ZSWZECJGpVR9c/tiMaYHeXLuJAr54EV56tEcXJQ3Dv
-SLRerBxpLi6C1VuLvoK+GRRe5w0ix1Eb/x6b8TCPcTEGszQnj196ZoJPii0Tq0LP
-IVael45mNg+Wm+Ur9AKpKmqMLMTDuHAsLSkeP1B3Hm0qVORVCpE4ocW1ZqJ2Wu4P
-v7Rn4ShuD+E2oYLRv9R34cRnMpN4yOdUU/4jeeZozCaQ9hBjXSpvkS2kczJRIfK7
-Fd+qJAhIBt6hnia/uoO/fKTIoIy90v+8hGknEyQYxEUYIyZeGBTKLoiHYqNT5iG3
-uIV7moW7FSZy+Ln3anQPST+SvqkFt5knv78JF0uZTK0REHzfdDH2jyZfqoiuOFfI
-VS3T+9gbUZm+JRs6usB9G+3O0km5z/PFfYmQgdhpSCAQo/jvklEYMosRGMA/G4VW
-zlfJ8oJkxt8CCS5KES+xJ203UvDwFmHxZ43fh3Kvh9rP+1CUbtSUheuKLOoh9ZZK
-RNXgzmp0RE3QBdOHFe020KSLZlVwk+5HBsF+LqUYeWfzKIXxcPcOg6R+VJ5adjLL
-ZRu4zfvIKAPSVJHRp8WFQwgXdqXmL2cI2KGigi0M+MGvY9RQd21rRkpBhdWQX3kt
-xOzXEYdAiuFo4mT4VTL7b5Ms2nfZIcEX5TYsTn6Qf6yUKzJnvjhQdriuQbnXIcUJ
-TGDIo1HENJtXN9/LyTNXi+v7dp8ZTcVqHypFrivtL42npQDLBPolYi50SBvKKoy6
-27Z+9rsCfKnD21h4ob/w/hoQVRHO6GlOlmXGFwPWB2iMVIKuHCJVP/H0CZcowEb3
-TgslHfcH1wkdOhhXODvoMwbnj3hGHlv1BrbsuKYN8boTS9YYIN1pM0ozFa64yJiK
-JyyTvC377jO/ZuZNurabBlVgl0u8RM1+9KHYqi/AAighFmJ42whU8vz0NOPGjxxD
-V86QGkvcLjsokYk/eto1HY4s7kns9DOtyVOojJ8EUz4kHFLJEvliV6O87izrQHwg
-I3ArlflzF4rRwRxpprc4mmf3cB16WgxAz2IPhTzCAk5+tfbFKimEsx83KuGqckLE
-7Wsaj5IcXb7R8lvyq6qp0vW4pEErK5FuEkjKmNg3jcjtADC1tgROfpzahOzA+nvl
-HYikU0awlORcG6ElLA9IUneXCWzsWxgzgwLlgn7NhSEwEf0nT8/kHuw/pVds6Sow
-GSqI5cNpOKtvOXF/hOFBw+HMKokgUi6DD2w5P0stFqwt8CSsAHP0m7MGPwW4FIUf
-q55cPJ5inQ5tO4AJ/ALqopd0ysf541bhw8qlpprAkOAkElPSwovavu0CQ15n4YmY
-ee7LqsrDG9znpUalfGsWh7ZaKNfbJzxepb22Ud0fQ887Jsg6jSVhwUn0PBvJROqv
-HMIrlAEqDjDRW4srR+XD0QQDmw45LNYn1OZwWtl1zyrYyQAF5BOI7MM5+4dhMDZD
-A8ienKIGwi/F/PCAY7FUBKBMqS7G9XZ62NDk1JQR5RW1eAbcuICPmakgMz0QhUxl
-Cco+WF5gk5qqYl3AUQYcXWCgDZxLQ/anFiGkh6rywS7ukjC4nt/fEAGLhglw2Gyo
-t1AeFpa092f9NTohkCoyxwB7TQcQCbkvc9gYfmeZBE8G/FDHhZudQJ2zljf6pdyy
-ck7vTgks/ZH9Tfe7pqE+q3uiA0CmqVUn4vr5Gc6HdarxdTbz87iR+JHDi3UTjkxl
-mhY5auU06HqWWX81sAD9W2n8Qyb69Shu/ofZfiT7tKCCblSi/66/YrT0cgHCy5hH
-mOFMtReAgM6PpijuHkVq+9/xHfxaO9bq9GwdYklXO4qPhurwUwTOnBZo/7q5/IgP
-R/cCRHJAuMo7LVOd3DxWjFl7aBosjXG7bADHGs5vQJKxoy8P2UTyo3Aunu4OrjLQ
-Oz6LB+rmebNcKeJ9a6he+Vox6AiWoowDmEbxuH2QVCbtdmL+numabl7JScdcNFMp
-VNns5EbhgDt12d/7edWH8bqe6xnOTFJz5luHriVPOXnMxrj5EHvs8JtxpAWg0ynT
-Tn8f9C0oeMxVlXsekS/MVhhzi7LbvGkH5tDYT+2i/1iFo23gSlO3Z32NDFxbe3co
-AjVEegTTKEPIazAXXTK4KTW6dto7FEp2GFik+JI8nk0zb0ZrCNkxSGjd9PskVjSy
-z2lmvkjSimYizfJpzcJTE0UpQSLWXZgftqSyo8LuAi9RG9yDpOxwJajUCGEyb+Sh
-gS58Y3L6KWW8cETPXQIDAQABMA0GCSqGSIb3DQEBBQUAA4IIAQBVmjRqIgZpCUUz
-x66pXMcJTpuGvEGQ1JRS9s0jKZRLIs3ovf6dzVLyve2rh8mrq0YEtL2iPyIwR1DA
-S4x2DwP1ktKxLcR6NZzJc4frpp/eD3ON03+Z2LqPb8Tzvhqui6KUNpDi5euNBfT8
-Zd+V8cSUTRdW1588j1A853e/lYYmZPtq/8ba6YyuQrtp5TPG2OkNxlUhScEMtKP5
-m0tc3oNPQQPOKnloOH3wVEkg9bYQ/wjcM2aWm/8G3gCe185WQ5pR/HDN9vBRo7fN
-tFyFYs1xt8YrIyvdw25AQvo3/zcc9npXlIeFI9fUycdfwU0vyQ3XXOycJe6eMIKR
-lnK4dR34CWhXl7ItS+4l7HokKe5y1JwT26vcAwrYShTJCFdEXaG1U4A08hSXz1Le
-og6KEOkU79BgvmGh8SVd1RhzP5MQypbus0DS26NVz1dapQ5PdUff6veQmm31cC4d
-FBw3ZARZULDccoZvnDc9XSivc1Xv0u4kdHQT79zbMUn7P2P10wg+M6XnnQreUyxR
-jmfbm0FlQVC91KSWbIe8EuCUx9PA5MtzWACD4awnhdadU51cvQo+A0OcDJH1bXv4
-QHJ1qxF2kSvhxqofcGl2cBUJ/pPQ1i23FWqbZ1y0aZ8lpn2K+30iqXHyzk6MuCEt
-3v5BcQ3/nexzprsHT4gOWEcufqnCx3jdunqeTuAwTmNvhdQgQen6/kNF5/uverLO
-pAUdIppYht/kzkyp/tgWpW/72M5We/XWIO/kR81jJP+5vvFIo8EBcua9wK3tJg3K
-NJ/8Ai0gTwUgriE9DMIgPD/wBITcz4n9uSWRjtBD5rMgq1wt1UCeoEvY9LLMffFY
-Co6H7YisNpbkVqARivKa0LNXozS7Gas44XRrIsQxzgHVGzbjHjhMM5PfQONZV06s
-bnseWj3FHVusyBCCNQIisvx16BCRjcR9eJNHnhydrGtiAliM1hwj1q94woCcpKok
-VBS1FJjG+CsaJMtxMgrimw5pa91+jGTRLmPvDn+xPohMnVXlyW4XBLdB/72KQcsl
-MW9Edz9HsfyBiAeOBUkgtxHZaQMqA525M4Sa399640Zzo9iijFMZiFVMdLj2RIQr
-0RQtTjkukmj/afyFYhvrVU/vJYRiRZnW2E5vP1MIfR0GlYGAf09OdDaYteKHcJjc
-1/XcUhXmxtZ5ljl/j5XPq4BTrRsLRUAO1Bi9LN6Kd3b98kRHxiHQ5HTw2BgFyHww
-csff8bv8AjCp9EImWQ2TBYKhc+005ThdzVCQ/pT8E7y9/KiiiKdzxLKo0V2IxAKi
-evEEyf6MdMnvHWRBn6welmdkrKsoQced98CYG24HwmR9WoNmVig2nOf7HHcOKKDE
-92t5OQQghMdXk7wboOq860LlqBH+/KxlzP34KIj0pZrlc1HgqJsNA3dO5eCYs4ja
-febGnnwUZsEuU0qSBzegfuk9CeQVfM/9uEGl755mncReBx2H+EGt6ucv0kFjGDf5
-FONN0OX3Q/0V4/k2cwYm3wFPqcNO3iBGd5i0eiQrO3UrTliNm12kxxagvDKIP6GD
-8wDI+NhY6WNdTCu18HJB2Kt3N9ZydK62NpzIpoNJS+DJVgspvgAwy93WyEKKANns
-FdE0cfJbZIf2J9K364awkL8p2yGeNozjIC+VI1FsG8Kk1ebYAkNnoP6bUANEf7vk
-ctXR5NqPkhRk+10UEBJKlQbJZQgpyiGjJjgRySffcGcE/cpIMn9jskV0MVBPh9kg
-cNIhcLHWEJ0zXXiDkW1Vguza5GJjx4FG1xllcipDGZC41yNNTBzgRKlmZ6zucXkn
-Jnhtcg71XUsjtXx8ZekXxjoLDd1eHlHDhrjsf8cnSqVG6GotGcGHo8uZk4dkolUU
-TLdDpZPX59JOeUDKZZlGPT96gHqIaswe5WszRvRQwNUfCbjNii6hJ+tdc6foawrl
-V4IqsPziVFJW8KupEsYjlgcknOC8RqW0IATaCZNj5dQuwn7FMe21FXSGF7mz8yaK
-HQJq2ho/6LrxBG2UUVTiWrRZgx1g0C1zzAe1Joz518aIke+Az10PoWDLRdRCItGx
-cB390LcwkDrGSG1n5TLaj9vjqOMdICWiHOFMuaT2xj9cWA27xrJ3ARaRnxcGDbdA
-PsyPjpxL4J1+mx4Fq4gi+tMoG1cUZEo+JCw4TSFpAHMu0FUtdPIV6JRDPkAqxsa5
-alveoswYUFRdTiqFbPaSiykZfufqSuAiKyW892bPd5pBdPI8FA10afVQg83NLyHb
-IkaK0PdRGpVX8gWLGhntO0XoNsJufvtXIgAfBlOprpPGj3EqMUWS545t5pkiwIP8
-79xXZndPojYx+6ETjeXKo5V9AQxkcDtTQmiAx7udqAA1aZgMqGfYQ+Wqz5XgUZWk
-Fz9CnbgEztN5ecjTihYykuDXou7XN0wvrLh7vkX28RgznHs3piTZvECrAOnDN4ur
-2LbzXoFOsBRrBz4f7ML2RCKVu7Pmb9b5cGW6CoNlqg4TL4MTI1OLQBb6zi/8TQT4
-69isxTbCFVdIOOxVs7Qeuq3SQgYXDXPIV6a+lk2p8sD7eiEc9clwqYKQtfEM1HkQ
-voGm6VxhnHd5mqTDNyZXN8lSLPoI/9BfxmHA9Ha+/N5Oz6tRmXHH33701s8GVhkT
-UwttdFlIGZtTBS2dMlTT5SxTi2Q+1GR744AJFMz+FkZja3Fp+PnLJ/aIVLxFs84C
-yJTuQFv5QgLC/7DYLOsof17JJgGZpw==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 0 (0x0)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: O=Thawte, OU=Thawte Universal CA Root, CN=Thawte Universal CA Root
- Validity
- Not Before: Dec 5 13:56:05 1999 GMT
- Not After : Apr 3 13:56:05 2037 GMT
- Subject: O=Thawte, OU=Thawte Universal CA Root, CN=Thawte Universal CA Root
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (16384 bit)
- Modulus (16384 bit):
- 00:e2:89:05:6d:c3:7f:ad:a6:89:3a:ff:bb:c7:cd:
- 9d:37:b1:e1:d2:21:1e:9b:61:2a:15:e7:7b:57:4f:
- 55:3c:d0:bb:f9:d9:3d:3e:a6:bc:ec:b4:ad:53:9a:
- 16:02:eb:0b:72:fd:8a:f2:8f:44:05:c5:eb:d3:e5:
- bd:b6:44:39:e6:fb:47:bf:6a:9e:0a:95:18:e2:68:
- e2:d6:96:d6:21:ad:88:fd:f5:17:f5:d3:da:42:a5:
- 90:ed:29:95:96:75:3a:da:87:a1:d4:f5:d3:87:de:
- 05:62:a6:e3:66:74:92:cf:a5:bc:bb:df:68:ff:71:
- 75:56:41:59:35:eb:33:5a:66:51:f2:d2:a3:0a:c1:
- 8c:ce:73:5c:11:6f:2d:8c:95:8c:91:b1:fd:cf:e5:
- ad:56:95:cc:85:92:83:90:55:41:c9:c2:77:ed:f9:
- a3:74:42:0a:68:08:f3:d0:d1:65:fd:67:2c:34:ff:
- 24:7f:e7:79:c8:07:3b:25:57:dd:a4:0c:98:3d:be:
- e0:cc:19:65:db:f2:54:a2:af:42:d4:9d:e2:ae:84:
- 23:25:09:33:12:b5:6a:1e:76:c4:8b:d9:49:00:6c:
- 5e:ba:1f:f2:1b:da:67:ca:27:aa:a3:44:23:1b:83:
- 82:ce:f2:ab:33:ed:54:a4:dc:c9:ab:59:65:d1:38:
- 0e:c1:3e:1b:67:8f:d6:75:01:e0:55:22:dd:76:77:
- ec:8e:dd:f4:cf:79:22:6d:b9:57:03:f5:99:08:a7:
- 3c:3e:34:fb:c4:17:ae:23:58:cd:24:f3:23:ca:6a:
- 02:28:94:01:81:34:b4:6c:6b:ae:8b:1a:c3:a3:d2:
- 09:3c:16:54:f5:36:5f:24:e3:9f:4a:a1:e2:64:c6:
- 16:c3:a6:81:7a:24:36:47:8e:c1:5e:0e:fb:f9:15:
- 78:04:d6:0e:59:d9:9d:58:66:62:d2:94:29:32:32:
- c8:78:b9:66:f6:b5:56:e1:6c:c6:14:4b:96:52:59:
- 91:02:24:6a:55:47:d7:3f:b6:23:1a:60:77:97:2e:
- e2:40:af:9e:04:57:9e:ad:11:c5:c9:43:70:ef:48:
- b4:5e:ac:1c:69:2e:2e:82:d5:5b:8b:be:82:be:19:
- 14:5e:e7:0d:22:c7:51:1b:ff:1e:9b:f1:30:8f:71:
- 31:06:b3:34:27:8f:5f:7a:66:82:4f:8a:2d:13:ab:
- 42:cf:21:56:9e:97:8e:66:36:0f:96:9b:e5:2b:f4:
- 02:a9:2a:6a:8c:2c:c4:c3:b8:70:2c:2d:29:1e:3f:
- 50:77:1e:6d:2a:54:e4:55:0a:91:38:a1:c5:b5:66:
- a2:76:5a:ee:0f:bf:b4:67:e1:28:6e:0f:e1:36:a1:
- 82:d1:bf:d4:77:e1:c4:67:32:93:78:c8:e7:54:53:
- fe:23:79:e6:68:cc:26:90:f6:10:63:5d:2a:6f:91:
- 2d:a4:73:32:51:21:f2:bb:15:df:aa:24:08:48:06:
- de:a1:9e:26:bf:ba:83:bf:7c:a4:c8:a0:8c:bd:d2:
- ff:bc:84:69:27:13:24:18:c4:45:18:23:26:5e:18:
- 14:ca:2e:88:87:62:a3:53:e6:21:b7:b8:85:7b:9a:
- 85:bb:15:26:72:f8:b9:f7:6a:74:0f:49:3f:92:be:
- a9:05:b7:99:27:bf:bf:09:17:4b:99:4c:ad:11:10:
- 7c:df:74:31:f6:8f:26:5f:aa:88:ae:38:57:c8:55:
- 2d:d3:fb:d8:1b:51:99:be:25:1b:3a:ba:c0:7d:1b:
- ed:ce:d2:49:b9:cf:f3:c5:7d:89:90:81:d8:69:48:
- 20:10:a3:f8:ef:92:51:18:32:8b:11:18:c0:3f:1b:
- 85:56:ce:57:c9:f2:82:64:c6:df:02:09:2e:4a:11:
- 2f:b1:27:6d:37:52:f0:f0:16:61:f1:67:8d:df:87:
- 72:af:87:da:cf:fb:50:94:6e:d4:94:85:eb:8a:2c:
- ea:21:f5:96:4a:44:d5:e0:ce:6a:74:44:4d:d0:05:
- d3:87:15:ed:36:d0:a4:8b:66:55:70:93:ee:47:06:
- c1:7e:2e:a5:18:79:67:f3:28:85:f1:70:f7:0e:83:
- a4:7e:54:9e:5a:76:32:cb:65:1b:b8:cd:fb:c8:28:
- 03:d2:54:91:d1:a7:c5:85:43:08:17:76:a5:e6:2f:
- 67:08:d8:a1:a2:82:2d:0c:f8:c1:af:63:d4:50:77:
- 6d:6b:46:4a:41:85:d5:90:5f:79:2d:c4:ec:d7:11:
- 87:40:8a:e1:68:e2:64:f8:55:32:fb:6f:93:2c:da:
- 77:d9:21:c1:17:e5:36:2c:4e:7e:90:7f:ac:94:2b:
- 32:67:be:38:50:76:b8:ae:41:b9:d7:21:c5:09:4c:
- 60:c8:a3:51:c4:34:9b:57:37:df:cb:c9:33:57:8b:
- eb:fb:76:9f:19:4d:c5:6a:1f:2a:45:ae:2b:ed:2f:
- 8d:a7:a5:00:cb:04:fa:25:62:2e:74:48:1b:ca:2a:
- 8c:ba:db:b6:7e:f6:bb:02:7c:a9:c3:db:58:78:a1:
- bf:f0:fe:1a:10:55:11:ce:e8:69:4e:96:65:c6:17:
- 03:d6:07:68:8c:54:82:ae:1c:22:55:3f:f1:f4:09:
- 97:28:c0:46:f7:4e:0b:25:1d:f7:07:d7:09:1d:3a:
- 18:57:38:3b:e8:33:06:e7:8f:78:46:1e:5b:f5:06:
- b6:ec:b8:a6:0d:f1:ba:13:4b:d6:18:20:dd:69:33:
- 4a:33:15:ae:b8:c8:98:8a:27:2c:93:bc:2d:fb:ee:
- 33:bf:66:e6:4d:ba:b6:9b:06:55:60:97:4b:bc:44:
- cd:7e:f4:a1:d8:aa:2f:c0:02:28:21:16:62:78:db:
- 08:54:f2:fc:f4:34:e3:c6:8f:1c:43:57:ce:90:1a:
- 4b:dc:2e:3b:28:91:89:3f:7a:da:35:1d:8e:2c:ee:
- 49:ec:f4:33:ad:c9:53:a8:8c:9f:04:53:3e:24:1c:
- 52:c9:12:f9:62:57:a3:bc:ee:2c:eb:40:7c:20:23:
- 70:2b:95:f9:73:17:8a:d1:c1:1c:69:a6:b7:38:9a:
- 67:f7:70:1d:7a:5a:0c:40:cf:62:0f:85:3c:c2:02:
- 4e:7e:b5:f6:c5:2a:29:84:b3:1f:37:2a:e1:aa:72:
- 42:c4:ed:6b:1a:8f:92:1c:5d:be:d1:f2:5b:f2:ab:
- aa:a9:d2:f5:b8:a4:41:2b:2b:91:6e:12:48:ca:98:
- d8:37:8d:c8:ed:00:30:b5:b6:04:4e:7e:9c:da:84:
- ec:c0:fa:7b:e5:1d:88:a4:53:46:b0:94:e4:5c:1b:
- a1:25:2c:0f:48:52:77:97:09:6c:ec:5b:18:33:83:
- 02:e5:82:7e:cd:85:21:30:11:fd:27:4f:cf:e4:1e:
- ec:3f:a5:57:6c:e9:2a:30:19:2a:88:e5:c3:69:38:
- ab:6f:39:71:7f:84:e1:41:c3:e1:cc:2a:89:20:52:
- 2e:83:0f:6c:39:3f:4b:2d:16:ac:2d:f0:24:ac:00:
- 73:f4:9b:b3:06:3f:05:b8:14:85:1f:ab:9e:5c:3c:
- 9e:62:9d:0e:6d:3b:80:09:fc:02:ea:a2:97:74:ca:
- c7:f9:e3:56:e1:c3:ca:a5:a6:9a:c0:90:e0:24:12:
- 53:d2:c2:8b:da:be:ed:02:43:5e:67:e1:89:98:79:
- ee:cb:aa:ca:c3:1b:dc:e7:a5:46:a5:7c:6b:16:87:
- b6:5a:28:d7:db:27:3c:5e:a5:bd:b6:51:dd:1f:43:
- cf:3b:26:c8:3a:8d:25:61:c1:49:f4:3c:1b:c9:44:
- ea:af:1c:c2:2b:94:01:2a:0e:30:d1:5b:8b:2b:47:
- e5:c3:d1:04:03:9b:0e:39:2c:d6:27:d4:e6:70:5a:
- d9:75:cf:2a:d8:c9:00:05:e4:13:88:ec:c3:39:fb:
- 87:61:30:36:43:03:c8:9e:9c:a2:06:c2:2f:c5:fc:
- f0:80:63:b1:54:04:a0:4c:a9:2e:c6:f5:76:7a:d8:
- d0:e4:d4:94:11:e5:15:b5:78:06:dc:b8:80:8f:99:
- a9:20:33:3d:10:85:4c:65:09:ca:3e:58:5e:60:93:
- 9a:aa:62:5d:c0:51:06:1c:5d:60:a0:0d:9c:4b:43:
- f6:a7:16:21:a4:87:aa:f2:c1:2e:ee:92:30:b8:9e:
- df:df:10:01:8b:86:09:70:d8:6c:a8:b7:50:1e:16:
- 96:b4:f7:67:fd:35:3a:21:90:2a:32:c7:00:7b:4d:
- 07:10:09:b9:2f:73:d8:18:7e:67:99:04:4f:06:fc:
- 50:c7:85:9b:9d:40:9d:b3:96:37:fa:a5:dc:b2:72:
- 4e:ef:4e:09:2c:fd:91:fd:4d:f7:bb:a6:a1:3e:ab:
- 7b:a2:03:40:a6:a9:55:27:e2:fa:f9:19:ce:87:75:
- aa:f1:75:36:f3:f3:b8:91:f8:91:c3:8b:75:13:8e:
- 4c:65:9a:16:39:6a:e5:34:e8:7a:96:59:7f:35:b0:
- 00:fd:5b:69:fc:43:26:fa:f5:28:6e:fe:87:d9:7e:
- 24:fb:b4:a0:82:6e:54:a2:ff:ae:bf:62:b4:f4:72:
- 01:c2:cb:98:47:98:e1:4c:b5:17:80:80:ce:8f:a6:
- 28:ee:1e:45:6a:fb:df:f1:1d:fc:5a:3b:d6:ea:f4:
- 6c:1d:62:49:57:3b:8a:8f:86:ea:f0:53:04:ce:9c:
- 16:68:ff:ba:b9:fc:88:0f:47:f7:02:44:72:40:b8:
- ca:3b:2d:53:9d:dc:3c:56:8c:59:7b:68:1a:2c:8d:
- 71:bb:6c:00:c7:1a:ce:6f:40:92:b1:a3:2f:0f:d9:
- 44:f2:a3:70:2e:9e:ee:0e:ae:32:d0:3b:3e:8b:07:
- ea:e6:79:b3:5c:29:e2:7d:6b:a8:5e:f9:5a:31:e8:
- 08:96:a2:8c:03:98:46:f1:b8:7d:90:54:26:ed:76:
- 62:fe:9e:e9:9a:6e:5e:c9:49:c7:5c:34:53:29:54:
- d9:ec:e4:46:e1:80:3b:75:d9:df:fb:79:d5:87:f1:
- ba:9e:eb:19:ce:4c:52:73:e6:5b:87:ae:25:4f:39:
- 79:cc:c6:b8:f9:10:7b:ec:f0:9b:71:a4:05:a0:d3:
- 29:d3:4e:7f:1f:f4:2d:28:78:cc:55:95:7b:1e:91:
- 2f:cc:56:18:73:8b:b2:db:bc:69:07:e6:d0:d8:4f:
- ed:a2:ff:58:85:a3:6d:e0:4a:53:b7:67:7d:8d:0c:
- 5c:5b:7b:77:28:02:35:44:7a:04:d3:28:43:c8:6b:
- 30:17:5d:32:b8:29:35:ba:76:da:3b:14:4a:76:18:
- 58:a4:f8:92:3c:9e:4d:33:6f:46:6b:08:d9:31:48:
- 68:dd:f4:fb:24:56:34:b2:cf:69:66:be:48:d2:8a:
- 66:22:cd:f2:69:cd:c2:53:13:45:29:41:22:d6:5d:
- 98:1f:b6:a4:b2:a3:c2:ee:02:2f:51:1b:dc:83:a4:
- ec:70:25:a8:d4:08:61:32:6f:e4:a1:81:2e:7c:63:
- 72:fa:29:65:bc:70:44:cf:5d
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 55:9a:34:6a:22:06:69:09:45:33:c7:ae:a9:5c:c7:09:4e:9b:
- 86:bc:41:90:d4:94:52:f6:cd:23:29:94:4b:22:cd:e8:bd:fe:
- 9d:cd:52:f2:bd:ed:ab:87:c9:ab:ab:46:04:b4:bd:a2:3f:22:
- 30:47:50:c0:4b:8c:76:0f:03:f5:92:d2:b1:2d:c4:7a:35:9c:
- c9:73:87:eb:a6:9f:de:0f:73:8d:d3:7f:99:d8:ba:8f:6f:c4:
- f3:be:1a:ae:8b:a2:94:36:90:e2:e5:eb:8d:05:f4:fc:65:df:
- 95:f1:c4:94:4d:17:56:d7:9f:3c:8f:50:3c:e7:77:bf:95:86:
- 26:64:fb:6a:ff:c6:da:e9:8c:ae:42:bb:69:e5:33:c6:d8:e9:
- 0d:c6:55:21:49:c1:0c:b4:a3:f9:9b:4b:5c:de:83:4f:41:03:
- ce:2a:79:68:38:7d:f0:54:49:20:f5:b6:10:ff:08:dc:33:66:
- 96:9b:ff:06:de:00:9e:d7:ce:56:43:9a:51:fc:70:cd:f6:f0:
- 51:a3:b7:cd:b4:5c:85:62:cd:71:b7:c6:2b:23:2b:dd:c3:6e:
- 40:42:fa:37:ff:37:1c:f6:7a:57:94:87:85:23:d7:d4:c9:c7:
- 5f:c1:4d:2f:c9:0d:d7:5c:ec:9c:25:ee:9e:30:82:91:96:72:
- b8:75:1d:f8:09:68:57:97:b2:2d:4b:ee:25:ec:7a:24:29:ee:
- 72:d4:9c:13:db:ab:dc:03:0a:d8:4a:14:c9:08:57:44:5d:a1:
- b5:53:80:34:f2:14:97:cf:52:de:a2:0e:8a:10:e9:14:ef:d0:
- 60:be:61:a1:f1:25:5d:d5:18:73:3f:93:10:ca:96:ee:b3:40:
- d2:db:a3:55:cf:57:5a:a5:0e:4f:75:47:df:ea:f7:90:9a:6d:
- f5:70:2e:1d:14:1c:37:64:04:59:50:b0:dc:72:86:6f:9c:37:
- 3d:5d:28:af:73:55:ef:d2:ee:24:74:74:13:ef:dc:db:31:49:
- fb:3f:63:f5:d3:08:3e:33:a5:e7:9d:0a:de:53:2c:51:8e:67:
- db:9b:41:65:41:50:bd:d4:a4:96:6c:87:bc:12:e0:94:c7:d3:
- c0:e4:cb:73:58:00:83:e1:ac:27:85:d6:9d:53:9d:5c:bd:0a:
- 3e:03:43:9c:0c:91:f5:6d:7b:f8:40:72:75:ab:11:76:91:2b:
- e1:c6:aa:1f:70:69:76:70:15:09:fe:93:d0:d6:2d:b7:15:6a:
- 9b:67:5c:b4:69:9f:25:a6:7d:8a:fb:7d:22:a9:71:f2:ce:4e:
- 8c:b8:21:2d:de:fe:41:71:0d:ff:9d:ec:73:a6:bb:07:4f:88:
- 0e:58:47:2e:7e:a9:c2:c7:78:dd:ba:7a:9e:4e:e0:30:4e:63:
- 6f:85:d4:20:41:e9:fa:fe:43:45:e7:fb:af:7a:b2:ce:a4:05:
- 1d:22:9a:58:86:df:e4:ce:4c:a9:fe:d8:16:a5:6f:fb:d8:ce:
- 56:7b:f5:d6:20:ef:e4:47:cd:63:24:ff:b9:be:f1:48:a3:c1:
- 01:72:e6:bd:c0:ad:ed:26:0d:ca:34:9f:fc:02:2d:20:4f:05:
- 20:ae:21:3d:0c:c2:20:3c:3f:f0:04:84:dc:cf:89:fd:b9:25:
- 91:8e:d0:43:e6:b3:20:ab:5c:2d:d5:40:9e:a0:4b:d8:f4:b2:
- cc:7d:f1:58:0a:8e:87:ed:88:ac:36:96:e4:56:a0:11:8a:f2:
- 9a:d0:b3:57:a3:34:bb:19:ab:38:e1:74:6b:22:c4:31:ce:01:
- d5:1b:36:e3:1e:38:4c:33:93:df:40:e3:59:57:4e:ac:6e:7b:
- 1e:5a:3d:c5:1d:5b:ac:c8:10:82:35:02:22:b2:fc:75:e8:10:
- 91:8d:c4:7d:78:93:47:9e:1c:9d:ac:6b:62:02:58:8c:d6:1c:
- 23:d6:af:78:c2:80:9c:a4:aa:24:54:14:b5:14:98:c6:f8:2b:
- 1a:24:cb:71:32:0a:e2:9b:0e:69:6b:dd:7e:8c:64:d1:2e:63:
- ef:0e:7f:b1:3e:88:4c:9d:55:e5:c9:6e:17:04:b7:41:ff:bd:
- 8a:41:cb:25:31:6f:44:77:3f:47:b1:fc:81:88:07:8e:05:49:
- 20:b7:11:d9:69:03:2a:03:9d:b9:33:84:9a:df:df:7a:e3:46:
- 73:a3:d8:a2:8c:53:19:88:55:4c:74:b8:f6:44:84:2b:d1:14:
- 2d:4e:39:2e:92:68:ff:69:fc:85:62:1b:eb:55:4f:ef:25:84:
- 62:45:99:d6:d8:4e:6f:3f:53:08:7d:1d:06:95:81:80:7f:4f:
- 4e:74:36:98:b5:e2:87:70:98:dc:d7:f5:dc:52:15:e6:c6:d6:
- 79:96:39:7f:8f:95:cf:ab:80:53:ad:1b:0b:45:40:0e:d4:18:
- bd:2c:de:8a:77:76:fd:f2:44:47:c6:21:d0:e4:74:f0:d8:18:
- 05:c8:7c:30:72:c7:df:f1:bb:fc:02:30:a9:f4:42:26:59:0d:
- 93:05:82:a1:73:ed:34:e5:38:5d:cd:50:90:fe:94:fc:13:bc:
- bd:fc:a8:a2:88:a7:73:c4:b2:a8:d1:5d:88:c4:02:a2:7a:f1:
- 04:c9:fe:8c:74:c9:ef:1d:64:41:9f:ac:1e:96:67:64:ac:ab:
- 28:41:c7:9d:f7:c0:98:1b:6e:07:c2:64:7d:5a:83:66:56:28:
- 36:9c:e7:fb:1c:77:0e:28:a0:c4:f7:6b:79:39:04:20:84:c7:
- 57:93:bc:1b:a0:ea:bc:eb:42:e5:a8:11:fe:fc:ac:65:cc:fd:
- f8:28:88:f4:a5:9a:e5:73:51:e0:a8:9b:0d:03:77:4e:e5:e0:
- 98:b3:88:da:7d:e6:c6:9e:7c:14:66:c1:2e:53:4a:92:07:37:
- a0:7e:e9:3d:09:e4:15:7c:cf:fd:b8:41:a5:ef:9e:66:9d:c4:
- 5e:07:1d:87:f8:41:ad:ea:e7:2f:d2:41:63:18:37:f9:14:e3:
- 4d:d0:e5:f7:43:fd:15:e3:f9:36:73:06:26:df:01:4f:a9:c3:
- 4e:de:20:46:77:98:b4:7a:24:2b:3b:75:2b:4e:58:8d:9b:5d:
- a4:c7:16:a0:bc:32:88:3f:a1:83:f3:00:c8:f8:d8:58:e9:63:
- 5d:4c:2b:b5:f0:72:41:d8:ab:77:37:d6:72:74:ae:b6:36:9c:
- c8:a6:83:49:4b:e0:c9:56:0b:29:be:00:30:cb:dd:d6:c8:42:
- 8a:00:d9:ec:15:d1:34:71:f2:5b:64:87:f6:27:d2:b7:eb:86:
- b0:90:bf:29:db:21:9e:36:8c:e3:20:2f:95:23:51:6c:1b:c2:
- a4:d5:e6:d8:02:43:67:a0:fe:9b:50:03:44:7f:bb:e4:72:d5:
- d1:e4:da:8f:92:14:64:fb:5d:14:10:12:4a:95:06:c9:65:08:
- 29:ca:21:a3:26:38:11:c9:27:df:70:67:04:fd:ca:48:32:7f:
- 63:b2:45:74:31:50:4f:87:d9:20:70:d2:21:70:b1:d6:10:9d:
- 33:5d:78:83:91:6d:55:82:ec:da:e4:62:63:c7:81:46:d7:19:
- 65:72:2a:43:19:90:b8:d7:23:4d:4c:1c:e0:44:a9:66:67:ac:
- ee:71:79:27:26:78:6d:72:0e:f5:5d:4b:23:b5:7c:7c:65:e9:
- 17:c6:3a:0b:0d:dd:5e:1e:51:c3:86:b8:ec:7f:c7:27:4a:a5:
- 46:e8:6a:2d:19:c1:87:a3:cb:99:93:87:64:a2:55:14:4c:b7:
- 43:a5:93:d7:e7:d2:4e:79:40:ca:65:99:46:3d:3f:7a:80:7a:
- 88:6a:cc:1e:e5:6b:33:46:f4:50:c0:d5:1f:09:b8:cd:8a:2e:
- a1:27:eb:5d:73:a7:e8:6b:0a:e5:57:82:2a:b0:fc:e2:54:52:
- 56:f0:ab:a9:12:c6:23:96:07:24:9c:e0:bc:46:a5:b4:20:04:
- da:09:93:63:e5:d4:2e:c2:7e:c5:31:ed:b5:15:74:86:17:b9:
- b3:f3:26:8a:1d:02:6a:da:1a:3f:e8:ba:f1:04:6d:94:51:54:
- e2:5a:b4:59:83:1d:60:d0:2d:73:cc:07:b5:26:8c:f9:d7:c6:
- 88:91:ef:80:cf:5d:0f:a1:60:cb:45:d4:42:22:d1:b1:70:1d:
- fd:d0:b7:30:90:3a:c6:48:6d:67:e5:32:da:8f:db:e3:a8:e3:
- 1d:20:25:a2:1c:e1:4c:b9:a4:f6:c6:3f:5c:58:0d:bb:c6:b2:
- 77:01:16:91:9f:17:06:0d:b7:40:3e:cc:8f:8e:9c:4b:e0:9d:
- 7e:9b:1e:05:ab:88:22:fa:d3:28:1b:57:14:64:4a:3e:24:2c:
- 38:4d:21:69:00:73:2e:d0:55:2d:74:f2:15:e8:94:43:3e:40:
- 2a:c6:c6:b9:6a:5b:de:a2:cc:18:50:54:5d:4e:2a:85:6c:f6:
- 92:8b:29:19:7e:e7:ea:4a:e0:22:2b:25:bc:f7:66:cf:77:9a:
- 41:74:f2:3c:14:0d:74:69:f5:50:83:cd:cd:2f:21:db:22:46:
- 8a:d0:f7:51:1a:95:57:f2:05:8b:1a:19:ed:3b:45:e8:36:c2:
- 6e:7e:fb:57:22:00:1f:06:53:a9:ae:93:c6:8f:71:2a:31:45:
- 92:e7:8e:6d:e6:99:22:c0:83:fc:ef:dc:57:66:77:4f:a2:36:
- 31:fb:a1:13:8d:e5:ca:a3:95:7d:01:0c:64:70:3b:53:42:68:
- 80:c7:bb:9d:a8:00:35:69:98:0c:a8:67:d8:43:e5:aa:cf:95:
- e0:51:95:a4:17:3f:42:9d:b8:04:ce:d3:79:79:c8:d3:8a:16:
- 32:92:e0:d7:a2:ee:d7:37:4c:2f:ac:b8:7b:be:45:f6:f1:18:
- 33:9c:7b:37:a6:24:d9:bc:40:ab:00:e9:c3:37:8b:ab:d8:b6:
- f3:5e:81:4e:b0:14:6b:07:3e:1f:ec:c2:f6:44:22:95:bb:b3:
- e6:6f:d6:f9:70:65:ba:0a:83:65:aa:0e:13:2f:83:13:23:53:
- 8b:40:16:fa:ce:2f:fc:4d:04:f8:eb:d8:ac:c5:36:c2:15:57:
- 48:38:ec:55:b3:b4:1e:ba:ad:d2:42:06:17:0d:73:c8:57:a6:
- be:96:4d:a9:f2:c0:fb:7a:21:1c:f5:c9:70:a9:82:90:b5:f1:
- 0c:d4:79:10:be:81:a6:e9:5c:61:9c:77:79:9a:a4:c3:37:26:
- 57:37:c9:52:2c:fa:08:ff:d0:5f:c6:61:c0:f4:76:be:fc:de:
- 4e:cf:ab:51:99:71:c7:df:7e:f4:d6:cf:06:56:19:13:53:0b:
- 6d:74:59:48:19:9b:53:05:2d:9d:32:54:d3:e5:2c:53:8b:64:
- 3e:d4:64:7b:e3:80:09:14:cc:fe:16:46:63:6b:71:69:f8:f9:
- cb:27:f6:88:54:bc:45:b3:ce:02:c8:94:ee:40:5b:f9:42:02:
- c2:ff:b0:d8:2c:eb:28:7f:5e:c9:26:01:99:a7
-
-UPS Document Exchange by DST
-============================
-MD5 Fingerprint: 78:A5:FB:10:4B:E4:63:2E:D2:6B:FB:F2:B6:C2:4B:8E
-PEM Data:
------BEGIN CERTIFICATE-----
-MIID+DCCAuACEQDQHkCLAAACfAAAAAcAAAABMA0GCSqGSIb3DQEBBQUAMIG5MQsw
-CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp
-dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjEeMBwGA1UE
-CxMVVW5pdGVkIFBhcmNlbCBTZXJ2aWNlMRkwFwYDVQQDExBEU1QgKFVQUykgUm9v
-dENBMSEwHwYJKoZIhvcNAQkBFhJjYUBkaWdzaWd0cnVzdC5jb20wHhcNOTgxMjEw
-MDAyNTQ2WhcNMDgxMjA3MDAyNTQ2WjCBuTELMAkGA1UEBhMCdXMxDTALBgNVBAgT
-BFV0YWgxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MSQwIgYDVQQKExtEaWdpdGFs
-IFNpZ25hdHVyZSBUcnVzdCBDby4xHjAcBgNVBAsTFVVuaXRlZCBQYXJjZWwgU2Vy
-dmljZTEZMBcGA1UEAxMQRFNUIChVUFMpIFJvb3RDQTEhMB8GCSqGSIb3DQEJARYS
-Y2FAZGlnc2lndHJ1c3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
-AQEA7xfsrynm2SsnwNt7JJ9m9ASjwq0KyrDNhCuqN/OAoWDvQo/lXXdfV0JU3Svb
-YbJxXpN7b1/rJCvnpPLr8XOzC431Wdcy36yQjk4xuiVNtgym8eWvDOHlb1IDFcHf
-vn5KpqYYRnA/76dNqNz1dNlhekA8oZQo6sKUiMs3FQUZPJViuhwt+yiM0ciekjxb
-EVQ7eNlHO5stSuY+e2vf9PYFzyj2upg2AJ48N4UKnN63pIXFY/23YhRtFx7MioCF
-QjIRsCHinXfJgBZBnuvlFIl/t8O8T8Gfh5uW7GP2+ZBWDpWjIwqMZNqbuxx3sExd
-5sjo9X15LVckP8zjPSyYzxKfFwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQC7OI4E
-IiZYDiFEVsy9WXwpaMtcD8iGVD+BeKetj8xG9xxUuHktW3IFaugh0OwdHf6kNFG+
-7u3OzJwWaOJddXMIQzGRahArEMJLafjJrZio/bjv9qvwXyHvy4VrCe0vSGa1YHLA
-6KDHmNsO9xtzjTQICnvFd2KqMCObsB6LgJhU3AWHs6liWfyLtxWarETszzUa9w8u
-XZJLAch77qA37eQdgg2ZQUMXrdTVyuP5fReiAdAwD0C53LkEgmmDtvkP+gaS96j0
-1hcc8F5/xCnI5uHi/zZoIVGu/6m6hJKtinsz2JDSwXltMzM5dKwbOHGfLAeQ6h3g
-04lfy+8UjSdUpb1G
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- d0:1e:40:8b:00:00:02:7c:00:00:00:07:00:00:00:01
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=United Parcel Service, CN=DST (UPS) RootCA/Email=caNOSPAMdigsigtrust.com
- Validity
- Not Before: Dec 10 00:25:46 1998 GMT
- Not After : Dec 7 00:25:46 2008 GMT
- Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=United Parcel Service, CN=DST (UPS) RootCA/Email=caNOSPAMdigsigtrust.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:ef:17:ec:af:29:e6:d9:2b:27:c0:db:7b:24:9f:
- 66:f4:04:a3:c2:ad:0a:ca:b0:cd:84:2b:aa:37:f3:
- 80:a1:60:ef:42:8f:e5:5d:77:5f:57:42:54:dd:2b:
- db:61:b2:71:5e:93:7b:6f:5f:eb:24:2b:e7:a4:f2:
- eb:f1:73:b3:0b:8d:f5:59:d7:32:df:ac:90:8e:4e:
- 31:ba:25:4d:b6:0c:a6:f1:e5:af:0c:e1:e5:6f:52:
- 03:15:c1:df:be:7e:4a:a6:a6:18:46:70:3f:ef:a7:
- 4d:a8:dc:f5:74:d9:61:7a:40:3c:a1:94:28:ea:c2:
- 94:88:cb:37:15:05:19:3c:95:62:ba:1c:2d:fb:28:
- 8c:d1:c8:9e:92:3c:5b:11:54:3b:78:d9:47:3b:9b:
- 2d:4a:e6:3e:7b:6b:df:f4:f6:05:cf:28:f6:ba:98:
- 36:00:9e:3c:37:85:0a:9c:de:b7:a4:85:c5:63:fd:
- b7:62:14:6d:17:1e:cc:8a:80:85:42:32:11:b0:21:
- e2:9d:77:c9:80:16:41:9e:eb:e5:14:89:7f:b7:c3:
- bc:4f:c1:9f:87:9b:96:ec:63:f6:f9:90:56:0e:95:
- a3:23:0a:8c:64:da:9b:bb:1c:77:b0:4c:5d:e6:c8:
- e8:f5:7d:79:2d:57:24:3f:cc:e3:3d:2c:98:cf:12:
- 9f:17
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- bb:38:8e:04:22:26:58:0e:21:44:56:cc:bd:59:7c:29:68:cb:
- 5c:0f:c8:86:54:3f:81:78:a7:ad:8f:cc:46:f7:1c:54:b8:79:
- 2d:5b:72:05:6a:e8:21:d0:ec:1d:1d:fe:a4:34:51:be:ee:ed:
- ce:cc:9c:16:68:e2:5d:75:73:08:43:31:91:6a:10:2b:10:c2:
- 4b:69:f8:c9:ad:98:a8:fd:b8:ef:f6:ab:f0:5f:21:ef:cb:85:
- 6b:09:ed:2f:48:66:b5:60:72:c0:e8:a0:c7:98:db:0e:f7:1b:
- 73:8d:34:08:0a:7b:c5:77:62:aa:30:23:9b:b0:1e:8b:80:98:
- 54:dc:05:87:b3:a9:62:59:fc:8b:b7:15:9a:ac:44:ec:cf:35:
- 1a:f7:0f:2e:5d:92:4b:01:c8:7b:ee:a0:37:ed:e4:1d:82:0d:
- 99:41:43:17:ad:d4:d5:ca:e3:f9:7d:17:a2:01:d0:30:0f:40:
- b9:dc:b9:04:82:69:83:b6:f9:0f:fa:06:92:f7:a8:f4:d6:17:
- 1c:f0:5e:7f:c4:29:c8:e6:e1:e2:ff:36:68:21:51:ae:ff:a9:
- ba:84:92:ad:8a:7b:33:d8:90:d2:c1:79:6d:33:33:39:74:ac:
- 1b:38:71:9f:2c:07:90:ea:1d:e0:d3:89:5f:cb:ef:14:8d:27:
- 54:a5:bd:46
-
-ValiCert Class 1 VA
-===================
-MD5 Fingerprint: 65:58:AB:15:AD:57:6C:1E:A8:A7:B5:69:AC:BF:FF:EB
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy
-NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y
-LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+
-TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y
-TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0
-LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW
-I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw
-nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 1 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 1 Policy Validation Authority, CN=http://www.valicert.com//Email=infoNOSPAMvalicert.com
- Validity
- Not Before: Jun 25 22:23:48 1999 GMT
- Not After : Jun 25 22:23:48 2019 GMT
- Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 1 Policy Validation Authority, CN=http://www.valicert.com//Email=infoNOSPAMvalicert.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:d8:59:82:7a:89:b8:96:ba:a6:2f:68:6f:58:2e:
- a7:54:1c:06:6e:f4:ea:8d:48:bc:31:94:17:f0:f3:
- 4e:bc:b2:b8:35:92:76:b0:d0:a5:a5:01:d7:00:03:
- 12:22:19:08:f8:ff:11:23:9b:ce:07:f5:bf:69:1a:
- 26:fe:4e:e9:d1:7f:9d:2c:40:1d:59:68:6e:a6:f8:
- 58:b0:9d:1a:8f:d3:3f:f1:dc:19:06:81:a8:0e:e0:
- 3a:dd:c8:53:45:09:06:e6:0f:70:c3:fa:40:a6:0e:
- e2:56:05:0f:18:4d:fc:20:82:d1:73:55:74:8d:76:
- 72:a0:1d:9d:1d:c0:dd:3f:71
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 50:68:3d:49:f4:2c:1c:06:94:df:95:60:7f:96:7b:17:fe:4f:
- 71:ad:64:c8:dd:77:d2:ef:59:55:e8:3f:e8:8e:05:2a:21:f2:
- 07:d2:b5:a7:52:fe:9c:b1:b6:e2:5b:77:17:40:ea:72:d6:23:
- cb:28:81:32:c3:00:79:18:ec:59:17:89:c9:c6:6a:1e:71:c9:
- fd:b7:74:a5:25:45:69:c5:48:ab:19:e1:45:8a:25:6b:19:ee:
- e5:bb:12:f5:7f:f7:a6:8d:51:c3:f0:9d:74:b7:a9:3e:a0:a5:
- ff:b6:49:03:13:da:22:cc:ed:71:82:2b:99:cf:3a:b7:f5:2d:
- 72:c8
-
-ValiCert Class 2 VA
-===================
-MD5 Fingerprint: A9:23:75:9B:BA:49:36:6E:31:C2:DB:F2:E7:66:BA:87
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
-NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
-dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
-WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
-v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
-UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
-IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
-W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 1 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//Email=infoNOSPAMvalicert.com
- Validity
- Not Before: Jun 26 00:19:54 1999 GMT
- Not After : Jun 26 00:19:54 2019 GMT
- Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//Email=infoNOSPAMvalicert.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:ce:3a:71:ca:e5:ab:c8:59:92:55:d7:ab:d8:74:
- 0e:f9:ee:d9:f6:55:47:59:65:47:0e:05:55:dc:eb:
- 98:36:3c:5c:53:5d:d3:30:cf:38:ec:bd:41:89:ed:
- 25:42:09:24:6b:0a:5e:b3:7c:dd:52:2d:4c:e6:d4:
- d6:7d:5a:59:a9:65:d4:49:13:2d:24:4d:1c:50:6f:
- b5:c1:85:54:3b:fe:71:e4:d3:5c:42:f9:80:e0:91:
- 1a:0a:5b:39:36:67:f3:3f:55:7c:1b:3f:b4:5f:64:
- 73:34:e3:b4:12:bf:87:64:f8:da:12:ff:37:27:c1:
- b3:43:bb:ef:7b:6e:2e:69:f7
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 3b:7f:50:6f:6f:50:94:99:49:62:38:38:1f:4b:f8:a5:c8:3e:
- a7:82:81:f6:2b:c7:e8:c5:ce:e8:3a:10:82:cb:18:00:8e:4d:
- bd:a8:58:7f:a1:79:00:b5:bb:e9:8d:af:41:d9:0f:34:ee:21:
- 81:19:a0:32:49:28:f4:c4:8e:56:d5:52:33:fd:50:d5:7e:99:
- 6c:03:e4:c9:4c:fc:cb:6c:ab:66:b3:4a:21:8c:e5:b5:0c:32:
- 3e:10:b2:cc:6c:a1:dc:9a:98:4c:02:5b:f3:ce:b9:9e:a5:72:
- 0e:4a:b7:3f:3c:e6:16:68:f8:be:ed:74:4c:bc:5b:d5:62:1f:
- 43:dd
-
-ValiCert Class 3 VA
-===================
-MD5 Fingerprint: A2:6F:53:B7:EE:40:DB:4A:68:E7:FA:18:D9:10:4B:72
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy
-NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD
-cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs
-2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY
-JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE
-Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ
-n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A
-PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number: 1 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 3 Policy Validation Authority, CN=http://www.valicert.com//Email=infoNOSPAMvalicert.com
- Validity
- Not Before: Jun 26 00:22:33 1999 GMT
- Not After : Jun 26 00:22:33 2019 GMT
- Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 3 Policy Validation Authority, CN=http://www.valicert.com//Email=infoNOSPAMvalicert.com
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:e3:98:51:96:1c:e8:d5:b1:06:81:6a:57:c3:72:
- 75:93:ab:cf:9e:a6:fc:f3:16:52:d6:2d:4d:9f:35:
- 44:a8:2e:04:4d:07:49:8a:38:29:f5:77:37:e7:b7:
- ab:5d:df:36:71:14:99:8f:dc:c2:92:f1:e7:60:92:
- 97:ec:d8:48:dc:bf:c1:02:20:c6:24:a4:28:4c:30:
- 5a:76:6d:b1:5c:f3:dd:de:9e:10:71:a1:88:c7:5b:
- 9b:41:6d:ca:b0:b8:8e:15:ee:ad:33:2b:cf:47:04:
- 5c:75:71:0a:98:24:98:29:a7:49:59:a5:dd:f8:b7:
- 43:62:61:f3:d3:e2:d0:55:3f
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 56:bb:02:58:84:67:08:2c:df:1f:db:7b:49:33:f5:d3:67:9d:
- f4:b4:0a:10:b3:c9:c5:2c:e2:92:6a:71:78:27:f2:70:83:42:
- d3:3e:cf:a9:54:f4:f1:d8:92:16:8c:d1:04:cb:4b:ab:c9:9f:
- 45:ae:3c:8a:a9:b0:71:33:5d:c8:c5:57:df:af:a8:35:b3:7f:
- 89:87:e9:e8:25:92:b8:7f:85:7a:ae:d6:bc:1e:37:58:2a:67:
- c9:91:cf:2a:81:3e:ed:c6:39:df:c0:3e:19:9c:19:cc:13:4d:
- 82:41:b5:8c:de:e0:3d:60:08:20:0f:45:7e:6b:a2:7f:a3:8c:
- 15:ee
-
-VeriSign Class 4 Primary CA
-===========================
-MD5 Fingerprint: 1B:D1:AD:17:8B:7F:22:13:24:F5:26:E2:5D:4E:B9:10
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICMTCCAZoCBQKmAAABMA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgNCBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NjAxMjkwMDAwMDBa
-Fw05OTEyMzEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2ln
-biwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZp
-Y2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LJ1
-9njQrlpQ9OlQqZ+M1++RlHDo0iSQdomF1t+s5gEXMoDwnZNHvJplnR+Xrr/phnVj
-IIm9gFidBAydqMEk6QvlMXi9/C0MN2qeeIDpRnX57aP7E3vIwUzSo+/1PLBij0pd
-O92VZ48TucE81qcmm+zDO3rZTbxtm+gVAePwR6kCAwEAATANBgkqhkiG9w0BAQIF
-AAOBgQBT3dPwnCR+QKri/AAa19oM/DJhuBUNlvP6Vxt/M3yv6ZiaYch6s7f/sdyZ
-g9ysEvxwyR84Qu1E9oAuW2szaayc01znX1oYx7EteQSWQZGZQbE8DbqEOcY7l/Am
-yY7uvcxClf8exwI/VAx49byqYHwCaejcrOICdmHEPgPq0ook0Q==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 02:a6:00:00:01
- Signature Algorithm: md2WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority
- Validity
- Not Before: Jan 29 00:00:00 1996 GMT
- Not After : Dec 31 23:59:59 1999 GMT
- Subject: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:d0:b2:75:f6:78:d0:ae:5a:50:f4:e9:50:a9:9f:
- 8c:d7:ef:91:94:70:e8:d2:24:90:76:89:85:d6:df:
- ac:e6:01:17:32:80:f0:9d:93:47:bc:9a:65:9d:1f:
- 97:ae:bf:e9:86:75:63:20:89:bd:80:58:9d:04:0c:
- 9d:a8:c1:24:e9:0b:e5:31:78:bd:fc:2d:0c:37:6a:
- 9e:78:80:e9:46:75:f9:ed:a3:fb:13:7b:c8:c1:4c:
- d2:a3:ef:f5:3c:b0:62:8f:4a:5d:3b:dd:95:67:8f:
- 13:b9:c1:3c:d6:a7:26:9b:ec:c3:3b:7a:d9:4d:bc:
- 6d:9b:e8:15:01:e3:f0:47:a9
- Exponent: 65537 (0x10001)
- Signature Algorithm: md2WithRSAEncryption
- 53:dd:d3:f0:9c:24:7e:40:aa:e2:fc:00:1a:d7:da:0c:fc:32:
- 61:b8:15:0d:96:f3:fa:57:1b:7f:33:7c:af:e9:98:9a:61:c8:
- 7a:b3:b7:ff:b1:dc:99:83:dc:ac:12:fc:70:c9:1f:38:42:ed:
- 44:f6:80:2e:5b:6b:33:69:ac:9c:d3:5c:e7:5f:5a:18:c7:b1:
- 2d:79:04:96:41:91:99:41:b1:3c:0d:ba:84:39:c6:3b:97:f0:
- 26:c9:8e:ee:bd:cc:42:95:ff:1e:c7:02:3f:54:0c:78:f5:bc:
- aa:60:7c:02:69:e8:dc:ac:e2:02:76:61:c4:3e:03:ea:d2:8a:
- 24:d1
-
-Verisign Class 1 Public Primary Certification Authority
-=======================================================
-MD5 Fingerprint: 97:60:E8:57:5F:D3:50:47:E5:43:0C:94:36:8A:B0:62
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh
-c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05
-NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD
-VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp
-bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB
-jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N
-H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR
-4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN
-BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo
-EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5
-FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx
-lA==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- cd:ba:7f:56:f0:df:e4:bc:54:fe:22:ac:b3:72:aa:55
- Signature Algorithm: md2WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority
- Validity
- Not Before: Jan 29 00:00:00 1996 GMT
- Not After : Aug 1 23:59:59 2028 GMT
- Subject: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:e5:19:bf:6d:a3:56:61:2d:99:48:71:f6:67:de:
- b9:8d:eb:b7:9e:86:80:0a:91:0e:fa:38:25:af:46:
- 88:82:e5:73:a8:a0:9b:24:5d:0d:1f:cc:65:6e:0c:
- b0:d0:56:84:18:87:9a:06:9b:10:a1:73:df:b4:58:
- 39:6b:6e:c1:f6:15:d5:a8:a8:3f:aa:12:06:8d:31:
- ac:7f:b0:34:d7:8f:34:67:88:09:cd:14:11:e2:4e:
- 45:56:69:1f:78:02:80:da:dc:47:91:29:bb:36:c9:
- 63:5c:c5:e0:d7:2d:87:7b:a1:b7:32:b0:7b:30:ba:
- 2a:2f:31:aa:ee:a3:67:da:db
- Exponent: 65537 (0x10001)
- Signature Algorithm: md2WithRSAEncryption
- 4c:3f:b8:8b:c6:68:df:ee:43:33:0e:5d:e9:a6:cb:07:84:4d:
- 7a:33:ff:92:1b:f4:36:ad:d8:95:22:36:68:11:6c:7c:42:cc:
- f3:9c:2e:c4:07:3f:14:b0:0f:4f:ff:90:92:76:f9:e2:bc:4a:
- e9:8f:cd:a0:80:0a:f7:c5:29:f1:82:22:5d:b8:b1:dd:81:23:
- a3:7b:25:15:46:30:79:16:f8:ea:05:4b:94:7f:1d:c2:1c:c8:
- e3:b7:f4:10:40:3c:13:c3:5f:1f:53:e8:48:e4:86:b4:7b:a1:
- 35:b0:7b:25:ba:b8:d3:8e:ab:3f:38:9d:00:34:00:98:f3:d1:
- 71:94
-
-Verisign Class 1 Public Primary Certification Authority - G2
-============================================================
-MD5 Fingerprint: F2:7D:E9:54:E4:A3:22:0D:76:9F:E7:0B:BB:B3:24:2B
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEDnKVIn+UCIy/jLZ2/sbhBkwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTE4MDUxODIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK
-VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm
-Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAIv3GhDOdlwHq4OZ3BeAbzQ5XZg+a3Is4cei
-e0ApuXiIukzFo2penm574/ICQQxmvq37rqIUzpLzojSLtLK2JPLl1eDI5WJthHvL
-vrsDi3xXyvA3qZCviu4Dvh0onNkmdqDNxJ1O8K4HFtW+r1cIatCgQkJCHvQgzKV4
-gpUmOIpH
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 39:ca:54:89:fe:50:22:32:fe:32:d9:db:fb:1b:84:19
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Validity
- Not Before: May 18 00:00:00 1998 GMT
- Not After : May 18 23:59:59 2018 GMT
- Subject: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:aa:d0:ba:be:16:2d:b8:83:d4:ca:d2:0f:bc:76:
- 31:ca:94:d8:1d:93:8c:56:02:bc:d9:6f:1a:6f:52:
- 36:6e:75:56:0a:55:d3:df:43:87:21:11:65:8a:7e:
- 8f:bd:21:de:6b:32:3f:1b:84:34:95:05:9d:41:35:
- eb:92:eb:96:dd:aa:59:3f:01:53:6d:99:4f:ed:e5:
- e2:2a:5a:90:c1:b9:c4:a6:15:cf:c8:45:eb:a6:5d:
- 8e:9c:3e:f0:64:24:76:a5:cd:ab:1a:6f:b6:d8:7b:
- 51:61:6e:a6:7f:87:c8:e2:b7:e5:34:dc:41:88:ea:
- 09:40:be:73:92:3d:6b:e7:75
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 8b:f7:1a:10:ce:76:5c:07:ab:83:99:dc:17:80:6f:34:39:5d:
- 98:3e:6b:72:2c:e1:c7:a2:7b:40:29:b9:78:88:ba:4c:c5:a3:
- 6a:5e:9e:6e:7b:e3:f2:02:41:0c:66:be:ad:fb:ae:a2:14:ce:
- 92:f3:a2:34:8b:b4:b2:b6:24:f2:e5:d5:e0:c8:e5:62:6d:84:
- 7b:cb:be:bb:03:8b:7c:57:ca:f0:37:a9:90:af:8a:ee:03:be:
- 1d:28:9c:d9:26:76:a0:cd:c4:9d:4e:f0:ae:07:16:d5:be:af:
- 57:08:6a:d0:a0:42:42:42:1e:f4:20:cc:a5:78:82:95:26:38:
- 8a:47
-
-Verisign Class 1 Public Primary Certification Authority - G3
-============================================================
-MD5 Fingerprint: B1:47:BC:18:57:D1:18:A0:78:2D:EC:71:E8:2A:95:73
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4
-nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO
-8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV
-ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb
-PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2
-6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr
-n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a
-qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4
-wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3
-ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs
-pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4
-E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 8b:5b:75:56:84:54:85:0b:00:cf:af:38:48:ce:b1:a4
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 1 Public Primary Certification Authority - G3
- Validity
- Not Before: Oct 1 00:00:00 1999 GMT
- Not After : Jul 16 23:59:59 2036 GMT
- Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 1 Public Primary Certification Authority - G3
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:dd:84:d4:b9:b4:f9:a7:d8:f3:04:78:9c:de:3d:
- dc:6c:13:16:d9:7a:dd:24:51:66:c0:c7:26:59:0d:
- ac:06:08:c2:94:d1:33:1f:f0:83:35:1f:6e:1b:c8:
- de:aa:6e:15:4e:54:27:ef:c4:6d:1a:ec:0b:e3:0e:
- f0:44:a5:57:c7:40:58:1e:a3:47:1f:71:ec:60:f6:
- 6d:94:c8:18:39:ed:fe:42:18:56:df:e4:4c:49:10:
- 78:4e:01:76:35:63:12:36:dd:66:bc:01:04:36:a3:
- 55:68:d5:a2:36:09:ac:ab:21:26:54:06:ad:3f:ca:
- 14:e0:ac:ca:ad:06:1d:95:e2:f8:9d:f1:e0:60:ff:
- c2:7f:75:2b:4c:cc:da:fe:87:99:21:ea:ba:fe:3e:
- 54:d7:d2:59:78:db:3c:6e:cf:a0:13:00:1a:b8:27:
- a1:e4:be:67:96:ca:a0:c5:b3:9c:dd:c9:75:9e:eb:
- 30:9a:5f:a3:cd:d9:ae:78:19:3f:23:e9:5c:db:29:
- bd:ad:55:c8:1b:54:8c:63:f6:e8:a6:ea:c7:37:12:
- 5c:a3:29:1e:02:d9:db:1f:3b:b4:d7:0f:56:47:81:
- 15:04:4a:af:83:27:d1:c5:58:88:c1:dd:f6:aa:a7:
- a3:18:da:68:aa:6d:11:51:e1:bf:65:6b:9f:96:76:
- d1:3d
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- ab:66:8d:d7:b3:ba:c7:9a:b6:e6:55:d0:05:f1:9f:31:8d:5a:
- aa:d9:aa:46:26:0f:71:ed:a5:ad:53:56:62:01:47:2a:44:e9:
- fe:3f:74:0b:13:9b:b9:f4:4d:1b:b2:d1:5f:b2:b6:d2:88:5c:
- b3:9f:cd:cb:d4:a7:d9:60:95:84:3a:f8:c1:37:1d:61:ca:e7:
- b0:c5:e5:91:da:54:a6:ac:31:81:ae:97:de:cd:08:ac:b8:c0:
- 97:80:7f:6e:72:a4:e7:69:13:95:65:1f:c4:93:3c:fd:79:8f:
- 04:d4:3e:4f:ea:f7:9e:ce:cd:67:7c:4f:65:02:ff:91:85:54:
- 73:c7:ff:36:f7:86:2d:ec:d0:5e:4f:ff:11:9f:72:06:d6:b8:
- 1a:f1:4c:0d:26:65:e2:44:80:1e:c7:9f:e3:dd:e8:0a:da:ec:
- a5:20:80:69:68:a1:4f:7e:e1:6b:cf:07:41:fa:83:8e:bc:38:
- dd:b0:2e:11:b1:6b:b2:42:cc:9a:bc:f9:48:22:79:4a:19:0f:
- b2:1c:3e:20:74:d9:6a:c3:be:f2:28:78:13:56:79:4f:6d:50:
- ea:1b:b0:b5:57:b1:37:66:58:23:f3:dc:0f:df:0a:87:c4:ef:
- 86:05:d5:38:14:60:99:a3:4b:de:06:96:71:2c:f2:db:b6:1f:
- a4:ef:3f:ee
-
-Verisign Class 2 Public Primary Certification Authority
-=======================================================
-MD5 Fingerprint: B3:9C:25:B1:C3:2E:32:53:80:15:30:9D:4D:02:77:3E
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
-cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
-MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
-BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh
-YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7
-FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G
-CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg
-J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc
-r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 2d:1b:fc:4a:17:8d:a3:91:eb:e7:ff:f5:8b:45:be:0b
- Signature Algorithm: md2WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority
- Validity
- Not Before: Jan 29 00:00:00 1996 GMT
- Not After : Aug 1 23:59:59 2028 GMT
- Subject: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:b6:5a:8b:a3:0d:6a:23:83:80:6b:cf:39:87:f4:
- 21:13:33:06:4c:25:a2:ed:55:12:97:c5:a7:80:b9:
- fa:83:c1:20:a0:fa:2f:15:0d:7c:a1:60:6b:7e:79:
- 2c:fa:06:0f:3a:ae:f6:1b:6f:b1:d2:ff:2f:28:52:
- 5f:83:7d:4b:c4:7a:b7:f8:66:1f:80:54:fc:b7:c2:
- 8e:59:4a:14:57:46:d1:9a:93:be:41:91:03:bb:15:
- 80:93:5c:eb:e7:cc:08:6c:3f:3e:b3:4a:fc:ff:4b:
- 6c:23:d5:50:82:26:44:19:8e:23:c3:71:ea:19:24:
- 47:04:9e:75:bf:c8:a6:00:1f
- Exponent: 65537 (0x10001)
- Signature Algorithm: md2WithRSAEncryption
- 8a:1b:2b:fa:39:c1:74:d7:5e:d8:19:64:a2:58:4a:2d:37:e0:
- 33:47:0f:ac:ed:f7:aa:db:1e:e4:8b:06:5c:60:27:ca:45:52:
- ce:16:ef:3f:06:64:e7:94:68:7c:60:33:15:11:69:af:9d:62:
- 8d:a3:03:54:6b:a6:be:e5:ee:05:18:60:04:bf:42:80:fd:d0:
- a8:a8:1e:01:3b:f7:a3:5c:af:a3:dc:e6:26:80:23:3c:b8:44:
- 74:f7:0a:ae:49:8b:61:78:cc:24:bf:88:8a:a7:0e:ea:73:19:
- 41:fd:4d:03:f0:88:d1:e5:78:8d:a5:2a:4f:f6:97:0d:17:77:
- ca:d8
-
-Verisign Class 2 Public Primary Certification Authority - G2
-============================================================
-MD5 Fingerprint: 2D:BB:E5:25:D3:D1:65:82:3A:B7:0E:FA:E6:EB:E2:E1
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns
-YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
-MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y
-aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe
-Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX
-MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj
-IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx
-KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
-eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM
-HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw
-DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC
-AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji
-nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX
-rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn
-jBJ7xUS0rg==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- b9:2f:60:cc:88:9f:a1:7a:46:09:b8:5b:70:6c:8a:af
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Validity
- Not Before: May 18 00:00:00 1998 GMT
- Not After : Aug 1 23:59:59 2028 GMT
- Subject: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:a7:88:01:21:74:2c:e7:1a:03:f0:98:e1:97:3c:
- 0f:21:08:f1:9c:db:97:e9:9a:fc:c2:04:06:13:be:
- 5f:52:c8:cc:1e:2c:12:56:2c:b8:01:69:2c:cc:99:
- 1f:ad:b0:96:ae:79:04:f2:13:39:c1:7b:98:ba:08:
- 2c:e8:c2:84:13:2c:aa:69:e9:09:f4:c7:a9:02:a4:
- 42:c2:23:4f:4a:d8:f0:0e:a2:fb:31:6c:c9:e6:6f:
- 99:27:07:f5:e6:f4:4c:78:9e:6d:eb:46:86:fa:b9:
- 86:c9:54:f2:b2:c4:af:d4:46:1c:5a:c9:15:30:ff:
- 0d:6c:f5:2d:0e:6d:ce:7f:77
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 72:2e:f9:7f:d1:f1:71:fb:c4:9e:f6:c5:5e:51:8a:40:98:b8:
- 68:f8:9b:1c:83:d8:e2:9d:bd:ff:ed:a1:e6:66:ea:2f:09:f4:
- ca:d7:ea:a5:2b:95:f6:24:60:86:4d:44:2e:83:a5:c4:2d:a0:
- d3:ae:78:69:6f:72:da:6c:ae:08:f0:63:92:37:e6:bb:c4:30:
- 17:ad:77:cc:49:35:aa:cf:d8:8f:d1:be:b7:18:96:47:73:6a:
- 54:22:34:64:2d:b6:16:9b:59:5b:b4:51:59:3a:b3:0b:14:f4:
- 12:df:67:a0:f4:ad:32:64:5e:b1:46:72:27:8c:12:7b:c5:44:
- b4:ae
-
-Verisign Class 2 Public Primary Certification Authority - G3
-============================================================
-MD5 Fingerprint: F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy
-aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s
-IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp
-Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
-eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV
-BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp
-Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu
-Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g
-Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
-IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU
-J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO
-JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY
-wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o
-koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN
-qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E
-Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe
-xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u
-7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU
-sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI
-sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP
-cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 61:70:cb:49:8c:5f:98:45:29:e7:b0:a6:d9:50:5b:7a
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 2 Public Primary Certification Authority - G3
- Validity
- Not Before: Oct 1 00:00:00 1999 GMT
- Not After : Jul 16 23:59:59 2036 GMT
- Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 2 Public Primary Certification Authority - G3
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:af:0a:0d:c2:d5:2c:db:67:b9:2d:e5:94:27:dd:
- a5:be:e0:b0:4d:8f:b3:61:56:3c:d6:7c:c3:f4:cd:
- 3e:86:cb:a2:88:e2:e1:d8:a4:69:c5:b5:e2:bf:c1:
- a6:47:50:5e:46:39:8b:d5:96:ba:b5:6f:14:bf:10:
- ce:27:13:9e:05:47:9b:31:7a:13:d8:1f:d9:d3:02:
- 37:8b:ad:2c:47:f0:8e:81:06:a7:0d:30:0c:eb:f7:
- 3c:0f:20:1d:dc:72:46:ee:a5:02:c8:5b:c3:c9:56:
- 69:4c:c5:18:c1:91:7b:0b:d5:13:00:9b:bc:ef:c3:
- 48:3e:46:60:20:85:2a:d5:90:b6:cd:8b:a0:cc:32:
- dd:b7:fd:40:55:b2:50:1c:56:ae:cc:8d:77:4d:c7:
- 20:4d:a7:31:76:ef:68:92:8a:90:1e:08:81:56:b2:
- ad:69:a3:52:d0:cb:1c:c4:23:3d:1f:99:fe:4c:e8:
- 16:63:8e:c6:08:8e:f6:31:f6:d2:fa:e5:76:dd:b5:
- 1c:92:a3:49:cd:cd:01:cd:68:cd:a9:69:ba:a3:eb:
- 1d:0d:9c:a4:20:a6:c1:a0:c5:d1:46:4c:17:6d:d2:
- ac:66:3f:96:8c:e0:84:d4:36:ff:22:59:c5:f9:11:
- 60:a8:5f:04:7d:f2:1a:f6:25:42:61:0f:c4:4a:b8:
- 3e:89
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 34:26:15:3c:c0:8d:4d:43:49:1d:bd:e9:21:92:d7:66:9c:b7:
- de:c5:b8:d0:e4:5d:5f:76:22:c0:26:f9:84:3a:3a:f9:8c:b5:
- fb:ec:60:f1:e8:ce:04:b0:c8:dd:a7:03:8f:30:f3:98:df:a4:
- e6:a4:31:df:d3:1c:0b:46:dc:72:20:3f:ae:ee:05:3c:a4:33:
- 3f:0b:39:ac:70:78:73:4b:99:2b:df:30:c2:54:b0:a8:3b:55:
- a1:fe:16:28:cd:42:bd:74:6e:80:db:27:44:a7:ce:44:5d:d4:
- 1b:90:98:0d:1e:42:94:b1:00:2c:04:d0:74:a3:02:05:22:63:
- 63:cd:83:b5:fb:c1:6d:62:6b:69:75:fd:5d:70:41:b9:f5:bf:
- 7c:df:be:c1:32:73:22:21:8b:58:81:7b:15:91:7a:ba:e3:64:
- 48:b0:7f:fb:36:25:da:95:d0:f1:24:14:17:dd:18:80:6b:46:
- 23:39:54:f5:8e:62:09:04:1d:94:90:a6:9b:e6:25:e2:42:45:
- aa:b8:90:ad:be:08:8f:a9:0b:42:18:94:cf:72:39:e1:b1:43:
- e0:28:cf:b7:e7:5a:6c:13:6b:49:b3:ff:e3:18:7c:89:8b:33:
- 5d:ac:33:d7:a7:f9:da:3a:55:c9:58:10:f9:aa:ef:5a:b6:cf:
- 4b:4b:df:2a
-
-Verisign Class 3 Public Primary Certification Authority
-=======================================================
-MD5 Fingerprint: 10:FC:63:5D:F6:26:3E:0D:F3:25:BE:5F:79:CD:67:67
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
-cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
-MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
-BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
-BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
-I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
-CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
-lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
-AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 70:ba:e4:1d:10:d9:29:34:b6:38:ca:7b:03:cc:ba:bf
- Signature Algorithm: md2WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
- Validity
- Not Before: Jan 29 00:00:00 1996 GMT
- Not After : Aug 1 23:59:59 2028 GMT
- Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:c9:5c:59:9e:f2:1b:8a:01:14:b4:10:df:04:40:
- db:e3:57:af:6a:45:40:8f:84:0c:0b:d1:33:d9:d9:
- 11:cf:ee:02:58:1f:25:f7:2a:a8:44:05:aa:ec:03:
- 1f:78:7f:9e:93:b9:9a:00:aa:23:7d:d6:ac:85:a2:
- 63:45:c7:72:27:cc:f4:4c:c6:75:71:d2:39:ef:4f:
- 42:f0:75:df:0a:90:c6:8e:20:6f:98:0f:f8:ac:23:
- 5f:70:29:36:a4:c9:86:e7:b1:9a:20:cb:53:a5:85:
- e7:3d:be:7d:9a:fe:24:45:33:dc:76:15:ed:0f:a2:
- 71:64:4c:65:2e:81:68:45:a7
- Exponent: 65537 (0x10001)
- Signature Algorithm: md2WithRSAEncryption
- bb:4c:12:2b:cf:2c:26:00:4f:14:13:dd:a6:fb:fc:0a:11:84:
- 8c:f3:28:1c:67:92:2f:7c:b6:c5:fa:df:f0:e8:95:bc:1d:8f:
- 6c:2c:a8:51:cc:73:d8:a4:c0:53:f0:4e:d6:26:c0:76:01:57:
- 81:92:5e:21:f1:d1:b1:ff:e7:d0:21:58:cd:69:17:e3:44:1c:
- 9c:19:44:39:89:5c:dc:9c:00:0f:56:8d:02:99:ed:a2:90:45:
- 4c:e4:bb:10:a4:3d:f0:32:03:0e:f1:ce:f8:e8:c9:51:8c:e6:
- 62:9f:e6:9f:c0:7d:b7:72:9c:c9:36:3a:6b:9f:4e:a8:ff:64:
- 0d:64
-
-Verisign Class 3 Public Primary Certification Authority - G2
-============================================================
-MD5 Fingerprint: A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
-pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
-13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
-U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
-F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
-oJ2daZH9
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 7d:d9:fe:07:cf:a8:1e:b7:10:79:67:fb:a7:89:34:c6
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Validity
- Not Before: May 18 00:00:00 1998 GMT
- Not After : Aug 1 23:59:59 2028 GMT
- Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:cc:5e:d1:11:5d:5c:69:d0:ab:d3:b9:6a:4c:99:
- 1f:59:98:30:8e:16:85:20:46:6d:47:3f:d4:85:20:
- 84:e1:6d:b3:f8:a4:ed:0c:f1:17:0f:3b:f9:a7:f9:
- 25:d7:c1:cf:84:63:f2:7c:63:cf:a2:47:f2:c6:5b:
- 33:8e:64:40:04:68:c1:80:b9:64:1c:45:77:c7:d8:
- 6e:f5:95:29:3c:50:e8:34:d7:78:1f:a8:ba:6d:43:
- 91:95:8f:45:57:5e:7e:c5:fb:ca:a4:04:eb:ea:97:
- 37:54:30:6f:bb:01:47:32:33:cd:dc:57:9b:64:69:
- 61:f8:9b:1d:1c:89:4f:5c:67
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 51:4d:cd:be:5c:cb:98:19:9c:15:b2:01:39:78:2e:4d:0f:67:
- 70:70:99:c6:10:5a:94:a4:53:4d:54:6d:2b:af:0d:5d:40:8b:
- 64:d3:d7:ee:de:56:61:92:5f:a6:c4:1d:10:61:36:d3:2c:27:
- 3c:e8:29:09:b9:11:64:74:cc:b5:73:9f:1c:48:a9:bc:61:01:
- ee:e2:17:a6:0c:e3:40:08:3b:0e:e7:eb:44:73:2a:9a:f1:69:
- 92:ef:71:14:c3:39:ac:71:a7:91:09:6f:e4:71:06:b3:ba:59:
- 57:26:79:00:f6:f8:0d:a2:33:30:28:d4:aa:58:a0:9d:9d:69:
- 91:fd
-
-Verisign Class 3 Public Primary Certification Authority - G3
-============================================================
-MD5 Fingerprint: CD:68:B6:A7:C7:C4:CE:75:E0:1D:4F:57:44:61:92:09
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
-N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
-KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
-kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
-CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
-Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
-imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
-2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
-DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
-/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
-F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
-TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 9b:7e:06:49:a3:3e:62:b9:d5:ee:90:48:71:29:ef:57
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3
- Validity
- Not Before: Oct 1 00:00:00 1999 GMT
- Not After : Jul 16 23:59:59 2036 GMT
- Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:cb:ba:9c:52:fc:78:1f:1a:1e:6f:1b:37:73:bd:
- f8:c9:6b:94:12:30:4f:f0:36:47:f5:d0:91:0a:f5:
- 17:c8:a5:61:c1:16:40:4d:fb:8a:61:90:e5:76:20:
- c1:11:06:7d:ab:2c:6e:a6:f5:11:41:8e:fa:2d:ad:
- 2a:61:59:a4:67:26:4c:d0:e8:bc:52:5b:70:20:04:
- 58:d1:7a:c9:a4:69:bc:83:17:64:ad:05:8b:bc:d0:
- 58:ce:8d:8c:f5:eb:f0:42:49:0b:9d:97:27:67:32:
- 6e:e1:ae:93:15:1c:70:bc:20:4d:2f:18:de:92:88:
- e8:6c:85:57:11:1a:e9:7e:e3:26:11:54:a2:45:96:
- 55:83:ca:30:89:e8:dc:d8:a3:ed:2a:80:3f:7f:79:
- 65:57:3e:15:20:66:08:2f:95:93:bf:aa:47:2f:a8:
- 46:97:f0:12:e2:fe:c2:0a:2b:51:e6:76:e6:b7:46:
- b7:e2:0d:a6:cc:a8:c3:4c:59:55:89:e6:e8:53:5c:
- 1c:ea:9d:f0:62:16:0b:a7:c9:5f:0c:f0:de:c2:76:
- ce:af:f7:6a:f2:fa:41:a6:a2:33:14:c9:e5:7a:63:
- d3:9e:62:37:d5:85:65:9e:0e:e6:53:24:74:1b:5e:
- 1d:12:53:5b:c7:2c:e7:83:49:3b:15:ae:8a:68:b9:
- 57:97
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 11:14:96:c1:ab:92:08:f7:3f:2f:c9:b2:fe:e4:5a:9f:64:de:
- db:21:4f:86:99:34:76:36:57:dd:d0:15:2f:c5:ad:7f:15:1f:
- 37:62:73:3e:d4:e7:5f:ce:17:03:db:35:fa:2b:db:ae:60:09:
- 5f:1e:5f:8f:6e:bb:0b:3d:ea:5a:13:1e:0c:60:6f:b5:c0:b5:
- 23:22:2e:07:0b:cb:a9:74:cb:47:bb:1d:c1:d7:a5:6b:cc:2f:
- d2:42:fd:49:dd:a7:89:cf:53:ba:da:00:5a:28:bf:82:df:f8:
- ba:13:1d:50:86:82:fd:8e:30:8f:29:46:b0:1e:3d:35:da:38:
- 62:16:18:4a:ad:e6:b6:51:6c:de:af:62:eb:01:d0:1e:24:fe:
- 7a:8f:12:1a:12:68:b8:fb:66:99:14:14:45:5c:ae:e7:ae:69:
- 17:81:2b:5a:37:c9:5e:2a:f4:c6:e2:a1:5c:54:9b:a6:54:00:
- cf:f0:f1:c1:c7:98:30:1a:3b:36:16:db:a3:6e:ea:fd:ad:b2:
- c2:da:ef:02:47:13:8a:c0:f1:b3:31:ad:4f:1c:e1:4f:9c:af:
- 0f:0c:9d:f7:78:0d:d8:f4:35:56:80:da:b7:6d:17:8f:9d:1e:
- 81:64:e1:fe:c5:45:ba:ad:6b:b9:0a:7a:4e:4f:4b:84:ee:4b:
- f1:7d:dd:11
-
-Verisign Class 4 Public Primary Certification Authority - G2
-============================================================
-MD5 Fingerprint: 26:6D:2C:19:98:B6:70:68:38:50:54:19:EC:90:34:60
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM
-HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK
-qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj
-cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y
-cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP
-T8qAkbYp
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 32:88:8e:9a:d2:f5:eb:13:47:f8:7f:c4:20:37:25:f8
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Validity
- Not Before: May 18 00:00:00 1998 GMT
- Not After : Aug 1 23:59:59 2028 GMT
- Subject: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1024 bit)
- Modulus (1024 bit):
- 00:ba:f0:e4:cf:f9:c4:ae:85:54:b9:07:57:f9:8f:
- c5:7f:68:11:f8:c4:17:b0:44:dc:e3:30:73:d5:2a:
- 62:2a:b8:d0:cc:1c:ed:28:5b:7e:bd:6a:dc:b3:91:
- 24:ca:41:62:3c:fc:02:01:bf:1c:16:31:94:05:97:
- 76:6e:a2:ad:bd:61:17:6c:4e:30:86:f0:51:37:2a:
- 50:c7:a8:62:81:dc:5b:4a:aa:c1:a0:b4:6e:eb:2f:
- e5:57:c5:b1:2b:40:70:db:5a:4d:a1:8e:1f:bd:03:
- 1f:d8:03:d4:8f:4c:99:71:bc:e2:82:cc:58:e8:98:
- 3a:86:d3:86:38:f3:00:29:1f
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 85:8c:12:c1:a7:b9:50:15:7a:cb:3e:ac:b8:43:8a:dc:aa:dd:
- 14:ba:89:81:7e:01:3c:23:71:21:88:2f:82:dc:63:fa:02:45:
- ac:45:59:d7:2a:58:44:5b:b7:9f:81:3b:92:68:3d:e2:37:24:
- f5:7b:6c:8f:76:35:96:09:a8:59:9d:b9:ce:23:ab:74:d6:83:
- fd:32:73:27:d8:69:3e:43:74:f6:ae:c5:89:9a:e7:53:7c:e9:
- 7b:f6:4b:f3:c1:65:83:de:8d:8a:9c:3c:88:8d:39:59:fc:aa:
- 3f:22:8d:a1:c1:66:50:81:72:4c:ed:22:64:4f:4f:ca:80:91:
- b6:29
-
-Verisign Class 4 Public Primary Certification Authority - G3
-============================================================
-MD5 Fingerprint: DB:C8:F2:27:2E:B1:EA:6A:29:23:5D:FE:56:3E:33:DF
-PEM Data:
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1
-GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ
-+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd
-U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm
-NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY
-ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/
-ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1
-CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq
-g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
-fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c
-2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/
-bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- ec:a0:a7:8b:6e:75:6a:01:cf:c4:7c:cc:2f:94:5e:d7
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary Certification Authority - G3
- Validity
- Not Before: Oct 1 00:00:00 1999 GMT
- Not After : Jul 16 23:59:59 2036 GMT
- Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary Certification Authority - G3
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (2048 bit)
- Modulus (2048 bit):
- 00:ad:cb:a5:11:69:c6:59:ab:f1:8f:b5:19:0f:56:
- ce:cc:b5:1f:20:e4:9e:26:25:4b:e0:73:65:89:59:
- de:d0:83:e4:f5:0f:b5:bb:ad:f1:7c:e8:21:fc:e4:
- e8:0c:ee:7c:45:22:19:76:92:b4:13:b7:20:5b:09:
- fa:61:ae:a8:f2:a5:8d:85:c2:2a:d6:de:66:36:d2:
- 9b:02:f4:a8:92:60:7c:9c:69:b4:8f:24:1e:d0:86:
- 52:f6:32:9c:41:58:1e:22:bd:cd:45:62:95:08:6e:
- d0:66:dd:53:a2:cc:f0:10:dc:54:73:8b:04:a1:46:
- 33:33:5c:17:40:b9:9e:4d:d3:f3:be:55:83:e8:b1:
- 89:8e:5a:7c:9a:96:22:90:3b:88:25:f2:d2:53:88:
- 02:0c:0b:78:f2:e6:37:17:4b:30:46:07:e4:80:6d:
- a6:d8:96:2e:e8:2c:f8:11:b3:38:0d:66:a6:9b:ea:
- c9:23:5b:db:8e:e2:f3:13:8e:1a:59:2d:aa:02:f0:
- ec:a4:87:66:dc:c1:3f:f5:d8:b9:f4:ec:82:c6:d2:
- 3d:95:1d:e5:c0:4f:84:c9:d9:a3:44:28:06:6a:d7:
- 45:ac:f0:6b:6a:ef:4e:5f:f8:11:82:1e:38:63:34:
- 66:50:d4:3e:93:73:fa:30:c3:66:ad:ff:93:2d:97:
- ef:03
- Exponent: 65537 (0x10001)
- Signature Algorithm: sha1WithRSAEncryption
- 8f:fa:25:6b:4f:5b:e4:a4:4e:27:55:ab:22:15:59:3c:ca:b5:
- 0a:d4:4a:db:ab:dd:a1:5f:53:c5:a0:57:39:c2:ce:47:2b:be:
- 3a:c8:56:bf:c2:d9:27:10:3a:b1:05:3c:c0:77:31:bb:3a:d3:
- 05:7b:6d:9a:1c:30:8c:80:cb:93:93:2a:83:ab:05:51:82:02:
- 00:11:67:6b:f3:88:61:47:5f:03:93:d5:5b:0d:e0:f1:d4:a1:
- 32:35:85:b2:3a:db:b0:82:ab:d1:cb:0a:bc:4f:8c:5b:c5:4b:
- 00:3b:1f:2a:82:a6:7e:36:85:dc:7e:3c:67:00:b5:e4:3b:52:
- e0:a8:eb:5d:15:f9:c6:6d:f0:ad:1d:0e:85:b7:a9:9a:73:14:
- 5a:5b:8f:41:28:c0:d5:e8:2d:4d:a4:5e:cd:aa:d9:ed:ce:dc:
- d8:d5:3c:42:1d:17:c1:12:5d:45:38:c3:38:f3:fc:85:2e:83:
- 46:48:b2:d7:20:5f:92:36:8f:e7:79:0f:98:5e:99:e8:f0:d0:
- a4:bb:f5:53:bd:2a:ce:59:b0:af:6e:7f:6c:bb:d2:1e:00:b0:
- 21:ed:f8:41:62:82:b9:d8:b2:c4:bb:46:50:f3:31:c5:8f:01:
- a8:74:eb:f5:78:27:da:e7:f7:66:43:f3:9e:83:3e:20:aa:c3:
- 35:60:91:ce
-
-Verisign/RSA Commercial CA
-==========================
-MD5 Fingerprint: 5A:0B:DD:42:9E:B2:B4:62:97:32:7F:7F:0A:AA:9A:39
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICIzCCAZACBQJBAAAWMA0GCSqGSIb3DQEBAgUAMFwxCzAJBgNVBAYTAlVTMSAw
-HgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjErMCkGA1UECxMiQ29tbWVy
-Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NDExMDQxODU4MzRaFw05
-OTExMDMxODU4MzRaMFwxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdSU0EgRGF0YSBT
-ZWN1cml0eSwgSW5jLjErMCkGA1UECxMiQ29tbWVyY2lhbCBDZXJ0aWZpY2F0aW9u
-IEF1dGhvcml0eTCBmzANBgkqhkiG9w0BAQEFAAOBiQAwgYUCfgCk+4Fie84QJ93o
-975sbsZwmdu41QUDaSiCnHJ/lj+O7Kwpkj+KFPhCdr69XQO5kNTQvAayUTNfxMK/
-touPmbZiImDd298ggrTKoi8tUO2UMt7gVY3UaOLgTNLNBRYulWZcYVI4HlGogqHE
-7yXpCuaLK44xZtn42f29O2nZ6wIDAQABMA0GCSqGSIb3DQEBAgUAA34AdrW2EP4j
-9/dZYkuwX5zBaLxJu7NJbyFHXSudVMQAKD+YufKKg5tgf+tQx6sFEC097TgCwaVI
-0v5loMC86qYjFmZsGySp8+x5NRhPJsjjr1BKx6cxa9B8GJ1Qv6km+iYrRpwUqbtb
-MJhCKLVLU7tDCZJAuqiqWqTGtotXTcU=
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 02:41:00:00:16
- Signature Algorithm: md2WithRSAEncryption
- Issuer: C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority
- Validity
- Not Before: Nov 4 18:58:34 1994 GMT
- Not After : Nov 3 18:58:34 1999 GMT
- Subject: C=US, O=RSA Data Security, Inc., OU=Commercial Certification Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1000 bit)
- Modulus (1000 bit):
- 00:a4:fb:81:62:7b:ce:10:27:dd:e8:f7:be:6c:6e:
- c6:70:99:db:b8:d5:05:03:69:28:82:9c:72:7f:96:
- 3f:8e:ec:ac:29:92:3f:8a:14:f8:42:76:be:bd:5d:
- 03:b9:90:d4:d0:bc:06:b2:51:33:5f:c4:c2:bf:b6:
- 8b:8f:99:b6:62:22:60:dd:db:df:20:82:b4:ca:a2:
- 2f:2d:50:ed:94:32:de:e0:55:8d:d4:68:e2:e0:4c:
- d2:cd:05:16:2e:95:66:5c:61:52:38:1e:51:a8:82:
- a1:c4:ef:25:e9:0a:e6:8b:2b:8e:31:66:d9:f8:d9:
- fd:bd:3b:69:d9:eb
- Exponent: 65537 (0x10001)
- Signature Algorithm: md2WithRSAEncryption
- 76:b5:b6:10:fe:23:f7:f7:59:62:4b:b0:5f:9c:c1:68:bc:49:
- bb:b3:49:6f:21:47:5d:2b:9d:54:c4:00:28:3f:98:b9:f2:8a:
- 83:9b:60:7f:eb:50:c7:ab:05:10:2d:3d:ed:38:02:c1:a5:48:
- d2:fe:65:a0:c0:bc:ea:a6:23:16:66:6c:1b:24:a9:f3:ec:79:
- 35:18:4f:26:c8:e3:af:50:4a:c7:a7:31:6b:d0:7c:18:9d:50:
- bf:a9:26:fa:26:2b:46:9c:14:a9:bb:5b:30:98:42:28:b5:4b:
- 53:bb:43:09:92:40:ba:a8:aa:5a:a4:c6:b6:8b:57:4d:c5
-
-Verisign/RSA Secure Server CA
-=============================
-MD5 Fingerprint: 74:7B:82:03:43:F0:00:9E:6B:B3:EC:47:BF:85:A5:93
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG
-A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD
-VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0
-MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV
-BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy
-dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ
-ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII
-0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI
-uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI
-hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3
-YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc
-1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA==
------END CERTIFICATE-----
-Certificate Ingredients:
- Data:
- Version: 1 (0x0)
- Serial Number:
- 02:ad:66:7e:4e:45:fe:5e:57:6f:3c:98:19:5e:dd:c0
- Signature Algorithm: md2WithRSAEncryption
- Issuer: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority
- Validity
- Not Before: Nov 9 00:00:00 1994 GMT
- Not After : Jan 7 23:59:59 2010 GMT
- Subject: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public Key: (1000 bit)
- Modulus (1000 bit):
- 00:92:ce:7a:c1:ae:83:3e:5a:aa:89:83:57:ac:25:
- 01:76:0c:ad:ae:8e:2c:37:ce:eb:35:78:64:54:03:
- e5:84:40:51:c9:bf:8f:08:e2:8a:82:08:d2:16:86:
- 37:55:e9:b1:21:02:ad:76:68:81:9a:05:a2:4b:c9:
- 4b:25:66:22:56:6c:88:07:8f:f7:81:59:6d:84:07:
- 65:70:13:71:76:3e:9b:77:4c:e3:50:89:56:98:48:
- b9:1d:a7:29:1a:13:2e:4a:11:59:9c:1e:15:d5:49:
- 54:2c:73:3a:69:82:b1:97:39:9c:6d:70:67:48:e5:
- dd:2d:d6:c8:1e:7b
- Exponent: 65537 (0x10001)
- Signature Algorithm: md2WithRSAEncryption
- 65:dd:7e:e1:b2:ec:b0:e2:3a:e0:ec:71:46:9a:19:11:b8:d3:
- c7:a0:b4:03:40:26:02:3e:09:9c:e1:12:b3:d1:5a:f6:37:a5:
- b7:61:03:b6:5b:16:69:3b:c6:44:08:0c:88:53:0c:6b:97:49:
- c7:3e:35:dc:6c:b9:bb:aa:df:5c:bb:3a:2f:93:60:b6:a9:4b:
- 4d:f2:20:f7:cd:5f:7f:64:7b:8e:dc:00:5c:d7:fa:77:ca:39:
- 16:59:6f:0e:ea:d3:b5:83:7f:4d:4d:42:56:76:b4:c9:5f:04:
- f8:38:f8:eb:d2:5f:75:5f:cd:7b:fc:e5:8e:80:7c:fc:50
-
-Root 5 - Equifax Secure Global eBusiness CA-1
-=============================================
-MD5 Fingerprint: 8F:5D:77:06:27:C4:98:3C:5B:93:78:E7:D7:7D:9B:CC
-PEM Data:
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc
-MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT
-ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw
-MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj
-dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l
-c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC
-UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc
-58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/
-o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH
-MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr
-aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA
-A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA
-Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv
-8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
------END CERTIFICATE-----
-
+++ /dev/null
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
- Changelog
-
-
-Version 7.10.8 (1 November 2003)
-
-Daniel (31 October)
-- Assume that MDTM on an FTP server returns the timestamp using the UTC time
- zone. This changes the time CURLINFO_FILETIME returns for a given file over
- FTP, and will change existing uses of CURLOPT_TIMECONDITION. It will make
- the functionality more similar to how the HTTP one is already working.
-
-- Command line options that take numerical parameters (such as -y, -Y, -C etc)
- now report error and exit if the parameter isn't truly a number greater than
- or equal to zero. This helps users to notice bad usage earlier. Before, when
- a user forgot or missed to add a numerical parameter to an option, the
- command line parser would simply "eat" the following option and it would
- cause great confusion.
-
-Daniel (30 October)
-- David Hull made libcurl deal with NOBODY and HEADER for file:// the same way
- it already does for FTP: it provides HTTP-looking headers that provide info
- only about the file, without doing the actual transfer. The curl tool then
- lets --head do this.
-
-Daniel (29 October)
-- runtests.pl now checks for and use valgrind if present. It will redirect the
- valgrind results in log/valgrind[num] but it currently doesn't scan that
- file for any errors or anything, that is still only made manually.
-
-- David Hull made the file: URL parser also accept the somewhat sloppy file
- syntax: file:/path. I added test case 203 to verify this.
-
-Daniel (28 October)
-- Dan C tracked down yet another weird behavior in the glibc gethostbyname_r()
- function for some specific versions (reported on 2.2.5 and 2.1.1), and
- provided a fix. On Linux machines with these glibc versioins, non-ipv6
- builds of libcurl would often fail to resolve perfectly resolvable host
- names.
-
-Daniel (26 October)
-- James Bursa found out that curl_msnprintf() could write the trailing
- zero-byte outside its given buffer size. This could happen if you generated
- a very long error message as then libcurl would overwrite the ERRORBUFFER
- with one byte. Using a non-existing very long local file:// name is one case
- that could make this occur.
-
-Daniel (24 October)
-- David Hull filed bug report #829827. It identified a problem with -C - if
- the full file already was downloaded and thus the server responded with a
- 416. libcurl would then wrongly use the Content-Length: header and expect
- that size to get transfer, causing a "hang" until the server closed the
- connection and then an error 18 ("still N bytes data left of the transfer").
-
- Now we don't return any error at all, but I think libcurl should perhaps
- return some kind of info since the requested range was out of the size of
- the document.
-
-- Based on David Hull's fix in bug report #804599, we now check for solaris and
- gcc in configure and set the -mimpure-text link flag for linking the lib
- better.
-
-- I've introduced a -t option to the runtests.pl script. With that option set,
- the script runs special "memory torture" tests. For each test command line
- in that section, the script first runs the command line and counts the total
- amount of allocations made. It then runs the exact same command line again,
- forcing allocation number N to fail. It will try every N from 1 to the total
- number of amounts made. For every invoke, it checks that no memory was
- leaked as that would indicate a bad cleanup somewhere in the code.
-
- This is just beginning to work, and I've already made some corrections in
- libcurl code. When this code works somewhat fine, I'll make sure 'make test'
- in the root dir will run these tests as well.
-
-Daniel (23 October)
-- Georg Horn fixed how the CA verification is made. Verifications can now be
- made while at the same time the result of it can be ignored. This also
- affects the curl tool as -k can now be used together with --cacert or
- --capath.
-
-Daniel (22 October)
-- Gisle Vanem found out --disable-eprt didn't work and patched it.
-
-- Test case 91 was modified and could now repeat the problem Kevin Roth has
- reported, and the bug was fixed.
-
-- Dylan Ellicott added vc-libcurl-ssl-dll as a target to the root makefile
- to build a static libcurl that links with a shared OpenSSL using MSVC.
-
-Daniel (21 October)
-- Andrés García updated the mingw32 makefiles.
-
-Version 7.10.8-pre5 (21 October 2003)
-
-Daniel (19 October)
-- Georg Horn made libcurl output more info on SSL failures when receiving
- data.
-
-Version 7.10.8-pre4 (18 October 2003)
-
-Daniel (17 October)
-- Dominick Meglio implemented CURLOPT_MAXFILESIZE and --max-filesize.
-
-- Made libcurl show verbose info about what auth type and user name that is
- being sent in its HTTP request-headers.
-
-Daniel (16 October)
-- Removed support for CURLOPT_PASSWDFUNCTION and CURLOPT_PASSWDDATA. libcurl
- no longer prompt for passwords under any circumstances. Password prompting
- was instead moved to curl, which now prompts for password if -u or -U lack
- it. This solves the problem Kevin Roth reported when curl prompted for
- password twice when doing NTLM authentication.
-
-- I rewrote the SSL subjectAltName check to avoid having to rely on OpenLDAP-
- licensed derivate code.
-
-Daniel (15 October)
-- Avoid doing getsockopt() on Windows to verify connects. It seems that this
- hogs Windows machines when libcurl is being used multi-threaded (with > ~50
- threads). Andrew Fuller helped us verify and test this.
-
-Daniel (14 October)
-- Kimmo Kinnunen fixed a crash with duphandle() when CURLDEBUG is set.
-
-- Gisle Vanem made libcurl build and work with IPv6 on Windows.
-
-Daniel (13 October)
-- Giuseppe Attardi reported yet another segfault with ares and the multi
- interface. Me fixed.
-
-- Domenico Andreoli removed the extra LDFLAGS assignment in lib/Makefile.am
- that was reported about in the debian bug report #212086.
-
- Domenico also fixed two makefiles where we used 'gnroff' instead of the more
- portable $(NROFF).
-
-Daniel (12 October)
-- Dirk Manske made the share locking around DNS lookups slightly different to
- allow the share system's DNS lookups to run somewhat more
- independent/faster.
-
-Daniel (9 October)
-- Lachlan O'Dea fixed a resume problem: "If I set CURLOPT_RESUME_FROM, perform
- an HTTP download, then reset CURLOPT_RESUME_FROM to 0, the next download
- still has a Range header with a garbage value." bug report #820502
-
-- Dominick Meglio made the inet_pton.c file build fine using MSVC.
-
-- The 'sws' test suite web server now #include setup.h from the lib directory.
- This makes it more portable easier.
-
-Version 7.10.8-pre3 (8 October 2003)
-
-Daniel (8 October)
-- Frank Ticheler provided a patch that fixes how libcurl connects to multiple
- addresses, if one of them fails (ipv4-code).
-
-Daniel (7 October)
-- Neil Dunbar provided a patch that now makes libcurl check SSL
- subjectAltNames when matching certs. This is apparently detailed in RFC2818
- as the right thing to do. I had to add configure checks for inet_pton() and
- our own (strictly speaking, code from BIND written by Paul Vixie) provided
- code for the function for platforms that miss it.
-
-- HTTP POST using the read callback didn't work, as Florian Schoppmann
- reported.
-
-Daniel (5 October)
-- Shared provided a few fixes to make libcurl build on BeOS
- out-of-the-box. New code for BeOS-style non-blocking sockets, provided by
- Shard and Jeremy Friesner. Modified the autoconf check for non-blocking
- sockets to check for this kind too.
-
-Daniel (4 October)
-- Vincent Bronner pointed out that if you set CURLOPT_COOKIE for a transfer
- and then set it to NULL in a subsequent one, the previous cookie was still
- sent off!
-
-- Jon Turner fixed a problem libcurl had when it failed on an FTP transfer due
- to a bad path, it would cause the next transfer to use a bad path as well.
-
-- Siddhartha Prakash Jain provided a patch with a fix for libcurl with ares,
- when working on IP-only names as we then could return "wait" status when the
- name in fact already was resolved. I edited the patch slightly to not expose
- async details to non-ares aware source code.
-
-Daniel (3 October)
-- Neil Spring posted the debian bug report #213180, and pointed out that using
- the name 'access' in a function prototype is not very wise as some compilers
- complain.
-
-- Peter Sylvester provided his and Jean-Paul Merlin's curlx.c example source
- code that shows how they use ssl and callbacks.
-
-Daniel (2 October)
-- James MacMillan's patch makes curl build on QNX 6.2.x.
-
-Daniel (26 September)
-- My daughter was born!
-
-Daniel (23 September)
-- Added support for -4/--ipv4 and -6/--ipv6 to force names to resolve to that
- particular IP version. They only work for IPv6-enabled libcurls.
-
-- curl -V now outputs 'SPNEGO' as a feature in case libcurl was built to
- support that.
-
-Version 7.10.8-pre2 (22 September 2003)
-
-Daniel (22 September)
-- Giuseppe Attardi found a segfault in libcurl when using the multi interface
- with ares and doing repeated operations against a non-resolving host name.
-
-Daniel (19 September)
-- Added the CURLOPT_IPRESOLVE option, that allows an application to select
- what kind of IP addresses he wants to use when resolving host names. This
- is only interesting when using host names that resolve addresses using more
- than one version of IP.
-
-- Applied Markus Moeller's patch that introduces SPNEGO support if libcurl
- is built with the FBopenssl libraries. curl_version_info() now returns
- info on SPNEGO availability. The patch also made the GSSAPI stuff work fine
- with the MIT GSS-library (the Heimdal one still works too).
-
-Daniel (16 September)
-- Doing PUT with --digest failed, as reported in bug report #805853.
-
-- Using --anyauth that picked NTLM, and then a redirect closed the connection
- and took curl to a second NTLM page made curl fail. Bug report #806328
- identified the problem, test case 90 was added to verify the fix.
-
-Daniel (14 September)
-- codemastr brought a patch for ares to make the Windows portions of it work
- properly on NT4. I uploaded a new diff and updated the docs on where to get
- it etc.
-
-- Jeff Pohlmeyer tracked down a very hard-to-find bug where we removed a
- cached DNS entry even though it may be in use, which caused "random" memory
- to get overwritten and thus "random" crashes.
-
-Daniel (12 September)
-- Based on a bug report by David Kimdon, I made the runtests.pl script clear
- all possible proxy environment variables before the tests are run.
-
-- By default, easy handles within a multi handle now share DNS cache.
-
-- Tim Bartley brought a patch that makes the GSSNEGOTIATE option work for
- Microsoft's "Negotiate" authentication as well.
-
-Daniel (11 September)
-- A zero-length proxy string confused FTP transfers.
-
-- Bjorn Reese found a case with an uninitialized pointer, only present when
- built for ares.
-
-Version 7.10.8-pre1 (8 September 2003)
-
-Daniel (7 September)
-- Jurij Smakov found out that the non-OpenSSL MD5 code was not working on
- Alpha (or ia64). Only the OpenSSL-version did. I made a fix I think corrects
- the problem.
-
-Daniel (5 September)
-- Kevin Fisk reported that configure --enable-thread didn't work. I fixed.
-
-- De-macrofied the lib/hash.c source code somewhat.
-
-Daniel (4 September)
-- CURLINFO_HTTPAUTH_AVAIL and CURLINFO_PROXYAUTH_AVAIL added, Based on Joerg
- Mueller-Tolk's patch,
-
-Early (4 September)
-- Added CURLOPT_FTP_RESPONSE_TIMEOUT - allows user to set strict timeout
- requirements on the FTP server's ability to respond to individual commands
- without placing global requirements on transfer or connect time. Files
- affected:
- - include/curl/curl.h
- Added option CURLOPT_FTP_RESPONSE_TIMEOUT
- - lib/ftp.c
- Added branch inside Curl_GetFTPResponse to check for
- data->set.ftp_response_timeout
- - lib/url.c
- Modified Curl_setopt to recognize CURLOPT_FTP_RESPONSE_TIMEOUT
- - lib/urldata.h
- Added ftp_response_timeout to struct UserDefined
-
-Daniel (3 September)
-- Peter Pentchev found and fixed two problems in the test suite's web server
- code, that made it segfault at times.
-
-- Jörg Mueller-Tolk improved the proxy user+password handling, especially
- when providing a blank password.
-
-Daniel (2 September)
-- Fix for making CONNECT to proxies do the correct magic to allow NTLM, Digest
- and similar to work.
-
-Daniel (1 September)
-- Henrik Storner made libcurl work fine with OpenLDAP 2.1.22 (current).
-
-- Jeff Pohlmeyer added a proper error message for non-resolving hosts when
- using ares for lookups.
-
-Daniel (25 August)
-- John McGowan reported that curl -k still failed if the HTTPS server's CN
- field wasn't obtainable. This was due to the CURLOPT_SSL_VERIFYHOST being
- set to 1, and libcurl failed if the CN was missing. Starting now, having it
- set to 1 will simply output a warning if no CN could be obtained (as having
- a mismatch is OK).
-
-Daniel (21 August)
-- Vincent Sanders provided a fix for name resolving when linked with uClibc.
-
-Daniel (20 August)
-- Gerd v. Egidy provided a patch that makes libcurl store the FTP response
- code from ftp servers. Using curl_easy_getinfo() with CURLINFO_HTTP_CODE
- returns that data. The option is therefore now also known as
- CURLINFO_RESPONSE_CODE.
-
-- Antoine Calando found a segfault when doing multi-part/formpost using
- the multi interface.
-
-- Antoine Calando pointed out that curl_multi_info_read() didn't set the
- msgs_in_queue to 0 properly when returning NULL.
-
-Daniel (19 August)
-- I made curl support multiple -T options, as well as -T "{file1,file2}"
- style globbing. One -T for each URL is supported.
-
-- Jeff Pohlmeyer found a segfault when using ares-enabled libcurl and the
- multi interface when trying a non-existing host name.
-
-- Made the libcurl printf code support long longs if available.
-
-- Loren Kirkby pointed out that we did not clean up all SSL-allocated memory
- in curl_global_cleanup().
-
-Daniel (17 August)
-- Setting CURLOPT_WRITEFUNCTION or CURLOPT_READFUNCTION to NULL will now make
- them get the internal defaults restored. Previously this could cause a
- segfault. We should aim at having all pointer-related options get restored
- to default/safe values when set to NULL.
-
-Version 7.10.7 (15 August 2003)
-
-Daniel (14 August)
-- I modified the memdebug system to return failure on memory allocation
- functions after a set amount of successful ones. This enables us to test
- out-of-memory situations in a controlled manner and we can make sure that
- curl/libcurl behaves good in those.
-
- This made me find and fix several spots where we did not cleanup properly
- when bailing out due to errors (low memory).
-
-- Corrected test case 74. Made using -o with bad #[num] codes complain and
- bail out. Made #[num] support numbers larger than 9 as well. Added test
- case 86 for a proper range globbing test as well.
-
-Version 7.10.7-pre4 (12 August 2003)
-
-Daniel (12 August)
-- curl_version_info() now returns a flag if libcurl was built with asynch DNS
- support, and this is now also displayed with 'curl -V'.
-
-- Added a few new man pages to the docs/libcurl dir: curl_share_init,
- curl_share_setopt, curl_share_cleanup, libcurl-easy and libcurl-share.
-
-Daniel (11 August)
-- Mike Cherepov made the local binding code work for Windows, which makes
- the option CURLOPT_INTERFACE work on Windows as well.
-
-- Vincent Sanders updated the fopen.c example code a lot.
-
-- --proxy-ntlm is now supported by the curl tool. It forces the proxy
- authentication to be made using NTLM. It does not yet work for HTTPS over
- proxies (or other proxy-tunneling options). Test case 81 and 82 do some
- simple initial ntlm testing.
-
-- Found and fixed a minor memory leak on re-used connections with
- proxy-authentication.
-
-- I removed -@ and -Z as valid short options. They were very rarely used (@
- wasn't even documented).
-
-- Serge Semashko introduced CURLOPT_PROXYAUTH, and make it work when set to
- CURLAUTH_NTLM and/or CURLAUTH_BASIC. The PROXAUTH is similar to HTTPAUTH,
- but is for the proxy connection only, and HTTPAUTH is for the remote host.
-
-- Fixed loading of cookies with blank contents from a cookie jar. Also made the
- cookie functions inform on added and skipped cookies (for cookie debugging).
-
-Version 7.10.7-pre3 (8 August 2003)
-
-Daniel (8 August)
-- Applied David Byron's fix for file:// URLs with drive letters included.
-
-- I added the --ftp-create-dirs to the client code, which activates Early's
- CURLOPT_FTP_CREATE_MISSING_DIRS option, and wrote test case 147 to verify
- it. Added the option to the curl.1 man page too. Added the option to the
- curl_easy_setopt.3 man page too.
-
-Daniel (7 August)
-- Test case 60 failed on ia64 and AMD Opteron. Fixed now.
-
-- Fixed a printf problem that resulted in urlglobbing bugs (bug #203827 in the
- debian bug tracker). Added test case 74 to verify the fix and to discover if
- this breaks in the future.
-
-- "make distcheck" works again.
-
-Version 7.10.7-pre2 (6 August 2003)
-
-Daniel (5 August)
-- Duncan Wilcox helped me verify that the latest incarnation of my ares patch
- builds fine on Mac OS X (see the new lib/README.ares) file for all details.
-
-- Salvatore Sorrentino filed bug report #783116 and Early Ehlinger posted a
- bug report to the libcurl list, both identifying a problem with FTP
- persitent connections and how the dir hiearchy was not properly reset
- between files.
-
-- David Byron's thoughts on a fixed Makefile in tests/ were applied.
-
-- Jan Sundin reported a case where curl ignored a cookie that browsers don't,
- which turned up to be due to the number of dots in the 'domain'. I've now
- made curl follow the the original netscape cookie spec less strict on that
- part.
-
-Daniel (4 August)
-- Dirk Manske added cookie support for the experimental, hidden and still
- undocumented share feature!
-
-- Mark Fletcher provided an excellent bug report that identified a problem
- with FOLLOWLOCATION and chunked transfer-encoding, as libcurl would not
- properly ignore the body contents of 3XX response that included the
- Location: header.
-
-Early (6 August)
-- Added option CURLOPT_FTP_CREATE_MISSING_DIRS
- This option will force the target file's path to be created if it
- does not already exist on the remote system.
-
- Files affected:
- - include/curl/curl.h
- Added option CURLOPT_FTP_CREATE_MISSING_DIRS
- - lib/ftp.c
- Added function ftp_mkd, which issues a MKD command
- Added function ftp_force_cwd, which attempts a CWD,
- and does a MKD and retries the CWD if the original CWD
- fails
- Modified ftp_perform() to call its change directory function
- through a pointer. The pointer points to ftp_cwd by default,
- and is modified to point to ftp_force_cwd IFF
- data->set.ftp_create_missing_dirs is not 0.
- - lib/url.c
- Modified Curl_setopt to recognize CURLOPT_FTP_CREATE_MISSING_DIRS
- - lib/urldata.h
- Added ftp_create_missing_dirs to struct UserDefined
-
-- Minor Bugfix for CURLOPT_TIMECONDITION with FTP - if the file was not
- present to do the time comparison, it would fail.
- Files affected:
- - lib/ftp.c
- In ftp_perform(), the call to ftp_getfiletime() used to be followed
- by
- if (result)
- return result;
- And then by the code that actually did the time comparison.
- The code that did the comparison handled the case where the filetime
- was not available (as indicated by info.filetime < 0 or set.timevalue
- < 0), so I replaced the if (result) return result with a switch(result)
- that allows CURLE_FTP_COULDNT_RETR_FILE to fall through to the
- normal time comparison.
-
-Daniel (3 August)
-- When proxy authentication is used in a CONNECT request (as used for all SSL
- connects and otherwise enforced tunnel-thru-proxy requests), the same
- authentication header is also wrongly sent to the remote host.
-
- This is a rather significant info leak. I've fixed it now and mailed a patch
- and warning to the mailing lists.
-
-Daniel (1 August)
-- David Byron provided a patch to make 7.10.6 build correctly with the
- compressed hugehelp.c source file.
-
-Version 7.10.7-pre1 (31 July 2003)
-
-Daniel (30 July)
-- Jörg Müller-Tolk updated the VC makefile.
-
-- Daniel Noguerol made the ftp code output "Accept-Ranges: bytes" in similar
- style like other faked HTTP headers when NOBODY and HEADER are used. I
- updated two corresponding test cases too.
-
-- Marty Kuhrt pointed out a compilation problem on VMS due to my having
- changed a type from long to time_t, and I'm now changing it back to work
- more portably...
-
- He also indicated that distributing the src/hugehelp.c in a compressed state
- like I acccidentally did may not be the smartest move... I've now fixed the
- distribute procudere to automaticly generate an uncompressed version when I
- make release archives.
-
-Daniel (29 July)
-- Gisle Vanem brought changes to the mkhelp script for the generation of the
- compressed help text on some platforms.
-
-Version 7.10.6 (28 July 2003)
-
-Daniel (28 July)
-- François Pons brought a patch that once again made curl deal with ftp and
- "double slash" as indicating the root directory. In the RFC1738-fix of April
- 30, that ability was removed (since it is not the "right" way). So, starting
- now we can list the root dir of an ftp server both these ways:
-
- curl ftp://server.com/%2f as well as
- curl ftp://server.com//
-
-Daniel (24 July)
-- Henry Bland pointed out that we included sys/resource.h without good reason
- in several source files. Without it included, QNX builds better...
-
-- Andrés García updated the mingw makefiles.
-
-Daniel (23 July)
-- Tracy Boehrer experienced DNS cache problems and did some nice debugging
- and tracking which made it easy for me to correct the problem and Tracy
- could verify that it did cure the problem! When re-using a connection we
- now make sure we don't re-use the 'connect_addr' struct.
-
-- Daniel Kouril corrected the GSS-Negotiate code.
-
-- Juan F. Codagnone provided fixes to allow curl to build fine on Windows
- again.
-
-Daniel (22 July)
-- Edited the curl/curl.h include file to build on Windows properly.
-
-Daniel (21 July)
-- Moved the proxy credentials from the SessionHandle struct to the connectdata
- struct, to make multiple proxy connections with differerent user names work.
-
-- Adjusted the NTLM code to support proxy functionality.
-
-- Made the krb4 stuff compile with the user+password fields moved.
-
-Version 7.10.6-pre4 (21 July 2003)
-
-Daniel (20 July)
-- David Gardner pointed out in bug report 770755 that using the FTP command
- CWD with a blank argument is a bad idea and I made libcurl skip empty path
- segments starting now.
-
-Daniel (18 July)
-- Cris pointed out that my fix on July 16th didn't work fully. His pointing
- out this (and his patch) also made me realize that we have a very similar
- bug in the FTP connection re-use code. We must store a separate user and
- password field for each connection we keep (at least for FTP and HTTP+NTLM
- connections, so I made us do this unconditionally).
-
-- Since NTLM authenticates connections instead of single requests, I had to
- re-arrange how we store the NTLM data and I had to improve the test suite to
- finally work properly with persistancy to make the NTLM tests run fine
- again. This also forced me to have to update lots of HTTP test cases.
-
-Daniel (16 July)
-- Cris Bailiff's bug report 768275 pointed out that using Basic auth with
- wrong user+password caused an endless loop. Fixed now. He also found out that
- we didn't properly authenticate connections with NTLM. Fixed too.
-
-- Dan Winship provided fixes for the NTLM code.
-
-Daniel (5 July)
-- Doug Kaufman provided additional fixes for the DOS port.
-
-Daniel (4 July)
-- Rick Richardson pointed out that using setvbuf() to achive non-buffering
- on output is no-good for SCO Xenix and other unixes. We switched over to
- using plain fflush() instead.
-
-- Dan Grayson pointed out that we set the CURL_CA_BUNDLE variable wrongly in
- the configure script, and I had to change some build stuff to make the new
- way work.
-
-- Peter Sylvester's patch was applied that introduces the following:
-
- CURLOPT_SSL_CTX_FUNCTION to set a callback that gets called with the
- OpenSSL's ssl_ctx pointer passed in and allow a callback to act on it. If
- anything but CURLE_OK is returned, that will also be returned by libcurl
- all the way back. If this function changes the CURLOPT_URL, libcurl will
- detect this and instead go use the new URL.
-
- CURLOPT_SSL_CTX_DATA is a pointer you set to get passed to the callback set
- with CURLOPT_SSL_CTX_FUNCTION.
-
-Daniel (1 July)
-- David Byron provided a patch that allows a client to quit the test suite's
- HTTP server.
-
-- Gisle Vanem found and patched a lib handle leak in the ldap code.
-
-Daniel (25 June)
-- More NTLM-improvements. Less code. Smaller packets back and forth.
-
-Daniel (23 June)
-- Eric Glass provided us with a better doc on NTLM details, and I added more
- comments and clarified the current code more. Using the new knowledge, we
- should be able to make the NTLM stuff work even better.
- Eric's original URL: http://davenport.sourceforge.net/ntlm.html
- Version stored and provided at curl site: http://curl.haxx.se/rfc/ntlm.html
-
-- Fixed the minor compile problems pre3 had if built without GSSAPI and/or
- SSL.
-
-Version 7.10.6-pre3 (19 June 2003)
-
-Daniel (19 June)
-- Made curl use curl_free() on memory returned by curl_getenv(), as this
- should theoreticly make it possibly to build and run curl and libcurl with
- different memory allocation schemes with no problems.
-
-Daniel (18 June)
-- Improved the mkhelp.pl a bit further to make a nicer hugehelp text and to
- include a better comment in the top for the gzip compressed version.
-
-Daniel (17 June)
-- CURLOPT_HTTPAUTH is now a bitmask, in which you set which authentication
- type(s) you want to use. If more than one is set, libcurl will use one of
- the selected one and the one it considers is more secure. Test case 67 and
- 68 (for NTLM) were fixed and we've reduced a round-trip for specific --ntlm
- featches, and test case 69 and 70 were added for testing authentication
- "picking". --anyauth is the new command line tool option, and I also added
- --basic for completeness (that's the default type).
-
-- Fixed the runtests.pl script to use the info provided by the new curl -V
- output.
-
-- --enable-debug now sets the CURLDEBUG define instead of MALLOCDEBUG, as it
- is meant to be a generic debug conditional.
-
-- curl_version_info() can now return CURL_VERSION_DEBUG as a feature bit, to
- indicate that the library was built with CURLDEBUG set.
-
-- Ralph Mitchell found out that some web applications very badly uses white
- spaces in Location: redirects, and apparently IE is a browser (the only
- one?) that supports this abomination. Based on Ralph's patch, I added code
- that now attempts to replace white spaces with the proper "%20" or "+".
- Test case 40 and 42 were added to verify my changes.
-
-- curl -V now also outputs a list of features the available library offers (if
- any).
-
-- The curl_version() string now includes "GSS" if libcurl is built with GSSAPI
- support.
-
-- David Orrell reported that libcurl still crashed when sending HUGE requests
- over HTTPS... I fixed.
-
-Version 7.10.6-pre2 (16 June 2003)
-
-Daniel (16 June)
-- curl_version_info() now returns bitmasked information weather NTLM and
- GSSNEGOTIATE are supported, since it is doomed to vary on different
- installatiions.
-
-- I remade the HTTP Digest code to use the MD5-code provided by OpenSSL if
- that is present, and only use our own MD5-code if it isn't.
-
-Daniel (13 June)
-- More NTLM help, fixes and patches from Cris Bailiff.
-
-- Marty Kuhrt brought include fixes for making VMS builds warning-free.
-
-Daniel (12 June)
-- NTLM authentication works somewhat against the test servers provided by
- Mathias Axelsson and Cris Bailiff. Use by setting CURLOPT_HTTPAUTH to
- CURLAUTH_NTLM to libcurl, or --ntlm for the curl tool. Test case 67 and 68
- were added for this. NTLM-support requires OpenSSL.
-
-- Dan Fandrich provided a patch, that granted that gzip and libz are available
- at build-time, compresses the hugehelp text in the curl command line and
- uncompresses it at request. Saves some ~60K in the final output executable.
-
-Daniel (11 June)
-- Long day of fighting the NTLM demons.
-
-Daniel (10 June)
-- Modified how to set auth type to libcurl. Now use CURLOPT_HTTPAUTH instead,
- and pick method. Supported ones currently are:
- CURLAUTH_BASIC - default selection
- CURLAUTH_DIGEST - formerly CURLOPT_HTTPDIGEST
- CURLAUTH_GSSNEGOTIATE
-
-- Daniel Kouril added HTTP GSS-Negotiate authentication support, as defined in
- the IETF draft draft-brezak-spnego-http-04.txt. In use already by various
- Microsoft web applications. --negotiate is the new family member. To take
- advantage of this, you need one of these packages:
-
- o Heimdal Kerberos5 http://www.pdc.kth.se/heimdal/heimdal.html
- o GSSAPI from Globus http://www.globus.org/
- o GSSAPI libraries from MIT Kerberos5 http://web.mit.edu/kerberos/www/
-
-- A missing ending bracket (']') while doing URL globbing could lead to a
- segfault. While fixing this, I also introduced better error reporting in the
- globbing code. (All this is application code outside libcurl.)
-
-Daniel (6 June)
-- David Orrell found out that sending a huge GET request over HTTPS could
- make libcurl fail and return an error code.
-
-Daniel (2 June)
-- Richard Bramante found out that "Content-Length: 0" was not properly used by
- libcurl if the response-headers indicated that the connection would be
- closed.
-
-- David Byron's patch was applied, that makes the --progress-bar take the
- local size into account when doing resumed downloads.
-
-- Feedback from Serge Semashko made me change the error message returned when
- CURLE_HTTP_RETURNED_ERROR is returned.
-
-- Anonymous in bug report #745122 pointed out that we should really be using
- SSL_CTX_set_options(... SSL_OP_ALL) to work around flaws in existing SSL
- implementations.
-
-Daniel (27 May)
-- Andreas Ley and Rich Gray helped me point out that no version of HP-UX has
- the sys/select.h header file so including it unconditionally in curl/multi.h
- is not a good thing. Now we check for HPUX and avoid using that header on
- such systems.
-
-- Rudy Koento experienced problems with curl's recent habit of POSTing data in
- two separate send() calls, first the headers and then the data. I've now
- made a fix that for static and known content that is less than 100K in size,
- everything is now sent in one single system call again. This is also better
- for network performance reasons.
-
-- I modified the main makefile to not build the test suite and a few other
- unnecessary things by default. Now, the test suite is built when 'make test'
- is run. This reduces build time for those who don't care for the test
- suite, and it also reduces confusion for people using platforms where the
- test suite build fails!
-
-Daniel (26 May)
-- Chris Lewis pointed out a flaw in the #ifdefs in curl/multi.h for Windows,
- which is now corrected.
-
-- Jis Joy found another flaw in the SOCK5 code, as libcurl treated the socks5
- proxy a little too much like as if it was a http proxy.
-
-Daniel (23 May)
-- Ricardo Cadime found a socket leak when listing directories without
- contents. Test cases 144 and 145 were added to verify the fix.
-
-- Rudy Koento found yet another problem when a HTTP server returns only a
- single-line of contents without any headers at all. libcurl then failed to
- count the data, thus returning error 52 "no contents". Test case 66 was
- added to verify that we now do right.
-
-Version 7.10.6-pre1 (23 May 2003)
-
-Daniel (23 May)
-- Jis in bug report #741841, fixed a bug in the SOCKS5 proxy-using code.
-
-Daniel (22 May)
-- David Remahl set up a test-server for me providing Digest authentication,
- and I wrote the first working code that support it. The test suite was
- modified slightly as well to work better for it and --digest was added to
- the command line options (and CURLOPT_HTTPDIGEST to the library)... RFC2617
- has all the gory details.
-
-Daniel (21 May)
-- David Balazic pointed out that curl_unescape() didn't check that %-codes
- were correctly followed by two hexadecimal digits when it unescape strings.
- Now, we do the check and only %XX codes are unescaped if the X letters are
- hexadecimals.
-
-- Gisle Vanem made curl build with djgpp on DOS.
-
-- Gisle Vanem improved the mkhelp.pl script to make a nicer manual that is
- shown with curl -M.
-
-Daniel (20 May)
-- Gisle Vanem provided a fix that makes libcurl more conservative, not
- expecting h_aliases of the hostent struct to always be non-NULL.
-
-Daniel (19 May)
-- As requested by Martin Michlmayr in Debian bug report #193630, libcurl now
- supports user name and password in the proxy environment variables. Added
- test case 63 to verify this.
-
-Version 7.10.5 (19 May 2003)
-
-Daniel (15 May)
-- Changed the order for the in_addr_t testing, as 'unsigned long' seems to be
- a very common type inet_addr() returns.
-
-Daniel (14 May)
-- George Comninos provided a fix that calls the progress meter when waiting
- for FTP command responses take >1 second. It'll make applications more
- "responsive" even when dealing with very slow ftp servers.
-
-Daniel (12 May)
-- George Comninos pointed out that libcurl uploads had two quirks:
- o when using FTP PORT command, it used blocking sockets!
- o it could loop a long time without doing progress meter updates
- Both items are fixed now.
-
-Daniel (9 May)
-- Dan Fandrich changed CURLOPT_ENCODING to select all supported encodings if
- set to "". This frees the application from having to know which encodings
- the library supports.
-
-- Dan Fandrich pointed out we had three unnecessary files in CVS that is
- generated with libtoolize, so they're now removed and libtoolize is invoked
- accordingly in the buildconf script.
-
-- Avery Fay found out that the CURLOPT_INTERFACE way of first checking if the
- given name is a network interface gave a real performance penalty on Linux,
- so now we more appropriately first check if it is an IP number and if so
- we don't check for a network interface with that name.
-
-- CURLOPT_FTP_USE_EPRT added. Set this to FALSE to disable libcurl's attempts
- to use EPRT and LPRT before the traditional PORT command. The command line
- tool sets this option with '--disable-eprt'.
-
-Version 7.10.5-pre2 (6 May 2003)
-
-Daniel (6 May)
-- Kevin Delafield reported another case where we didn't correctly check for
- EAGAIN but only EWOULDBLOCK, which caused badness on HPUX.
-
-Daniel (4 May)
-- Ben Greear noticed that the check for 'writable argv' exited the configure
- script when run for cross-compiling, which wasn't nice. Now it'll default to
- no and output a warning about the fact that it was not checked for.
-
-Daniel (2 May)
-- Added test case 62 and fixed some more on the cookie sending with a custom
- Host: header set.
-
-Daniel (1 May)
-- Andy Cedilnik fixed a few compiler warnings.
-
-- Made the "SSL read error: 5" error message more verbose, by adding code that
- queries the OpenSSL library to fill in the error buffer.
-
-Daniel (30 Apr)
-- Added sys/select.h include in the curl/multi.h file, after having been
- reminded about this by Rich Gray.
-
-- I made each test set its own server requirements, thus abandoning the
- previous system where the test number implied what server(s) to use for a
- specific test.
-
-- David Balazic made curl more RFC1738-compliant for FTP URLs, by fixing so
- that libcurl now uses one CWD command for each path part. A bunch of test
- cases were fixed to work accordingly.
-
-- Cookie fixes:
-
- A. Save domains in jars like Mozilla does. It means all domains set in
- Set-Cookie: headers are dot-prefixed.
- B. Save and use the 'tailmatch' field in the Mozilla/Netscape cookie jars
- (the second column).
- C. Reject cookies using illegal domains in the Set-Cookie: line. Concerns
- both domains with too few dots or domains that are outside the currently
- operating server host's domain.
- D. Set the path part by default to the one used in the request, if none was
- set in the Set-Cookie line.
-
- To make item C really good, I also made libcurl notice custom Host: headers
- and extract the host name set in there and use that as the host name for the
- site we're getting the cookies from. This allows user to specify a site's
- IP-address, but still be able to receive and send its cookies properly if
- you provide a valid Host: name for the site.
-
-Daniel (29 Apr)
-- Peter Kovacs provided a patch that makes the CURLINFO_CONNECT_TIME work fine
- when using the multi interface (too).
-
-Version 7.10.5-pre1 (23 Apr 2003)
-
-Daniel (23 Apr)
-- Upgraded to libtool 1.5.
-
-Daniel (22 Apr)
-- Peter Sylvester pointed out that curl_easy_setopt() will always (wrongly)
- return CURLE_OK no matter what happens.
-
-- Dan Fandrich fixed some gzip decompression bugs and flaws.
-
-Daniel (16 Apr)
-- Fixed minor typo in man page, reported in the Debian bug tracker.
-
-Daniel (15 Apr)
-- Fixed some FTP tests in the test suite that failed on my Solaris host, due
- to the config.h not being included before the system headers. When done that
- way, it did get a mixed sense of if big files are supported or not and then
- stat() and fstat() (as used in test case 505) got confused and failed to
- return a proper file size.
-
-- Formposting a file using a .html suffix is now properly set to Content-Type: text/html.
-
-Daniel (14 Apr)
-- Fixed the SSL error handling to return proper SSL error messages again, they
- broke in 7.10.4. I also attempt to track down CA cert problems and then
- return the CURLE_SSL_CACERT error code.
-
-- The curl tool now intercepts the CURLE_SSL_CACERT error code and displays
- a fairly big and explanatory error message. Kevin Roth helped me out with
- the wording.
-
-Daniel (11 Apr)
-- Nic Hines provided a second patch for gzip decompression, and fixed a bug
- when deflate or gzip contents were downloaded using chunked encoding.
-
-- Dan Fandrich made libcurl support automatic decompression of gzip contents
- (as an addition to the previous deflate support).
-
-- I made the CWD command during FTP session consider all 2xy codes to be OK
- responses.
-
-Daniel (10 Apr)
-- Vlad Krupin fixed a URL parsing issue. URLs that were not using a slash
- after the host name, but still had "?" and parameters appended, as in
- "http://hostname.com?foobar=moo", were not properly parsed by libcurl.
-
-Daniel (9 Apr)
-- Made CURLOPT_TIMECONDITION work for FTP transfers, using the same syntax as
- for HTTP. This then made -z work for ftp transfers too. Added test case 139
- and 140 for verifying this.
-
-- Getting the file date of an ftp file used the wrong time zone when
- displayed. It is supposedly always GMT. Added test case 141 for this.
-
-- Made the test suite's FTP server support MDTM.
-
-- The default DEBUGFUNCTION, as enabled with CURLOPT_VERBOSE now outputs
- CURLINFO_HEADER_IN data as well. The most notable effect from this is that
- using curl -v, you get to see the incoming "headers" as well. This is
- perhaps most useful when doing ftp.
-
-Daniel (8 Apr)
-- James Bursa fixed a flaw in the Content-Type extraction code, which missed
- the first letter if no space followed the colon.
-
-- Magnus Nilsson pointed out that share.c was missing in the MSVC project
- file.
-
-Daniel (6 Apr)
-- Ryan Weaver provided a patch that makes the CA cert bundle not get installed
- anymore when 'configure --without-ssl' has been used.
-
-Daniel (4 Apr)
-- Martijn Broenland found another cases where a server application didn't
- like the boundary string used by curl when foing a multi-part/formpost. We
- modified the boundary string to look like the one IE uses, as this is
- probably gonna make curl work with more applications.
-
-Daniel (3 Apr)
-- Kevin Roth reported that a bunch of tests fails on cygwin. One set fails
- when using perl 5.8 (and they run fine with perl 5.6), and another set
- failed because of an artifact in the test suite's FTP server that I
- corrected. It turned out the FTP server code was still having a file opened
- while the main test script removed it and invoked the HTTP server that
- attempted to create the same file name of the file the FTP server kept open.
- This operation works fine on unix, but not on cygwin.
-
-Version 7.10.4 (2 Apr 2003)
-
-Daniel (1 Apr)
-- Added test case 505 to exercise FTP upload with rename done with libcurl,
- and for that I had to extend the test suite's FTP server to deal with the
- RNFR and RNTO commands.
-
-Daniel (31 Mar)
-- Even more SSL config check modifications after Richard's testing.
-
-Version 7.10.4-pre6 (31 Mar 2003)
-
-Daniel (31 Mar)
-- More fixes for the SSL session ID cache checks when SSL configs are changed
- between connections. Based on tests and talks with Richard Bramante.
-
-- Guillaume Cottenceau provided a patch that added CURLOPT_UNRESTRICTED_AUTH.
- When enabled, it will prevent libcurl from limiting to which host it sends
- user+password to when following locations. By default, libcurl only sends
- name and password to the original host used in the first URL, but with this
- option set it will send the auth info to all hosts it follows location
- headers to. The new tool command line option for this is named
- "--location-trusted".
-
-- Frankie Fong reported a problem with libcurl if you re-used an easy handle
- with a proxy, and you first made a https:// connction to a host and then
- switched to a http:// one to the same host. libcurl would then wrongly re-use
- the same connection for it and fail to get the second URL properly
-
-Daniel (29 Mar)
-- Dan Shearer's fix that makes curl complain if invoked with nothing but "curl
- -O" was applied.
-
-Daniel (26 Mar)
-- Bryan Kemp was friendly enough to lend me an account on his Redhat 9 box and
- I could fix the configure problems on redhat 8.1 and 9 in no time thanks to
- this. Thanks a bunch Bryan!
-
-Daniel (25 Mar)
-- Renamed configure.in to configure.ac
-
-Version 7.10.4-pre5 (25 Mar 2003)
-
-Daniel (25 Mar)
-- Richard Bramante provided a fix for a handle re-use problem seen when you
- change options on an SSL-enabled connection between requests. Previously,
- changing peer verification or host verification and similar things was not
- taken into account when a connection were checked for re-use and thus
- enabling stricter check between requests on a re-used connection made no
- difference and the connection would thus be used erroneously.
-
-Daniel (24 Mar)
-- Götz Babin-Ebell pointed out that the ca-bundle.crt file contained a
- certificate from Trustcenter that was a demo certificate only that was never
- indended to be part of a CA bundle.
-
-Daniel (21 Mar)
-- Life is a mystery. Within a time period of 17 hours, Tim Pope and Michael
- Churchill filed one bug report each, both identifying problems with a second
- transfer when doing persistant transfers re-using a connection. Tim's one is
- #706624, labeled "Multiple uploads per handle fail" and Michael's #707003
- "Does not send Authorization: header when reusing connection". I could track
- both down to the same piece of logic and it turned out libcurl was not using
- new settings properly when re-using an existing connection. This concerned
- both uploading and downloading and involved exactly those pieces these two
- reports identified. This code has been this faulty since the day I
- introduced persistant connection support in libcurl, more than 2 years ago.
-
-Daniel (20 Mar 2003)
-- Five year anniversary. Today five years ago, the first ever curl release saw
- the light of day.
-
-Daniel (17 Mar)
-- Andy Cedilnik corrected flaws in some libcurl example-usage sources.
-
-Daniel (16 Mar)
-- Juan F. Codagnone reported that the fix from March 2nd was incomplete.
-
-- Added code to the configure.in to check for select() argument types. I've
- not made any code use the results just yet though.
-
-Daniel (15 Mar)
-- Gisle Vanem provided two patches to build better on Windows.
-
-- Adjusted the test suite code to better make sure that the server(s) required
- for a specific test is properly started before the test case is attempted.
- Many tests now run a lot faster than before.
-
-Daniel (14 Mar)
-- Another configure.in adjustment made the configure detect functions properly
- on HPUX now.
-
-Daniel (13 Mar)
-- Philippe Raoult fixed pre4-compile quirks for FreeBSD.
-
-Version 7.10.4-pre4 (13 Mar 2003)
-
-Daniel (13 Mar)
-- Added a backup-check for functions that aren't found by AC_CHECK_FUNCS()
- as I believe some checks on HPUX need this. At least some of the info given
- to us by Rick Jones seemed to indicate this.
-
-Daniel (12 Mar)
-- Thomas Tonino found out that if you used the curl tool to do PUT operations
- as in 'curl www.foo.com/dir/ -T file' and the file name included for example
- space or other characters that don't belong in URLs, curl did not properly
- URL encode them before using them in the URL.
-
-- Added an option to configure called --enable-libgcc that simply adds -lgcc
- to the LIBS variable, as this seems to be a common problem.
-
-- I modified the configure.in file, so that the headers are now checked in an
- order of "viality". We must also make sure to use the "default headers"
- parameter to AC_CHECK_HEADERS() so that headers are checked with the proper
- prerequisites included (i.e all the major and generally important header
- files are included there by default). This might be what we need for various
- Sun, HP, AIX and Tru64 systems to behave good again on the header check
- front.
-
-- Rick Jones pointed out a few compiler warnings on HP-UX that I addressed.
-
-- I made the configure --help output nicer by using AC_HELP_STRING() a lot
- more.
-
-Daniel (11 Mar)
-- Christophe Demory fixed the socket sending code to work better on HP-UX
- when sending data to a socket that would block. It then returns EAGAIN, not
- EWOULDBLOCK.
-
-- Richard Gorton improved the seeding function for systems without a good
- and reliable random source.
-
-- Richard Gorton fixed a few warnings that popped up when you built curl
- using the Sun compiler on a 64bit SPARC platform.
-
-- Martin C. Martin fixed a case where a connect failure using the multi
- interface didn't produce a human readable error string.
-
-Daniel (10 Mar)
-- Reverted ltmain.sh back to libtool 1.4.2 status again, as the 1.4.3 version
- broke the build on numerous platforms. It seems that libtool 1.4.3 puts some
- requirements on what versions of the other tools (autoconf + automake) that
- I am not familiar with and thus I couldn't fulfill at this point.
-
- Yes, this is more than mildly frustrating.
-
-Daniel (7 Mar)
-- Run libtoolize version 1.4.3.
-
-Version 7.10.4-pre3 (4 Mar 2003)
-
-Daniel (3 Mar)
-- Added share.obj to the VC6 and Borland libcurl makefiles.
-
-- Troels Walsted Hansen found and investigated a problem with libcurl on AIX,
- presumably only on 4.3 or later. gethostbyname_r() is not returning data
- that is possible to "keep" and cache the way libcurl does. But instead these
- versions of AIX uses a gethostbyname() that works thread-safely we can
- instead use the ordinary gethostbyname() and our pack_hostent() approach to
- achieve what we want. The configure script now attempts to detect AIX 4.3 or
- later to adjust for this.
-
-Daniel (2 Mar)
-- Juan F. Codagnone found a problem introduced in 7.10.3 when you first did a
- POST and then back to a GET using the same easy handle.
-
-Daniel (28 Feb)
-- Removed the strequal and strnequal defines from curl/curl.h header. They
- were never meant for the public header anyway. Philippe Raoult brought it
- up.
-
-- James Bursa fixed the RISC OS build.
-
-Daniel (27 Feb)
-- Avery Fay pointed out the very misleading curl_multi_info_read man page, and
- I updated it to become more accurate.
-
-- Salvatore Sorrentino found a problem with FTP downloading that turned out to
- be his FTP server returning size zero (0 bytes) when SIZE was used on a file
- while being in BINARY mode. We now make a second check for the actual size
- by scanning the RETR reply anyway, even if the SIZE command returned 0.
-
-Daniel (26 Feb)
-- Kyle Sallee reported a case where he would do a transfer that didn't update
- the progress meter properly. It turned out to be a case where libcurl would
- loop a little too eagerly in the tranfer loop, which isn't really good for
- the APIs, especially not the multi API.
-
-Version 7.10.4-pre2 (24 Feb 2003)
-
-Daniel (24 Feb)
-- Kjetil Jacobsen found out that setting CURLOPT_MAXCONNECTS to a value higher
- than 5 could cause a segfault.
-
-- I believe I fixed the 'Expect: 100-continue' behavior that has been broken
- for a while (I think since my change dated Dec 10 2002). When this header is
- used, libcurl should wait for a HTTP 100 (or timeout) before sending the
- post/put data.
-
-Daniel (14 Feb)
-- Matthew Clarke provided some info what to modify to make curl build
- flawlessly on AIX 3.2.5.
-
-- Martin C. Martin found and fixed a problem in the multi interface when
- running on Windows and trying to connect to a port without a listener.
-
-Daniel (13 Feb)
-- Christopher R. Palmer fixed Curl_base64_encode() to deal with zeroes in the
- data to encode.
-
-Daniel (4 Feb)
-- Jean-Philippe added the first code that enables the 'share' system. This
- should now enable sharing of DNS data between two curl easy handles.
-
-- Incorporated Nico Baggus' fixes to again compile flawlessly on VMS.
-
-- James Bursa corrected a bad comment in the public include file curl/multi.h
-
-- Peter Forret reported one of those error:00000000 cases in libcurl again
- when connecting to a HTTPS site, and this time I did discover some oddities
- in how curl reports SSL errors back. It could miss showing the actual error.
-
-Version 7.10.4-pre1 (3 Feb 2003)
-
-Daniel (3 Feb)
-- Removed things in the docs saying capath doesn't work on Windows, as Julian
- Noble told us it works fine.
-
-Daniel (31 Jan)
-- Kevin Roth fixed the zlib build stuff in the Mingw32 makefile.
-
-Daniel (30 Jan)
-- Kevin Roth found out that curl on Windows always checked for the CA cert
- bundle using the environment variable and the path scan, even though
- -k/--insecure was used.
-
-- Hamish Mackenzie pointed out that curl only did strict host name verifying
- if capath or cainfo was used. Now it'll always do it unless -k / --insecure
- is used!
-
-- Pavel Cenek pointed out that the Content-Type extraction was done wrongly
- as the full string was not fetched. Added test case 57 to verify that curl
- does it right now.
-
-Daniel (29 Jan)
-- Jamie Wilkinson provided a patch that now makes curl attempt to clear out
- "sensitive" command line arguments so that they don't appear in ps outputs
- (only on platforms that allow writing to argv[]).
-
-- John McGowan found out that the DEBUGFUNCTION could be called with bad
- arguments and thus cause the --trace outputs to go wrong.
-
-- Removed all the emacs local variables from all files. Mats Lidell provided
- the new sample.emacs file (for a sample of what to include in your .emacs)
- and the curl-style.el that sets a better c-style for editing curl sources.
-
-- Dave Halbakken found a problem with FTP downloads that could accidently
- return CURLE_PARTIAL_FILE when curl_easy_perform() was called with NOBODY
- set TRUE.
-
-Daniel (27 Jan)
-- The fopen.c example was flawed as Nick Humfrey noticed, and I fixed it to
- work again.
-
-Daniel (24 Jan)
-- Bertrand Demiddelaer found and fixed a memory leak (the content-type string)
- when following locations.
-
-Daniel (22 Jan 2003)
-- Ian Wilkes and Legoff Vincent both independently provided fixes for making
- curl/multi.h work properly when compiled with a C++ compiler.
-
-Daniel (20 Jan 2003)
-- Fixed 'buildconf' to check version number of the required tools before
- they're actually used.
-
-- Wrote 'testcurl.sh', a script targeted for automatic and distributed curl
- tests on various platforms.
-
-- David Thiel pointed out that the .netrc file was not being dealt with
- properly anymore. I broke this in the password prompting "fix".
-
-- Markus F.X.J. Oberhumer patched libcurl to allocate the scratch buffer only
- on demand and thus we save 32KB in each curl handle that don't use that
- buffer. This need appeared when some people started using thousands of
- simultaneous curl handles... :-)
-
-Daniel (16 Jan 2003)
-- Markus Oberhumer fixed curl-config --cflags when the includedir was not
- /usr/include.
-
-- Markus Oberhumer fixed CURLINFO_PRIVATE to properly return NULL if it was
- set to NULL!
-
-Version 7.10.3 (14 Jan 2003)
-
-Daniel (10 Jan 2003)
-- Steve Oliphant pointed out that test case 105 did not work anymore and this
- was due to a missing fix for the password prompting.
-
-Version 7.10.3-pre6 (10 Jan 2003)
-
-Daniel (9 Jan 2003)
-- Bryan Kemp pointed out that curl -u could not provide a blank password
- without prompting the user. It can now. -u username: makes the password
- empty, while -u username makes curl prompt the user for a password.
-
-- Kjetil Jacobsen found a remaining connect problem in the multi interface on
- ipv4 systems (Linux only?), that I fixed and Kjetil verified that it fixed
- his problems.
-
-- memanalyze.pl now reads a file name from the command line, and no longer
- takes the data on stdin as before.
-
-Version 7.10.3-pre5 (9 Jan 2003)
-
-Daniel (9 Jan 2003)
-- Fixed tests/memanalyze.pl to work with file names that contain colons (as on
- Windows).
-
-- Kjetil Jacobsen quickly pointed out that lib/share.h was missing...
-
-Version 7.10.3-pre4 (9 Jan 2003)
-
-Daniel (9 Jan 2003)
-- Updated lib/share.c quite a bit to match the design document at
- http://curl.haxx.se/dev/sharing.txt a lot more.
-
- I'll try to update the document soonish. share.c is still not actually used
- by libcurl, but the API is slowly getting there and we can start
- implementing code that takes advantage of this system.
-
-Daniel (8 Jan 2003)
-- Updated share stuff in curl/curl.h, including data types, structs and
- function prototypes. The corresponding files in lib/ were also modified
- of course to remain compilable. Based on input from Jean-Philippe and also
- to make it more in line with the design document.
-
-- Jean-Philippe Barrette-LaPierre patched a very trivial memory leak in
- curl_escape() that would happen when realloc() returns NULL...
-
-- Matthew Blain provided feedback to make the --create-dirs stuff build
- properly on Windows.
-
-- Fixed the #include in tests/libtest/first.c as Legoff Vincent pointed out.
-
-Daniel (7 Jan 2003)
-- Philippe Raoult provided a patch that now makes libcurl properly support
- wildcard checks for certificate names.
-
-- Simon Liu added CURLOPT_HTTP200ALIASES, to let an application set other
- strings recognized as "HTTP 200" to allow http-like protocols to get
- downloaded fine by curl.
-
-- Now using autoconf 2.57 and automake 1.7.2
-
-- Doing "curl -I ftp://domain/non-existing-file" still outputed a date!
- Wayne Haigh reported.
-
-- The error message is now written properly with a newline in the --trace
- file.
-
-Daniel (6 Jan 2003)
-- Sterling Hughes fixed a possible bug: previously, if you called
- curl_easy_perform and then set the global dns cache, the global cache
- wouldn't be used. Pointed out by Jean-Philippe Barrette-LaPierre.
-
-- Matthew Blain's fixed the VC6 libcurl makefile to include better debug data
- on debug builds.
+++ /dev/null
-COPYRIGHT AND PERMISSION NOTICE
-
-Copyright (c) 1996 - 2003, Daniel Stenberg, <danielNOSPAMhaxx.se>.
-
-All rights reserved.
-
-Permission to use, copy, modify, and distribute this software for any purpose
-with or without fee is hereby granted, provided that the above copyright
-notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
-NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder shall not
-be used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization of the copyright holder.
+++ /dev/null
-Updated: June 17, 2003 (http://curl.haxx.se/docs/faq.html)
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
-FAQ
-
- 1. Philosophy
- 1.1 What is cURL?
- 1.2 What is libcurl?
- 1.3 What is cURL not?
- 1.4 When will you make curl do XXXX ?
- 1.5 Who makes cURL?
- 1.6 What do you get for making cURL?
- 1.7 What about CURL from curl.com?
- 1.8 I have a problem who do I mail?
-
- 2. Install Related Problems
- 2.1 configure doesn't find OpenSSL even when it is installed
- 2.1.1. native linker doesn't find openssl
- 2.1.2. only the libssl lib is missing
- 2.2 Does curl work/build with other SSL libraries?
- 2.3 Where can I find a copy of LIBEAY32.DLL?
- 2.4 Does cURL support Socks (RFC 1928) ?
-
- 3. Usage Problems
- 3.1 curl: (1) SSL is disabled, https: not supported
- 3.2 How do I tell curl to resume a transfer?
- 3.3 Why doesn't my posting using -F work?
- 3.4 How do I tell curl to run custom FTP commands?
- 3.5 How can I disable the Pragma: nocache header?
- 3.6 Does curl support ASP, XML, XHTML or HTML version Y?
- 3.7 Can I use curl to delete/rename a file through FTP?
- 3.8 How do I tell curl to follow HTTP redirects?
- 3.9 How do I use curl in my favorite programming language?
- 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
- 3.11 How do I POST with a different Content-Type?
- 3.12 Why do FTP specific features over HTTP proxy fail?
- 3.13 Why does my single/double quotes fail?
- 3.14 Does curl support javascript or pac (automated proxy config)?
-
- 4. Running Problems
- 4.1 Problems connecting to SSL servers.
- 4.2 Why do I get problems when I use & or % in the URL?
- 4.3 How can I use {, }, [ or ] to specify multiple URLs?
- 4.4 Why do I get downloaded data even though the web page doesn't exist?
- 4.5 Why do I get return code XXX from a HTTP server?
- 4.5.1 "400 Bad Request"
- 4.5.2 "401 Unauthorized"
- 4.5.3 "403 Forbidden"
- 4.5.4 "404 Not Found"
- 4.5.5 "405 Method Not Allowed"
- 4.5.6 "301 Moved Permanently"
- 4.6 Can you tell me what error code 142 means?
- 4.7 How do I keep user names and passwords secret in Curl command lines?
- 4.8 I found a bug!
- 4.9 Curl can't authenticate to the server that requires NTLM?
- 4.10 My HTTP request using HEAD, PUT or DELETE doesn't work!
- 4.11 Why does my HTTP range requests return the full document?
- 4.12 Why do I get "certificate verify failed" ?
-
- 5. libcurl Issues
- 5.1 Is libcurl thread-safe?
- 5.2 How can I receive all data into a large memory chunk?
- 5.3 How do I fetch multiple files with libcurl?
- 5.4 Does libcurl do Winsock initing on win32 systems?
- 5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?
- 5.6 What about Keep-Alive or persistent connections?
- 5.7 Link errors when building libcurl on Windows!
-
- 6. License Issues
- 6.1 I have a GPL program, can I use the libcurl library?
- 6.2 I have a closed-source program, can I use the libcurl library?
- 6.3 I have a BSD licensed program, can I use the libcurl library?
- 6.4 I have a program that uses LGPL libraries, can I use libcurl?
- 6.5 Can I modify curl/libcurl for my program and keep the changes secret?
- 6.6 Can you please change the curl/libcurl license to XXXX?
-
-==============================================================================
-
-1. Philosophy
-
- 1.1 What is cURL?
-
- cURL (or simply just 'curl') is a command line tool for getting or sending
- files using URL syntax. The name is a play on 'Client for URLs', originally
- with URL spelled in uppercase to make it obvious it deals with URLs. The
- fact it can also be pronounced 'see URL' also helped, it works as an
- abbrivation for "Client URL Request Library" or why not the recursive
- version: "Curl is a URL Request Library".
-
- Curl supports a range of common Internet protocols, currently including
- HTTP, HTTPS, FTP, FTPS, GOPHER, LDAP, DICT, TELNET and FILE.
-
- We spell it cURL or just curl. We pronounce it with an initial k sound:
- [kurl].
-
- NOTE: there are numerous sub-projects and related projects that also use the
- word curl in the project names in various combinations, but you should take
- notice that this FAQ is directed at the command-line tool named curl (and
- libcurl the library), and may therefore not be valid for other curl
- projects.
-
- 1.2 What is libcurl?
-
- libcurl is a reliable and portable library which provides you with an easy
- interface to a range of common Internet protocols.
-
- You can use libcurl for free in your application even if it is commercial
- or closed-source.
-
- 1.3 What is cURL not?
-
- Curl is *not* a wget clone even though that is a very common misconception.
- Never, during curl's development, have we intended curl to replace wget or
- compete on its market. Curl is targeted at single-shot file transfers.
-
- Curl is not a web site mirroring program. If you wanna use curl to mirror
- something: fine, go ahead and write a script that wraps around curl to make
- it reality (like curlmirror.pl does).
-
- Curl is not an FTP site mirroring program. Sure, get and send FTP with curl
- but if you want systematic and sequential behavior you should write a
- script (or write a new program that interfaces libcurl) and do it.
-
- Curl is not a PHP tool, even though it works perfectly well when used from
- or with PHP.
-
- Curl is not a single-OS program. Curl exists, compiles, builds and runs
- under a wide range of operating systems, including all modern Unixes (and a
- bunch of older ones too), Windows, Amiga, BeOS, OS/2, OS X, QNX etc.
-
- 1.4 When will you make curl do XXXX ?
-
- We love suggestions of what to change in order to make curl and libcurl
- better. We do however believe in a few rules when it comes to the future of
- curl:
-
- * Curl -- the command line tool -- is to remain a non-graphical command line
- tool. If you want GUIs or fancy scripting capabilities, you should look
- for another tool that uses libcurl.
-
- * We do not add things to curl that other small and available tools already
- do very fine at the side. Curl's output is fine to pipe into another
- program or redirect to another file for the next program to interpret.
-
- * We focus on protocol related issues and improvements. If you wanna do more
- magic with the supported protocols than curl currently does, chances are
- big we will agree. If you wanna add more protocols, we may very well
- agree.
-
- * If you want someone else to make all the work while you wait for us to
- implement it for you, that is not a very friendly attitude. We spend a
- considerable time already on maintaining and developing curl. In order to
- get more out of us, you should consider trading in some of your time and
- efforts in return.
-
- * If you write the code, chances are bigger that it will get into curl
- faster.
-
- 1.5 Who makes cURL?
-
- cURL and libcurl are not made by any single individual. Sure, Daniel
- Stenberg writes the major parts, but other persons' submissions are
- important and crucial. Anyone can contribute and post their changes and
- improvements and have them inserted in the main sources (of course on the
- condition that developers agree on that the fixes are good).
-
- The list of contributors in the docs/THANKS file is only a small part of all
- the people that every day provide us with bug reports, suggestions, ideas
- and source code.
-
- curl is developed by a community, with Daniel at the wheel.
-
- 1.6 What do you get for making cURL?
-
- Project cURL is entirely free and open. No person gets paid for developing
- curl. We do this voluntarily on our spare time.
-
- We get some help from companies. Contactor Data hosts the curl web site,
- Haxx owns the curl web site's domain and sourceforge.net hosts several
- project services we take advantage from, like the bug tracker, mailing lists
- and more.
-
- If you want to support our project with a donation or similar, one way of
- doing that would be to buy "gift certificates" at useful online shopping
- sites, such as amazon.com or thinkgeek.com. Another way would be to sponsor
- us through a banner-program or even better: by helping us coding,
- documenting, testing etc. You're welcome to send us a buck using paypal, as
- described here: http://curl.haxx.se/donation.html
-
- 1.7 What about CURL from curl.com?
-
- During the summer 2001, curl.com was busy advertising their client-side
- programming language for the web, named CURL.
-
- We are in no way associated with curl.com or their CURL programming
- language.
-
- Our project name curl has been in effective use since 1998. We were not the
- first computer related project to use the name "curl" and do not claim any
- first-hand rights to the name.
-
- We recognize that we will be living in parallel with curl.com and wish them
- every success.
-
- 1.8 I have a problem who do I mail?
-
- Please do not mail any single individual unless you really need to. Keep
- curl-related questions on a suitable mailing list. All available mailing
- lists are listed in the MANUAL document and online at
- http://curl.haxx.se/mail/
-
- Keeping curl-related questions and discussions on mailing lists allows
- others to join in and help, to share their ideas, contribute their
- suggestions and spread their wisdom. Keeping discussions on public mailing
- lists also allows for others to learn from this (both current and future
- users thanks to the web based archives of the mailing lists), thus saving us
- from having to repeat ourselves even more. Thanks for respecting this.
-
-
-2. Install Related Problems
-
- 2.1. configure doesn't find OpenSSL even when it is installed
-
- This may be because of several reasons.
-
- 2.1.1. native linker doesn't find openssl
-
- Affected platforms:
- Solaris (native cc compiler)
- HPUX (native cc compiler)
- SGI IRIX (native cc compiler)
- SCO UNIX (native cc compiler)
-
- When configuring curl, I specify --with-ssl. OpenSSL is installed in
- /usr/local/ssl Configure reports SSL in /usr/local/ssl, but fails to find
- CRYPTO_lock in -lcrypto
-
- Cause: The cc for this test places the -L/usr/local/ssl/lib AFTER
- -lcrypto, so ld can't find the library. This is due to a bug in the GNU
- autoconf tool.
-
- Workaround: Specifying "LDFLAGS=-L/usr/local/ssl/lib" in front of
- ./configure places the -L/usr/local/ssl/lib early enough in the command
- line to make things work
-
- Solution submitted by: Bob Allison <allisonbNOSPAMusers.sourceforge.net>
-
- 2.1.2. only the libssl lib is missing
-
- If all include files and the libcrypto lib is present, with only the
- libssl being missing according to configure, this is mostly likely because
- a few functions are left out from the libssl.
-
- If the function names missing include RSA or RSAREF you can be certain
- that this is because libssl requires the RSA and RSAREF libs to build.
-
- See the INSTALL file section that explains how to add those libs to
- configure. Make sure that you remove the config.cache file before you
- rerun configure with the new flags.
-
- 2.2. Does curl work/build with other SSL libraries?
-
- Curl has been written to use OpenSSL, although there should not be much
- problems using a different library. If anyone does "port" curl to use a
- different SSL library, we are of course very interested in getting the
- patch!
-
- 2.3. Where can I find a copy of LIBEAY32.DLL?
-
- That is an OpenSSL binary built for Windows.
-
- Curl uses OpenSSL to do the SSL stuff. The LIBEAY32.DLL is what curl needs
- on a windows machine to do https://. Check out the curl web site to find
- accurate and up-to-date pointers to recent OpenSSL DLLs and other binary
- packages.
-
- 2.4. Does cURL support Socks (RFC 1928) ?
-
- There is limited support for SOCKS5 for curl built with IPv6 support
- disabled.
-
-
-3. Usage problems
-
- 3.1. curl: (1) SSL is disabled, https: not supported
-
- If you get this output when trying to get anything from a https:// server,
- it means that the configure script couldn't find all libs and include files
- it requires for SSL to work. If the configure script fails to find them,
- curl is simply built without SSL support.
-
- To get the https:// support into a curl that was previously built but that
- reports that https:// is not supported, you should dig through the document
- and logs and check out why the configure script doesn't find the SSL libs
- and/or include files.
-
- Also, check out the other paragraph in this FAQ labeled "configure doesn't
- find OpenSSL even when it is installed".
-
- 3.2. How do I tell curl to resume a transfer?
-
- Curl supports resumed transfers both ways on both FTP and HTTP.
-
- Try the -C option.
-
- 3.3. Why doesn't my posting using -F work?
-
- You can't simply use -F or -d at your choice. The web server that will
- receive your post assumes one of the formats. If the form you're trying to
- "fake" sets the type to 'multipart/form-data', then and only then you must
- use the -F type. In all the most common cases, you should use -d which then
- causes a posting with the type 'application/x-www-form-urlencoded'.
-
- This is described in some detail in the MANUAL and TheArtOfHttpScripting
- documents, and if you don't understand it the first time, read it again
- before you post questions about this to the mailing list. Also, try reading
- through the mailing list archives for old postings and questions regarding
- this.
-
- 3.4. How do I tell curl to run custom FTP commands?
-
- You can tell curl to perform optional commands both before and/or after a
- file transfer. Study the -Q/--quote option.
-
- Since curl is used for file transfers, you don't use curl to just perform
- FTP commands without transferring anything. Therefore you must always specify
- a URL to transfer to/from even when doing custom FTP commands.
-
- 3.5. How can I disable the Pragma: nocache header?
-
- You can change all internally generated headers by adding a replacement with
- the -H/--header option. By adding a header with empty contents you safely
- disable that one. Use -H "Pragma:" to disable that specific header.
-
- 3.6. Does curl support ASP, XML, XHTML or HTML version Y?
-
- To curl, all contents are alike. It doesn't matter how the page was
- generated. It may be ASP, PHP, Perl, shell-script, SSI or plain
- HTML-files. There's no difference to curl and it doesn't even know what kind
- of language that generated the page.
-
- See also item 3.14 regarding javascript.
-
- 3.7. Can I use curl to delete/rename a file through FTP?
-
- Yes. You specify custom FTP commands with -Q/--quote.
-
- One example would be to delete a file after you have downloaded it:
-
- curl -O ftp://download.com/coolfile -Q '-DELE coolfile'
-
- 3.8 How do I tell curl to follow HTTP redirects?
-
- Curl does not follow so-called redirects by default. The Location: header
- that informs the client about this is only interpreted if you're using the
- -L/--location option. As in:
-
- curl -L http://redirector.com
-
- 3.9 How do I use curl in my favorite programming language?
-
- There exist many language interfaces/bindings for curl that integrates it
- better with various languages. If you are fluid in a script language, you
- may very well opt to use such an interface instead of using the command line
- tool.
-
- Find out more about which languages that support curl directly, and how to
- install and use them, in the libcurl section of the curl web site:
-
- http://curl.haxx.se/libcurl/
-
- In February 2003, there are interfaces available for the following
- languages: Basic, C, C++, Cocoa, Dylan, Euphoria, Java, Lua, Object-Pascal,
- Pascal, Perl, PHP, PostgreSQL, Python, Rexx, Ruby, Scheme and Tcl. By the
- time you read this, additional ones may have appeared!
-
- 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
-
- Curl adheres to the HTTP spec, which basically means you can play with *any*
- protocol that is built on top of HTTP. Protocols such as SOAP, WEBDAV and
- XML-RPC are all such ones. You can use -X to set custom requests and -H to
- set custom headers (or replace internally generated ones).
-
- Using libcurl is of course just as fine and you'd just use the proper
- library options to do the same.
-
- 3.11 How do I POST with a different Content-Type?
-
- You can always replace the internally generated headers with -H/--header.
- To make a simple HTTP POST with text/xml as content-type, do something like:
-
- curl -d "datatopost" -H "Content-Type: text/xml" [URL]
-
- 3.12 Why do FTP specific features over HTTP proxy fail?
-
- Because when you use a HTTP proxy, the protocol spoken on the network will
- be HTTP, even if you specify a FTP URL. This effectively means that you
- normally can't use FTP specific features such as FTP upload and FTP quote
- etc.
-
- There is one exception to this rule, and that is if you can "tunnel through"
- the given HTTP proxy. Proxy tunneling is enabled with a special option (-p)
- and is generally not available as proxy admins usually disable tunneling to
- other ports than 443 (which is used for HTTPS access through proxies).
-
- 3.13 Why does my single/double quotes fail?
-
- To specify a command line option that includes spaces, you might need to
- put the entire option within quotes. Like in:
-
- curl -d " with spaces " url.com
-
- or perhaps
-
- curl -d ' with spaces ' url.com
-
- Exactly what kind of quotes and how to do this is entirely up to the shell
- or command line interpreter that you are using. For most unix shells, you
- can more or less pick either single (') or double (") quotes. For
- Windows/DOS prompts I believe you're forced to use double (") quotes.
-
- Please study the documentation for your particular environment. Examples in
- the curl docs will use a mix of both these ones as shown above. You must
- adjust them to work in your environment.
-
- Remember that curl works and runs on more operating systems than most single
- individuals have ever tried.
-
- 3.14 Does curl support javascript or pac (automated proxy config)?
-
- Many web pages do magic stuff using embedded javascript. Curl and libcurl
- have no built-in support for that, so it will be treated just like any other
- contents.
-
- .pac files are a netscape invention and are sometimes used by organizations
- to allow them to differentiate which proxies to use. The .pac contents is
- just a javascript program that gets invoked by the browser and that returns
- the name of the proxy to connect to. Since curl doesn't support javascript,
- it can't support .pac proxy configuration either.
-
- Some work-arounds usually suggested to overcome this javascript dependency:
-
- - Depending on the javascript complexity, write up a script that
- translates it to another language and execute that.
-
- - Read the javascript code and rewrite the same logic in another language.
-
- - Implement a javascript interpreted, people have successfully used the
- Mozilla javascript engine in the past.
-
- - Ask your admins to stop this, for a static proxy setup or similar.
-
-
-4. Running Problems
-
- 4.1. Problems connecting to SSL servers.
-
- It took a very long time before we could sort out why curl had problems to
- connect to certain SSL servers when using SSLeay or OpenSSL v0.9+. The
- error sometimes showed up similar to:
-
- 16570:error:1407D071:SSL routines:SSL2_READ:bad mac decode:s2_pkt.c:233:
-
- It turned out to be because many older SSL servers don't deal with SSLv3
- requests properly. To correct this problem, tell curl to select SSLv2 from
- the command line (-2/--sslv2).
-
- There has also been examples where the remote server didn't like the SSLv2
- request and instead you had to force curl to use SSLv3 with -3/--sslv3.
-
- 4.2. Why do I get problems when I use & or % in the URL?
-
- In general unix shells, the & letter is treated special and when used, it
- runs the specified command in the background. To safely send the & as a part
- of a URL, you should quote the entire URL by using single (') or double (")
- quotes around it.
-
- An example that would invoke a remote CGI that uses &-letters could be:
-
- curl 'http://www.altavista.com/cgi-bin/query?text=yes&q=curl'
-
- In Windows, the standard DOS shell treats the %-letter specially and you
- need to use TWO %-letters for each single one you want to use in the URL.
-
- Also note that if you want the literal %-letter to be part of the data you
- pass in a POST using -d/--data you must encode it as '%25' (which then also
- needs the %-letter doubled on Windows machines).
-
- 4.3. How can I use {, }, [ or ] to specify multiple URLs?
-
- Because those letters have a special meaning to the shell, and to be used in
- a URL specified to curl you must quote them.
-
- An example that downloads two URLs (sequentially) would do:
-
- curl '{curl,www}.haxx.se'
-
- To be able to use those letters as actual parts of the URL (without using
- them for the curl URL "globbing" system), use the -g/--globoff option:
-
- curl -g 'www.site.com/weirdname[].html'
-
- 4.4. Why do I get downloaded data even though the web page doesn't exist?
-
- Curl asks remote servers for the page you specify. If the page doesn't exist
- at the server, the HTTP protocol defines how the server should respond and
- that means that headers and a "page" will be returned. That's simply how
- HTTP works.
-
- By using the --fail option you can tell curl explicitly to not get any data
- if the HTTP return code doesn't say success.
-
- 4.5 Why do I get return code XXX from a HTTP server?
-
- RFC2616 clearly explains the return codes. This is a short transcript. Go
- read the RFC for exact details:
-
- 4.5.1 "400 Bad Request"
-
- The request could not be understood by the server due to malformed
- syntax. The client SHOULD NOT repeat the request without modifications.
-
- 4.5.2 "401 Unauthorized"
-
- The request requires user authentication.
-
- 4.5.3 "403 Forbidden"
-
- The server understood the request, but is refusing to fulfill it.
- Authorization will not help and the request SHOULD NOT be repeated.
-
- 4.5.4 "404 Not Found"
-
- The server has not found anything matching the Request-URI. No indication
- is given of whether the condition is temporary or permanent.
-
- 4.5.5 "405 Method Not Allowed"
-
- The method specified in the Request-Line is not allowed for the resource
- identified by the Request-URI. The response MUST include an Allow header
- containing a list of valid methods for the requested resource.
-
- 4.5.6 "301 Moved Permanently"
-
- If you get this return code and an HTML output similar to this:
-
- <H1>Moved Permanently</H1> The document has moved <A
- HREF="http://same_url_now_with_a_trailing_slash/">here</A>.
-
- it might be because you request a directory URL but without the trailing
- slash. Try the same operation again _with_ the trailing URL, or use the
- -L/--location option to follow the redirection.
-
- 4.6. Can you tell me what error code 142 means?
-
- All error codes that are larger than the highest documented error code means
- that curl has exited due to a crash. This is a serious error, and we
- appreciate a detailed bug report from you that describes how we could go
- ahead and repeat this!
-
- 4.7. How do I keep user names and passwords secret in Curl command lines?
-
- This problem has two sides:
-
- The first part is to avoid having clear-text passwords in the command line
- so that they don't appear in 'ps' outputs and similar. That is easily
- avoided by using the "-K" option to tell curl to read parameters from a
- file or stdin to which you can pass the secret info.
-
- To keep the passwords in your account secret from the rest of the world is
- not a task that curl addresses. You could of course encrypt them somehow to
- at least hide them from being read by human eyes, but that is not what
- anyone would call security.
-
- Also note that regular HTTP and FTP passwords are sent in clear across the
- network. All it takes for anyone to fetch them is to listen on the network.
- Eavesdropping is very easy.
-
- 4.8 I found a bug!
-
- It is not a bug if the behavior is documented. Read the docs first.
-
- If it is a problem with a binary you've downloaded or a package for your
- particular platform, try contacting the person who built the package/archive
- you have.
-
- If there is a bug, read the BUGS document first. Then report it as described
- in there.
-
- 4.9. Curl can't authenticate to the server that requires NTLM?
-
- This is supported in curl 7.10.6 or later. No earlier curl version knows
- of this magic.
-
- NTLM is a Microsoft proprietary protocol. Proprietary formats are evil. You
- should not use such ones.
-
- 4.10 My HTTP request using HEAD, PUT or DELETE doesn't work!
-
- Many web servers allow or demand that the administrator configures the
- server properly for these requests to work on the web server.
-
- Some servers seem to support HEAD only on certain kinds of URLs.
-
- To fully grasp this, try the documentation for the particular server
- software you're trying to interact with. This is not anything curl can do
- anything about.
-
- 4.11 Why does my HTTP range requests return the full document?
-
- Because the range may not be supported by the server, or the server may
- choose to ignore it and return the full document anyway.
-
- 4.12 Why do I get "certificate verify failed" ?
-
- You invoke curl 7.10 or later to communicate on a https:// URL and get an
- error back looking something similar to this:
-
- curl: (35) SSL: error:14090086:SSL routines:
- SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
-
- Then it means that curl couldn't verify that the server's certificate was
- good. Curl verifies the certificate using the CA cert bundle that comes with
- the curl installation.
-
- To disable the verification (which makes it act like curl did before 7.10),
- use -k. This does however enable man-in-the-middle attacks.
-
- If you get this failure but are having a CA cert bundle installed and used,
- the server's certificate is not signed by one of the CA's in the bundle. It
- might for example be self-signed. You then correct this problem by obtaining
- a valid CA cert for the server. Or again, decrease the security by disabling
- this check.
-
- Details are also in the SSLCERTS file in the release archives, found online
- here: http://curl.haxx.se/docs/sslcerts.html
-
-5. libcurl Issues
-
- 5.1. Is libcurl thread-safe?
-
- Yes.
-
- We have written the libcurl code specificly adjusted for multi-threaded
- programs. libcurl will use thread-safe functions instead of non-safe ones if
- your system has such.
-
- We would appreciate some kind of report or README file from those who have
- used libcurl in a threaded environment.
-
- 5.2 How can I receive all data into a large memory chunk?
-
- [ See also the examples/getinmemory.c source ]
-
- You are in full control of the callback function that gets called every time
- there is data received from the remote server. You can make that callback do
- whatever you want. You do not have to write the received data to a file.
-
- One solution to this problem could be to have a pointer to a struct that you
- pass to the callback function. You set the pointer using the
- curl_easy_setopt(CURLOPT_FILE) function. Then that pointer will be passed to
- the callback instead of a FILE * to a file:
-
- /* imaginary struct */
- struct MemoryStruct {
- char *memory;
- size_t size;
- };
-
- /* imaginary callback function */
- size_t
- WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
- {
- register int realsize = size * nmemb;
- struct MemoryStruct *mem = (struct MemoryStruct *)data;
-
- mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
- if (mem->memory) {
- memcpy(&(mem->memory[mem->size]), ptr, realsize);
- mem->size += realsize;
- mem->memory[mem->size] = 0;
- }
- return realsize;
- }
-
- 5.3 How do I fetch multiple files with libcurl?
-
- libcurl has excellent support for transferring multiple files. You should
- just repeatedly set new URLs with curl_easy_setopt() and then transfer it
- with curl_easy_perform(). The handle you get from curl_easy_init() is not
- only reusable, but you're even encouraged to reuse it if you can, as that
- will enable libcurl to use persistent connections.
-
- 5.4 Does libcurl do Winsock initialization on win32 systems?
-
- Yes, if told to in the curl_global_init() call.
-
- 5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?
-
- Yes, but you cannot open a FILE * and pass the pointer to a DLL and have
- that DLL use the FILE *. If you set CURLOPT_FILE you must also use
- CURLOPT_WRITEFUNCTION as well to set a function that writes the file, even
- if that simply writes the data to the specified FILE*. Similarly, if you use
- CURLOPT_INFILE you must also specify CURLOPT_READFUNCTION.
-
- (Provided by Joel DeYoung and Bob Schader)
-
- 5.6 What about Keep-Alive or persistent connections?
-
- curl and libcurl have excellent support for persistent connections when
- transferring several files from the same server. Curl will attempt to reuse
- connections for all URLs specified on the same command line/config file, and
- libcurl will reuse connections for all transfers that are made using the
- same libcurl handle.
-
- 5.7 Link errors when building libcurl on Windows!
-
- You need to make sure that your project, and all the libraries (both static
- and dynamic) that it links against, are compiled/linked against the same run
- time library.
-
- This is determined by the /MD, /ML, /MT (and their corresponding /M?d)
- options to the command line compiler. /MD (linking against MSVCRT dll) seems
- to be the most commonly used option.
-
- (Provided by Andrew Francis)
-
-
-6. License Issues
-
- Curl and libcurl are released under a MIT/X derivate license. The license is
- very liberal and should not impose a problem for your project. This section
- is just a brief summary for the cases we get the most questions. (Parts of
- this section was much enhanced by Bjorn Reese.)
-
- 6.1. I have a GPL program, can I use the libcurl library?
-
- Yes!
-
- Since libcurl may be distributed under the MIT/X derivate license, it can be
- used together with GPL in any software.
-
- 6.2. I have a closed-source program, can I use the libcurl library?
-
- Yes!
-
- libcurl does not put any restrictions on the program that uses the library.
-
- 6.3. I have a BSD licensed program, can I use the libcurl library?
-
- Yes!
-
- libcurl does not put any restrictions on the program that uses the library.
-
- 6.4. I have a program that uses LGPL libraries, can I use libcurl?
-
- Yes!
-
- The LGPL license doesn't clash with other licenses.
-
- 6.5. Can I modify curl/libcurl for my program and keep the changes secret?
-
- Yes!
-
- The MIT/X derivate license practically allows you to do almost anything with
- the sources, on the condition that the copyright texts in the sources are
- left intact.
-
- 6.6. Can you please change the curl/libcurl license to XXXX?
-
- No.
-
- We have carefully picked this license after years of development and
- discussions and a large amount of people have contributed with source code
- knowing that this is the license we use. This license puts the restrictions
- we want on curl/libcurl and it does not spread to other programs or
- libraries that use it. It should be possible for everyone to use libcurl or
- curl in their projects, no matter what license they already have in use.
+++ /dev/null
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
-FEATURES
-
-Misc
- - full URL syntax
- - custom maximum download time
- - custom least download speed acceptable
- - custom output result after completion
- - multiple URLs
- - guesses protocol from host name unless specified
- - uses .netrc
- - progress bar/time specs while downloading
- - "standard" proxy environment variables support
- - config file support
- - compiles on win32 (reported builds on 40+ operating systems)
- - redirectable stderr
- - selectable network interface for outgoing traffic
- - IPv6 support
- - persistant connections
- - socks5 support
- - supports user name + password in proxy environment variables
- - operations through proxy "tunnel" (using CONNECT)
-
-HTTP
- - HTTP/1.1 compliant (optionally uses 1.0)
- - GET
- - PUT
- - HEAD
- - POST
- - multipart formpost (RFC1867-style)
- - authentication: Basic, Digest, NTLM(*1), GSS-Negotiate/Negotiate(*3) and
- SPNEGO (*4)
- - resume (both GET and PUT)
- - follow redirects
- - maximum amount of redirects to follow
- - custom HTTP request
- - cookie get/send fully parsed
- - reads/writes the netscape cookie file format
- - custom headers (replace/remove internally generated headers)
- - custom user-agent string
- - custom referer string
- - range
- - proxy authentication
- - time conditions
- - via http-proxy
- - retrieve file modification date
- - Content-Encoding support for deflate and gzip
- - "Transfer-Encoding: chunked" support for "uploads"
-
-HTTPS (*1)
- - (all the HTTP features)
- - using certificates
- - verify server certificate
- - via http-proxy
- - select desired encryption
- - force usage of a specific SSL version (SSLv2, SSLv3 or TLSv1)
-
-FTP
- - download
- - authentication
- - kerberos4 (*5)
- - active/passive using PORT, EPRT, PASV or EPSV
- - single file size information (compare to HTTP HEAD)
- - 'type=' URL support
- - dir listing
- - dir listing names-only
- - upload
- - upload append
- - upload via http-proxy as HTTP PUT
- - download resume
- - upload resume
- - custom ftp commands (before and/or after the transfer)
- - simple "range" support
- - via http-proxy
- - all operations can be tunneled through a http-proxy
- - customizable to retrieve file modification date
-
-TELNET
- - connection negotiation
- - custom telnet options
- - stdin/stdout I/O
-
-LDAP (*2)
- - full LDAP URL support
-
-DICT
- - extended DICT URL support
-
-GOPHER
- - GET
- - via http-proxy
-
-FILE
- - URL support
-
-FOOTNOTES
-=========
-
- *1 = requires OpenSSL
- *2 = requires OpenLDAP
- *3 = requires a GSSAPI-compliant library, such as Heimdal or similar.
- *4 = requires FBopenssl
- *5 = requires a krb4 library, such as the MIT one or similar.
+++ /dev/null
-
- LICENSE ISSUES
- ==============
-
- The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
- the OpenSSL License and the original SSLeay license apply to the toolkit.
- See below for the actual license texts. Actually both licenses are BSD-style
- Open Source licenses. In case of any license issues related to OpenSSL
- please contact openssl-coreNOSPAMopenssl.org.
-
- OpenSSL License
- ---------------
-
-/* ====================================================================
- * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * openssl-coreNOSPAMopenssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eayNOSPAMcryptsoft.com). This product includes software written by Tim
- * Hudson (tjhNOSPAMcryptsoft.com).
- *
- */
-
- Original SSLeay License
- -----------------------
-
-/* Copyright (C) 1995-1998 Eric Young (eayNOSPAMcryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eayNOSPAMcryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjhNOSPAMcryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eayNOSPAMcryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjhNOSPAMcryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
+++ /dev/null
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
-README
-
- Curl is a command line tool for transfering data specified with URL
- syntax. Find out how to use Curl by reading the curl.1 man page or the
- MANUAL document. Find out how to install Curl by reading the INSTALL
- document.
-
- libcurl is the library curl is using to do its job. It is readily
- available to be used by your software. Read the libcurl.3 man page to
- learn how!
-
- You find answers to the most frequent questions we get in the FAQ document.
-
- Study the COPYING file for distribution terms and similar.
-
-CONTACT
-
- If you have problems, questions, ideas or suggestions, please contact us
- by posting to a suitable mailing list. See http://curl.haxx.se/mail/
-
- Many major contributors to the project are listed in the THANKS document.
-
-WEB SITE
-
- Visit the curl web site or mirrors for the latest news:
-
- Sweden -- http://curl.haxx.se/
- Russia -- http://curl.tsuren.net/
- US -- http://curl.sf.net/
- Australia -- http://curl.planetmirror.com/
-
-DOWNLOAD
-
- The official download mirror sites are:
-
- Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/
- Sweden -- http://cool.haxx.se/curl/
- Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/
- Australia -- http://curl.planetmirror.com/download/
- US -- http://curl.sourceforge.net/download/
- Hongkong -- http://www.execve.net/curl/
- Russia -- http://curl.tsuren.net/download/
-
-CVS
-
- To download the very latest source off the CVS server do this:
-
- cvs -d :pserver:cvsreadNOSPAMcvs.php.net:/repository login
-
- (enter "phpfi" when asked for password)
-
- cvs -d :pserver:cvsreadNOSPAMcvs.php.net:/repository co curl
-
- (you'll get a directory named curl created, filled with the source code)
-
- cvs -d :pserver:cvsreadNOSPAMcvs.php.net:/repository logout
-
- (you're off the hook!)
-
-NOTICE
-
- Curl contains pieces of source code that is Copyright (c) 1998, 1999
- Kungliga Tekniska Högskolan. This notice is included here to comply with the
- distribution terms.
+++ /dev/null
- _ _ ____ _
- ___| | | | _ \| |
- / __| | | | |_) | |
- | (__| |_| | _ <| |___
- \___|\___/|_| \_\_____|
-
-README.win32
-
- Read the README file first.
-
- Curl has been compiled, built and run on all sorts of Windows and win32
- systems. While not being the main develop target, a fair share of curl users
- are win32-based.
-
- The unix-style man pages are tricky to read on windows, so therefore are all
- those pages converted to HTML as well as pdf, and included in the release
- archives.
-
- The main curl.1 man page is also "built-in" in the command line tool. Use a
- command line similar to this in order to extract a separate text file:
-
- curl -M >manual.txt
+++ /dev/null
-<HTML>
-<BODY>
-<PRE>
-<!-- Manpage converted by man2html 3.0.1 -->
- curl - transfer a URL
-
-
-</PRE>
-<H2>SYNOPSIS</H2><PRE>
- <B>curl</B> <B>[options]</B> <I>[URL...]</I>
-
-
-</PRE>
-<H2>DESCRIPTION</H2><PRE>
- <B>curl</B> is a tool to transfer data from or to a server, using
- one of the supported protocols (HTTP, HTTPS, FTP, FTPS,
- GOPHER, DICT, TELNET, LDAP or FILE). The command is
- designed to work without user interaction.
-
- curl offers a busload of useful tricks like proxy support,
- user authentication, ftp upload, HTTP post, SSL (https:)
- connections, cookies, file transfer resume and more. As
- you will see below, the amount of features will make your
- head spin!
-
- curl is powered by libcurl for all transfer-related fea-
- tures. See <B>libcurl(3)</B> for details.
-
-
-</PRE>
-<H2>URL</H2><PRE>
- The URL syntax is protocol dependent. You'll find a
- detailed description in RFC 2396.
-
- You can specify multiple URLs or parts of URLs by writing
- part sets within braces as in:
-
- http://site.{one,two,three}.com
-
- or you can get sequences of alphanumeric series by using
- [] as in:
-
- ftp://ftp.numericals.com/file[1-100].txt
- ftp://ftp.numericals.com/file[001-100].txt (with lead-
- ing zeros)
- ftp://ftp.letters.com/file[a-z].txt
-
- No nesting of the sequences is supported at the moment:
-
- http://www.any.org/archive[1996-1999]/vol-
- ume[1-4]part{a,b,c,index}.html
-
- You can specify any amount of URLs on the command line.
- They will be fetched in a sequential manner in the speci-
- fied order.
-
- Curl will attempt to re-use connections for multiple file
- transfers, so that getting many files from the same server
- will not do multiple connects / handshakes. This improves
- speed. Of course this is only done on files specified on a
- single command line and cannot be used between separate
- curl invokes.
- -a/--append
- (FTP) When used in an FTP upload, this will tell
- curl to append to the target file instead of over-
- writing it. If the file doesn't exist, it will be
- created.
-
- If this option is used twice, the second one will
- disable append mode again.
-
- -A/--user-agent <agent string>
- (HTTP) Specify the User-Agent string to send to the
- HTTP server. Some badly done CGIs fail if its not
- set to "Mozilla/4.0". To encode blanks in the
- string, surround the string with single quote
- marks. This can also be set with the -H/--header
- flag of course.
-
- If this option is set more than once, the last one
- will be the one that's used.
-
- --anyauth
- (HTTP) Tells curl to figure out authentication
- method by itself, and use the most secure one the
- remote site claims it supports. This is done by
- first doing a request and checking the response-
- headers, thus inducing an extra network round-trip.
- This is used instead of setting a specific authen-
- tication method, which you can do with <I>--digest</I>,
- <I>--ntlm</I>, and <I>--negotiate</I>. (Added in 7.10.6)
-
- If this option is used several times, the following
- occurrences make no difference.
-
- -b/--cookie <name=data>
- (HTTP) Pass the data to the HTTP server as a
- cookie. It is supposedly the data previously
- received from the server in a "Set-Cookie:" line.
- The data should be in the format "NAME1=VALUE1;
- NAME2=VALUE2".
-
- If no '=' letter is used in the line, it is treated
- as a filename to use to read previously stored
- cookie lines from, which should be used in this
- session if they match. Using this method also acti-
- vates the "cookie parser" which will make curl
- record incoming cookies too, which may be handy if
- you're using this in combination with the
- -L/--location option. The file format of the file
- to read cookies from should be plain HTTP headers
- or the Netscape/Mozilla cookie file format.
-
- <B>NOTE</B> that the file specified with -b/--cookie is
- option or you could even save the HTTP headers to a
- file using -D/--dump-header!
-
- If this option is set more than once, the last one
- will be the one that's used.
-
- -B/--use-ascii
- Use ASCII transfer when getting an FTP file or LDAP
- info. For FTP, this can also be enforced by using
- an URL that ends with ";type=A". This option causes
- data sent to stdout to be in text mode for win32
- systems.
-
- If this option is used twice, the second one will
- disable ASCII usage.
-
- --basic
- (HTTP) Tells curl to use HTTP Basic authentication.
- This is the default and this option is usually
- pointless, unless you use it to override a previ-
- ously set option that sets a different authentica-
- tion method (such as <I>--ntlm</I>, <I>--digest</I> and <I>--negoti-</I>
- <I>ate</I>). (Added in 7.10.6)
-
- If this option is used several times, the following
- occurrences make no difference.
-
- --ciphers <list of ciphers>
- (SSL) Specifies which ciphers to use in the connec-
- tion. The list of ciphers must be using valid
- ciphers. Read up on SSL cipher list details on this
- URL: <I>http://www.openssl.org/docs/apps/ciphers.html</I>
-
- If this option is used several times, the last one
- will override the others.
-
- --compressed
- (HTTP) Request a compressed response using one of
- the algorithms libcurl supports, and return the
- uncompressed document. If this option is used and
- the server sends an unsupported encoding, Curl will
- report an error.
-
- If this option is used several times, each occur-
- rence will toggle it on/off.
-
- --connect-timeout <seconds>
- Maximum time in seconds that you allow the connec-
- tion to the server to take. This only limits the
- connection phase, once curl has connected this
- option is of no more use. See also the <I>--max-time</I>
- option.
- will be used.
-
- -c/--cookie-jar <file name>
- Specify to which file you want curl to write all
- cookies after a completed operation. Curl writes
- all cookies previously read from a specified file
- as well as all cookies received from remote
- server(s). If no cookies are known, no file will be
- written. The file will be written using the
- Netscape cookie file format. If you set the file
- name to a single dash, "-", the cookies will be
- written to stdout.
-
- <B>NOTE</B> If the cookie jar can't be created or written
- to, the whole curl operation won't fail or even
- report an error clearly. Using -v will get a warn-
- ing displayed, but that is the only visible feed-
- back you get about this possibly lethal situation.
-
- If this option is used several times, the last
- specfied file name will be used.
-
- -C/--continue-at <offset>
- Continue/Resume a previous file transfer at the
- given offset. The given offset is the exact number
- of bytes that will be skipped counted from the
- beginning of the source file before it is trans-
- fered to the destination. If used with uploads,
- the ftp server command SIZE will not be used by
- curl.
-
- Use "-C -" to tell curl to automatically find out
- where/how to resume the transfer. It then uses the
- given output/input files to figure that out.
-
- If this option is used several times, the last one
- will be used.
-
- --create-dirs
- When used in conjunction with the -o option, curl
- will create the necessary local directory hierarchy
- as needed.
-
- --crlf (FTP) Convert LF to CRLF in upload. Useful for MVS
- (OS/390).
-
- If this option is used twice, the second will again
- disable crlf converting.
-
- -d/--data <data>
- (HTTP) Sends the specified data in a POST request
- to the HTTP server, in a way that can emulate as if
- as specified with no extra processing (with all
- newlines cut off). The data is expected to be
- "url-encoded". This will cause curl to pass the
- data to the server using the content-type applica-
- tion/x-www-form-urlencoded. Compare to -F. If more
- than one -d/--data option is used on the same com-
- mand line, the data pieces specified will be merged
- together with a separating &-letter. Thus, using
- '-d name=daniel -d skill=lousy' would generate a
- post chunk that looks like
- 'name=daniel&skill=lousy'.
-
- If you start the data with the letter @, the rest
- should be a file name to read the data from, or -
- if you want curl to read the data from stdin. The
- contents of the file must already be url-encoded.
- Multiple files can also be specified. Posting data
- from a file named 'foobar' would thus be done with
- "--data @foobar".
-
- To post data purely binary, you should instead use
- the --data-binary option.
-
- -d/--data is the same as --data-ascii.
-
- If this option is used several times, the ones fol-
- lowing the first will append data.
-
- --data-ascii <data>
- (HTTP) This is an alias for the -d/--data option.
-
- If this option is used several times, the ones fol-
- lowing the first will append data.
-
- --data-binary <data>
- (HTTP) This posts data in a similar manner as
- --data-ascii does, although when using this option
- the entire context of the posted data is kept as-
- is. If you want to post a binary file without the
- strip-newlines feature of the --data-ascii option,
- this is for you.
-
- If this option is used several times, the ones fol-
- lowing the first will append data.
-
- --digest
- (HTTP) Enables HTTP Digest authentication. This is
- a authentication that prevents the password from
- being sent over the wire in clear text. Use this in
- combination with the normal -u/--user option to set
- user name and password. See also <I>--ntlm</I>, <I>--negoti-</I>
- <I>ate</I> and <I>--anyauth</I> for related options. (Added in
- occurrences make no difference.
-
- --disable-eprt
- (FTP) Tell curl to disable the use of the EPRT and
- LPRT commands when doing active FTP transfers. Curl
- will normally always first attempt to use EPRT,
- then LPRT before using PORT, but with this option,
- it will use PORT right away. EPRT and LPRT are
- extensions to the original FTP protocol, may not
- work on all servers but enable more functionality
- in a better way than the traditional PORT command.
- (Aded in 7.10.5)
-
- If this option is used several times, each occur-
- rence will toggle this on/off.
-
- --disable-epsv
- (FTP) Tell curl to disable the use of the EPSV com-
- mand when doing passive FTP transfers. Curl will
- normally always first attempt to use EPSV before
- PASV, but with this option, it will not try using
- EPSV.
-
- If this option is used several times, each occur-
- rence will toggle this on/off.
-
- -D/--dump-header <file>
- Write the protocol headers to the specified file.
-
- This option is handy to use when you want to store
- the headers that a HTTP site sends to you. Cookies
- from the headers could then be read in a second
- curl invoke by using the -b/--cookie option! The
- -c/--cookie-jar option is however a better way to
- store cookies.
-
- When used on FTP, the ftp server response lines are
- considered being "headers" and thus are saved
- there.
-
- If this option is used several times, the last one
- will be used.
-
- -e/--referer <URL>
- (HTTP) Sends the "Referer Page" information to the
- HTTP server. This can also be set with the
- -H/--header flag of course. When used with
- <I>-L/--location</I> you can append ";auto" to the referer
- URL to make curl automatically set the previous URL
- when it follows a Location: header. The ";auto"
- string can be used alone, even if you don't set an
- initial referer.
- will be used.
-
- --environment
- (RISC OS ONLY) Sets a range of environment vari-
- ables, using the names the -w option supports, to
- easier allow extraction of useful information after
- having run curl.
-
- If this option is used several times, each occur-
- rence will toggle this on/off.
-
- --egd-file <file>
- (HTTPS) Specify the path name to the Entropy Gath-
- ering Daemon socket. The socket is used to seed the
- random engine for SSL connections. See also the
- <I>--random-file</I> option.
-
- -E/--cert <certificate[:password]>
- (HTTPS) Tells curl to use the specified certificate
- file when getting a file with HTTPS. The certifi-
- cate must be in PEM format. If the optional pass-
- word isn't specified, it will be queried for on the
- terminal. Note that this certificate is the private
- key and the private certificate concatenated!
-
- If this option is used several times, the last one
- will be used.
-
- --cacert <CA certificate>
- (HTTPS) Tells curl to use the specified certificate
- file to verify the peer. The file may contain mul-
- tiple CA certificates. The certificate(s) must be
- in PEM format.
-
- curl recognizes the environment variable named
- 'CURL_CA_BUNDLE' if that is set, and uses the given
- path as a path to a CA cert bundle. This option
- overrides that variable.
-
- The windows version of curl will automatically look
- for a CA certs file named 'curl-ca-bundle.crt',
- either in the same directory as curl.exe, or in the
- Current Working Directory, or in any folder along
- your PATH.
-
- If this option is used several times, the last one
- will be used.
-
- --capath <CA certificate directory>
- (HTTPS) Tells curl to use the specified certificate
- directory to verify the peer. The certificates must
- be in PEM format, and the directory must have been
- https connections much more efficiently than using
- --cacert if the --cacert file contains many CA cer-
- tificates.
-
- If this option is used several times, the last one
- will be used.
-
- -f/--fail
- (HTTP) Fail silently (no output at all) on server
- errors. This is mostly done like this to better
- enable scripts etc to better deal with failed
- attempts. In normal cases when a HTTP server fails
- to deliver a document, it returns a HTML document
- stating so (which often also describes why and
- more). This flag will prevent curl from outputting
- that and fail silently instead.
-
- If this option is used twice, the second will again
- disable silent failure.
-
- --ftp-create-dirs
- (FTP) When an FTP URL/operation uses a path that
- doesn't currently exist on the server, the standard
- behaviour of curl is to fail. Using this option,
- curl will instead attempt to create missing direc-
- tories. (Added in 7.10.7)
-
- If this option is used twice, the second will again
- disable silent failure.
-
- -F/--form <name=content>
- (HTTP) This lets curl emulate a filled in form in
- which a user has pressed the submit button. This
- causes curl to POST data using the content-type
- multipart/form-data according to RFC1867. This
- enables uploading of binary files etc. To force the
- 'content' part to be be a file, prefix the file
- name with an @ sign. To just get the content part
- from a file, prefix the file name with the letter
- <. The difference between @ and < is then that @
- makes a file get attached in the post as a file
- upload, while the < makes a text field and just get
- the contents for that text field from a file.
-
- Example, to send your password file to the server,
- where 'password' is the name of the form-field to
- which /etc/passwd will be the input:
-
- <B>curl</B> -F password=@/etc/passwd www.mypasswords.com
-
- To read the file's content from stdin insted of a
- file, use - where the file name should've been.
- the file upload part, by using 'type=', in a manner
- similar to:
-
- <B>curl</B> -F "web=@index.html;type=text/html" url.com
-
- See further examples and details in the MANUAL.
-
- This option can be used multiple times.
-
- -g/--globoff
- This option switches off the "URL globbing parser".
- When you set this option, you can specify URLs that
- contain the letters {}[] without having them being
- interpreted by curl itself. Note that these letters
- are not normal legal URL contents but they should
- be encoded according to the URI standard.
-
- -G/--get
- When used, this option will make all data specified
- with -d/--data or --data-binary to be used in a
- HTTP GET request instead of the POST request that
- otherwise would be used. The data will be appended
- to the URL with a '?' separator.
-
- If used in combination with -I, the POST data will
- instead be appended to the URL with a HEAD request.
-
- If used multiple times, nothing special happens.
-
- -h/--help
- Usage help.
-
- -H/--header <header>
- (HTTP) Extra header to use when getting a web page.
- You may specify any number of extra headers. Note
- that if you should add a custom header that has the
- same name as one of the internal ones curl would
- use, your externally set header will be used
- instead of the internal one. This allows you to
- make even trickier stuff than curl would normally
- do. You should not replace internally set headers
- without knowing perfectly well what you're doing.
- Replacing an internal header with one without con-
- tent on the right side of the colon will prevent
- that header from appearing.
-
- This option can be used multiple times to
- add/replace/remove multiple headers.
-
- -i/--include
- (HTTP) Include the HTTP-header in the output. The
- HTTP-header includes things like server-name, date
- disable header include.
-
- --interface <name>
- Perform an operation using a specified interface.
- You can enter interface name, IP address or host
- name. An example could look like:
-
- <B>curl</B> <B>--interface</B> <B>eth0:1</B> <B>http://www.netscape.com/</B>
-
- If this option is used several times, the last one
- will be used.
-
- -I/--head
- (HTTP/FTP/FILE) Fetch the HTTP-header only! HTTP-
- servers feature the command HEAD which this uses to
- get nothing but the header of a document. When used
- on a FTP or FILE file, curl displays the file size
- and last modification time only.
-
- If this option is used twice, the second will again
- disable header only.
-
- -j/--junk-session-cookies
- (HTTP) When curl is told to read cookies from a
- given file, this option will make it discard all
- "session cookies". This will basicly have the same
- effect as if a new session is started. Typical
- browsers always discard session cookies when
- they're closed down. (Added in 7.9.7)
-
- If this option is used several times, each occur-
- rence will toggle this on/off.
-
- -k/--insecure
- (SSL) This option explicitly allows curl to perform
- "insecure" SSL connections and transfers. Starting
- with curl 7.10, all SSL connections will be
- attempted to be made secure by using the CA cer-
- tificate bundle installed by default. This makes
- all connections considered "insecure" to fail
- unless -k/--insecure is used.
-
- This option is ignored if --cacert or --capath is
- used!
-
- If this option is used twice, the second time will
- again disable it.
-
- --krb4 <level>
- (FTP) Enable kerberos4 authentication and use. The
- level must be entered and should be one of 'clear',
- 'safe', 'confidential' or 'private'. Should you use
-
- If this option is used several times, the last one
- will be used.
-
- -K/--config <config file>
- Specify which config file to read curl arguments
- from. The config file is a text file in which com-
- mand line arguments can be written which then will
- be used as if they were written on the actual com-
- mand line. Options and their parameters must be
- specified on the same config file line. If the
- parameter is to contain white spaces, the parameter
- must be inclosed within quotes. If the first col-
- umn of a config line is a '#' character, the rest
- of the line will be treated as a comment.
-
- Specify the filename as '-' to make curl read the
- file from stdin.
-
- Note that to be able to specify a URL in the config
- file, you need to specify it using the --url
- option, and not by simply writing the URL on its
- own line. So, it could look similar to this:
-
- url = "http://curl.haxx.se/docs/"
-
- This option can be used multiple times.
-
- --limit-rate <speed>
- Specify the maximum transfer rate you want curl to
- use. This feature is useful if you have a limited
- pipe and you'd like your transfer not use your
- entire bandwidth.
-
- The given speed is measured in bytes/second, unless
- a suffix is appended. Appending 'k' or 'K' will
- count the number as kilobytes, 'm' or M' makes it
- megabytes while 'g' or 'G' makes it gigabytes.
- Examples: 200K, 3m and 1G.
-
- This option was introduced in curl 7.10.
-
- If this option is used several times, the last one
- will be used.
-
- -l/--list-only
- (FTP) When listing an FTP directory, this switch
- forces a name-only view. Especially useful if you
- want to machine-parse the contents of an FTP direc-
- tory since the normal directory view doesn't use a
- standard look or format.
-
- to NLST; they do not include subdirectories and
- symbolic links.
-
- If this option is used twice, the second will again
- disable list only.
-
- -L/--location
- (HTTP/HTTPS) If the server reports that the
- requested page has a different location (indicated
- with the header line Location:) this flag will let
- curl attempt to reattempt the get on the new place.
- If used together with -i or -I, headers from all
- requested pages will be shown. If authentication is
- used, curl will only send its credentials to the
- initial host, so if a redirect takes curl to a dif-
- ferent host, it won't intercept the user+password.
- See also <I>--location-trusted</I> on how to change this.
-
- If this option is used twice, the second will again
- disable location following.
-
- --location-trusted
- (HTTP/HTTPS) Like <I>--location</I>, but will allow send-
- ing the name + password to all hosts that the site
- may redirect to. This may or may not introduce a
- security breach if the site redirects you do a site
- to which you'll send your authentication info
- (which is plaintext in the case of HTTP Basic
- authentication).
-
- If this option is used twice, the second will again
- disable location following.
-
- --max-filesize <bytes>
- Specify the maximum size (in bytes) of a file to
- download. If the file requested is larger than this
- value, the transfer will not start and curl will
- return with exit code 63.
-
- NOTE: The file size is not always known prior to
- download, and for such files this option has no
- effect even if the file transfer ends up being
- larger than this given limit. This concerns both
- FTP and HTTP transfers.
-
- -m/--max-time <seconds>
- Maximum time in seconds that you allow the whole
- operation to take. This is useful for preventing
- your batch jobs from hanging for hours due to slow
- networks or links going down. This doesn't work
- fully in win32 systems. See also the <I>--connect-</I>
- <I>timeout</I> option.
- will be used.
-
- -M/--manual
- Manual. Display the huge help text.
-
- -n/--netrc
- Makes curl scan the <I>.netrc</I> file in the user's home
- directory for login name and password. This is typ-
- ically used for ftp on unix. If used with http,
- curl will enable user authentication. See <B>netrc(4)</B>
- or <B>ftp(1)</B> for details on the file format. Curl will
- not complain if that file hasn't the right permis-
- sions (it should not be world nor group readable).
- The environment variable "HOME" is used to find the
- home directory.
-
- A quick and very simple example of how to setup a
- <I>.netrc</I> to allow curl to ftp to the machine
- host.domain.com with user name 'myself' and pass-
- word 'secret' should look similar to:
-
- <B>machine</B> <B>host.domain.com</B> <B>login</B> <B>myself</B> <B>password</B>
- <B>secret</B>
-
- If this option is used twice, the second will again
- disable netrc usage.
-
- --negotiate
- (HTTP) Enables GSS-Negotiate authentication. The
- GSS-Negotiate method was designed by Microsoft and
- is used in their web aplications. It is primarily
- meant as a support for Kerberos5 authentication but
- may be also used along with another authentication
- methods. For more information see IETF draft draft-
- brezak-spnego-http-04.txt. (Added in 7.10.6)
-
- <B>NOTE</B> that this option requiures that the library
- was built with GSSAPI support. This is not very
- common. Use <I>curl</I> <I>--version</I> to see if your version
- supports GSS-Negotiate.
-
- If this option is used several times, the following
- occurrences make no difference.
-
- -N/--no-buffer
- Disables the buffering of the output stream. In
- normal work situations, curl will use a standard
- buffered output stream that will have the effect
- that it will output the data in chunks, not neces-
- sarily exactly when the data arrives. Using this
- option will disable that buffering.
-
-
- --ntlm (HTTP) Enables NTLM authentication. The NTLM
- authentication method was designed by Microsoft and
- is used by IIS web servers. It is a proprietary
- protocol, reversed engineered by clever people and
- implemented in curl based on their efforts. This
- kind of behavior should not be endorsed, you should
- encourage everyone who uses NTLM to switch to a
- public and documented authentication method
- instead. Such as Digest. (Added in 7.10.6)
-
- <B>NOTE</B> that this option requiures that the library
- was built with SSL support. Use <I>curl</I> <I>--version</I> to
- see if your version supports NTLM.
-
- If this option is used several times, the following
- occurrences make no difference.
-
- -o/--output <file>
- Write output to <file> instead of stdout. If you
- are using {} or [] to fetch multiple documents, you
- can use '#' followed by a number in the <file>
- specifier. That variable will be replaced with the
- current string for the URL being fetched. Like in:
-
- curl http://{one,two}.site.com -o "file_#1.txt"
-
- or use several variables like:
-
- curl http://{site,host}.host[1-5].com -o "#1_#2"
-
- You may use this option as many times as you have
- number of URLs.
-
- See also the --create-dirs option to create the
- local directories dynamically.
-
- -O/--remote-name
- Write output to a local file named like the remote
- file we get. (Only the file part of the remote file
- is used, the path is cut off.)
-
- You may use this option as many times as you have
- number of URLs.
-
- -p/--proxytunnel
- When an HTTP proxy is used, this option will cause
- non-HTTP protocols to attempt to tunnel through the
- proxy instead of merely using it to do HTTP-like
- operations. The tunnel approach is made with the
- HTTP proxy CONNECT request and requires that the
- proxy allows direct connect to the remote port num-
- disable proxy tunnel.
-
- -P/--ftpport <address>
- (FTP) Reverses the initiator/listener roles when
- connecting with ftp. This switch makes Curl use the
- PORT command instead of PASV. In practice, PORT
- tells the server to connect to the client's speci-
- fied address and port, while PASV asks the server
- for an ip address and port to connect to. <address>
- should be one of:
-
- <B>interface</B> i.e "eth0" to specify which interface's
- IP address you want to use (Unix only)
-
- <B>IP</B> <B>address</B> i.e "192.168.10.1" to specify exact IP
- number
-
- <B>host</B> <B>name</B> i.e "my.host.domain" to specify machine
-
- <B>-</B> (any single-letter string) to make it
- pick the machine's default
-
- If this option is used several times, the last one will be
- used.
-
- -q If used as the first parameter on the command line,
- the <I>$HOME/.curlrc</I> file will not be read and used as
- a config file.
-
- -Q/--quote <comand>
- (FTP) Send an arbitrary command to the remote FTP
- server, by using the QUOTE command of the server.
- Not all servers support this command, and the set
- of QUOTE commands are server specific! Quote com-
- mands are sent BEFORE the transfer is taking place.
- To make commands take place after a successful
- transfer, prefix them with a dash '-'. You may
- specify any amount of commands to be run before and
- after the transfer. If the server returns failure
- for one of the commands, the entire operation will
- be aborted.
-
- This option can be used multiple times.
-
- --random-file <file>
- (HTTPS) Specify the path name to file containing
- what will be considered as random data. The data is
- used to seed the random engine for SSL connections.
- See also the <I>--edg-file</I> option.
-
- -r/--range <range>
- (HTTP/FTP) Retrieve a byte range (i.e a partial
-
- <B>0-499</B> specifies the first 500 bytes
-
- <B>500-999</B> specifies the second 500 bytes
-
- <B>-500</B> specifies the last 500 bytes
-
- <B>9500</B> specifies the bytes from offset 9500 and
- forward
-
- <B>0-0,-1</B> specifies the first and last byte
- only(*)(H)
-
- <B>500-700,600-799</B>
- specifies 300 bytes from offset 500(H)
-
- <B>100-199,500-599</B>
- specifies two separate 100 bytes
- ranges(*)(H)
-
- (*) = NOTE that this will cause the server to reply with a
- multipart response!
-
- You should also be aware that many HTTP/1.1 servers do not
- have this feature enabled, so that when you attempt to get
- a range, you'll instead get the whole document.
-
- FTP range downloads only support the simple syntax 'start-
- stop' (optionally with one of the numbers omitted). It
- depends on the non-RFC command SIZE.
-
- If this option is used several times, the last one will be
- used.
-
- -R/--remote-time
- When used, this will make libcurl attempt to figure
- out the timestamp of the remote file, and if that
- is available make the local file get that same
- timestamp.
-
- If this option is used twice, the second time dis-
- ables this again.
-
- -s/--silent
- Silent mode. Don't show progress meter or error
- messages. Makes Curl mute.
-
- If this option is used twice, the second will again
- disable mute.
-
- -S/--show-error
- When used with -s it makes curl show error message
- disable show error.
-
- --stderr <file>
- Redirect all writes to stderr to the specified file
- instead. If the file name is a plain '-', it is
- instead written to stdout. This option has no point
- when you're using a shell with decent redirecting
- capabilities.
-
- If this option is used several times, the last one
- will be used.
-
- -t/--telnet-option <OPT=val>
- Pass options to the telnet protocol. Supported
- options are:
-
- TTYPE=<term> Sets the terminal type.
-
- XDISPLOC=<X display> Sets the X display location.
-
- NEW_ENV=<var,val> Sets an environment variable.
-
- -T/--upload-file <file>
- This transfers the specified local file to the
- remote URL. If there is no file part in the speci-
- fied URL, Curl will append the local file name.
- NOTE that you must use a trailing / on the last
- directory to really prove to Curl that there is no
- file name or curl will think that your last direc-
- tory name is the remote file name to use. That will
- most likely cause the upload operation to fail. If
- this is used on a http(s) server, the PUT command
- will be used.
-
- Use the file name "-" (a single dash) to use stdin
- instead of a given file.
-
- Before 7.10.8, when this option was used several
- times, the last one was used.
-
- In curl 7.10.8 and later, you can specify one -T
- for each URL on the command line. Each -T + URL
- pair specifies what to upload and to where. curl
- also supports "globbing" of the -T argument, mean-
- ing that you can upload multiple files to a single
- URL by using the same URL globbing style supported
- in the URL, like this:
-
- curl -T "{file1,file2}" http://www.upload-
- tothissite.com
-
- or even
- nia.com/upload/
-
- --trace <file>
- Enables a full trace dump of all incoming and out-
- going data, including descriptive information, to
- the given output file. Use "-" as filename to have
- the output sent to stdout.
-
- If this option is used several times, the last one
- will be used. (Added in 7.9.7)
-
- --trace-ascii <file>
- Enables a full trace dump of all incoming and out-
- going data, including descriptive information, to
- the given output file. Use "-" as filename to have
- the output sent to stdout.
-
- This is very similar to --trace, but leaves out the
- hex part and only shows the ASCII part of the dump.
- It makes smaller output that might be easier to
- read for untrained humans.
-
- If this option is used several times, the last one
- will be used. (Added in 7.9.7)
-
- -u/--user <user:password>
- Specify user and password to use when fetching.
- Read the MANUAL for detailed examples of how to use
- this. If no password is specified, curl will ask
- for it interactively.
-
- You can also use the --digest option to enable
- Digest authentication when communicating with HTTP
- 1.1 servers.
-
- If this option is used several times, the last one
- will be used.
-
- -U/--proxy-user <user:password>
- Specify user and password to use for Proxy authen-
- tication. If no password is specified, curl will
- ask for it interactively.
-
- If this option is used several times, the last one
- will be used.
-
- --url <URL>
- Specify a URL to fetch. This option is mostly handy
- when you want to specify URL(s) in a config file.
-
- This option may be used any number of times. To
- control where this URL is written, use the <I>-o</I> or
- Makes the fetching more verbose/talkative. Mostly
- usable for debugging. Lines starting with '>' means
- data sent by curl, '<' means data received by curl
- that is hidden in normal cases and lines starting
- with '*' means additional info provided by curl.
-
- Note that if you want to see HTTP headers in the
- output, <I>-i/--include</I> might be option you're looking
- for.
-
- If you think this option still doesn't give you
- enough details, consider using <I>--trace</I> or <I>--trace-</I>
- <I>ascii</I> instead.
-
- If this option is used twice, the second will again
- disable verbose.
-
- -V/--version
- Displays information about curl and the libcurl
- version it uses.
-
- The first line includes the full version of curl,
- libcurl and other 3rd party libraries linked with
- the executable.
-
- The second line (starts with "Protocols:") shows
- all protocols that libcurl reports to support.
-
- The third line (starts with "Features:") shows spe-
- cific features libcurl reports to offer.
-
-
- -w/--write-out <format>
- Defines what to display after a completed and suc-
- cessful operation. The format is a string that may
- contain plain text mixed with any number of vari-
- ables. The string can be specified as "string", to
- get read from a particular file you specify it
- "@filename" and to tell curl to read the format
- from stdin you write "@-".
-
- The variables present in the output format will be
- substituted by the value or text that curl thinks
- fit, as described below. All variables are speci-
- fied like %{variable_name} and to output a normal %
- you just write them like %%. You can output a new-
- line by using \n, a carriage return with \r and a
- tab space with \t.
-
- <B>NOTE:</B> The %-letter is a special letter in the
- win32-environment, where all occurrences of % must
- be doubled when using this option.
-
- <B>url_effective</B> The URL that was fetched last. This
- is mostly meaningful if you've told
- curl to follow location: headers.
-
- <B>http_code</B> The numerical code that was found in
- the last retrieved HTTP(S) page.
-
- <B>time_total</B> The total time, in seconds, that the
- full operation lasted. The time will
- be displayed with millisecond reso-
- lution.
-
- <B>time_namelookup</B>
- The time, in seconds, it took from
- the start until the name resolving
- was completed.
-
- <B>time_connect</B> The time, in seconds, it took from
- the start until the connect to the
- remote host (or proxy) was com-
- pleted.
-
- <B>time_pretransfer</B>
- The time, in seconds, it took from
- the start until the file transfer is
- just about to begin. This includes
- all pre-transfer commands and nego-
- tiations that are specific to the
- particular protocol(s) involved.
-
- <B>time_starttransfer</B>
- The time, in seconds, it took from
- the start until the first byte is
- just about to be transfered. This
- includes time_pretransfer and also
- the time the server needs to calcu-
- late the result.
-
- <B>size_download</B> The total amount of bytes that were
- downloaded.
-
- <B>size_upload</B> The total amount of bytes that were
- uploaded.
-
- <B>size_header</B> The total amount of bytes of the
- downloaded headers.
-
- <B>size_request</B> The total amount of bytes that were
- sent in the HTTP request.
-
- <B>speed_download</B> The average download speed that curl
- measured for the complete upload.
-
- <B>content_type</B> The Content-Type of the requested
- document, if there was any. (Added
- in 7.9.5)
-
- If this option is used several times, the last one will be
- used.
-
- -x/--proxy <proxyhost[:port]>
- Use specified HTTP proxy. If the port number is not
- specified, it is assumed at port 1080.
-
- This option overrides existing environment vari-
- ables that sets proxy to use. If there's an envi-
- ronment variable setting a proxy, you can set proxy
- to "" to override it.
-
- <B>Note</B> that all operations that are performed over a
- HTTP proxy will transparantly be converted to HTTP.
- It means that certain protocol specific operations
- might not be available. This is not the case if you
- can tunnel through the proxy, as done with the
- <I>-p/--proxytunnel</I> option.
-
- If this option is used several times, the last one
- will be used.
-
- -X/--request <command>
- (HTTP) Specifies a custom request to use when com-
- municating with the HTTP server. The specified
- request will be used instead of the standard GET.
- Read the HTTP 1.1 specification for details and
- explanations.
-
- (FTP) Specifies a custom FTP command to use instead
- of LIST when doing file lists with ftp.
-
- If this option is used several times, the last one
- will be used.
-
- -y/--speed-time <time>
- If a download is slower than speed-limit bytes per
- second during a speed-time period, the download
- gets aborted. If speed-time is used, the default
- speed-limit will be 1 unless set with -y.
-
- This option controls transfers and thus will not
- affect slow connects etc. If this is a concern for
- you, try the <I>--connect-timeout</I> option.
-
- If this option is used several times, the last one
- If a download is slower than this given speed, in
- bytes per second, for speed-time seconds it gets
- aborted. speed-time is set with -Y and is 30 if not
- set.
-
- If this option is used several times, the last one
- will be used.
-
- -z/--time-cond <date expression>
- (HTTP) Request to get a file that has been modified
- later than the given time and date, or one that has
- been modified before that time. The date expression
- can be all sorts of date strings or if it doesn't
- match any internal ones, it tries to get the time
- from a given file name instead! See the <B>GNU</B> <B>date(1)</B>
- or <B>curl_getdate(3)</B> man pages for date expression
- details.
-
- Start the date expression with a dash (-) to make
- it request for a document that is older than the
- given date/time, default is a document that is
- newer than the specified date/time.
-
- If this option is used several times, the last one
- will be used.
-
- -Z/--max-redirs <num>
- Set maximum number of redirection-followings
- allowed. If -L/--location is used, this option can
- be used to prevent curl from following redirections
- "in absurdum".
-
- If this option is used several times, the last one
- will be used.
-
- -0/--http1.0
- (HTTP) Forces curl to issue its requests using HTTP
- 1.0 instead of using its internally preferred: HTTP
- 1.1.
-
- -1/--tlsv1
- (HTTPS) Forces curl to use TSL version 1 when nego-
- tiating with a remote TLS server.
-
- -2/--sslv2
- (HTTPS) Forces curl to use SSL version 2 when nego-
- tiating with a remote SSL server.
-
- -3/--sslv3
- (HTTPS) Forces curl to use SSL version 3 when nego-
- tiating with a remote SSL server.
-
- If libcurl is capable of resolving an address to
- multiple IP versions (which it is if it is
- ipv6-capable), this option tells libcurl to resolve
- names to IPv4 addresses only. (Added in 7.10.8)
-
- -6/--ipv6
- If libcurl is capable of resolving an address to
- multiple IP versions (which it is if it is
- ipv6-capable), this option tells libcurl to resolve
- names to IPv6 addresses only. (Added in 7.10.8)
-
- -#/--progress-bar
- Make curl display progress information as a
- progress bar instead of the default statistics.
-
- If this option is used twice, the second will again
- disable the progress bar.
-
-
-</PRE>
-<H2>FILES</H2><PRE>
- <I>~/.curlrc</I>
- Default config file.
-
-
-
-</PRE>
-<H2>ENVIRONMENT</H2><PRE>
- http_proxy [protocol://]<host>[:port]
- Sets proxy server to use for HTTP.
-
- HTTPS_PROXY [protocol://]<host>[:port]
- Sets proxy server to use for HTTPS.
-
- FTP_PROXY [protocol://]<host>[:port]
- Sets proxy server to use for FTP.
-
- GOPHER_PROXY [protocol://]<host>[:port]
- Sets proxy server to use for GOPHER.
-
- ALL_PROXY [protocol://]<host>[:port]
- Sets proxy server to use if no protocol-specific
- proxy is set.
-
- NO_PROXY <comma-separated list of hosts>
- list of host names that shouldn't go through any
- proxy. If set to a asterisk
-
-
-</PRE>
-<H2>EXIT CODES</H2><PRE>
- There exists a bunch of different error codes and their
- corresponding error messages that may appear during bad
- conditions. At the time of this writing, the exit codes
- are:
-
- 1 Unsupported protocol. This build of curl has no
- support for this protocol.
-
- 3 URL malformat. The syntax was not correct.
-
- 4 URL user malformatted. The user-part of the URL
- syntax was not correct.
-
- 5 Couldn't resolve proxy. The given proxy host could
- not be resolved.
-
- 6 Couldn't resolve host. The given remote host was
- not resolved.
-
- 7 Failed to connect to host.
-
- 8 FTP weird server reply. The server sent data curl
- couldn't parse.
-
- 9 FTP access denied. The server denied login.
-
- 10 FTP user/password incorrect. Either one or both
- were not accepted by the server.
-
- 11 FTP weird PASS reply. Curl couldn't parse the reply
- sent to the PASS request.
-
- 12 FTP weird USER reply. Curl couldn't parse the reply
- sent to the USER request.
-
- 13 FTP weird PASV reply, Curl couldn't parse the reply
- sent to the PASV request.
-
- 14 FTP weird 227 format. Curl couldn't parse the
- 227-line the server sent.
-
- 15 FTP can't get host. Couldn't resolve the host IP we
- got in the 227-line.
-
- 16 FTP can't reconnect. Couldn't connect to the host
- we got in the 227-line.
-
- 17 FTP couldn't set binary. Couldn't change transfer
- method to binary.
-
- 18 Partial file. Only a part of the file was trans-
- fered.
-
- 19 FTP couldn't download/access the given file, the
- RETR (or similar) command failed.
-
- 20 FTP write error. The transfer was reported bad by
- the server.
-
-
- 22 HTTP page not retrieved. The requested url was not
- found or returned another error with the HTTP error
- code being 400 or above. This return code only
- appears if --fail is used.
-
- 23 Write error. Curl couldn't write data to a local
- filesystem or similar.
-
- 24 Malformed user. User name badly specified.
-
- 25 FTP couldn't STOR file. The server denied the STOR
- operation, used for FTP uploading.
-
- 26 Read error. Various reading problems.
-
- 27 Out of memory. A memory allocation request failed.
-
- 28 Operation timeout. The specified time-out period
- was reached according to the conditions.
-
- 29 FTP couldn't set ASCII. The server returned an
- unknown reply.
-
- 30 FTP PORT failed. The PORT command failed. Not all
- FTP servers support the PORT command, try doing a
- transfer using PASV instead!
-
- 31 FTP couldn't use REST. The REST command failed.
- This command is used for resumed FTP transfers.
-
- 32 FTP couldn't use SIZE. The SIZE command failed. The
- command is an extension to the original FTP spec
- RFC 959.
-
- 33 HTTP range error. The range "command" didn't work.
-
- 34 HTTP post error. Internal post-request generation
- error.
-
- 35 SSL connect error. The SSL handshaking failed.
-
- 36 FTP bad download resume. Couldn't continue an ear-
- lier aborted download.
-
- 37 FILE couldn't read file. Failed to open the file.
- Permissions?
-
- 38 LDAP cannot bind. LDAP bind operation failed.
-
- 39 LDAP search failed.
-
- not found.
-
- 42 Aborted by callback. An application told curl to
- abort the operation.
-
- 43 Internal error. A function was called with a bad
- parameter.
-
- 44 Internal error. A function was called in a bad
- order.
-
- 45 Interface error. A specified outgoing interface
- could not be used.
-
- 46 Bad password entered. An error was signaled when
- the password was entered.
-
- 47 Too many redirects. When following redirects, curl
- hit the maximum amount.
-
- 48 Unknown TELNET option specified.
-
- 49 Malformed telnet option.
-
- 51 The remote peer's SSL certificate wasn't ok
-
- 52 The server didn't reply anything, which here is
- considered an error.
-
- 53 SSL crypto engine not found
-
- 54 Cannot set SSL crypto engine as default
-
- 55 Failed sending network data
-
- 56 Failure in receiving network data
-
- 57 Share is in use (internal error)
-
- 58 Problem with the local certificate
-
- 59 Couldn't use specified SSL cipher
-
- 60 Problem with the CA cert (path? permission?)
-
- 61 Unrecognized transfer encoding
-
- 62 Invalid LDAP URL
-
- 63 Maximum file size exceeded
-
- XX There will appear more error codes here in future
-
-
-</PRE>
-<H2>AUTHORS / CONTRIBUTORS</H2><PRE>
- Daniel Stenberg is the main author, but the whole list of
- contributors is found in the separate THANKS file.
-
-
-</PRE>
-<H2>WWW</H2><PRE>
- http://curl.haxx.se
-
-
-</PRE>
-<H2>FTP</H2><PRE>
- ftp://ftp.sunet.se/pub/www/utilities/curl/
-
-
-</PRE>
-<H2>SEE ALSO</H2><PRE>
- <B>ftp(1)</B>, <B>wget(1)</B>, <B>snarf(1)</B>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-</PRE>
-<HR>
-<ADDRESS>
-Man(1) output converted with
-<a href="http://www.oac.uci.edu/indiv/ehood/man2html.html">man2html</a>
-</ADDRESS>
-</BODY>
-</HTML>