1553 ucx_map_free(map); |
1541 ucx_map_free(map); |
1554 return NULL; |
1542 return NULL; |
1555 } |
1543 } |
1556 return map; |
1544 return map; |
1557 } |
1545 } |
|
1546 |
|
1547 |
|
1548 /* ----------------------------- streams ----------------------------- */ |
|
1549 |
|
1550 static size_t in_write(const char *ptr, size_t size, size_t nitems, void *in_stream) { |
|
1551 DavInputStream *in = in_stream; |
|
1552 size_t len = size * nitems; |
|
1553 |
|
1554 if(in->alloc < len) { |
|
1555 char *newb = realloc(in->buffer, len); |
|
1556 if(!newb) { |
|
1557 if(in->buffer) free(in->buffer); |
|
1558 in->eof = 1; |
|
1559 return 0; |
|
1560 } |
|
1561 |
|
1562 in->buffer = newb; |
|
1563 in->alloc = len; |
|
1564 } |
|
1565 |
|
1566 memcpy(in->buffer, ptr, len); |
|
1567 |
|
1568 in->size = len; |
|
1569 in->pos = 0; |
|
1570 |
|
1571 return nitems; |
|
1572 } |
|
1573 |
|
1574 DavInputStream* dav_inputstream_open(DavResource *res) { |
|
1575 DavSession *sn = res->session; |
|
1576 |
|
1577 DavInputStream *in = dav_session_malloc(sn, sizeof(DavInputStream)); |
|
1578 if(!in) { |
|
1579 return NULL; |
|
1580 } |
|
1581 memset(in, 0, sizeof(DavInputStream)); |
|
1582 |
|
1583 in->res = res; |
|
1584 |
|
1585 in->c = curl_easy_duphandle(sn->handle); |
|
1586 char *url = util_get_url(sn, dav_resource_get_href(res)); |
|
1587 curl_easy_setopt(in->c, CURLOPT_URL, url); |
|
1588 free(url); |
|
1589 |
|
1590 in->m = curl_multi_init(); |
|
1591 |
|
1592 curl_easy_setopt(in->c, CURLOPT_HTTPHEADER, NULL); |
|
1593 curl_easy_setopt(in->c, CURLOPT_CUSTOMREQUEST, NULL); |
|
1594 curl_easy_setopt(in->c, CURLOPT_PUT, 0L); |
|
1595 curl_easy_setopt(in->c, CURLOPT_UPLOAD, 0L); |
|
1596 |
|
1597 curl_multi_add_handle(in->m, in->c); |
|
1598 |
|
1599 dav_write_func write_fnc = (dav_write_func)in_write; |
|
1600 void *stream = in; |
|
1601 |
|
1602 // check encryption |
|
1603 AESDecrypter *dec = NULL; |
|
1604 DavKey *key = NULL; |
|
1605 if(DAV_DECRYPT_CONTENT(sn)) { |
|
1606 char *keyname = dav_get_string_property_ns(res, DAV_NS, "crypto-key"); |
|
1607 if(keyname) { |
|
1608 key = dav_context_get_key(sn->context, keyname); |
|
1609 if(key) { |
|
1610 dec = aes_decrypter_new(key, stream, write_fnc); |
|
1611 stream = dec; |
|
1612 write_fnc = (dav_write_func)aes_write; |
|
1613 } |
|
1614 } |
|
1615 } |
|
1616 |
|
1617 curl_easy_setopt(in->c, CURLOPT_WRITEFUNCTION, write_fnc); |
|
1618 curl_easy_setopt(in->c, CURLOPT_WRITEDATA, stream); |
|
1619 |
|
1620 in->dec = dec; |
|
1621 |
|
1622 return in; |
|
1623 } |
|
1624 |
|
1625 size_t dav_read(void *buf, size_t size, size_t nitems, DavInputStream *in) { |
|
1626 size_t len = in->size - in->pos; |
|
1627 size_t rl = size * nitems; |
|
1628 if(len > 0) { |
|
1629 len = rl > len ? len : rl; |
|
1630 len -= len % size; |
|
1631 memcpy(buf, in->buffer + in->pos, len); |
|
1632 in->pos += len; |
|
1633 return len / size; |
|
1634 } |
|
1635 in->size = 0; |
|
1636 |
|
1637 if(in->eof) { |
|
1638 if(in->dec) { |
|
1639 aes_decrypter_shutdown(in->dec); // get final bytes |
|
1640 aes_decrypter_close(in->dec); |
|
1641 in->dec = NULL; |
|
1642 } else { |
|
1643 return 0; |
|
1644 } |
|
1645 } else { |
|
1646 int running; |
|
1647 while(!in->eof && in->size == 0) { |
|
1648 CURLMcode r = curl_multi_perform(in->m, &running); |
|
1649 if(r != CURLM_OK || running == 0) { |
|
1650 in->eof = 1; |
|
1651 break; |
|
1652 } |
|
1653 |
|
1654 int numfds; |
|
1655 if(curl_multi_poll(in->m, NULL, 0, 5000, &numfds) != CURLM_OK) { |
|
1656 in->eof = 1; |
|
1657 } |
|
1658 } |
|
1659 } |
|
1660 |
|
1661 return in->size > 0 ? dav_read(buf, size, nitems, in) : 0; |
|
1662 } |
|
1663 |
|
1664 void dav_inputstream_close(DavInputStream *in) { |
|
1665 curl_multi_cleanup(in->m); |
|
1666 curl_easy_cleanup(in->c); |
|
1667 if(in->buffer) free(in->buffer); |
|
1668 dav_session_free(in->res->session, in); |
|
1669 } |
|
1670 |
|
1671 |
|
1672 static size_t out_read(char *ptr, size_t size, size_t nitems, void *out_stream) { |
|
1673 DavOutputStream *out = out_stream; |
|
1674 size_t len = size * nitems; |
|
1675 size_t available = out->size - out->pos; |
|
1676 if(available == 0) { |
|
1677 return 0; |
|
1678 } |
|
1679 |
|
1680 size_t r = len > available ? available : len; |
|
1681 r -= r % size; |
|
1682 memcpy(ptr, out->buffer + out->pos, r); |
|
1683 |
|
1684 out->pos += r; |
|
1685 |
|
1686 return r / size; |
|
1687 } |
|
1688 |
|
1689 static size_t dummy_write(void *buf, size_t s, size_t n, void *data) { |
|
1690 return s*n; |
|
1691 } |
|
1692 |
|
1693 DavOutputStream* dav_outputstream_open(DavResource *res) { |
|
1694 DavSession *sn = res->session; |
|
1695 |
|
1696 DavOutputStream *out = dav_session_malloc(sn, sizeof(DavOutputStream)); |
|
1697 if(!out) { |
|
1698 return NULL; |
|
1699 } |
|
1700 memset(out, 0, sizeof(DavOutputStream)); |
|
1701 |
|
1702 out->res = res; |
|
1703 |
|
1704 out->c = curl_easy_duphandle(sn->handle); |
|
1705 char *url = util_get_url(sn, dav_resource_get_href(res)); |
|
1706 curl_easy_setopt(out->c, CURLOPT_URL, url); |
|
1707 free(url); |
|
1708 |
|
1709 out->m = curl_multi_init(); |
|
1710 curl_multi_add_handle(out->m, out->c); |
|
1711 |
|
1712 void *stream = out; |
|
1713 dav_read_func read_fnc = (dav_read_func)out_read; |
|
1714 |
|
1715 // if encryption or hashing in enabled, we need a stream wrapper |
|
1716 if(DAV_ENCRYPT_CONTENT(sn) && sn->key) { |
|
1717 AESEncrypter *enc = aes_encrypter_new(sn->key, out, (dav_read_func)out_read, NULL); |
|
1718 out->enc = enc; |
|
1719 stream = enc; |
|
1720 read_fnc = (dav_read_func)aes_read; |
|
1721 } else if((sn->flags & DAV_SESSION_STORE_HASH) == DAV_SESSION_STORE_HASH) { |
|
1722 HashStream *hstr = dav_session_malloc(sn, sizeof(HashStream)); |
|
1723 out->hstr = hstr; |
|
1724 init_hash_stream(hstr, out, (dav_read_func)out_read, NULL); |
|
1725 stream = hstr; |
|
1726 read_fnc = (dav_read_func)dav_read_h; |
|
1727 } |
|
1728 |
|
1729 curl_easy_setopt(out->c, CURLOPT_HEADERFUNCTION, NULL); |
|
1730 curl_easy_setopt(out->c, CURLOPT_HTTPHEADER, NULL); |
|
1731 curl_easy_setopt(out->c, CURLOPT_CUSTOMREQUEST, NULL); |
|
1732 curl_easy_setopt(out->c, CURLOPT_PUT, 1L); |
|
1733 curl_easy_setopt(out->c, CURLOPT_UPLOAD, 1L); |
|
1734 curl_easy_setopt(out->c, CURLOPT_READFUNCTION, read_fnc); |
|
1735 curl_easy_setopt(out->c, CURLOPT_READDATA, stream); |
|
1736 curl_easy_setopt(out->c, CURLOPT_SEEKFUNCTION, NULL); |
|
1737 curl_easy_setopt(out->c, CURLOPT_INFILESIZE, -1); |
|
1738 curl_easy_setopt(out->c, CURLOPT_INFILESIZE_LARGE, -1L); |
|
1739 |
|
1740 curl_easy_setopt(out->c, CURLOPT_WRITEFUNCTION, dummy_write); |
|
1741 curl_easy_setopt(out->c, CURLOPT_WRITEDATA, NULL); |
|
1742 |
|
1743 return out; |
|
1744 } |
|
1745 |
|
1746 size_t dav_write(const void *buf, size_t size, size_t nitems, DavOutputStream *out) { |
|
1747 if(out->eof) return 0; |
|
1748 |
|
1749 out->buffer = buf; |
|
1750 out->size = size * nitems; |
|
1751 out->pos = 0; |
|
1752 |
|
1753 int running; |
|
1754 while(!out->eof && (out->size == 0 || out->size - out->pos > 0)) { |
|
1755 CURLMcode r = curl_multi_perform(out->m, &running); |
|
1756 if(r != CURLM_OK || running == 0) { |
|
1757 out->eof = 1; |
|
1758 break; |
|
1759 } |
|
1760 |
|
1761 int numfds; |
|
1762 if(curl_multi_poll(out->m, NULL, 0, 5000, &numfds) != CURLM_OK) { |
|
1763 out->eof = 1; |
|
1764 } |
|
1765 } |
|
1766 |
|
1767 return (out->size - out->pos) / size; |
|
1768 } |
|
1769 |
|
1770 int dav_outputstream_close(DavOutputStream *out) { |
|
1771 DavSession *sn = out->res->session; |
|
1772 DavResource *res = out->res; |
|
1773 DavResourceData *data = res->data; |
|
1774 |
|
1775 int ret = 0; |
|
1776 |
|
1777 dav_write(NULL, 1, 0, out); |
|
1778 |
|
1779 curl_multi_cleanup(out->m); |
|
1780 curl_easy_cleanup(out->c); |
|
1781 |
|
1782 int store = 0; |
|
1783 if(out->enc) { |
|
1784 // get sha256 hash |
|
1785 char hash[32]; |
|
1786 dav_get_hash(&out->enc->sha256, (unsigned char*)data->hash); |
|
1787 aes_encrypter_close(out->enc); |
|
1788 char *enc_hash = aes_encrypt(hash, DAV_SHA256_DIGEST_LENGTH, sn->key); |
|
1789 // add crypto properties |
|
1790 if(resource_add_crypto_info(sn, out->res->href, out->res->name, enc_hash)) { |
|
1791 ret = 1; |
|
1792 } |
|
1793 free(enc_hash); |
|
1794 } else if(out->hstr) { |
|
1795 dav_hash_final(out->hstr->sha, (unsigned char*)data->hash); |
|
1796 char *hash = util_hexstr((unsigned char*)data->hash, 32); |
|
1797 dav_set_string_property_ns(res, DAV_NS, "content-hash", hash); |
|
1798 free(hash); |
|
1799 dav_session_free(sn, out->hstr); |
|
1800 store = 1; |
|
1801 } |
|
1802 |
|
1803 if(store) { |
|
1804 ret = dav_store(out->res); |
|
1805 } |
|
1806 |
|
1807 dav_session_free(out->res->session, out); |
|
1808 |
|
1809 return ret; |
|
1810 } |
|
1811 |