static void parse_dc_event(char *line, struct membuffer *str, void *_dc) { int m, s = 0; const char *name; struct divecomputer *dc = _dc; struct event event = { 0 }; m = strtol(line, &line, 10); if (*line == ':') s = strtol(line+1, &line, 10); event.time.seconds = m*60+s; for (;;) { char c; while (isspace(c = *line)) line++; if (!c) break; line = parse_keyvalue_entry(parse_event_keyvalue, &event, line); } name = ""; if (str->len) name = mb_cstring(str); add_event(dc, event.time.seconds, event.type, event.flags, event.value, name); }
/* * Note that the act of "getting" the error string * buffer doesn't de-allocate the buffer, but it does * set the buffer length to zero, so that any future * error reports will overwrite the string rather than * append to it. */ const char *get_error_string(void) { const char *str; if (!error_string_buffer.len) return ""; str = mb_cstring(&error_string_buffer); error_string_buffer.len = 0; return str; }
int report_error(const char *fmt, ...) { struct membuffer *buf = &error_string_buffer; /* Previous unprinted errors? Add a newline in between */ if (buf->len) put_bytes(buf, "\n", 1); VA_BUF(buf, fmt); mb_cstring(buf); return -1; }
static void parse_site_geo(char *line, struct membuffer *str, void *_ds) { struct dive_site *ds = _ds; if (ds->taxonomy.category == NULL) ds->taxonomy.category = alloc_taxonomy(); int nr = ds->taxonomy.nr; if (nr < TC_NR_CATEGORIES) { struct taxonomy *t = &ds->taxonomy.category[nr]; t->value = strdup(mb_cstring(str)); sscanf(line, "cat %d origin %d \"", &t->category, (int *)&t->origin); ds->taxonomy.nr++; } }
int report_error(const char *fmt, ...) { struct membuffer buf = { 0 }; /* if there is no error callback registered, don't produce errors */ if (!error_cb) return -1; VA_BUF(&buf, fmt); mb_cstring(&buf); error_cb(detach_buffer(&buf)); return -1; }
static int tree_insert(git_treebuilder *dir, const char *name, int mkunique, git_oid *id, unsigned mode) { int ret; struct membuffer uniquename = { 0 }; if (mkunique && git_treebuilder_get(dir, name)) { char hex[8]; git_oid_nfmt(hex, 7, id); hex[7] = 0; put_format(&uniquename, "%s~%s", name, hex); name = mb_cstring(&uniquename); } ret = git_treebuilder_insert(NULL, dir, name, id, mode); free_buffer(&uniquename); return ret; }
/* * Write a membuffer to the git repo, and free it */ static int blob_insert(git_repository *repo, struct dir *tree, struct membuffer *b, const char *fmt, ...) { int ret; git_oid blob_id; struct membuffer name = { 0 }; ret = git_blob_create_frombuffer(&blob_id, repo, b->buffer, b->len); free_buffer(b); if (ret) return ret; VA_BUF(&name, fmt); ret = tree_insert(tree->files, mb_cstring(&name), 1, &blob_id, GIT_FILEMODE_BLOB); free_buffer(&name); return ret; }
static void parse_dc_event(char *line, struct membuffer *str, void *_dc) { int m, s = 0; const char *name; struct divecomputer *dc = _dc; struct event event = { 0 }, *ev; m = strtol(line, &line, 10); if (*line == ':') s = strtol(line+1, &line, 10); event.time.seconds = m*60+s; for (;;) { char c; while (isspace(c = *line)) line++; if (!c) break; line = parse_keyvalue_entry(parse_event_keyvalue, &event, line); } name = ""; if (str->len) name = mb_cstring(str); ev = add_event(dc, event.time.seconds, event.type, event.flags, event.value, name); /* * Older logs might mark the dive to be CCR by having an "SP change" event at time 0:00. * Better to mark them being CCR on import so no need for special treatments elsewhere on * the code. */ if (ev && event.time.seconds == 0 && event.type == SAMPLE_EVENT_PO2 && dc->divemode==OC) { dc->divemode = CCR; } if (ev && event_is_gaschange(ev)) { /* * We subtract one here because "0" is "no index", * and the parsing will add one for actual cylinder * index data (see parse_event_keyvalue) */ ev->gas.index = event.gas.index-1; if (event.gas.mix.o2.permille || event.gas.mix.he.permille) ev->gas.mix = event.gas.mix; } }
void subsurface_user_info(struct user_info *user) { struct passwd *pwd = getpwuid(getuid()); const char *username = getenv("USER"); if (pwd) { if (pwd->pw_gecos && *pwd->pw_gecos) user->name = pwd->pw_gecos; if (!username) username = pwd->pw_name; } if (username && *username) { char hostname[64]; struct membuffer mb = { 0 }; gethostname(hostname, sizeof(hostname)); put_format(&mb, "%s@%s", username, hostname); user->email = mb_cstring(&mb); } }
/* * The 'divecomputerid' is a bit harder to parse than some other things, because * it can have multiple strings (but see the tag parsing for another example of * that) in addition to the non-string entries. * * We keep the "next" string in "id.cstr" and update it as we use it. */ static void parse_settings_divecomputerid(char *line, struct membuffer *str, void *_unused) { struct divecomputerid id = { mb_cstring(str) }; id.cstr = id.model + strlen(id.model) + 1; /* Skip the '"' that stood for the model string */ line++; for (;;) { char c; while (isspace(c = *line)) line++; if (!c) break; line = parse_keyvalue_entry(parse_divecomputerid_keyvalue, &id, line); } create_device_node(id.model, id.deviceid, id.serial, id.firmware, id.nickname); }
/* * We can have multiple tags in the membuffer. They are separated by * NUL bytes. */ static void parse_dive_tags(char *line, struct membuffer *str, void *_dive) { struct dive *dive = _dive; const char *tag; int len = str->len; if (!len) return; /* Make sure there is a NUL at the end too */ tag = mb_cstring(str); for (;;) { int taglen = strlen(tag); if (taglen) taglist_add_tag(&dive->tag_list, tag); len -= taglen; if (!len) return; tag += taglen+1; len--; } }
/* keyvalue "key" "value" * so we have two strings (possibly empty) in the membuffer, separated by a '\0' */ static void parse_dc_keyvalue(char *line, struct membuffer *str, void *_dc) { const char *key, *value; struct divecomputer *dc = _dc; // Let's make sure we have two strings... int string_counter = 0; while(*line) { if (*line == '"') string_counter++; line++; } if (string_counter != 2) return; // stupidly the second string in the membuffer isn't NUL terminated; // asking for a cstring fixes that; interestingly enough, given that there are two // strings in the mb, the next command at the same time assigns a pointer to the // first string to 'key' and NUL terminates the second string (which then goes to 'value') key = mb_cstring(str); value = key + strlen(key) + 1; add_extra_data(dc, key, value); }
/* * This does *not* make sure the new subdirectory doesn't * alias some existing name. That is actually useful: you * can create multiple directories with the same name, and * set the "unique" flag, which will then append the SHA1 * of the directory to the name when it is written. */ static struct dir *new_directory(struct dir *parent, struct membuffer *namebuf) { struct dir *subdir; const char *name = mb_cstring(namebuf); int len = namebuf->len; subdir = malloc(sizeof(*subdir)+len); /* * It starts out empty: no subdirectories of its own, * and an empty treebuilder list of files. */ subdir->subdirs = NULL; git_treebuilder_create(&subdir->files, NULL); memcpy(subdir->name, name, len); subdir->unique = 0; subdir->name[len] = 0; /* Add it to the list of subdirs of the parent */ subdir->sibling = parent->subdirs; parent->subdirs = subdir; return subdir; }
static void parse_dc_event(char *line, struct membuffer *str, void *_dc) { int m, s = 0; const char *name; struct divecomputer *dc = _dc; struct event event = { 0 }, *ev; m = strtol(line, &line, 10); if (*line == ':') s = strtol(line+1, &line, 10); event.time.seconds = m*60+s; for (;;) { char c; while (isspace(c = *line)) line++; if (!c) break; line = parse_keyvalue_entry(parse_event_keyvalue, &event, line); } name = ""; if (str->len) name = mb_cstring(str); ev = add_event(dc, event.time.seconds, event.type, event.flags, event.value, name); if (ev && event_is_gaschange(ev)) { /* * We subtract one here because "0" is "no index", * and the parsing will add one for actual cylinder * index data (see parse_event_keyvalue) */ ev->gas.index = event.gas.index-1; if (event.gas.mix.o2.permille || event.gas.mix.he.permille) ev->gas.mix = event.gas.mix; } }
static void parse_site_name(char *line, struct membuffer *str, void *_ds) { (void) line; struct dive_site *ds = _ds; ds->name = strdup(mb_cstring(str)); }
static void parse_site_description(char *line, struct membuffer *str, void *_ds) { struct dive_site *ds = _ds; ds->description = strdup(mb_cstring(str)); }
static void parse_site_notes(char *line, struct membuffer *str, void *_ds) { struct dive_site *ds = _ds; ds->notes = strdup(mb_cstring(str)); }
// TODO: This looks like should be ported to C code. or a big part of it. bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, const bool selected) { static const char errPrefix[] = "divelog.de-upload:"; if (!amount_selected) { report_error(tr("no dives were selected").toUtf8()); return false; } xsltStylesheetPtr xslt = NULL; struct zip *zip; xslt = get_stylesheet("divelogs-export.xslt"); if (!xslt) { qDebug() << errPrefix << "missing stylesheet"; return false; } int error_code; zip = zip_open(QFile::encodeName(QDir::toNativeSeparators(tempfile)), ZIP_CREATE, &error_code); if (!zip) { char buffer[1024]; zip_error_to_str(buffer, sizeof buffer, error_code, errno); report_error(tr("failed to create zip file for upload: %s").toUtf8(), buffer); return false; } /* walk the dive list in chronological order */ int i; struct dive *dive; struct membuffer mb = { 0 }; for_each_dive (i, dive) { FILE *f; char filename[PATH_MAX]; int streamsize; const char *membuf; xmlDoc *transformed; struct zip_source *s; /* * Get the i'th dive in XML format so we can process it. * We need to save to a file before we can reload it back into memory... */ if (selected && !dive->selected) continue; /* make sure the buffer is empty and add the dive */ mb.len = 0; save_one_dive_to_mb(&mb, dive); membuf = mb_cstring(&mb); streamsize = strlen(membuf); /* * Parse the memory buffer into XML document and * transform it to divelogs.de format, finally dumping * the XML into a character buffer. */ xmlDoc *doc = xmlReadMemory(membuf, streamsize, "divelog", NULL, 0); if (!doc) { qWarning() << errPrefix << "could not parse back into memory the XML file we've just created!"; report_error(tr("internal error").toUtf8()); goto error_close_zip; } free((void *)membuf); transformed = xsltApplyStylesheet(xslt, doc, NULL); xmlDocDumpMemory(transformed, (xmlChar **)&membuf, &streamsize); xmlFreeDoc(doc); xmlFreeDoc(transformed); /* * Save the XML document into a zip file. */ snprintf(filename, PATH_MAX, "%d.xml", i + 1); s = zip_source_buffer(zip, membuf, streamsize, 1); if (s) { int64_t ret = zip_add(zip, filename, s); if (ret == -1) qDebug() << errPrefix << "failed to include dive:" << i; } }