示例#1
0
文件: rfc3676.c 项目: aschrab/mutt
/*
 * This routine does RfC3676 space stuffing since it's a MUST.
 * Space stuffing means that we have to add leading spaces to
 * certain lines:
 *   - lines starting with a space
 *   - lines starting with 'From '
 * This routine is only called once right after editing the
 * initial message so it's up to the user to take care of stuffing
 * when editing the message several times before actually sending it
 *
 * This is more or less a hack as it replaces the message's content with
 * a freshly created copy in a tempfile and modifies the file's mtime
 * so we don't trigger code paths watching for mtime changes
 */
void rfc3676_space_stuff (HEADER* hdr)
{
#if DEBUG
  int lc = 0;
  size_t len = 0;
  unsigned char c = '\0';
#endif
  FILE *in = NULL, *out = NULL;
  char buf[LONG_STRING];
  char tmpfile[_POSIX_PATH_MAX];

  if (!hdr || !hdr->content || !hdr->content->filename)
    return;

  dprint (2, (debugfile, "f=f: postprocess %s\n", hdr->content->filename));

  if ((in = safe_fopen (hdr->content->filename, "r")) == NULL)
    return;

  mutt_mktemp (tmpfile, sizeof (tmpfile));
  if ((out = safe_fopen (tmpfile, "w+")) == NULL)
  {
    safe_fclose (&in);
    return;
  }

  while (fgets (buf, sizeof (buf), in))
  {
    if (ascii_strncmp ("From ", buf, 5) == 0 || buf[0] == ' ') {
      fputc (' ', out);
#if DEBUG
      lc++;
      len = mutt_strlen (buf);
      if (len > 0)
      {
        c = buf[len-1];
        buf[len-1] = '\0';
      }
      dprint (4, (debugfile, "f=f: line %d needs space-stuffing: '%s'\n",
                  lc, buf));
      if (len > 0)
        buf[len-1] = c;
#endif
    }
    fputs (buf, out);
  }
  safe_fclose (&in);
  safe_fclose (&out);
  mutt_set_mtime (hdr->content->filename, tmpfile);
  unlink (hdr->content->filename);
  mutt_str_replace (&hdr->content->filename, tmpfile);
}
示例#2
0
文件: browse.c 项目: hww3/pexts
static int browse_add_list_result (IMAP_DATA* idata, const char* cmd,
  struct browser_state* state, short isparent)
{
  char *name;
  int noselect;
  int noinferiors;
  IMAP_MBOX mx;

  if (imap_parse_path (state->folder, &mx))
  {
    dprint (2, (debugfile,
      "browse_add_list_result: current folder %s makes no sense\n", state->folder));
    return -1;
  }

  imap_cmd_start (idata, cmd);

  do 
  {
    if (imap_parse_list_response(idata, &name, &noselect, &noinferiors,
        &idata->delim) != 0)
    {
      FREE (&mx.mbox);
      return -1;
    }

    if (name)
    {
      /* Let a parent folder never be selectable for navigation */
      if (isparent)
        noselect = 1;
      /* prune current folder from output */
      if (isparent || mutt_strncmp (name, mx.mbox, strlen (name)))
        imap_add_folder (idata->delim, name, noselect, noinferiors, state,
          isparent);
    }
  }
  while ((ascii_strncmp (idata->cmd.buf, idata->cmd.seq, SEQLEN) != 0));

  FREE (&mx.mbox);
  return 0;
}
示例#3
0
文件: browse.c 项目: hww3/pexts
/* Check which namespaces have contents */
static int browse_verify_namespace (IMAP_DATA* idata,
  IMAP_NAMESPACE_INFO *nsi, int nns)
{
  char buf[LONG_STRING];
  int i = 0;
  char *name;
  char delim;

  for (i = 0; i < nns; i++, nsi++)
  {
    /* Cyrus gives back nothing if the % isn't added. This may return lots
     * of data in some cases, I guess, but I currently feel that's better
     * than invisible namespaces */
    if (nsi->delim)
      snprintf (buf, sizeof (buf), "%s \"\" \"%s%c%%\"",
		option (OPTIMAPLSUB) ? "LSUB" : "LIST", nsi->prefix,
		nsi->delim);
    else
      snprintf (buf, sizeof (buf), "%s \"\" \"%s%%\"",
		option (OPTIMAPLSUB) ? "LSUB" : "LIST", nsi->prefix);

    imap_cmd_start (idata, buf);

    nsi->listable = 0;
    nsi->home_namespace = 0;
    do 
    {
      if (imap_parse_list_response(idata, &name, &nsi->noselect,
          &nsi->noinferiors, &delim) != 0)
	return -1;
      nsi->listable |= (name != NULL);
    }
    while ((ascii_strncmp (idata->cmd.buf, idata->cmd.seq, SEQLEN) != 0));
  }

  return 0;
}
示例#4
0
文件: auth_sasl.c 项目: sunny256/mutt
/* imap_auth_sasl: Default authenticator if available. */
imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method)
{
  sasl_conn_t* saslconn;
  sasl_interact_t* interaction = NULL;
  int rc, irc;
  char buf[HUGE_STRING];
  const char* mech;
  const char *pc = NULL;
  unsigned int len, olen;
  unsigned char client_start;

  if (mutt_sasl_client_new (idata->conn, &saslconn) < 0)
  {
    dprint (1, (debugfile,
      "imap_auth_sasl: Error allocating SASL connection.\n"));
    return IMAP_AUTH_FAILURE;
  }

  rc = SASL_FAIL;

  /* If the user hasn't specified a method, use any available */
  if (!method)
  {
    method = idata->capstr;

    /* hack for SASL ANONYMOUS support:
     * 1. Fetch username. If it's "" or "anonymous" then
     * 2. attempt sasl_client_start with only "AUTH=ANONYMOUS" capability
     * 3. if sasl_client_start fails, fall through... */

    if (mutt_account_getuser (&idata->conn->account))
      return IMAP_AUTH_FAILURE;

    if (mutt_bit_isset (idata->capabilities, AUTH_ANON) &&
	(!idata->conn->account.user[0] ||
	 !ascii_strncmp (idata->conn->account.user, "anonymous", 9)))
      rc = sasl_client_start (saslconn, "AUTH=ANONYMOUS", NULL, &pc, &olen, 
                              &mech);
  } else if (!ascii_strcasecmp ("login", method) &&
	!strstr (NONULL (idata->capstr), "AUTH=LOGIN"))
    /* do not use SASL login for regular IMAP login (#3556) */
    return IMAP_AUTH_UNAVAIL;
  
  if (rc != SASL_OK && rc != SASL_CONTINUE)
    do
    {
      rc = sasl_client_start (saslconn, method, &interaction,
        &pc, &olen, &mech);
      if (rc == SASL_INTERACT)
	mutt_sasl_interact (interaction);
    }
    while (rc == SASL_INTERACT);

  client_start = (olen > 0);

  if (rc != SASL_OK && rc != SASL_CONTINUE)
  {
    if (method)
      dprint (2, (debugfile, "imap_auth_sasl: %s unavailable\n", method));
    else
      dprint (1, (debugfile, "imap_auth_sasl: Failure starting authentication exchange. No shared mechanisms?\n"));
    /* SASL doesn't support LOGIN, so fall back */

    return IMAP_AUTH_UNAVAIL;
  }

  mutt_message (_("Authenticating (%s)..."), mech);

  snprintf (buf, sizeof (buf), "AUTHENTICATE %s", mech);
  if (mutt_bit_isset (idata->capabilities, SASL_IR) && client_start)
  {
    len = mutt_strlen (buf);
    buf[len++] = ' ';
    if (sasl_encode64 (pc, olen, buf + len, sizeof (buf) - len, &olen) != SASL_OK)
    {
      dprint (1, (debugfile, "imap_auth_sasl: error base64-encoding client response.\n"));
      goto bail;
    }
    client_start = olen = 0;
  }
  imap_cmd_start (idata, buf);
  irc = IMAP_CMD_CONTINUE;

  /* looping protocol */
  while (rc == SASL_CONTINUE || olen > 0)
  {
    do
      irc = imap_cmd_step (idata);
    while (irc == IMAP_CMD_CONTINUE);

    if (irc == IMAP_CMD_BAD || irc == IMAP_CMD_NO)
      goto bail;

    if (irc == IMAP_CMD_RESPOND)
    {
      /* Exchange incorrectly returns +\r\n instead of + \r\n */
      if (idata->buf[1] == '\0')
      {
	buf[0] = '\0';
	len = 0;
      }
      else if (sasl_decode64 (idata->buf+2, strlen (idata->buf+2), buf,
			      LONG_STRING-1, &len) != SASL_OK)
      {
	dprint (1, (debugfile, "imap_auth_sasl: error base64-decoding server response.\n"));
	goto bail;
      }
    }

    /* client-start is only available with the SASL-IR extension, but
     * SASL 2.1 seems to want to use it regardless, at least for DIGEST
     * fast reauth. Override if the server sent an initial continuation */
    if (!client_start || buf[0])
    {
      do
      {
	rc = sasl_client_step (saslconn, buf, len, &interaction, &pc, &olen);
	if (rc == SASL_INTERACT)
	  mutt_sasl_interact (interaction);
      }
      while (rc == SASL_INTERACT);
    }
    else
      client_start = 0;

    /* send out response, or line break if none needed */
    if (olen)
    {
      if (sasl_encode64 (pc, olen, buf, sizeof (buf), &olen) != SASL_OK)
      {
	dprint (1, (debugfile, "imap_auth_sasl: error base64-encoding client response.\n"));
	goto bail;
      }
    }
    
    if (irc == IMAP_CMD_RESPOND)
    {
      strfcpy (buf + olen, "\r\n", sizeof (buf) - olen);
      mutt_socket_write (idata->conn, buf);
    }

    /* If SASL has errored out, send an abort string to the server */
    if (rc < 0)
    {
      mutt_socket_write (idata->conn, "*\r\n");
      dprint (1, (debugfile, "imap_auth_sasl: sasl_client_step error %d\n",rc));
    }
	  
    olen = 0;
  }

  while (irc != IMAP_CMD_OK)
    if ((irc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
      break;

  if (rc != SASL_OK)
    goto bail;

  if (imap_code (idata->buf))
  {
    mutt_sasl_setup_conn (idata->conn, saslconn);
    return IMAP_AUTH_SUCCESS;
  }

 bail:
  sasl_dispose (&saslconn);

  if (method)
  {
    dprint (2, (debugfile, "imap_auth_sasl: %s failed\n", method));
    return IMAP_AUTH_UNAVAIL;
  }

  mutt_error _("SASL authentication failed.");
  mutt_sleep(2);

  return IMAP_AUTH_FAILURE;
}
示例#5
0
/* imap_parse_path: given an IMAP mailbox name, return host, port
 *   and a path IMAP servers will recognise.
 * mx.mbox is malloc'd, caller must free it */
int imap_parse_path (const char* path, IMAP_MBOX* mx)
{
  static unsigned short ImapPort = 0;
  static unsigned short ImapsPort = 0;
  struct servent* service;
  char tmp[128];
  ciss_url_t url;
  char *c;
  int n;

  if (!ImapPort)
  {
    service = getservbyname ("imap", "tcp");
    if (service)
      ImapPort = ntohs (service->s_port);
    else
      ImapPort = IMAP_PORT;
    dprint (3, (debugfile, "Using default IMAP port %d\n", ImapPort));
  }
  if (!ImapsPort)
  {
    service = getservbyname ("imaps", "tcp");
    if (service)
      ImapsPort = ntohs (service->s_port);
    else
      ImapsPort = IMAP_SSL_PORT;
    dprint (3, (debugfile, "Using default IMAPS port %d\n", ImapsPort));
  }

  /* Defaults */
  memset(&mx->account, 0, sizeof(mx->account));
  mx->account.port = ImapPort;
  mx->account.type = M_ACCT_TYPE_IMAP;

  c = safe_strdup (path);
  url_parse_ciss (&url, c);
  if (url.scheme == U_IMAP || url.scheme == U_IMAPS)
  {
    if (mutt_account_fromurl (&mx->account, &url) < 0 || !*mx->account.host)
    {
      FREE (&c);
      return -1;
    }

    mx->mbox = safe_strdup (url.path);

    if (url.scheme == U_IMAPS)
      mx->account.flags |= M_ACCT_SSL;

    FREE (&c);
  }
  /* old PINE-compatibility code */
  else
  {
    FREE (&c);
    if (sscanf (path, "{%127[^}]}", tmp) != 1)
      return -1;

    c = strchr (path, '}');
    if (!c)
      return -1;
    else
      /* walk past closing '}' */
      mx->mbox = safe_strdup (c+1);

    if ((c = strrchr (tmp, '@')))
    {
      *c = '\0';
      strfcpy (mx->account.user, tmp, sizeof (mx->account.user));
      strfcpy (tmp, c+1, sizeof (tmp));
      mx->account.flags |= M_ACCT_USER;
    }

    if ((n = sscanf (tmp, "%127[^:/]%127s", mx->account.host, tmp)) < 1)
    {
      dprint (1, (debugfile, "imap_parse_path: NULL host in %s\n", path));
      FREE (&mx->mbox);
      return -1;
    }

    if (n > 1) {
      if (sscanf (tmp, ":%hu%127s", &(mx->account.port), tmp) >= 1)
	mx->account.flags |= M_ACCT_PORT;
      if (sscanf (tmp, "/%s", tmp) == 1)
      {
	if (!ascii_strncmp (tmp, "ssl", 3))
	  mx->account.flags |= M_ACCT_SSL;
	else
	{
	  dprint (1, (debugfile, "imap_parse_path: Unknown connection type in %s\n", path));
	  FREE (&mx->mbox);
	  return -1;
	}
      }
    }
  }

  if ((mx->account.flags & M_ACCT_SSL) && !(mx->account.flags & M_ACCT_PORT))
    mx->account.port = ImapsPort;

  return 0;
}
示例#6
0
RIFActVarBind RIFActVarBind::parse(DPtr<uint8_t> *utf8str)
    throw(BadAllocException, SizeUnknownException,
          InvalidCodepointException, InvalidEncodingException,
          MalformedIRIRefException, TraceableException) {
  if (utf8str == NULL) {
    THROW(TraceableException, "utf8str must not be NULL.");
  }
  if (!utf8str->sizeKnown()) {
    THROWX(SizeUnknownException);
  }
  const uint8_t *begin = utf8str->dptr();
  const uint8_t *end = begin + utf8str->size();
  const uint8_t *left_bound = begin;
  const uint8_t *right_bound = end;
  for (; left_bound != end && is_space(*left_bound); ++left_bound) {
    // find first non-space character
  }
  if (left_bound == end || *left_bound != to_ascii('(')) {
    THROW(TraceableException, "Could not find opening parenthesis.");
  }
  for (--right_bound; right_bound != left_bound && is_space(*right_bound);
       --right_bound) {
    // find last non-space character
  }
  if (right_bound == left_bound || *right_bound != to_ascii(')')) {
    THROW(TraceableException, "Ends without closing parenthesis.");
  }
  for (++left_bound; left_bound != right_bound && is_space(*left_bound);
       ++left_bound) {
    // find beginning of action variable
  }
  if (left_bound == right_bound || *left_bound != to_ascii('?')) {
    THROW(TraceableException, "Unable to find action variable.");
  }
  for (--right_bound; right_bound != left_bound && is_space(*right_bound);
       --right_bound) {
    // find end of binding value
  }
  if (right_bound == left_bound) {
    THROW(TraceableException, "Unable to find binding value.");
  }
  ++right_bound;
  const uint8_t *var = left_bound;
  while (var != right_bound) {
    for (++var; var != right_bound && !is_space(*var); ++var) {
      // find end of variable... maybe
    }
    DPtr<uint8_t> *varstr = utf8str->sub(left_bound - begin,
                                         var - left_bound);
    RIFVar v;
    try {
      v = RIFVar::parse(varstr);
      varstr->drop();
    } catch (BadAllocException &e) {
      varstr->drop();
      RETHROW(e, "Unable to parse action variable.");
    } catch (InvalidCodepointException &e) {
      varstr->drop();
      RETHROW(e, "Unable to parse action variable.");
    } catch (InvalidEncodingException &e) {
      varstr->drop();
      RETHROW(e, "Unable to parse action variable.");
    } catch (TraceableException &e) {
      varstr->drop();
      continue;
    }

    const uint8_t *bindval = var;
    for (; bindval != right_bound && is_space(*bindval); ++bindval) {
      // find beginning of binding value
    }
    if (bindval == right_bound) {
      THROW(TraceableException, "Unable to find binding value.");
    }
    if (right_bound - bindval == 5 &&
        ascii_strncmp(bindval, "New()", 5) == 0) {
      return RIFActVarBind(v);
    }
    DPtr<uint8_t> *framestr = utf8str->sub(bindval - begin,
                                           right_bound - bindval);
    try {
      RIFAtomic frame = RIFAtomic::parse(framestr);
      framestr->drop();
      framestr = NULL;
      return RIFActVarBind(v, frame);
    } catch (BadAllocException &e) {
      if (framestr != NULL) {
        framestr->drop();
      }
      RETHROW(e, "Unable to parse binding value.");
    } catch (InvalidCodepointException &e) {
      framestr->drop();
      RETHROW(e, "Unable to parse binding value.");
    } catch (InvalidEncodingException &e) {
      framestr->drop();
      RETHROW(e, "Unable to parse binding value.");
    } catch (MalformedIRIRefException &e) {
      framestr->drop();
      RETHROW(e, "Unable to parse binding value.");
    } catch (TraceableException &e) {
      if (framestr != NULL) {
        framestr->drop();
      }
      RETHROW(e, "Unable to parse binding value.");
    }
  }
  THROW(TraceableException, "Unable to parse action variable binding.");
}
示例#7
0
RIFActionBlock RIFActionBlock::parse(DPtr<uint8_t> *utf8str)
    throw(BadAllocException, SizeUnknownException,
          InvalidCodepointException, InvalidEncodingException,
          MalformedIRIRefException, TraceableException) {
  if (utf8str == NULL) {
    THROW(TraceableException, "utf8str must not be NULL.");
  }
  if (!utf8str->sizeKnown()) {
    THROWX(SizeUnknownException);
  }
  const uint8_t *begin = utf8str->dptr();
  const uint8_t *end = begin + utf8str->size();
  const uint8_t *mark = begin;
  for (; mark != end && is_space(*mark); ++mark) {
    // find beginning of action block
  }
  if (end - mark < 4) {
    THROW(TraceableException, "Could not find action block.");
  }
  if (ascii_strncmp(mark, "Do", 2) != 0) {
    THROW(TraceableException, "Action block must start with \"Do\".");
  }
  mark += 2;
  for (; mark != end && is_space(*mark); ++mark) {
    // search for left parenthesis
  }
  if (mark == end || *mark != to_ascii('(')) {
    THROW(TraceableException, "Could not find opening parenthesis.");
  }
  for (--end; end != mark && is_space(*end); --end) {
    // find right parenthesis
  }
  if (end == mark || *end != to_ascii(')')) {
    THROW(TraceableException, "Could not find closing parenthesis.");
  }
  for (--end; end != mark && is_space(*end); --end) {
    // find end of last action
  }
  ++end;
  for (++mark; mark != end && is_space(*mark); ++mark) {
    // find first binding or action
  }
  if (mark == end) {
    THROW(TraceableException, "Action block is (illegaly) empty.");
  }
  deque<RIFAction> actions;
  ActVarMap bindings(RIFVar::cmplt0);
  bool find_bindings = (*mark == to_ascii('('));
  const uint8_t *bound = mark;
  while (bound != end) {
    for (; bound != end && *bound != to_ascii(')'); ++bound) {
      // find end of action block binding or action... maybe
    }
    if (bound != end) {
      ++bound;
    }
    DPtr<uint8_t> *str = utf8str->sub(mark - begin, bound - mark);
    if (find_bindings) {
      try {
        RIFActVarBind bind = RIFActVarBind::parse(str);
        str->drop();
        str = NULL;
        pair<ActVarMap::iterator, bool> p = bindings.insert(
            pair<RIFVar, RIFActVarBind>(bind.getActVar(), bind));
        if (!p.second) {
          THROW(TraceableException,
                "Cannot have multiple bindings for same action variable.");
        }
      } catch (BadAllocException &e) {
        str->drop();
        RETHROW(e, "Cannot parse action variable binding.");
      } catch (InvalidCodepointException &e) {
        str->drop();
        RETHROW(e, "Cannot parse action variable binding.");
      } catch (InvalidEncodingException &e) {
        str->drop();
        RETHROW(e, "Cannot parse action variable binding.");
      } catch (MalformedIRIRefException &e) {
        str->drop();
        continue;
      } catch (TraceableException &e) {
        if (str == NULL) {
          RETHROW(e, "Malformed action block.");
        }
        str->drop();
        continue;
      }
    } else {
      try {
        RIFAction act = RIFAction::parse(str);
        str->drop();
        actions.push_back(act);
      } catch (BadAllocException &e) {
        str->drop();
        RETHROW(e, "Cannot parse action.");
      } catch (InvalidCodepointException &e) {
        str->drop();
        RETHROW(e, "Cannot parse action.");
      } catch (InvalidEncodingException &e) {
        str->drop();
        RETHROW(e, "Cannot parse action.");
      } catch (MalformedIRIRefException &e) {
        str->drop();
        continue;
      } catch (TraceableException &e) {
        str->drop();
        continue;
      }
    }
    for (mark = bound; mark != end && is_space(*mark); ++mark) {
      // find beginning of next action block binding or action... maybe
    }
    bound = mark;
    find_bindings = find_bindings && (*mark == to_ascii('('));
  }
  DPtr<RIFAction> *pact;
  try {
    NEW(pact, APtr<RIFAction>, actions.size());
  } RETHROW_BAD_ALLOC
  copy(actions.begin(), actions.end(), pact->dptr());
  try {
    RIFActionBlock block(pact, bindings);
    pact->drop();
    return block;
  } catch (TraceableException &e) {
    pact->drop();
    RETHROW(e, "Cannot parse action block.");
  }
}
示例#8
0
文件: browse.c 项目: hww3/pexts
/* imap_browse: IMAP hook into the folder browser, fills out browser_state,
 *   given a current folder to browse */
int imap_browse (char* path, struct browser_state* state)
{
  IMAP_DATA* idata;
  char buf[LONG_STRING];
  char buf2[LONG_STRING];
  char nsbuf[LONG_STRING];
  char mbox[LONG_STRING];
  char list_cmd[5];
  IMAP_NAMESPACE_INFO nsi[16];
  int home_namespace = 0;
  int n;
  int i;
  int nsup;
  char ctmp;
  int nns;
  char *cur_folder;
  short showparents = 0;
  int noselect;
  int noinferiors;
  IMAP_MBOX mx;

  if (imap_parse_path (path, &mx))
  {
    mutt_error (_("%s is an invalid IMAP path"), path);
    return -1;
  }

  strfcpy (list_cmd, option (OPTIMAPLSUB) ? "LSUB" : "LIST", sizeof (list_cmd));

  if (!(idata = imap_conn_find (&(mx.account), 0)))
    goto fail;

  if (!mx.mbox)
  {
    home_namespace = 1;
    mbox[0] = '\0';		/* Do not replace "" with "INBOX" here */
    mx.mbox = safe_strdup(ImapHomeNamespace);
    nns = 0;
    if (mutt_bit_isset(idata->capabilities,NAMESPACE))
    {
      mutt_message _("Getting namespaces...");
      if (browse_get_namespace (idata, nsbuf, sizeof (nsbuf), 
				nsi, sizeof (nsi),  &nns) != 0)
	goto fail;
      if (browse_verify_namespace (idata, nsi, nns) != 0)
	goto fail;
    }
  }

  mutt_message _("Getting folder list...");

  /* skip check for parents when at the root */
  if (mx.mbox && mx.mbox[0] != '\0')
  {
    imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox));
    imap_munge_mbox_name (buf, sizeof (buf), mbox);
    imap_unquote_string(buf); /* As kludgy as it gets */
    mbox[sizeof (mbox) - 1] = '\0';
    strncpy (mbox, buf, sizeof (mbox) - 1);
    n = mutt_strlen (mbox);

    dprint (3, (debugfile, "imap_browse: mbox: %s\n", mbox));

    /* if our target exists and has inferiors, enter it if we
     * aren't already going to */
    if (mbox[n-1] != idata->delim)
    {
      snprintf (buf, sizeof (buf), "%s \"\" \"%s\"", list_cmd, mbox);
      imap_cmd_start (idata, buf);
      do 
      {
        if (imap_parse_list_response (idata, &cur_folder, &noselect,
            &noinferiors, &idata->delim) != 0)
	  goto fail;

        if (cur_folder)
        {
          imap_unmunge_mbox_name (cur_folder);

          if (!noinferiors && cur_folder[0] &&
            (n = strlen (mbox)) < LONG_STRING-1)
          {
            mbox[n++] = idata->delim;
            mbox[n] = '\0';
          }
        }
      }
      while (ascii_strncmp (idata->cmd.buf, idata->cmd.seq, SEQLEN));
    }

    /* if we're descending a folder, mark it as current in browser_state */
    if (mbox[n-1] == idata->delim)
    {
      /* don't show parents in the home namespace */
      if (!home_namespace)
	showparents = 1;
      imap_qualify_path (buf, sizeof (buf), &mx, mbox);
      state->folder = safe_strdup (buf);
      n--;
    }

    /* Find superiors to list
     * Note: UW-IMAP servers return folder + delimiter when asked to list
     *  folder + delimiter. Cyrus servers don't. So we ask for folder,
     *  and tack on delimiter ourselves.
     * Further note: UW-IMAP servers return nothing when asked for 
     *  NAMESPACES without delimiters at the end. Argh! */
    for (n--; n >= 0 && mbox[n] != idata->delim ; n--);
    if (n > 0)			/* "aaaa/bbbb/" -> "aaaa" */
    {
      /* forget the check, it is too delicate (see above). Have we ever
       * had the parent not exist? */
      ctmp = mbox[n];
      mbox[n] = '\0';

      if (showparents)
      {
	dprint (3, (debugfile, "imap_init_browse: adding parent %s\n", mbox));
	imap_add_folder (idata->delim, mbox, 1, 0, state, 1);
      }

      /* if our target isn't a folder, we are in our superior */
      if (!state->folder)
      {
        /* store folder with delimiter */
        mbox[n++] = ctmp;
        ctmp = mbox[n];
        mbox[n] = '\0';
        imap_qualify_path (buf, sizeof (buf), &mx, mbox);
        state->folder = safe_strdup (buf);
      }
      mbox[n] = ctmp;
    } 
    /* "/bbbb/" -> add  "/", "aaaa/" -> add "" */
    else
    {
      char relpath[2];
      /* folder may be "/" */
      snprintf (relpath, sizeof (relpath), "%c" , n < 0 ? '\0' : idata->delim);
      if (showparents)
        imap_add_folder (idata->delim, relpath, 1, 0, state, 1); 
      if (!state->folder)
      {
        imap_qualify_path (buf, sizeof (buf), &mx, relpath);
        state->folder = safe_strdup (buf);
      }
    }
  }

  /* no namespace, no folder: set folder to host only */
  if (!state->folder)
  {
    imap_qualify_path (buf, sizeof (buf), &mx, NULL);
    state->folder = safe_strdup (buf);
  }

  if (home_namespace && mbox[0] != '\0')
  {
    /* Listing the home namespace, so INBOX should be included. Home 
     * namespace is not "", so we have to list it explicitly. We ask the 
     * server to see if it has descendants. */
    dprint (2, (debugfile, "imap_init_browse: adding INBOX\n"));
    if (browse_add_list_result (idata, "LIST \"\" \"INBOX\"", state, 0))
      goto fail;

    if (!state->entrylen)
    {
      mutt_error _("No such folder");
      goto fail;
    }
  }

  nsup = state->entrylen;

  dprint (3, (debugfile, "imap_browse: Quoting mailbox scan: %s -> ", mbox));
  snprintf (buf, sizeof (buf), "%s%%", mbox);
  imap_quote_string (buf2, sizeof (buf2), buf);
  dprint (3, (debugfile, "%s\n", buf2));
  snprintf (buf, sizeof (buf), "%s \"\" %s", list_cmd, buf2);
  if (browse_add_list_result (idata, buf, state, 0))
    goto fail;

  mutt_clear_error ();

  qsort(&(state->entry[nsup]),state->entrylen-nsup,sizeof(state->entry[0]),
	(int (*)(const void*,const void*)) compare_names);
  if (home_namespace)
  {				/* List additional namespaces */
    for (i = 0; i < nns; i++)
      if (nsi[i].listable && !nsi[i].home_namespace) {
	imap_add_folder(nsi[i].delim, nsi[i].prefix, nsi[i].noselect,
			nsi[i].noinferiors, state, 0);
	dprint (3, (debugfile, "imap_init_browse: adding namespace: %s\n",
		    nsi[i].prefix));
      }
  }

  FREE (&mx.mbox);
  return 0;

 fail:
  FREE (&mx.mbox);
  return -1;
}
示例#9
0
文件: browse.c 项目: hww3/pexts
static int browse_get_namespace (IMAP_DATA* idata, char* nsbuf, int nsblen,
  IMAP_NAMESPACE_INFO* nsi, int nsilen, int* nns)
{
  char *s;
  int n;
  char ns[LONG_STRING];
  char delim = '/';
  int type;
  int nsbused = 0;
  int rc;

  *nns = 0;
  nsbuf[nsblen-1] = '\0';

  imap_cmd_start (idata, "NAMESPACE");
  
  do 
  {
    if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
      break;

    s = imap_next_word (idata->cmd.buf);
    if (ascii_strncasecmp ("NAMESPACE", s, 9) == 0)
    {
      /* There are three sections to the response, User, Other, Shared,
       * and maybe more by extension */
      for (type = IMAP_NS_PERSONAL; *s; type++)
      {
	s = imap_next_word (s);
	if (*s && ascii_strncmp (s, "NIL", 3))
	{
	  s++;
	  while (*s && *s != ')')
	  {
	    s++; /* skip ( */
	    /* copy namespace */
	    n = 0;
	    delim = '\0';

	    if (*s == '\"')
	    {
	      s++;
	      while (*s && *s != '\"') 
	      {
		if (*s == '\\')
		  s++;
		ns[n++] = *s;
		s++;
	      }
	      /* skip trailing ", if we found one, otherwise
	       * imap_next_word will get confused */
	      if (*s)
		s++;
	    }
	    else
	      while (*s && !ISSPACE (*s)) 
	      {
		ns[n++] = *s;
		s++;
	      }
	    ns[n] = '\0';
	    /* delim? */
	    s = imap_next_word (s);
	    /* delimiter is meaningless if namespace is "". Why does
	     * Cyrus provide one?! */
	    if (n && *s && *s == '\"')
	    {
	      if (s[1] && s[2] == '\"')
		delim = s[1];
	      else if (s[1] && s[1] == '\\' && s[2] && s[3] == '\"')
		delim = s[2];
	    }
	    /* skip "" namespaces, they are already listed at the root */
	    if ((ns[0] != '\0') && (nsbused < nsblen) && (*nns < nsilen))
	    {
	      dprint (3, (debugfile, "browse_get_namespace: adding %s\n", ns));
	      nsi->type = type;
	      /* Cyrus doesn't append the delimiter to the namespace,
	       * but UW-IMAP does. We'll strip it here and add it back
	       * as if it were a normal directory, from the browser */
	      if (n && (ns[n-1] == delim))
		ns[--n] = '\0';
	      strncpy (nsbuf+nsbused,ns,nsblen-nsbused-1);
	      nsi->prefix = nsbuf+nsbused;
	      nsbused += n+1;
	      nsi->delim = delim;
	      nsi++;
	      (*nns)++;
	    }
	    while (*s && *s != ')')
	      s++;
	    if (*s)
	      s++;
	  }
	}
      }
    }
  }
  while (rc == IMAP_CMD_CONTINUE);

  if (rc != IMAP_CMD_OK)
    return -1;

  return 0;
}
示例#10
0
文件: RIFAction.cpp 项目: jrweave/phd
RIFAction RIFAction::parse(DPtr<uint8_t> *utf8str)
    throw(BadAllocException, SizeUnknownException,
          InvalidCodepointException, InvalidEncodingException,
          MalformedIRIRefException, TraceableException) {
  if (utf8str == NULL) {
    THROW(TraceableException, "utf8str must not be NULL.");
  }
  if (!utf8str->sizeKnown()) {
    THROWX(SizeUnknownException);
  }
  const uint8_t *begin = utf8str->dptr();
  const uint8_t *end = begin + utf8str->size();
  const uint8_t *beginkw = begin;
  for (; beginkw != end && is_space(*beginkw); ++beginkw) {
    // find beginning of keyword
  }
  if (beginkw == end) {
    THROW(TraceableException, "No keyword found when parsing RIFAction.");
  }
  const uint8_t *endkw = beginkw;
  for (; endkw != end && is_alnum(*endkw); ++endkw) {
    // find end of keyword
  }
  
  enum RIFActType type;
  if (endkw - beginkw == 6) {
    if (ascii_strncmp(beginkw, "Assert", 6) == 0) {
      type = ASSERT_FACT;
    } else if (ascii_strncmp(beginkw, "Modify", 6) == 0) {
      type = MODIFY;
    } else {
      THROW(TraceableException, "Unrecognized RIFAction type.");
    }
  } else if (endkw - beginkw == 7) {
    if (ascii_strncmp(beginkw, "Retract", 7) == 0) {
      type = RETRACT_FACT; // validate later
    } else if (ascii_strncmp(beginkw, "Execute", 7) == 0) {
      type = EXECUTE;
    } else {
      THROW(TraceableException, "Unrecognized RIFAction type.");
    }
  } else {
    THROW(TraceableException, "Unrecognized RIFAction type.");
  }

  const uint8_t *left_bound = endkw;
  for (; left_bound != end && *left_bound != to_ascii('('); ++left_bound) {
    // find left paren enclosing target
  }
  if (left_bound == end) {
    THROW(TraceableException,
          "Could not find left paren when parsing RIFAction.");
  }
  const uint8_t *right_bound = end;
  for (--right_bound; right_bound != left_bound &&
                      *right_bound != to_ascii(')'); --right_bound) {
    // find right paren enclosing target
  }
  if (right_bound == left_bound) {
    THROW(TraceableException,
          "Could not find right paren when parsing RIFAction.");
  }
  for (++left_bound; left_bound != right_bound && is_space(*left_bound);
       ++left_bound) {
    // find left bound of target
  }
  if (left_bound == right_bound) {
    if (type == EXECUTE) {
      return RIFAction();
    }
    THROW(TraceableException, "No target specified for RIFAction.");
  }
  for (--right_bound; right_bound != left_bound && is_space(*right_bound);
       --right_bound) {
    // find right bound of target
  }
  ++right_bound;
  DPtr<uint8_t> *targetstr = utf8str->sub(left_bound - begin,
                                          right_bound - left_bound);
  try {
    RIFAtomic atom = RIFAtomic::parse(targetstr);
    RIFAction act (type, atom);
    targetstr->drop();
    return act;
  } catch (BadAllocException &e) {
    targetstr->drop();
    RETHROW(e, "Unable to parse target.");
  } catch (InvalidCodepointException &e) {
    targetstr->drop();
    RETHROW(e, "Unable to parse target.");
  } catch (InvalidEncodingException &e) {
    targetstr->drop();
    RETHROW(e, "Unable to parse target.");
  } catch (MalformedIRIRefException &e) {
    targetstr->drop();
    RETHROW(e, "Unable to parse target.");
  } catch (BaseException<enum RIFActType> &e) {
    targetstr->drop();
    RETHROW(e, "Unable to parse target.");
  } catch (TraceableException &e) {
    if (type != RETRACT_FACT) {
      targetstr->drop();
      RETHROW(e, "Unable to parse target.");
    }
  }
  try {
    RIFTerm term = RIFTerm::parse(targetstr);
    RIFAction act (term);
    targetstr->drop();
    return act;
  } catch (BadAllocException &e) {
    targetstr->drop();
    RETHROW(e, "Unable to parse target.");
  } catch (InvalidCodepointException &e) {
    targetstr->drop();
    RETHROW(e, "Unable to parse target.");
  } catch (InvalidEncodingException &e) {
    targetstr->drop();
    RETHROW(e, "Unable to parse target.");
  } catch (MalformedIRIRefException &e) {
    targetstr->drop();
    RETHROW(e, "Unable to parse target.");
  } catch (TraceableException &e) {
    // ignore and check if RETRACT_SLOTS
  }
  RIFTerm obj, attr;
  begin = targetstr->dptr();
  end = begin + targetstr->size();
  while (begin != end) {
    for (; begin != end && is_space(*begin); ++begin) {
      // creep forward to first non-space
    }
    for (++begin; begin != end && !is_space(*begin); ++begin) {
      // search for space between terms
    }
    if (begin == end) {
      targetstr->drop();
      THROW(TraceableException, "Invalid RETRACT target.");
    }
    DPtr<uint8_t> *str = targetstr->sub(0, begin - targetstr->dptr());
    try {
      obj = RIFTerm::parse(str);
      str->drop();
    } catch (TraceableException &e) {
      str->drop();
      continue;
    }
    for (++begin; begin != end && is_space(*begin); ++begin) {
      // search for second term
    }
    str = targetstr->sub(begin - targetstr->dptr(), end - begin);
    try {
      attr = RIFTerm::parse(str);
      str->drop();
    } catch (TraceableException &e) {
      str->drop();
      continue;
    }
    try {
      targetstr->drop();
      return RIFAction(obj, attr);
    } RETHROW_BAD_ALLOC
  }
  targetstr->drop();
  THROW(TraceableException, "Invalid RETRACT target.");
}