Esempio n. 1
0
bool AchdHandle::start(QString hostname, QString description)
{
    if(!parse_description(description))
        return false;
    
    return start(hostname);
}
Esempio n. 2
0
cst_val *cst_args(char **argv, int argc,
		  const char *description,
		  cst_features *args)
{
    /* parses the given arguments wrt the description */
    cst_features *op_types = new_features();
    cst_val *files = NULL;
    int i;
    const char *type;
 
    parse_description(description,op_types);

    for (i=1; i<argc; i++)
    {
	if (argv[i][0] == '-')
	{
	    if ((!feat_present(op_types,argv[i])) ||
		(cst_streq("-h",argv[i])) ||
		(cst_streq("-?",argv[i])) ||
		(cst_streq("--help",argv[i])) ||
		(cst_streq("-help",argv[i])))
		parse_usage(argv[0],"","",description);
	    else
	    {
		type = feat_string(op_types,argv[i]);
		if (cst_streq("<binary>",type))
		    feat_set_string(args,argv[i],"true");
		else
		{
		    if (i+1 == argc)
			parse_usage(argv[0],
				    "missing argument for ",argv[i],
				    description);
		    if (cst_streq("<int>",type))
			feat_set_int(args,argv[i],atoi(argv[i+1]));
		    else if (cst_streq("<float>",type))
			feat_set_float(args,argv[i],atof(argv[i+1]));
		    else if (cst_streq("<string>",type))
			feat_set_string(args,argv[i],argv[i+1]);
		    else
			parse_usage(argv[0],
				    "unknown arg type ",type,
				    description);
		    i++;
		}
	    }
	}
	else
	    files = cons_val(string_val(argv[i]),files);
    }
    delete_features(op_types);

    return val_reverse(files);
}
void
gabble_jingle_content_parse_accept (GabbleJingleContent *c,
    WockyNode *content_node, gboolean google_mode, GError **error)
{
  GabbleJingleContentPrivate *priv = c->priv;
  const gchar *senders;
  WockyNode *trans_node, *desc_node;
  JingleDialect dialect = gabble_jingle_session_get_dialect (c->session);
  JingleContentSenders newsenders;

  desc_node = wocky_node_get_child (content_node, "description");
  trans_node = wocky_node_get_child (content_node, "transport");
  senders = wocky_node_get_attribute (content_node, "senders");

  if (GABBLE_IS_JINGLE_MEDIA_RTP (c) &&
      JINGLE_IS_GOOGLE_DIALECT (dialect) && trans_node == NULL)
    {
      DEBUG ("no transport node, assuming GTalk3 dialect");
      /* gtalk lj0.3 assumes google-p2p transport */
      g_object_set (c->session, "dialect", JINGLE_DIALECT_GTALK3, NULL);
    }

  if (senders == NULL)
    newsenders = get_default_senders (c);
  else
    newsenders = parse_senders (senders);

  if (newsenders == JINGLE_CONTENT_SENDERS_NONE)
    {
      SET_BAD_REQ ("invalid content senders");
      return;
    }

  if (newsenders != priv->senders)
    {
      DEBUG ("changing senders from %s to %s", produce_senders (priv->senders),
          produce_senders (newsenders));
      priv->senders = newsenders;
      g_object_notify ((GObject *) c, "senders");
    }

  parse_description (c, desc_node, error);
  if (*error != NULL)
      return;

  priv->state = JINGLE_CONTENT_STATE_ACKNOWLEDGED;
  g_object_notify ((GObject *) c, "state");

  if (trans_node != NULL)
    {
      gabble_jingle_transport_iface_parse_candidates (priv->transport,
        trans_node, NULL);
    }
}
void
gabble_jingle_content_parse_description_info (GabbleJingleContent *c,
    WockyNode *content_node, GError **error)
{
  GabbleJingleContentPrivate *priv = c->priv;
  WockyNode *desc_node;
  desc_node = wocky_node_get_child (content_node, "description");
  if (desc_node == NULL)
    {
      SET_BAD_REQ ("invalid description-info action");
      return;
    }

  if (priv->created_by_us && priv->state < JINGLE_CONTENT_STATE_ACKNOWLEDGED)
    {
      /* The stream was created by us and the other side didn't acknowledge it
       * yet, thus we don't have their codec information, thus the
       * description-info isn't meaningful and can be ignored */
      DEBUG ("Ignoring description-info as we didn't receive the codecs yet");
      return;
    }

  parse_description (c, desc_node, error);
}
Esempio n. 5
0
bool mdk_dict::load_ifo(const gchar *file)
{
    gchar *buffer;

    if (!g_file_get_contents(file, &buffer, NULL, NULL))
        return false;

#define DICT_MAGIC_DATA "StarDict's dict ifo file\nversion="
    if (!g_str_has_prefix(buffer, DICT_MAGIC_DATA))
    {
        g_free(buffer);
        return false;
    }

    bool is_dict_300 = false;
    gchar *p1;
    p1 = buffer + sizeof(DICT_MAGIC_DATA) -1;
#define DICT_VERSION_242 "2.4.2\n"
#define DICT_VERSION_300 "3.0.0\n"
    if (g_str_has_prefix(p1, DICT_VERSION_242)) {
        p1 += sizeof(DICT_VERSION_242) -2;
    } else if (g_str_has_prefix(p1, DICT_VERSION_300)) {
        p1 += sizeof(DICT_VERSION_300) -2;
        is_dict_300 = true;
    } else {
        g_print("Load %s failed: Unknown version.\n", file);
        g_free(buffer);
        return false;
    }

    gchar *p2, *p3;

    p2 = strstr(p1,"\nwordcount=");
    if (!p2) {
        g_free(buffer);
        return false;
    }

    p3 = strchr(p2 + sizeof("\nwordcount=")-1,'\n');
    gchar *tmpstr = (gchar *)g_memdup(p2 + sizeof("\nwordcount=") - 1,
                                      p3 - (p2+sizeof("\nwordcount=") - 1) + 1);
    tmpstr[p3 - (p2 + sizeof("\nwordcount=") - 1)] = '\0';
    wordcount = atol(tmpstr);
    g_free(tmpstr);

    p2 = strstr(p1,"\nsynwordcount=");
    if (p2) {
        p3 = strchr(p2 + sizeof("\nsynwordcount=") - 1, '\n');
        gchar *tmpstr = (gchar *)g_memdup(p2 + sizeof("\nsynwordcount=") - 1,
                                          p3 - (p2 + sizeof("\nsynwordcount=") - 1) + 1);
        tmpstr[p3-(p2+sizeof("\nsynwordcount=")-1)] = '\0';
        synwordcount = atol(tmpstr);
        g_free(tmpstr);
    } else {
        synwordcount = 0;
    }

    p2 = strstr(p1,"\nidxfilesize=");
    if (!p2) {
        g_free(buffer);
        return false;
    }

    p3 = strchr(p2+ sizeof("\nidxfilesize=")-1,'\n');
    tmpstr = (gchar *)g_memdup(p2 + sizeof("\nidxfilesize=")-1,
                               p3 - (p2 + sizeof("\nidxfilesize=")-1)+1);
    tmpstr[p3-(p2+sizeof("\nidxfilesize=")-1)] = '\0';
    index_file_size = atol(tmpstr);
    g_free(tmpstr);

    p2 = strstr(p1,"\ndicttype=");
    if (p2) {
        p2+=sizeof("\ndicttype=")-1;
        p3 = strchr(p2, '\n');
        dicttype.assign(p2, p3-p2);
    }

    p2 = strstr(p1,"\nbookname=");

    if (!p2) {
        g_free(buffer);
        return false;
    }

    p2 = p2 + sizeof("\nbookname=") -1;
    p3 = strchr(p2, '\n');
    bookname.assign(p2, p3-p2);

    p2 = strstr(p1,"\nauthor=");
    if (p2) {
        p2 = p2 + sizeof("\nauthor=") -1;
        p3 = strchr(p2, '\n');
        author.assign(p2, p3-p2);
    }

    p2 = strstr(p1,"\nemail=");
    if (p2) {
        p2 = p2 + sizeof("\nemail=") -1;
        p3 = strchr(p2, '\n');
        email.assign(p2, p3-p2);
    }

    p2 = strstr(p1,"\nwebsite=");
    if (p2) {
        p2 = p2 + sizeof("\nwebsite=") -1;
        p3 = strchr(p2, '\n');
        website.assign(p2, p3-p2);
    }

    p2 = strstr(p1,"\ndate=");
    if (p2) {
        p2 = p2 + sizeof("\ndate=") -1;
        p3 = strchr(p2, '\n');
        date.assign(p2, p3-p2);
    }

    p2 = strstr(p1,"\ndescription=");
    if (p2)
    {
        p2 = p2 + sizeof("\ndescription=")-1;
        p3 = strchr(p2, '\n');

        parse_description(p2, p3 - p2, description);
    }

    p2 = strstr(p1,"\nsametypesequence=");
    if (p2)
    {
        p2 += sizeof("\nsametypesequence=") - 1;
        p3 = strchr(p2, '\n');
        sametypesequence.assign(p2, p3 - p2);
    }

    g_free(buffer);

    if (wordcount == 0)
        return false;

    return true;
}
Esempio n. 6
0
//looks not optimal, TODO: refactor
bool DictInfo::load_from_ifo_file(const std::string& ifofilename,
                                  bool istreedict)
{
    ifo_file_name=ifofilename;
    gchar *buffer;
    if (!g_file_get_contents(ifofilename.c_str(), &buffer, NULL, NULL))
        return false;

#define TREEDICT_MAGIC_DATA "StarDict's treedict ifo file\nversion="
#define DICT_MAGIC_DATA "StarDict's dict ifo file\nversion="
    const gchar *magic_data=istreedict ? TREEDICT_MAGIC_DATA : DICT_MAGIC_DATA;
    if (!g_str_has_prefix(buffer, magic_data)) {
        g_free(buffer);
        return false;
    }

    bool is_dict_300 = false;
    gchar *p1;
    if (istreedict) {
        p1 = buffer + sizeof(TREEDICT_MAGIC_DATA) -1;
#define TREEDICT_VERSION_242 "2.4.2\n"
        if (g_str_has_prefix(p1, TREEDICT_VERSION_242)) {
            p1 += sizeof(TREEDICT_VERSION_242) -2;
        } else {
            g_print("Load %s failed: Unknown version.\n", ifofilename.c_str());
            g_free(buffer);
            return false;
        }
    } else {
        p1 = buffer + sizeof(DICT_MAGIC_DATA) -1;
#define DICT_VERSION_242 "2.4.2\n"
#define DICT_VERSION_300 "3.0.0\n"
        if (g_str_has_prefix(p1, DICT_VERSION_242)) {
            p1 += sizeof(DICT_VERSION_242) -2;
        } else if (g_str_has_prefix(p1, DICT_VERSION_300)) {
            p1 += sizeof(DICT_VERSION_300) -2;
            is_dict_300 = true;
        } else {
            g_print("Load %s failed: Unknown version.\n", ifofilename.c_str());
            g_free(buffer);
            return false;
        }
    }

    gchar *p2,*p3;

    if (is_dict_300) {
        p2 = strstr(p1,"\nidxoffsetbits=");
        if (p2) {
            p2 = p2 + sizeof("\nidxoffsetbits=") -1;
            if (g_str_has_prefix(p2, "64\n")) {
                // TODO
                g_print("Load %s failed: not supported presently.\n", ifofilename.c_str());
                g_free(buffer);
                return false;
            }
        }
    }

    p2 = strstr(p1,"\nwordcount=");
    if (!p2) {
        g_free(buffer);
        return false;
    }

    p3 = strchr(p2+ sizeof("\nwordcount=")-1,'\n');
    gchar *tmpstr = (gchar *)g_memdup(p2+sizeof("\nwordcount=")-1, p3-(p2+sizeof("\nwordcount=")-1)+1);
    tmpstr[p3-(p2+sizeof("\nwordcount=")-1)] = '\0';
    wordcount = atol(tmpstr);
    g_free(tmpstr);

    p2 = strstr(p1,"\nsynwordcount=");
    if (p2) {
        p3 = strchr(p2+ sizeof("\nsynwordcount=")-1,'\n');
        gchar *tmpstr = (gchar *)g_memdup(p2+sizeof("\nsynwordcount=")-1, p3-(p2+sizeof("\nsynwordcount=")-1)+1);
        tmpstr[p3-(p2+sizeof("\nsynwordcount=")-1)] = '\0';
        synwordcount = atol(tmpstr);
        g_free(tmpstr);
    } else {
        synwordcount = 0;
    }

    if (istreedict) {
        p2 = strstr(p1,"\ntdxfilesize=");
        if (!p2) {
            g_free(buffer);
            return false;
        }
        p3 = strchr(p2+ sizeof("\ntdxfilesize=")-1,'\n');
        tmpstr = (gchar *)g_memdup(p2+sizeof("\ntdxfilesize=")-1, p3-(p2+sizeof("\ntdxfilesize=")-1)+1);
        tmpstr[p3-(p2+sizeof("\ntdxfilesize=")-1)] = '\0';
        index_file_size = atol(tmpstr);
        g_free(tmpstr);
    } else {
        p2 = strstr(p1,"\nidxfilesize=");
        if (!p2) {
            g_free(buffer);
            return false;
        }

        p3 = strchr(p2+ sizeof("\nidxfilesize=")-1,'\n');
        tmpstr = (gchar *)g_memdup(p2+sizeof("\nidxfilesize=")-1, p3-(p2+sizeof("\nidxfilesize=")-1)+1);
        tmpstr[p3-(p2+sizeof("\nidxfilesize=")-1)] = '\0';
        index_file_size = atol(tmpstr);
        g_free(tmpstr);

        p2 = strstr(p1,"\ndicttype=");
        if (p2) {
            p2+=sizeof("\ndicttype=")-1;
            p3 = strchr(p2, '\n');
            dicttype.assign(p2, p3-p2);
        }
    }

    p2 = strstr(p1,"\nbookname=");

    if (!p2) {
        g_free(buffer);
        return false;
    }

    p2 = p2 + sizeof("\nbookname=") -1;
    p3 = strchr(p2, '\n');
    bookname.assign(p2, p3-p2);

    p2 = strstr(p1,"\nauthor=");
    if (p2) {
        p2 = p2 + sizeof("\nauthor=") -1;
        p3 = strchr(p2, '\n');
        author.assign(p2, p3-p2);
    }

    p2 = strstr(p1,"\nemail=");
    if (p2) {
        p2 = p2 + sizeof("\nemail=") -1;
        p3 = strchr(p2, '\n');
        email.assign(p2, p3-p2);
    }

    p2 = strstr(p1,"\nwebsite=");
    if (p2) {
        p2 = p2 + sizeof("\nwebsite=") -1;
        p3 = strchr(p2, '\n');
        website.assign(p2, p3-p2);
    }

    p2 = strstr(p1,"\ndate=");
    if (p2) {
        p2 = p2 + sizeof("\ndate=") -1;
        p3 = strchr(p2, '\n');
        date.assign(p2, p3-p2);
    }

    p2 = strstr(p1,"\ndescription=");
    if (p2) {
        p2 = p2 + sizeof("\ndescription=")-1;
        p3 = strchr(p2, '\n');
        parse_description(p2, p3-p2, description);
    }

    p2 = strstr(p1,"\nsametypesequence=");
    if (p2) {
        p2+=sizeof("\nsametypesequence=")-1;
        p3 = strchr(p2, '\n');
        sametypesequence.assign(p2, p3-p2);
    }

    g_free(buffer);

    return true;
}
Esempio n. 7
0
static void
parse_line (Package *pkg, const char *untrimmed, const char *path,
	    gboolean ignore_requires, gboolean ignore_private_libs,
	    gboolean ignore_requires_private)
{
  char *str;
  char *p;
  char *tag;

  debug_spew ("  line>%s\n", untrimmed);
  
  str = trim_string (untrimmed);
  
  if (*str == '\0') /* empty line */
    {
      g_free(str);
      return;
    }
  
  p = str;

  /* Get first word */
  while ((*p >= 'A' && *p <= 'Z') ||
	 (*p >= 'a' && *p <= 'z') ||
	 (*p >= '0' && *p <= '9') ||
	 *p == '_' || *p == '.')
    p++;

  tag = g_strndup (str, p - str);
  
  while (*p && isspace ((guchar)*p))
    ++p;

  if (*p == ':')
    {
      /* keyword */
      ++p;
      while (*p && isspace ((guchar)*p))
        ++p;

      if (strcmp (tag, "Name") == 0)
        parse_name (pkg, p, path);
      else if (strcmp (tag, "Description") == 0)
        parse_description (pkg, p, path);
      else if (strcmp (tag, "Version") == 0)
        parse_version (pkg, p, path);
      else if (strcmp (tag, "Requires.private") == 0)
	{
	  if (!ignore_requires_private)
	    parse_requires_private (pkg, p, path);
	}
      else if (strcmp (tag, "Requires") == 0)
	{
          if (ignore_requires == FALSE)
	    parse_requires (pkg, p, path);
          else
	    goto cleanup;
        }
      else if ((strcmp (tag, "Libs.private") == 0) && 
               ignore_private_libs == FALSE)
        parse_libs_private (pkg, p, path);
      else if (strcmp (tag, "Libs") == 0)
        parse_libs (pkg, p, path);
      else if (strcmp (tag, "Cflags") == 0 ||
               strcmp (tag, "CFlags") == 0)
        parse_cflags (pkg, p, path);
      else if (strcmp (tag, "Conflicts") == 0)
        parse_conflicts (pkg, p, path);
      else if (strcmp (tag, "URL") == 0)
        parse_url (pkg, p, path);
      else
        {
	  /* we don't error out on unknown keywords because they may
	   * represent additions to the .pc file format from future
	   * versions of pkg-config.  We do make a note of them in the
	   * debug spew though, in order to help catch mistakes in .pc
	   * files. */
          debug_spew ("Unknown keyword '%s' in '%s'\n",
		      tag, path);
        }
    }
  else if (*p == '=')
    {
      /* variable */
      char *varname;
      char *varval;
      
      ++p;
      while (*p && isspace ((guchar)*p))
        ++p;
      
      if (pkg->vars == NULL)
        pkg->vars = g_hash_table_new (g_str_hash, g_str_equal);

#ifdef G_OS_WIN32
      if (!dont_define_prefix && strcmp (tag, prefix_variable) == 0)
	{
	  /* This is the prefix variable. Try to guesstimate a value for it
	   * for this package from the location of the .pc file.
	   */

	  gchar *prefix = pkg->pcfiledir;
	  const int prefix_len = strlen (prefix);
	  const char *const lib_pkgconfig = "\\lib\\pkgconfig";
	  const char *const share_pkgconfig = "\\share\\pkgconfig";
	  const int lib_pkgconfig_len = strlen (lib_pkgconfig);
	  const int share_pkgconfig_len = strlen (share_pkgconfig);

	  if ((strlen (prefix) > lib_pkgconfig_len &&
	       pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0) ||
	      (strlen (prefix) > share_pkgconfig_len &&
	       pathnamecmp (prefix + prefix_len - share_pkgconfig_len, share_pkgconfig) == 0))
	    {
	      /* It ends in lib\pkgconfig or share\pkgconfig. Good. */
	      
	      gchar *q;
	      
	      orig_prefix = g_strdup (p);

	      prefix = g_strdup (prefix);
	      if (strlen (prefix) > lib_pkgconfig_len &&
		  pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0)
		prefix[prefix_len - lib_pkgconfig_len] = '\0';
	      else
		prefix[prefix_len - share_pkgconfig_len] = '\0';
	      
	      /* Turn backslashes into slashes or
	       * poptParseArgvString() will eat them when ${prefix}
	       * has been expanded in parse_libs().
	       */
	      q = prefix;
	      while (*q)
		{
		  if (*q == '\\')
		    *q = '/';
		  q++;
		}
	      varname = g_strdup (tag);
	      debug_spew (" Variable declaration, '%s' overridden with '%s'\n",
			  tag, prefix);
	      g_hash_table_insert (pkg->vars, varname, prefix);
	      goto cleanup;
	    }
	}
      else if (!dont_define_prefix &&
	       orig_prefix != NULL &&
	       strncmp (p, orig_prefix, strlen (orig_prefix)) == 0 &&
	       G_IS_DIR_SEPARATOR (p[strlen (orig_prefix)]))
	{
	  char *oldstr = str;

	  p = str = g_strconcat (g_hash_table_lookup (pkg->vars, prefix_variable), p + strlen (orig_prefix), NULL);
	  g_free (oldstr);
	}
#endif

      if (g_hash_table_lookup (pkg->vars, tag))
        {
          verbose_error ("Duplicate definition of variable '%s' in '%s'\n",
                         tag, path);

          exit (1);
        }

      varname = g_strdup (tag);
      varval = trim_and_sub (pkg, p, path);     

      debug_spew (" Variable declaration, '%s' has value '%s'\n",
                  varname, varval);
      g_hash_table_insert (pkg->vars, varname, varval);
  
    }

 cleanup:  
  g_free (str);
  g_free (tag);
}
DescriptionParser::DescriptionParser(const std::string& description,
                                     const std::vector<std::string>& valid_types)
    : is_valid_(parse_description(description, valid_types)) {
  if (!is_valid_) return;

  // check if placeholders in connections_ refer to existing quiddity
  for (auto& it : connections_) {
    std::string placeholder;
    if (!it.src.empty() && *it.src.begin() == '.') {
      // removing the '.'
      placeholder = std::string(it.src.begin() + 1, it.src.end());
      // saving appropriate name instead of placeholder
      it.src = placeholder;
    } else if (!it.sink.empty() && *it.sink.begin() == '.') {
      // removing the '.'
      placeholder = std::string(it.sink.begin() + 1, it.sink.end());
      // saving appropriate name instead of placeholder
      it.sink = placeholder;
    }
    if (placeholder.empty()) continue;
    if (quiddities_.cend() ==
        std::find_if(quiddities_.begin(), quiddities_.end(), [&](const quiddity_spec_t& quid_spec) {
          if (quid_spec.name == placeholder) return true;
          return false;
        })) {
      parsing_error_ =
          std::string("placeholder name ") + placeholder + " is not a valid quiddity name";
      is_valid_ = false;
      return;
    }
  }

  // read connections_ and feed data into quiddities_
  for (auto& it : connections_) {
    auto quid = std::find_if(quiddities_.begin(),
                             quiddities_.end(),
                             [&](const quiddity_spec_t& quid) { return it.src == quid.name; });
    if (quid == quiddities_.end()) {
      parsing_error_ = "BUG during analysis of connections";
      is_valid_ = false;
      return;
    }
    quid->connects_to_.push_back(it.sink);
  }

  // check params, build blacklist and remove prefixed '_' if found
  std::regex rgx("_.+");
  for (auto& it : quiddities_) {
    std::vector<std::pair<std::string, std::string>> tmp_params;
    for (auto& prop : it.params) {
      std::string actual_param_name;
      if (std::regex_match(prop.first, rgx)) {  // blacklist '_' if properties are exposed
        actual_param_name = std::string(prop.first.begin() + 1, prop.first.end());
        if (it.expose_prop)
          it.blacklisted_params.push_back(actual_param_name);
        else
          it.whitelisted_params.push_back(actual_param_name);
      } else {
        actual_param_name = std::string(prop.first.begin(), prop.first.end());
      }
      tmp_params.push_back(std::make_pair(actual_param_name, prop.second));
    }
    std::swap(it.params, tmp_params);
  }
}
void
gabble_jingle_content_parse_add (GabbleJingleContent *c,
    WockyNode *content_node, gboolean google_mode, GError **error)
{
  GabbleJingleContentPrivate *priv = c->priv;
  const gchar *name, *creator, *senders, *disposition;
  WockyNode *trans_node, *desc_node;
  GType transport_type = 0;
  GabbleJingleTransportIface *trans = NULL;
  JingleDialect dialect = gabble_jingle_session_get_dialect (c->session);

  priv->created_by_us = FALSE;

  desc_node = wocky_node_get_child (content_node, "description");
  trans_node = wocky_node_get_child (content_node, "transport");
  creator = wocky_node_get_attribute (content_node, "creator");
  name = wocky_node_get_attribute (content_node, "name");
  senders = wocky_node_get_attribute (content_node, "senders");

  g_assert (priv->transport_ns == NULL);

  if (google_mode)
    {
      if (creator == NULL)
          creator = "initiator";

      /* the google protocols don't give the contents names, so put in a dummy
       * value if none was set by the session*/
      if (priv->name == NULL)
        name = priv->name = g_strdup ("gtalk");
      else
        name = priv->name;

      if (trans_node == NULL)
        {
          /* gtalk lj0.3 assumes google-p2p transport */
          DEBUG ("detected GTalk3 dialect");

          dialect = JINGLE_DIALECT_GTALK3;
          g_object_set (c->session, "dialect", JINGLE_DIALECT_GTALK3, NULL);
          transport_type = gabble_jingle_factory_lookup_transport (
              gabble_jingle_session_get_factory (c->session),
              "");

          /* in practice we do support gtalk-p2p, so this can't happen */
          if (G_UNLIKELY (transport_type == 0))
            {
              SET_BAD_REQ ("gtalk-p2p transport unsupported");
              return;
            }

          priv->transport_ns = g_strdup ("");
        }
    }
  else
    {
      if (creator == NULL &&
          gabble_jingle_session_peer_has_cap (c->session,
              QUIRK_GOOGLE_WEBMAIL_CLIENT))
        {
          if (gabble_jingle_content_creator_is_initiator (c))
            creator = "initiator";
          else
            creator = "responder";

          DEBUG ("Working around GMail omitting creator=''; assuming '%s'",
              creator);
        }

      if ((trans_node == NULL) || (creator == NULL) || (name == NULL))
        {
          SET_BAD_REQ ("missing required content attributes or elements");
          return;
        }

      /* In proper protocols the name comes from the stanza */
      g_assert (priv->name == NULL);
      priv->name = g_strdup (name);
    }

  /* if we didn't set it to google-p2p implicitly already, detect it */
  if (transport_type == 0)
    {
      const gchar *ns = wocky_node_get_ns (trans_node);

      transport_type = gabble_jingle_factory_lookup_transport (
          gabble_jingle_session_get_factory (c->session), ns);

      if (transport_type == 0)
        {
          SET_BAD_REQ ("unsupported content transport");
          return;
        }

      priv->transport_ns = g_strdup (ns);
    }

  if (senders == NULL)
    priv->senders = get_default_senders (c);
  else
    priv->senders = parse_senders (senders);

  if (priv->senders == JINGLE_CONTENT_SENDERS_NONE)
    {
      SET_BAD_REQ ("invalid content senders");
      return;
    }

  parse_description (c, desc_node, error);
  if (*error != NULL)
      return;

  disposition = wocky_node_get_attribute (content_node, "disposition");
  if (disposition == NULL)
      disposition = "session";

  if (wocky_strdiff (disposition, priv->disposition))
    {
      g_free (priv->disposition);
      priv->disposition = g_strdup (disposition);
    }

  DEBUG ("content creating new transport type %s", g_type_name (transport_type));

  trans = gabble_jingle_transport_iface_new (transport_type,
      c, priv->transport_ns);

  g_signal_connect (trans, "new-candidates",
      (GCallback) new_transport_candidates_cb, c);

  /* Depending on transport, there may be initial candidates specified here */
  if (trans_node != NULL)
    {
      gabble_jingle_transport_iface_parse_candidates (trans, trans_node, error);
      if (*error)
        {
          g_object_unref (trans);
          return;
        }
    }

  g_assert (priv->transport == NULL);
  priv->transport = trans;
  transport_created (c);

  g_assert (priv->creator == NULL);
  priv->creator = g_strdup (creator);

  priv->state = JINGLE_CONTENT_STATE_NEW;

  /* GTalk4 seems to require "transport-accept" for acknowledging
   * the transport type. wjt confirms that this is apparently necessary for
   * incoming calls to work.
   */
  if (dialect == JINGLE_DIALECT_GTALK4)
    priv->gtalk4_event_id = g_idle_add (send_gtalk4_transport_accept, c);

  return;
}