/*! Returns the name of a local file equivalent to \a url, or a null string if \a url is not a local file. */ QString QUrlDrag::urlToLocalFile(const char* url) { QString result; if ( url && 0==qstrnicmp(url,"file:/",6) ) { url += 6; if ( url[0] != '/' || url[1] == '/' ) { // It is local. while (*url) { switch (*url) { case '|': result += ':'; break; case '+': result += ' '; break; case '%': { int ch = url[1]; if ( ch && url[2] ) { ch = htod(ch)*16 + htod(url[2]); result += ch; } } break; default: result += *url; } ++url; } } } return result; }
/*! Returns the Unicode URI (only useful for displaying to humans) equivalent to \a uri. \sa localFileToUri() */ QString QUriDrag::uriToUnicodeUri(const char* uri) { QCString utf8; while (*uri) { switch (*uri) { case '%': { uint ch = uri[1]; if ( ch && uri[2] ) { ch = htod(ch)*16 + htod(uri[2]); utf8 += char(ch); uri += 2; } } break; default: utf8 += *uri; } ++uri; } return QString::fromUtf8(utf8); }
int tlv_from_file(tlv_t *tlv, int fd, char type, uint32_t date) { int tlv_size; int rc = 0; int len = 0; int tlv_start = date ? TLV_SIZEOF_DATE + TLV_SIZEOF_HEADER : 0; tlv_size = tlv_start + TLV_SIZEOF_HEADER; *tlv = (tlv_t)safe_realloc(*tlv, tlv_size); if (*tlv == NULL) { ERROR("realloc", -1); } do { len += rc; if (len + tlv_start == tlv_size) { tlv_size *= 2; *tlv = safe_realloc(*tlv, tlv_size); if (*tlv == NULL) { ERROR("realloc", -1); } } } while ((rc = read(fd, *tlv + tlv_start + len, tlv_size - len - tlv_start)) > 0); if (rc == -1) { PERROR("read"); return -1; } if (len + tlv_start > TLV_MAX_SIZE) { LOGERROR("Too large to fit in a TLV: %d.", len + tlv_start); } (*tlv)[tlv_start] = type; htod(len, &((*tlv)[tlv_start + 1])); if (date) { tlv_set_type(tlv, TLV_DATED); tlv_set_length(tlv, len + tlv_start); tlv_set_date(tlv, date); } return 0; }
uint32_t ltlv_split_value(char *src, uint32_t len) { int nb_chunks = ltlv_nb_chunks(len), w_idx = 0; uint32_t remaining = len; for (int i = 0; i < nb_chunks; i++) { uint32_t size = MIN(TLV_MAX_VALUE_SIZE, remaining); /* shift memory */ memmove(src + w_idx + TLV_SIZEOF_HEADER, src + w_idx, remaining); /* write LONGC header */ src[w_idx] = TLV_LONGC; htod(size, src + w_idx + 1); /* update counters */ w_idx += size + TLV_SIZEOF_HEADER; remaining -= size; } return w_idx; }
int tlv_from_inputs(tlv_t *tlv, struct tlv_input *inputs, int nb_inputs, time_t date) { int i, len = 0, cmpnd_idx = 0, write_idx, status = 0, nb_lhead = 0, nb_lcontent = 0, content_idx = 0; /* Compute needed length */ for (int i = 0; i < nb_inputs; i++) { if (inputs[i].len > TLV_MAX_VALUE_SIZE) { nb_lhead++; nb_lcontent += ltlv_nb_chunks(inputs[i].len); } else { len += TLV_SIZEOF_HEADER; } len += inputs[i].len; } if (nb_inputs > 1) { /* If more than one input * we make a compound */ len += TLV_SIZEOF_HEADER; content_idx += TLV_SIZEOF_HEADER; } /* Set date and update pointers if needed. */ if (date) { cmpnd_idx += TLV_SIZEOF_HEADER + TLV_SIZEOF_DATE; content_idx += TLV_SIZEOF_HEADER + TLV_SIZEOF_DATE; len += TLV_SIZEOF_HEADER + TLV_SIZEOF_DATE; } /* Add space needed by large tlv headers */ len += nb_lcontent * TLV_SIZEOF_HEADER; len += nb_lhead * TLV_SIZEOF_LONGH; /* If we are making a compound with large content * we will need to include it in a large tlv * But we wont need space for compound header * as it will be included in LONGH value * content_idx will move TLV_SIZEOF_LONGH */ if (len > TLV_MAX_SIZE && nb_inputs > 1) { nb_lhead++; len -= TLV_SIZEOF_HEADER; len += ltlv_nb_chunks(len) * TLV_SIZEOF_HEADER; len += TLV_SIZEOF_LONGH; content_idx += TLV_SIZEOF_LONGH - TLV_SIZEOF_HEADER; } /* Same behavior with a date, * but cmpnd_idx move as well */ if (len > TLV_MAX_SIZE && date) { nb_lhead++; len -= TLV_SIZEOF_HEADER; len += ltlv_nb_chunks(len) * TLV_SIZEOF_HEADER; len += TLV_SIZEOF_LONGH; content_idx += TLV_SIZEOF_LONGH - TLV_SIZEOF_HEADER; cmpnd_idx += TLV_SIZEOF_LONGH - TLV_SIZEOF_HEADER; } *tlv = safe_realloc(*tlv, sizeof(**tlv) * len); if (*tlv == NULL) { PERROR("safe_realloc"); return -1; } write_idx = content_idx; /* Copy inputs value and add TLV headers */ for (i = 0; i < nb_inputs; i++) { if (inputs[i].len > TLV_MAX_VALUE_SIZE) { char *false_tlv = *tlv + write_idx; /* Need to insert TLV in a long TLV */ int wrote = ltlv_mk_tlv( &false_tlv, inputs[i].data, inputs[i].type, inputs[i].len); write_idx += wrote; } else { (*tlv)[write_idx] = inputs[i].type; write_idx += TLV_SIZEOF_TYPE; htod(inputs[i].len, *tlv + write_idx); write_idx += TLV_SIZEOF_LENGTH; memcpy(*tlv + write_idx, inputs[i].data, inputs[i].len); write_idx += inputs[i].len; } } /* Write compound header if needed */ if (nb_inputs > 1) { int content_len = write_idx - content_idx; char *false_tlv = *tlv + cmpnd_idx; if (content_len > TLV_MAX_VALUE_SIZE) { mk_longh(&false_tlv, TLV_COMPOUND, content_len); uint32_t new_size = ltlv_split_value( false_tlv + TLV_SIZEOF_LONGH, content_len); write_idx = content_idx + new_size; } else { tlv_set_type(&false_tlv, TLV_COMPOUND); tlv_set_length(&false_tlv, content_len); } } if (date != 0) { int content_len = write_idx - (cmpnd_idx - TLV_SIZEOF_DATE); if (content_len > TLV_MAX_VALUE_SIZE) { mk_longh(tlv, TLV_DATED, content_len); memcpy(*tlv + TLV_SIZEOF_LONGH, &date, TLV_SIZEOF_DATE); uint32_t new_size = ltlv_split_value( *tlv + TLV_SIZEOF_LONGH, content_len); write_idx = TLV_SIZEOF_LONGH + new_size; } else { tlv_set_type(tlv, TLV_DATED); tlv_set_length(tlv, content_len); tlv_set_date(tlv, date); } } if (write_idx != len) { LOGERROR("written %d bytes, expected %d.", write_idx, len); status = -1; } return status; }
void tlv_set_length(tlv_t *tlv, unsigned int n) { htod(n, tlv_get_length_ptr(tlv)); }