📄 jid.c
字号:
/* if nothing failed, the node is valid */ return 0;}/** * resourceprep the resource identifier in a JID and check if it is valid * * @param jid data structure holding the JID * @return 0 if JID is valid, non zero otherwise */int _jid_safe_resource(jid id) { int result=0; /* it is valid to have no resource identifier in the JID */ if (id->resource == NULL) return 0; /* resource prep the resource identifier */ result = _jid_cached_stringprep(id->resource, strlen(id->resource)+1, _jid_prep_cache_resource); if (result == STRINGPREP_TOO_SMALL_BUFFER) { /* resourceprep wants to expand the string, e.g. conversion from ß to ss */ size_t biggerbuffersize = 1024; char *biggerbuffer = pmalloc(id->p, biggerbuffersize); if (biggerbuffer == NULL) return 1; strcpy(biggerbuffer, id->resource); result = _jid_cached_stringprep(id->resource, strlen(id->resource)+1, _jid_prep_cache_resource); id->resource = biggerbuffer; } if (result != STRINGPREP_OK) return 1; /* the resourcepreped node must not be longer than 1023 bytes */ if (j_strlen(id->resource) > 1023) return 1; /* if nothing failed, the resource is valid */ return 0;}#else /* no LIBIDN *//** * check if the domain identifier in a JID is valid * * @param jid data structure holding the JID * @return 0 if domain is valid, non zero otherwise */int _jid_safe_domain(jid id) { char *str; /* there must be a domain identifier */ if (j_strlen(id->server) == 0) return 1; /* and it must not be longer than 1023 bytes */ if (strlen(id->server) > 1023) return 1; /* lowercase the hostname, make sure it's valid characters */ for(str = id->server; *str != '\0'; str++) { *str = tolower(*str); if(!(isalnum(*str) || *str == '.' || *str == '-' || *str == '_')) return 1; } /* otherwise it's okay as far as we can tell without LIBIDN */ return 0;}/** * check if the node identifier in a JID is valid * * @param jid data structure holding the JID * @return 0 if node is valid, non zero otherwise */int _jid_safe_node(jid id) { char *str; /* node identifiers may not be longer than 1023 bytes */ if (j_strlen(id->user) > 1023) return 1; /* check for low and invalid ascii characters in the username */ if(id->user != NULL) for(str = id->user; *str != '\0'; str++) if(*str <= 32 || *str == ':' || *str == '@' || *str == '<' || *str == '>' || *str == '\'' || *str == '"' || *str == '&') return 1; /* otherwise it's okay as far as we can tell without LIBIDN */ return 0;}/** * check if the resource identifier in a JID is valid * * @param jid data structure holding the JID * @return 0 if resource is valid, non zero otherwise */int _jid_safe_resource(jid id) { /* resources may not be longer than 1023 bytes */ if (j_strlen(id->resource) > 1023) return 1; /* otherwise it's okay as far as we can tell without LIBIDN */ return 0;}#endif/** * nodeprep/nameprep/resourceprep the JID and check if it is valid * * @param jid data structure holding the JID * @return NULL if the JID is invalid, pointer to the jid otherwise */jid jid_safe(jid id){ if (_jid_safe_domain(id)) return NULL; if (_jid_safe_node(id)) return NULL; if (_jid_safe_resource(id)) return NULL; return id;}jid jid_new(pool p, char *idstr){ char *server, *resource, *type, *str; jid id; if(p == NULL || idstr == NULL || strlen(idstr) == 0) return NULL; /* user@server/resource */ str = pstrdup(p, idstr); id = pmalloco(p,sizeof(struct jid_struct)); id->p = p; resource = strstr(str,"/"); if(resource != NULL) { *resource = '\0'; ++resource; if(strlen(resource) > 0) id->resource = resource; }else{ resource = str + strlen(str); /* point to end */ } type = strstr(str,":"); if(type != NULL && type < resource) { *type = '\0'; ++type; str = type; /* ignore the type: prefix */ } server = strstr(str,"@"); if(server == NULL || server > resource) { /* if there's no @, it's just the server address */ id->server = str; }else{ *server = '\0'; ++server; id->server = server; if(strlen(str) > 0) id->user = str; } return jid_safe(id);}void jid_set(jid id, char *str, int item){ char *old; if(id == NULL) return; /* invalidate the cached copy */ id->full = NULL; switch(item) { case JID_RESOURCE: old = id->resource; if(str != NULL && strlen(str) != 0) id->resource = pstrdup(id->p, str); else id->resource = NULL; if(_jid_safe_resource(id)) id->resource = old; /* revert if invalid */ break; case JID_USER: old = id->user; if(str != NULL && strlen(str) != 0) id->user = pstrdup(id->p, str); else id->user = NULL; if(_jid_safe_node(id)) id->user = old; /* revert if invalid */ break; case JID_SERVER: old = id->server; id->server = pstrdup(id->p, str); if(_jid_safe_domain(id)) id->server = old; /* revert if invalid */ break; }}char *jid_full(jid id){ spool s; if(id == NULL) return NULL; /* use cached copy */ if(id->full != NULL) return id->full; s = spool_new(id->p); if(id->user != NULL) spooler(s, id->user,"@",s); spool_add(s, id->server); if(id->resource != NULL) spooler(s, "/",id->resource,s); id->full = spool_print(s); return id->full;}/* parses a /resource?name=value&foo=bar into an xmlnode representing <resource name="value" foo="bar"/> */xmlnode jid_xres(jid id){ char *cur, *qmark, *amp, *eq; xmlnode x; if(id == NULL || id->resource == NULL) return NULL; cur = pstrdup(id->p, id->resource); qmark = strstr(cur, "?"); if(qmark == NULL) return NULL; *qmark = '\0'; qmark++; x = _xmlnode_new(id->p, cur, NTYPE_TAG); cur = qmark; while(cur != '\0') { eq = strstr(cur, "="); if(eq == NULL) break; *eq = '\0'; eq++; amp = strstr(eq, "&"); if(amp != NULL) { *amp = '\0'; amp++; } xmlnode_put_attrib(x,cur,eq); if(amp != NULL) cur = amp; else break; } return x;}/* local utils */int _jid_nullstrcmp(char *a, char *b){ if(a == NULL && b == NULL) return 0; if(a == NULL || b == NULL) return -1; return strcmp(a,b);}int _jid_nullstrcasecmp(char *a, char *b){ if(a == NULL && b == NULL) return 0; if(a == NULL || b == NULL) return -1; return strcasecmp(a,b);}int jid_cmp(jid a, jid b){ if(a == NULL || b == NULL) return -1; if(_jid_nullstrcmp(a->resource, b->resource) != 0) return -1; if(_jid_nullstrcasecmp(a->user, b->user) != 0) return -1; if(_jid_nullstrcmp(a->server, b->server) != 0) return -1; return 0;}/* suggested by Anders Qvist <quest@valdez.netg.se> */int jid_cmpx(jid a, jid b, int parts){ if(a == NULL || b == NULL) return -1; if(parts & JID_RESOURCE && _jid_nullstrcmp(a->resource, b->resource) != 0) return -1; if(parts & JID_USER && _jid_nullstrcasecmp(a->user, b->user) != 0) return -1; if(parts & JID_SERVER && _jid_nullstrcmp(a->server, b->server) != 0) return -1; return 0;}/* makes a copy of b in a's pool, requires a valid a first! */jid jid_append(jid a, jid b){ jid next; if(a == NULL) return NULL; if(b == NULL) return a; next = a; while(next != NULL) { /* check for dups */ if(jid_cmp(next,b) == 0) break; if(next->next == NULL) next->next = jid_new(a->p,jid_full(b)); next = next->next; } return a;}xmlnode jid_nodescan(jid id, xmlnode x){ xmlnode cur; pool p; jid tmp; if(id == NULL || xmlnode_get_firstchild(x) == NULL) return NULL; p = pool_new(); for(cur = xmlnode_get_firstchild(x); cur != NULL; cur = xmlnode_get_nextsibling(cur)) { if(xmlnode_get_type(cur) != NTYPE_TAG) continue; tmp = jid_new(p,xmlnode_get_attrib(cur,"jid")); if(tmp == NULL) continue; if(jid_cmp(tmp,id) == 0) break; } pool_free(p); return cur;}jid jid_user(jid a){ jid ret; if(a == NULL || a->resource == NULL) return a; ret = pmalloco(a->p,sizeof(struct jid_struct)); ret->p = a->p; ret->user = a->user; ret->server = a->server; return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -