+ header))
+
+(defun nnmairix-group-toggle-parameter (group parameter description &optional par)
+ "Toggle on GROUP a certain PARAMETER.
+DESCRIPTION will be shown to the user with the activation
+status. If PAR is a positive number, the group parameter will be
+set to t and to nil otherwise."
+ (let* ((method (gnus-find-method-for-group group))
+ (par (or par
+ (not (gnus-group-get-parameter group parameter)))))
+ (if (eq (car method) 'nnmairix)
+ (progn
+ (when (numberp par)
+ (setq par (> par 0)))
+ (gnus-group-set-parameter group parameter par)
+ (if par
+ (message "%s activated for group %s" description group)
+ (message "%s deactivated for group %s" description group))
+ t)
+ (error "This is no nnmairix group")
+ nil)))
+
+;; Search for original article helper functions
+
+(defun nnmairix-goto-original-article (&optional no-registry)
+ "Jump to the original group and display article.
+The original group of the article is first determined with the
+registry (if enabled). If the registry is not enabled or did not
+find the article or the prefix NO-REGISTRY is non-nil, this
+function will try to determine the original group form the path
+of the mail file. The path is obtained through another mairix
+search in raw mode."
+ (interactive "P")
+ (when (not (eq (car gnus-current-select-method) 'nnmairix))
+ (let ((method (gnus-find-method-for-group gnus-newsgroup-name)))
+ (if (eq (car method) 'nnmairix)
+ (nnmairix-open-server (nth 1 method))
+ (error "Not in a nnmairix group"))))
+ (when (not (gnus-buffer-live-p gnus-article-buffer))
+ (error "No article buffer available"))
+ (let ((server (nth 1 gnus-current-select-method))
+ mid rval group allgroups)
+ ;; get message id
+ (with-current-buffer gnus-article-buffer
+ (gnus-summary-toggle-header 1)
+ (setq mid (message-fetch-field "Message-ID"))
+ ;; first check the registry (if available)
+ (unless no-registry
+ (setq allgroups (nnmairix-determine-original-group-from-registry mid)))
+ (unless (or allgroups
+ nnmairix-only-use-registry)
+ ;; registry was not available or did not find article
+ ;; so we search again with mairix in raw mode to get filename
+ (setq allgroups
+ (nnmairix-determine-original-group-from-path mid server))
+ ;; if available and allowed, add this entry to the registry
+ (when (and (not no-registry)
+ (boundp 'gnus-registry-install)
+ gnus-registry-install)
+ (dolist (cur allgroups)
+ (unless (gnus-parameter-registry-ignore cur)
+ (gnus-registry-add-group mid cur)))))
+ (if (> (length allgroups) 1)
+ (setq group
+ (gnus-completing-read
+ "Message exists in more than one group. Choose"
+ allgroups t))
+ (setq group (car allgroups))))
+ (if group
+ ;; show article in summary buffer
+ (nnmairix-show-original-article group mid)
+ (nnheader-message 3 "Couldn't find original article"))))
+
+(defun nnmairix-determine-original-group-from-registry (mid)
+ "Try to determinale original group for message-id MID from the registry."
+ (when (and (boundp 'gnus-registry-install)
+ gnus-registry-install)
+ (unless (string-match "^<" mid)
+ (set mid (concat "<" mid)))
+ (unless (string-match ">$" mid)
+ (set mid (concat mid ">")))
+ (gnus-registry-fetch-groups mid)))
+
+(defun nnmairix-determine-original-group-from-path (mid server)
+ "Determine original group(s) for message-id MID from the file path.
+The file path is obtained through a mairix search for the id on
+SERVER."
+ (nnmairix-open-server server)
+ (while (string-match "[<>]" mid)
+ (setq mid (replace-match "" t t mid)))
+ ;; mairix somehow does not like '$' in message-id
+ (when (string-match "\\$" mid)
+ (setq mid (concat mid "=")))
+ (while (string-match "\\$" mid)
+ (setq mid (replace-match "=," t t mid)))
+ (let (allgroups)
+ (if (zerop (nnmairix-call-mairix-binary-raw
+ (split-string nnmairix-mairix-command)
+ (list (concat "m:" mid))))
+ (with-current-buffer nnmairix-mairix-output-buffer
+ (goto-char (point-min))
+ (while (re-search-forward "^/.*$" nil t)
+ (push (nnmairix-get-group-from-file-path (match-string 0))
+ allgroups)
+ (forward-line 1)))
+ (error "Mairix could not find original article. See buffer %s for details"
+ nnmairix-mairix-output-buffer))
+ allgroups))
+
+(defun nnmairix-get-group-from-file-path (file)
+ "Get group by parsing the message location FILE."
+ (let (path filename serverbase group maildirflag allgroups)
+ (string-match "^\\(.*\\)/\\(.*?\\)$" file)
+ (setq path (expand-file-name (match-string 1 file)))
+ (setq filename (match-string 2 file))
+ ;; when we deal with maildir, remove cur/new/tmp from path
+ (setq maildirflag (string-match ".+\\..+\\..+" filename))
+ (when maildirflag
+ (setq path
+ (replace-regexp-in-string
+ ".*\\(/cur\\|/new\\|/tmp\\)$" "" path t t 1)))
+ ;; we first check nnml and nnmaildir servers
+ (setq
+ group
+ (catch 'found
+ (dolist (cur gnus-opened-servers)
+ (when (or (and (not maildirflag)
+ (eq (caar cur) 'nnml))
+ (and maildirflag
+ (eq (caar cur) 'nnmaildir)))
+ ;; get base path from server
+ (if maildirflag
+ (setq serverbase (cadr (assoc 'directory (car cur))))
+ (setq serverbase (cadr (assoc 'nnml-directory (car cur))))
+ (unless serverbase
+ (setq serverbase nnml-directory)))
+ (setq serverbase (file-name-as-directory
+ (expand-file-name serverbase)))
+ (when (string-match (concat serverbase "\\(.*\\)") path)
+ ;; looks good - rest of the path should be the group
+ (setq group (match-string 1 path))
+ (when (string-match "/$" group)
+ (setq group (replace-match "" t t group)))
+ (unless maildirflag
+ ;; for nnml: convert slashes to dots
+ (while (string-match "/" group)
+ (setq group (replace-match "." t t group))))
+ (setq group (gnus-group-prefixed-name group (car cur)))
+ ;; check whether this group actually exists
+ (when (gnus-group-entry group)
+ (throw 'found group)))))))
+ (unless group
+ ;; we haven't found it yet --> look for nnimap groups. Assume
+ ;; last element of the path is the group. This might fail since
+ ;; IMAP servers may present groups to the client in arbitrary
+ ;; ways...
+ (string-match "^.*/\\.?\\(.*\\)$" path)
+ (setq group (match-string 1 path))
+ ;; convert dots to slashes (nested group)
+ (while (string-match "\\." group)
+ (setq group (replace-match "/" t t group)))
+ (dolist (cur gnus-opened-servers)
+ (when (eq (caar cur) 'nnimap)
+ (when (gnus-group-entry
+ (gnus-group-prefixed-name group (car cur)))
+ (push
+ (gnus-group-prefixed-name group (car cur))
+ allgroups))))
+ (if (> (length allgroups) 1)
+ (setq group (gnus-completing-read
+ "Group %s exists on more than one IMAP server. Choose"
+ allgroups t))
+ (setq group (car allgroups))))
+ group))