📄 xdb_file.c
字号:
if(flag_set) { act = xmlnode_get_attrib(p->x,"action"); match = xmlnode_get_attrib(p->x,"match"); if(act != NULL) { switch(*act) { case 'i': /* insert action */ if(data == NULL) { /* we're inserting into something that doesn't exist?!?!? */ data = xmlnode_insert_tag(top,"foo"); xmlnode_put_attrib(data,"xdbns",ns); xmlnode_put_attrib(data,"xmlns",ns); /* should have a top-level xmlns attrib */ } xmlnode_hide(xmlnode_get_tag(data,match)); /* any match is a goner */ /* insert the new chunk into the existing data */ xmlnode_insert_tag_node(data, xmlnode_get_firstchild(p->x)); break; case 'c': /* check action */ if(match != NULL) data = xmlnode_get_tag(data,match); if(j_strcmp(xmlnode_get_data(data),xmlnode_get_data(xmlnode_get_firstchild(p->x))) != 0) { log_debug2(ZONE, LOGT_STORAGE|LOGT_DELIVER, "xdb check action returning error to signify unsuccessful check"); return r_ERR; } flag_set = 0; /* * XXX Is there a bug here? * * I suspect that the check action will always return r_ERR! * Up to this point the ret variable has not been changed, and if * we arrived here I cannot imagine how it should be changed afterwards. * This means that the function will return r_ERR too. * I expect this is a bug and something like "ret = 1;" should be inserted * at this point. * * The problem is that I am not completely sure what the check action is * supposed to do. What I imagine is: * It is intended to compare the content of xdb with the content of the * xdb request and return r_ERR if it is different and r_DONE if it * is the same. * * It is only used in jsm/modules/mod_auth_plain.c in the function * mod_auth_plain_jane(...) function. At this function there is already * a check if the password is the same some lines above ... so it * would make no sence to call the check action if it does what I said * above as it would be always result in being different - in which * case it is no surprize that we have no problem, that this function * always returns r_ERR (which would signal that it's different too). * * It should be checked if the xdb_act(...) in mod_auth_plain_jane(...) * is needed. If it isn't, we could remove the check action from * xdb completely. * * Please see also: * http://web.archive.org/web/20020601233959/http://jabberd.jabberstudio.org/1.4/142changelog.html * In that case it seems to be a bug here ... */ break; default: log_warn("xdb_file","unable to handle unknown xdb action '%s'",act); return r_ERR; } }else{ if(data != NULL) xmlnode_hide(data); /* copy the new data into file */ data = xmlnode_insert_tag_node(top, xmlnode_get_firstchild(p->x)); xmlnode_put_attrib(data,"xdbns",ns); } /* save the file if we still want to */ if (flag_set) { int tmp = xmlnode2file_limited(full,file,xf->sizelimit); if (tmp == 0) log_notice(p->id->server,"xdb request failed, due to the size limit of %i to file %s", xf->sizelimit, full); else if (tmp < 0) log_error(p->id->server,"xdb request failed, unable to save to file %s",full); else ret = 1; } }else{ /* a get always returns, data or not */ ret = 1; if(data != NULL) { /* cool, send em back a copy of the data */ xmlnode_hide_attrib(xmlnode_insert_tag_node(p->x, data),"xdbns"); } } if(ret) { xmlnode_put_attrib(p->x,"type","result"); xmlnode_put_attrib(p->x,"to",xmlnode_get_attrib(p->x,"from")); xmlnode_put_attrib(p->x,"from",jid_full(p->id)); deliver(dpacket_new(p->x), NULL); /* dpacket_new() shouldn't ever return NULL */ /* remove the cache'd item if it was a set or we're not configured to cache */ if(xf->timeout == 0 || flag_set) { log_debug2(ZONE, LOGT_STORAGE, "decaching %s",full); xhash_zap(xf->cache,full); xmlnode_free(file); } return r_DONE; }else{ return r_ERR; }}void xdb_file_cleanup(void *arg){ xdbf xf = (xdbf)arg; xhash_free(xf->cache);}/** * convert a spool directory for a given host from the old format * to the new one which distributes the files over several subdirs * * @param p the memory pool we can use * @param spoolroot the root folder of the spool * @param host the host for which we should try to convert */void _xdb_convert_hostspool(pool p, const char *spoolroot, char *host){ DIR *sdir; struct dirent *dent; char digit01[3], digit23[3]; char *hostspool; /* get the dir location */ hostspool = spools(p, spoolroot, "/", host, p); log_notice(ZONE, "trying to convert spool %s (this may take some time)", hostspool); /* we have to convert the spool */ sdir = opendir(hostspool); if (sdir == NULL) { log_error("xdb_file", "failed to open directory %s for conversion: %s", hostspool, strerror(errno)); return; } while ((dent = readdir(sdir))!=NULL) { char *str_ptr; size_t filenamelength = strlen(dent->d_name); if (filenamelength<4) continue; str_ptr = (dent->d_name)+filenamelength-4; /* do we have to convert this file? */ if (j_strcmp(str_ptr, ".xml") == 0) { char *oldname, *newname; _xdb_get_hashes(dent->d_name, digit01, digit23); oldname = spools(p, hostspool, "/", dent->d_name, p); newname = spools(p, hostspool, "/", digit01, "/", digit23, "/", dent->d_name, p); if (!_xdb_gen_dirs(spool_new(p), spoolroot, host, digit01, digit23, 1)) log_error("xdb_file", "failed to create necessary directory for conversion"); else if (rename(oldname, newname) < 0) log_error("xdb_file", "failed to move %s to %s while converting spool: %s", oldname, newname, strerror(errno)); } } /* close the directory */ closedir(sdir);}/** * convert a spool directory from the old format to the new one * which distributes the files over several subdirs * * @param spoolroot the root folder of the spool */void xdb_convert_spool(const char *spoolroot){ DIR *sdir; struct dirent *dent; pool p; char *flagfile; struct stat s; FILE *flagfileh; /* use our own memory pool */ p = pool_new(); /* check if we already converted this spool */ flagfile = spools(p, spoolroot, "/.hashspool", p); if (stat(flagfile, &s) == 0) { log_debug2(ZONE, LOGT_STORAGE, "there is already a new hashspool"); pool_free(p); return; } /* what is in this directory? */ sdir = opendir(spoolroot); if (sdir == NULL) { pool_free(p); return; } while ((dent = readdir(sdir)) != NULL) { struct stat s; char *dirname = spools(p, spoolroot, "/", dent->d_name, p); if (stat(dirname, &s)<0) continue; /* we only care about directories */ if (!S_ISDIR(s.st_mode)) continue; if (dent->d_name[0]!='\0' && dent->d_name[0]!='.') _xdb_convert_hostspool(p, spoolroot, dent->d_name); } closedir(sdir); /* write the flag that we converted the spool */ flagfileh = fopen(flagfile, "w"); if (flagfileh != NULL) { fwrite("Please do not delete this file.\n", 1, 32, flagfileh); fclose(flagfileh); } /* cleanup */ pool_free(p);}void xdb_file(instance i, xmlnode x){ char *spl, *temp; xmlnode config; xdbcache xc; xdbf xf; int timeout = 3600; /* defaults to timeout in 3600 seconds */ int sizelimit = 500000; /* defaults to 500000 bytes */ log_debug2(ZONE, LOGT_INIT, "xdb_file loading"); xc = xdb_cache(i); config = xdb_get(xc, jid_new(xmlnode_pool(x),"config@-internal"),"jabber:config:xdb_file"); spl = xmlnode_get_tag_data(config,"spool"); if(spl == NULL) { log_error(NULL,"xdb_file: No filesystem spool location configured"); return; } if(xmlnode_get_tag(config, "sizelimit")) { temp = xmlnode_get_tag_data(config,"sizelimit"); if(temp != NULL) sizelimit = atoi(temp); else /* no value: disable timeout */ sizelimit = 0; } if(xmlnode_get_tag(config, "timeout")) { temp = xmlnode_get_tag_data(config,"timeout"); if(temp != NULL) timeout = atoi(temp); else /* no value: disable timeout */ timeout = -1; } xf = pmalloco(i->p,sizeof(_xdbf)); xf->spool = pstrdup(i->p,spl); xf->timeout = timeout; xf->sizelimit = sizelimit; xf->i = i; xf->cache = xhash_new(j_atoi(xmlnode_get_tag_data(config,"maxfiles"),FILES_PRIME)); xf->use_hashspool = xmlnode_get_tag(config, "use_hierarchical_spool") ? 1 : 0; if (xf->use_hashspool) xdb_convert_spool(spl); register_phandler(i, o_DELIVER, xdb_file_phandler, (void *)xf); if(timeout > 0) /* 0 is expired immediately, -1 is cached forever */ register_beat(timeout, xdb_file_purge, (void *)xf); xmlnode_free(config); pool_cleanup(i->p, xdb_file_cleanup, (void*)xf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -