/* Insert a row into the full-text index; set *piRowid to be the ID of the * new row. */ static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestRowid, const char *zText, sqlite_int64 *piRowid){ Hash terms; /* maps term string -> PosList */ HashElem *e; int rc = content_insert(v, pRequestRowid, zText, -1); if( rc!=SQLITE_OK ) return rc; *piRowid = sqlite3_last_insert_rowid(v->db); if( !zText ) return SQLITE_OK; /* nothing to index */ rc = build_terms(&terms, v->pTokenizer, zText, *piRowid); if( rc!=SQLITE_OK ) return rc; for(e=HashFirst(&terms); e; e=HashNext(e)){ DocList *p = HashData(e); rc = index_insert_term(v, HashKey(e), HashKeysize(e), *piRowid, p); if( rc!=SQLITE_OK ) break; } for(e=HashFirst(&terms); e; e=HashNext(e)){ DocList *p = HashData(e); docListDelete(p); } HashClear(&terms); return rc; }
HashElement * HashNext(HashHandle handle, HashElement * since) { HashTable * table = __validate(handle); HashElement * e = NULL; int i = 0; ASSERT(table); /* from top. */ if (since == NULL) return HashFirst(handle); /* in a chain. */ if (since->next) return since->next; /* jump to next element. */ for (i = since->index + 1; i < table->size; i++) { if ((e = table->table[i]) != NULL) { return e; } } return NULL; }
/* Delete a row from the full-text index. */ static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){ char *zText; Hash terms; HashElem *e; int rc = content_select(v, iRow, &zText); if( rc!=SQLITE_OK ) return rc; rc = build_terms(&terms, v->pTokenizer, zText, iRow); free(zText); if( rc!=SQLITE_OK ) return rc; for(e=HashFirst(&terms); e; e=HashNext(e)){ rc = index_delete_term(v, HashKey(e), HashKeysize(e), iRow); if( rc!=SQLITE_OK ) break; } for(e=HashFirst(&terms); e; e=HashNext(e)){ DocList *p = HashData(e); docListDelete(p); } HashClear(&terms); return content_delete(v, iRow); }
void HashDump(HashHandle handle) { #ifdef WEBCFG_DEBUG HashTable * table = NULL; HashElement * e = NULL; table = __validate(handle); WEBLOG_API(); ASSERT(table); dumpHex((void *)table, sizeof(HashTable)); ASSERT(table->table); dumpHex((void *)table->table, table->size * sizeof(HashElement*)); e = HashFirst(handle); while(e) { switch(e->value.type) { case eHashString: WEBLOG_INFO("<%s> [%s]-[%s]\n", __FUNCTION__, e->name, e->value.data.string); break; case eHashInt: WEBLOG_INFO("<%s> [%s]-[%d]\n", __FUNCTION__, e->name, e->value.data.integer); break; case eHashPointer: WEBLOG_INFO("<%s> [%s]-[0x%p]\n", __FUNCTION__, e->name, e->value.data.pointer); break; default: WEBLOG_INFO("<%s> [%s]-[????]\n", __FUNCTION__, e->name); break; } e = HashNext(handle, e); } #endif }
static int _GetObjectProps(HashHandle hash, CacheHandle cache, char * webpath) { int ret = 0; char localpath[128] = {0}; char strbuf[128] = {0}; HashElement * e = NULL; int directory = FALSE; struct stat filestt; char last_modify_time[100] = {0}; getlocalpath(webpath, localpath); WEBLOG_INFO("<%s> [w]%s, [l]%s.\n", __FUNCTION__, webpath, localpath); ret = stat(localpath, &filestt); if(ret != 0) { switch (errno) { case ENOENT: WEBLOG_INFO("<%s> File %s not found.\n", __FUNCTION__, localpath); return WEBDAVR_NOT_FOUND; case EINVAL: default: WEBLOG_INFO("<%s> Unexpected error in _stat.\n", __FUNCTION__); return WEBDAVR_NG; } } directory = (S_IFDIR & filestt.st_mode); WEBLOG_INFO("<%s> %s is a %s.\n", __FUNCTION__, localpath, directory?"folder":"file"); if(directory) { HashAdd(hash, "resourcetype", HashString("<D:collection/>", TRUE)); HashAdd(hash, "getcontenttype", HashString("httpd/unix-directory", TRUE)); HashAdd(hash, "getcontentlength", HashString("", TRUE)); } else { //HashAdd(hash, "resourcetype", HashString("", TRUE)); // empty this HashAdd(hash, "getcontenttype", HashString("application/octet-stream", TRUE)); sprintf(strbuf, "%ld", filestt.st_size); WEBLOG_INFO("<%s> File size : %ld\n", __FUNCTION__, filestt.st_size ); HashAdd(hash, "getcontentlength", HashString(strbuf, TRUE)); } WEBLOG_INFO("<%s> Time modified : %s", __FUNCTION__, ctime(&filestt.st_mtime)); //HashAdd(hash, "getlastmodified", HashString(ctime(&filestt.st_mtime), TRUE)); //HashAdd(hash, "getlastmodified", HashString("Thu, 28 Mar 2013 06:30:48 GMT", TRUE)); strftime( last_modify_time, sizeof(last_modify_time), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&filestt.st_mtime)); HashAdd(hash, "getlastmodified", HashString(last_modify_time, TRUE)); CacheWriteString(cache, "\t<D:response>\n" "\t\t<D:href>"); CacheWriteString(cache, "/webdav"); memset(strbuf, 0, sizeof(strbuf)); url_encode(webpath, strbuf); CacheWriteString(cache, strbuf); CacheWriteString(cache, "</D:href>\n"); /* first comes valid props. */ CacheWriteString(cache, "\t\t<D:propstat>\n" "\t\t\t<D:prop>\n"); e = HashFirst(hash); while(e) { if(e->value.data.string[0]) { CacheWriteString(cache, "\t\t\t\t<D:"); CacheWriteString(cache, e->name); CacheWriteString(cache, ">"); CacheWriteString(cache, e->value.data.string); // just for test CacheWriteString(cache, "</D:"); CacheWriteString(cache, e->name); CacheWriteString(cache, ">\n"); } e = HashNext(hash, e); } CacheWriteString(cache, "\t\t\t</D:prop>\n" "\t\t\t<D:status>"); CacheWriteString(cache, "HTTP/1.1 200 OK"); CacheWriteString(cache, "</D:status>\n" "\t\t</D:propstat>\n"); /* then invalid props. */ CacheWriteString(cache, "\t\t<D:propstat>\n" "\t\t\t<D:prop>\n"); e = HashFirst(hash); while(e) { if(!e->value.data.string[0]) { CacheWriteString(cache, "\t\t\t\t<D:"); CacheWriteString(cache, e->name); CacheWriteString(cache, "/>\n"); } e = HashNext(hash, e); }; CacheWriteString(cache, "\t\t\t</D:prop>\n" "\t\t\t<D:status>"); CacheWriteString(cache, "HTTP/1.1 404 Not Found"); CacheWriteString(cache, "</D:status>\n" "\t\t</D:propstat>\n"); CacheWriteString(cache, "\t</D:response>\n"); return WEBDAVR_OK; }
int http_send_response(http_rsp * rsp) { CacheHandle cache = NULL_HANDLE; char * datapointer = NULL; int datalength = 0; char strbuf[64] = {0}; char bodybuf[256] = {0}; HashElement * e = NULL; http_status * stt = get_http_status(rsp->code); WEBLOG_API(); ASSERT(stt); if(using_customized_body != rsp->body) { /* if body is empty, make a default body. */ if(!rsp->body) { WEBLOG_VERBOSE("<%s> body empty. add default body.\n", __FUNCTION__); sprintf(bodybuf, "<HTML><BODY><b>%s</b></BODY></HTML>", stt->s_name); rsp->body = bodybuf; http_add_rspoption(rsp, "Content-Type", "text/html"); } /* if Content-Length is not given, try caculating it here. */ if(!HashLookup(rsp->headOptions, "Content-Length")) { if(rsp->body) sprintf(strbuf, sizett, strlen(rsp->body)); else sprintf(strbuf, "%d", 0); http_add_rspoption(rsp, "Content-Length", strbuf); } } /* server info is always present. */ http_add_rspoption(rsp, "Server", SERVER_VER); #ifdef WEBCFG_SUPPORT_HTTPRANGE http_add_rspoption(rsp, "Accept-Ranges", "bytes"); #endif if(NULL_HANDLE == cache) cache = CacheCreate(); ASSERT(NULL_HANDLE != cache); CacheClean(cache); /* send first line! */ CacheWriteString(cache, "HTTP/1.1 "); CacheWriteString(cache, stt->s_code); CacheWriteString(cache, " "); CacheWriteString(cache, stt->s_name); CacheWriteString(cache, "\r\n"); //HashDump(rsp->headOptions); /* send head options! */ e = HashFirst(rsp->headOptions); while(e) { CacheWriteString(cache, e->name); CacheWriteString(cache, ": "); if(e->value.type == eHashString) { CacheWriteString(cache, e->value.data.string); } else if(e->value.type == eHashInt) { sprintf(strbuf, "%d", e->value.data.integer); CacheWriteString(cache, strbuf); } CacheWriteString(cache, "\r\n"); e = HashNext(rsp->headOptions, e); } CacheWriteString(cache, "\r\n"); /* send body */ if(rsp->body && rsp->body != using_customized_body) CacheWriteString(cache, rsp->body); datalength = CacheGetData(cache, &datapointer); ASSERT(datapointer && datalength > 0); WebWrite(rsp->sock, datapointer, datalength); CacheDestroy(cache); return OK; }