├── .gitignore
├── c_tests
├── .gitignore
├── Makefile
├── tests.c
├── test_common.h
└── test_service.c
├── .github
└── FUNDING.yml
├── etebase.pc.in
├── Cargo.toml
├── README.md
├── EtebaseConfig.cmake
├── Makefile
├── ChangeLog.md
├── LICENSE
├── cbindgen.toml
├── Cargo.lock
└── src
└── lib.rs
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
3 | Session.vim
4 |
--------------------------------------------------------------------------------
/c_tests/.gitignore:
--------------------------------------------------------------------------------
1 | /tests
2 | *.o
3 |
4 | /compile_commands.json
5 | /.clangd/
6 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: etesync
2 | custom: https://www.etesync.com/contribute/#donate
3 |
--------------------------------------------------------------------------------
/etebase.pc.in:
--------------------------------------------------------------------------------
1 | prefix=@prefix@
2 | libdir=${prefix}/lib
3 | includedir=${prefix}/include
4 |
5 | Name: Etebase
6 | Description: A C library for Etebase
7 | Version: 0.5.3
8 | Libs: -L${libdir} -letebase
9 | Cflags: -I${includedir}/etebase
10 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "libetebase"
3 | description = "C library for etebase"
4 | homepage = "https://www.etebase.com"
5 | repository = "https://github.com/etesync/libetebase/"
6 | version = "0.5.3"
7 | authors = ["Tom Hacohen "]
8 | edition = "2018"
9 | license = "BSD-3-Clause"
10 | readme = "README.md"
11 | publish = false
12 |
13 | [lib]
14 | name = "etebase"
15 | crate-type = ["staticlib", "cdylib"]
16 |
17 | [build-dependencies]
18 | cbindgen = "^0.14.2"
19 |
20 | [dependencies]
21 | etebase = "^0.5.3"
22 |
--------------------------------------------------------------------------------
/c_tests/Makefile:
--------------------------------------------------------------------------------
1 | TARGET = tests
2 | LIBS = -L. -l:../target/debug/libetebase.so
3 | CC = gcc
4 | CFLAGS = -g -Wall -I ../target
5 |
6 | .PHONY: default all clean
7 |
8 | default: $(TARGET)
9 | all: default
10 |
11 | OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
12 | HEADERS = $(wildcard *.h) ../target/etebase.h
13 |
14 | %.o: %.c $(HEADERS)
15 | $(CC) $(CFLAGS) -c $< -o $@
16 |
17 | .PRECIOUS: $(TARGET) $(OBJECTS)
18 |
19 | $(TARGET): $(OBJECTS)
20 | $(CC) $(OBJECTS) -Wall -fsanitize=address -fno-omit-frame-pointer $(LIBS) -o $@
21 |
22 | check: $(TARGET)
23 | ./tests
24 |
25 | clean:
26 | -rm -f *.o
27 | -rm -f $(TARGET)
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Etebase - Encrypt Everything
4 |
5 |
6 | A C library for Etebase
7 |
8 | This package is implemented in Rust and exposes a C API for people to use.
9 |
10 | 
11 | [](https://travis-ci.com/etesync/libetebase)
12 | [](https://www.etebase.com/community-chat/)
13 |
14 | # Documentation
15 |
16 | In addition to the API documentation, there are docs available at https://docs.etebase.com
17 |
18 | # Build
19 |
20 | ```
21 | make
22 | ```
23 |
24 | # Install
25 |
26 | ```
27 | sudo make install
28 | ```
29 |
--------------------------------------------------------------------------------
/c_tests/tests.c:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: © 2020 EteSync Authors
2 | // SPDX-License-Identifier: LGPL-2.1-only
3 |
4 | #include "test_common.h"
5 |
6 | int test_simple_getters();
7 | int test_base64();
8 | int test_utils();
9 | int test_check_etebase_server();
10 | int test_simple();
11 | int test_item_deps();
12 | int test_collection_transactions();
13 | int test_items_transactions();
14 | int test_collection_as_item();
15 | int test_item_revisions();
16 | int test_basic_invitations();
17 | int test_bad_auth();
18 |
19 | int
20 | main() {
21 | int ret = 0;
22 |
23 | RUN_TEST(test_simple_getters);
24 | RUN_TEST(test_base64);
25 | RUN_TEST(test_utils);
26 | RUN_TEST(test_check_etebase_server);
27 | RUN_TEST(test_simple);
28 | RUN_TEST(test_item_deps);
29 | RUN_TEST(test_collection_transactions);
30 | RUN_TEST(test_items_transactions);
31 | RUN_TEST(test_collection_as_item);
32 | RUN_TEST(test_item_revisions);
33 | RUN_TEST(test_basic_invitations);
34 | RUN_TEST(test_bad_auth);
35 |
36 | return ret;
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/EtebaseConfig.cmake:
--------------------------------------------------------------------------------
1 | # - Try to find etebase
2 | # Once done this will define
3 | # ETEBASE_FOUND - System has etebase
4 | # ETEBASE_INCLUDE_DIRS - The etebase include directories
5 | # ETEBASE_LIBRARIES - The libraries needed to use etebase
6 | # ETEBASE_DEFINITIONS - Compiler switches required for using etebase
7 |
8 | find_package(PkgConfig)
9 | if ("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER "2.8.1")
10 | # "QUIET" was introduced in 2.8.2
11 | set(_QUIET QUIET)
12 | endif ()
13 | pkg_check_modules(PC_ETEBASE ${_QUIET} etebase)
14 |
15 | find_library(ETEBASE_LIBRARY
16 | NAMES ${PC_ETEBASE_LIBRARIES}
17 | HINTS ${PC_ETEBASE_LIBDIR} ${PC_ETEBASE_LIBRARY_DIRS} )
18 |
19 | set(ETEBASE_DEFINITIONS ${PC_ETEBASE_CFLAGS_OTHER})
20 | set(ETEBASE_LIBRARIES ${ETEBASE_LIBRARY})
21 | set(ETEBASE_INCLUDE_DIRS ${PC_ETEBASE_INCLUDE_DIRS})
22 |
23 | include(FindPackageHandleStandardArgs)
24 | # handle the QUIETLY and REQUIRED arguments and set ETEBASE_FOUND to TRUE
25 | # if all listed variables are TRUE
26 | find_package_handle_standard_args(Etebase DEFAULT_MSG
27 | ETEBASE_LIBRARIES ETEBASE_INCLUDE_DIRS)
28 |
29 | mark_as_advanced(ETEBASE_INCLUDE_DIRS ETEBASE_LIBRARY ETEBASE_LIBRARIES ETEBASE_DEFINITIONS)
30 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PREFIX ?= /usr
2 | DESTDIR ?=
3 | # Set MODE to debug to build in debug mode
4 | MODE ?= release
5 |
6 | PKGNAME = etebase
7 |
8 | BUILDDIR = ./target
9 |
10 | DST_LIBRARY_DIR = $(DESTDIR)$(PREFIX)/lib
11 | DST_PKGCONFIG_DIR = $(DST_LIBRARY_DIR)/pkgconfig
12 | DST_CMAKECONFIG_DIR = $(DST_LIBRARY_DIR)/cmake/Etebase
13 | DST_INCLUDE_DIR = $(DESTDIR)$(PREFIX)/include/$(PKGNAME)
14 |
15 | LIBRARY_FILE = $(BUILDDIR)/$(MODE)/lib$(PKGNAME).so
16 | HEADER_FILE = $(BUILDDIR)/$(PKGNAME).h
17 | PKGCONFIG_FILE = $(BUILDDIR)/$(PKGNAME).pc
18 | CMAKECONFIG_FILE = EtebaseConfig.cmake
19 |
20 | .PHONY: default all clean
21 |
22 | all: build
23 |
24 | pkgconfig: $(PKGCONFIG_FILE)
25 |
26 | $(PKGCONFIG_FILE): $(PKGNAME).pc.in
27 | mkdir -p "$(BUILDDIR)"
28 | sed "s#@prefix@#$(PREFIX)#g" $< > "$(BUILDDIR)/$(PKGNAME).pc"
29 |
30 | build-release: pkgconfig
31 | cargo build --release
32 |
33 | build-debug: pkgconfig
34 | cargo build
35 |
36 | # https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-06-rust-on-ios.html
37 | build-ios: pkgconfig
38 | cargo lipo --release
39 |
40 | build: build-$(MODE)
41 |
42 | install:
43 | install -Dm644 "$(PKGCONFIG_FILE)" -t "$(DST_PKGCONFIG_DIR)"
44 | install -Dm644 "$(CMAKECONFIG_FILE)" -t "$(DST_CMAKECONFIG_DIR)"
45 | install -Dm644 "$(HEADER_FILE)" -t "$(DST_INCLUDE_DIR)"
46 | install -Dm755 "$(LIBRARY_FILE)" -t "$(DST_LIBRARY_DIR)"
47 |
48 | check: build
49 | cargo check
50 | cd c_tests && $(MAKE) check
51 |
52 | clean:
53 | cargo clean
54 | cd c_tests && $(MAKE) clean
55 | rm -f "$(BUILDDIR)/$(PKGNAME).p"c
56 |
--------------------------------------------------------------------------------
/ChangeLog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## Version 0.5.2
4 | * Update openssl deps to support more recent libopenssl vesrions
5 |
6 | ## Version 0.5.1
7 | * Update to the latest etebase-rs release
8 |
9 | ## Version 0.5.0
10 | * Document all of the API
11 | * Add fetch_multi te fetch items by UIDs
12 |
13 | ## Version 0.4.1
14 | * Build the release version by default
15 |
16 | ## Version 0.4.0
17 | * Relicense to BSD-3-Clause
18 | * Improve Makefile
19 | * Set SONAME for the library on Unix-like systems
20 |
21 | ## Version 0.3.1
22 | * Fix issue with custom urls lacking a trailing slash
23 | * Update etebase dependency
24 |
25 | ## Version 0.3.0
26 | * Login: automatically create the account if not init
27 | * Have global and immutable collection types (changes the create and list APIs)
28 | * Update etebase dependency
29 |
30 | ## Version 0.2.0
31 | * Expose a function to fetch the dashboard url of an account
32 | * Expose the FileSystemCache module for caching the data locally
33 | * Expose a function te check whether it's an etebase server
34 | * Update etebase dependency
35 |
36 | ## Version 0.1.4
37 | * Invitations: expose from_username
38 | * Update etebase dependency
39 |
40 | ## Version 0.1.3
41 | * Collection stoken: fix fetching a collection's stoken
42 | * Update etebase dependency
43 |
44 | ## Version 0.1.2
45 | * Expose the access level as int rather than string
46 | * Add Cmake configuration file
47 | * Update etebase dependency
48 |
49 | ## Version 0.1.1
50 | * Split the batch/transaction functions to with and without deps
51 |
52 | ## Version 0.1.0
53 | * Initial release
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2020, Tom Hacohen. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | 3. Neither the name of the copyright holder nor the names of its
14 | contributors may be used to endorse or promote products derived from
15 | this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/c_tests/test_common.h:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: © 2020 EteSync Authors
2 | // SPDX-License-Identifier: LGPL-2.1-only
3 |
4 | #ifndef _TEST_COMMON_H
5 | #define _TEST_COMMON_H
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "etebase.h"
14 |
15 |
16 | #define fail_if(expr) \
17 | do { \
18 | if (expr) { \
19 | fprintf(stderr, "%s:%d: Failure '"#expr"' occurred.\n", __func__, __LINE__); \
20 | exit(1); \
21 | } \
22 | } while (0)
23 |
24 | #define assert_str_eq(str1, str2) \
25 | do { \
26 | const char *a = str1, *b = str2; \
27 | if (strcmp(a, b)) { \
28 | fprintf(stderr, "%s:%d: Falilure: '%s' != '%s'.\n", __func__, __LINE__, a, b); \
29 | exit(1); \
30 | } \
31 | } while (0)
32 |
33 | #define assert_int_eq(num1, num2) \
34 | do { \
35 | const int a = num1, b = num2; \
36 | if (a != b) { \
37 | fprintf(stderr, "%s:%d: Falilure: '%d' != '%d'.\n", __func__, __LINE__, a, b); \
38 | exit(1); \
39 | } \
40 | } while (0)
41 |
42 | #define assert_int_ne(num1, num2) \
43 | do { \
44 | const int a = num1, b = num2; \
45 | if (a == b) { \
46 | fprintf(stderr, "%s:%d: Falilure: '%d' == '%d'.\n", __func__, __LINE__, a, b); \
47 | exit(1); \
48 | } \
49 | } while (0)
50 |
51 | #define RUN_TEST(test) \
52 | do { \
53 | fprintf(stderr, "> Starting test: %s\n", #test); \
54 | ret = ret || test(); \
55 | fprintf(stderr, "= Finished test: %s\n", #test); \
56 | } while(0)
57 |
58 |
59 | #endif
60 |
--------------------------------------------------------------------------------
/cbindgen.toml:
--------------------------------------------------------------------------------
1 | language = "C"
2 |
3 | # An optional name to use as an include guard
4 | # default: doesn't emit an include guard
5 | include_guard = "ETEBASE_H"
6 |
7 | cpp_compat = true
8 |
9 | # An optional string of text to output between major sections of the generated
10 | # file as a warning against manual editing
11 | autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
12 |
13 | # Whether to include a comment with the version of cbindgen used to generate the file
14 | # default: false
15 | include_version = true
16 |
17 | after_includes = """
18 | // +1 so we fake ceil it
19 | #define ETEBASE_UTILS_FROM_BASE64_MAX_LEN(X) (((X) * 3U / 4U) + 1U)
20 |
21 | // +2 so we fake ceil it + terminating null
22 | #define ETEBASE_UTILS_TO_BASE64_MAX_LEN(X) (((X) * 4U / 3U) + 2U)
23 |
24 | #define ETEBASE_UTILS_C_ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))
25 | """
26 |
27 | # Codegen Options
28 |
29 | # When generating a C header, the kind of declaration style to use for structs
30 | # or enums.
31 | #
32 | # possible values:
33 | # * "type": typedef struct { ... } MyType;
34 | # * "tag": struct MyType { ... };
35 | # * "both": typedef struct MyType { ... } MyType;
36 | #
37 | # default: "both"
38 | style = "both"
39 |
40 | [export]
41 | prefix = "Etebase"
42 | renaming_overrides_prefixing = true
43 |
44 | exclude = ["CURRENT_VERSION", "SYMMETRIC_KEY_SIZE", "SYMMETRIC_NONCE_SIZE", "SYMMETRIC_TAG_SIZE"]
45 |
46 | [export.rename]
47 | "ETEBASE_UTILS_PRETTY_FINGERPRINT_SIZE" = "ETEBASE_UTILS_PRETTY_FINGERPRINT_SIZE"
48 |
49 | [fn]
50 | # An optional prefix to put before every function declaration
51 | # default: no prefix added
52 | # prefix = "WR_START_FUNC"
53 |
54 | # An optional postfix to put after any function declaration
55 | # default: no postix added
56 | # postfix = "WR_END_FUNC"
57 |
58 | sort_by = "None"
59 |
60 | [struct]
61 | # A rule to use to rename struct field names. The renaming assumes the input is
62 | # the Rust standard snake_case, however it acccepts all the different rename_args
63 | # inputs. This means many options here are no-ops or redundant.
64 | #
65 | # possible values (that actually do something):
66 | # * "CamelCase": my_arg => myArg
67 | # * "PascalCase": my_arg => MyArg
68 | # * "GeckoCase": my_arg => mMyArg
69 | # * "ScreamingSnakeCase": my_arg => MY_ARG
70 | # * "None": apply no renaming
71 | #
72 | # technically possible values (that shouldn't have a purpose here):
73 | # * "SnakeCase": apply no renaming
74 | # * "LowerCase": apply no renaming (actually applies to_lowercase, is this bug?)
75 | # * "UpperCase": same as ScreamingSnakeCase in this context
76 | # * "QualifiedScreamingSnakeCase" => same as ScreamingSnakeCase in this context
77 | #
78 | # default: "None"
79 | rename_fields = "None"
80 |
81 |
82 | [enum]
83 | # A rule to use to rename enum variants, and the names of any fields those
84 | # variants have. This should probably be split up into two separate options, but
85 | # for now, they're the same! See the documentation for `[struct]rename_fields`
86 | # for how this applies to fields. Renaming of the variant assumes that the input
87 | # is the Rust standard PascalCase. In the case of QualifiedScreamingSnakeCase,
88 | # it also assumed that the enum's name is PascalCase.
89 | #
90 | # possible values (that actually do something):
91 | # * "CamelCase": MyVariant => myVariant
92 | # * "SnakeCase": MyVariant => my_variant
93 | # * "ScreamingSnakeCase": MyVariant => MY_VARIANT
94 | # * "QualifiedScreamingSnakeCase": MyVariant => ENUM_NAME_MY_VARIANT
95 | # * "LowerCase": MyVariant => myvariant
96 | # * "UpperCase": MyVariant => MYVARIANT
97 | # * "None": apply no renaming
98 | #
99 | # technically possible values (that shouldn't have a purpose for the variants):
100 | # * "PascalCase": apply no renaming
101 | # * "GeckoCase": apply no renaming
102 | #
103 | # default: "None"
104 | rename_variants = "ScreamingSnakeCase"
105 | prefix_with_name = true
106 |
107 | [parse]
108 | parse_deps = true
109 | include = ["etebase"]
110 | extra_bindings = ["etebase"]
111 |
--------------------------------------------------------------------------------
/c_tests/test_service.c:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: © 2020 EteSync Authors
2 | // SPDX-License-Identifier: LGPL-2.1-only
3 |
4 | #include "etebase.h"
5 | #include "test_common.h"
6 | #include
7 | #include
8 | #include
9 |
10 | const char TEST_USER_SESSION[] = "gqd2ZXJzaW9uAa1lbmNyeXB0ZWREYXRhxQGr_KWyDChQ6tXOJwJKf0Kw3QyR99itPIF3vZ5w6pVXSIq7AWul3fIXjIZOsBEwTVRumw7e9Af38D5oIL2VLNPLlmTOMjzIvuB00z3zDMFbH8pwrg2p_FvAhLHGjUGoXzU2XIxS4If7rQUfEz1zWkHPqWMrj4hACML5fks302dOUw7OsSMekcQaaVqMyj82MY3lG2qj8CL6ykSED7nW6OYWwMBJ1rSDGXhQRd5JuCGl6kgAHxKS6gkkIAWeUKjC6-Th2etk1XPKDiks0SZrQpmuXG8h_TBdd4igjRUqnIk09z5wvJFViXIU4M3pQomyFPk3Slh7KHvWhzxG0zbC2kUngQZ5h-LbVTLuT_TQWjYmHiOIihenrzl7z9MLebUq6vuwusZMRJ1Atau0Y2HcOzulYt4tLRP49d56qFEId3R4xomZ666hy-EFodsbzpxEKHeBUro3_gifOOKR8zkyLKTRz1UipZfKvnWk_RHFgZlSClRsXyaP34wstUavSiz-HNmTEmflNQKM7Awfel108FcSbW9NQAogW2Y2copP-P-R-DiHThrXmgDsWkTQFA";
11 |
12 | const char *COL_TYPE = "some.coltype";
13 |
14 | const char *
15 | get_test_url() {
16 | const char *env = getenv("ETEBASE_TEST_API_URL");
17 | return (env) ? env : "http://localhost:8033";
18 | }
19 |
20 | int
21 | test_simple_getters() {
22 | EtebaseUser *user = etebase_user_new("username", "email@localhost");
23 | assert_str_eq(etebase_user_get_username(user), "username");
24 | assert_str_eq(etebase_user_get_email(user), "email@localhost");
25 | etebase_user_destroy(user);
26 |
27 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
28 | EtebaseAccount *etebase = etebase_account_restore(client, TEST_USER_SESSION, NULL, 0);
29 | etebase_client_destroy(client);
30 |
31 | EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase);
32 | EtebaseItemMetadata *col_meta = etebase_item_metadata_new();
33 | etebase_item_metadata_set_name(col_meta, "Name");
34 | const char content[] = "Something";
35 | EtebaseCollection *col = etebase_collection_manager_create(col_mgr, COL_TYPE, col_meta, content, strlen(content));
36 | etebase_item_metadata_destroy(col_meta);
37 |
38 | {
39 | char *col_type = etebase_collection_get_collection_type(col);
40 | assert_str_eq(col_type, COL_TYPE);
41 | free(col_type);
42 | }
43 |
44 | // Check we can just get the content size if we pass null as the buffer
45 | {
46 | uintptr_t len = etebase_collection_get_content(col, NULL, 0);
47 | assert_int_eq(len, strlen(content));
48 | char tmp[len];
49 | etebase_collection_get_content(col, tmp, len);
50 | }
51 |
52 | EtebaseCollectionInvitationManager *invitation_manager = etebase_account_get_invitation_manager(etebase);
53 |
54 | uintptr_t pubkey_size = etebase_invitation_manager_get_pubkey_size(invitation_manager);
55 | fail_if(pubkey_size == 0);
56 | const char *pubkey = etebase_invitation_manager_get_pubkey(invitation_manager);
57 | fail_if(!pubkey);
58 |
59 | etebase_invitation_manager_destroy(invitation_manager);
60 | etebase_collection_destroy(col);
61 | etebase_collection_manager_destroy(col_mgr);
62 | etebase_account_destroy(etebase);
63 |
64 | return 0;
65 | }
66 |
67 | int
68 | test_base64() {
69 | const char *text = "Test";
70 | char encoded[ETEBASE_UTILS_TO_BASE64_MAX_LEN(strlen(text) + 1)];
71 | fail_if(etebase_utils_to_base64(text, strlen(text) + 1, encoded, sizeof(encoded)));
72 | char decoded[ETEBASE_UTILS_FROM_BASE64_MAX_LEN(strlen(encoded))];
73 | uintptr_t decoded_len = 0;
74 | fail_if(etebase_utils_from_base64(encoded, decoded, sizeof(decoded), &decoded_len));
75 | assert_int_eq(decoded_len, strlen(text) + 1);
76 | assert_str_eq(decoded, text);
77 |
78 | fail_if(etebase_utils_from_base64(encoded, decoded, sizeof(decoded), NULL));
79 |
80 | fail_if(!etebase_utils_from_base64("#@$@#$*@#$", decoded, sizeof(decoded), NULL));
81 | assert_int_eq(ETEBASE_ERROR_CODE_BASE64, etebase_error_get_code());
82 | return 0;
83 | }
84 |
85 | int
86 | test_utils() {
87 | assert_str_eq(etebase_get_default_server_url(), "https://api.etebase.com");
88 | char buf[32];
89 | fail_if(etebase_utils_randombytes(buf, sizeof(buf)));
90 | char pretty[ETEBASE_UTILS_PRETTY_FINGERPRINT_SIZE];
91 | fail_if(etebase_utils_pretty_fingerprint(buf, sizeof(buf), pretty));
92 | return 0;
93 | }
94 |
95 | int
96 | test_check_etebase_server() {
97 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
98 | fail_if(etebase_client_check_etebase_server(client));
99 | etebase_client_destroy(client);
100 | /*
101 | let test_url = format!("{}/a", test_url());
102 | let client = Client::new(CLIENT_NAME, &test_url)?;
103 | assert!(!Account::is_etebase_server(&client)?);
104 | */
105 | client = etebase_client_new("libetebase-test", "http://doesnotexist");
106 | fail_if(!etebase_client_check_etebase_server(client));
107 | etebase_client_destroy(client);
108 |
109 | return 0;
110 | }
111 |
112 | int
113 | test_simple() {
114 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
115 | EtebaseAccount *etebase = etebase_account_restore(client, TEST_USER_SESSION, NULL, 0);
116 | etebase_client_destroy(client);
117 |
118 | etebase_account_force_server_url(etebase, get_test_url());
119 | etebase_account_fetch_token(etebase);
120 |
121 | EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase);
122 | EtebaseItemMetadata *col_meta = etebase_item_metadata_new();
123 | etebase_item_metadata_set_name(col_meta, "Name");
124 | const char content[] = "Something";
125 | EtebaseCollection *col = etebase_collection_manager_create(col_mgr, COL_TYPE, col_meta, content, strlen(content));
126 | etebase_item_metadata_destroy(col_meta);
127 |
128 | {
129 | char tmp[1000];
130 | intptr_t tmp_size = etebase_collection_get_content(col, &tmp, sizeof(tmp));
131 | fail_if(tmp_size < 0);
132 | assert_int_eq(tmp_size, strlen(content));
133 | tmp[tmp_size] = 0;
134 | assert_str_eq(tmp, content);
135 | }
136 |
137 | {
138 | EtebaseFetchOptions *fetch_options = etebase_fetch_options_new();
139 | etebase_fetch_options_set_prefetch(fetch_options, ETEBASE_PREFETCH_OPTION_AUTO);
140 | fail_if(etebase_collection_manager_upload(col_mgr, col, fetch_options));
141 | etebase_fetch_options_destroy(fetch_options);
142 | }
143 |
144 | {
145 | EtebaseCollectionListResponse *col_list = etebase_collection_manager_list(col_mgr, COL_TYPE, NULL);
146 | fail_if(!col_list);
147 | assert_int_ne(0, etebase_collection_list_response_get_data_length(col_list));
148 |
149 | EtebaseFetchOptions *fetch_options = etebase_fetch_options_new();
150 | etebase_fetch_options_set_stoken(fetch_options, etebase_collection_list_response_get_stoken(col_list));
151 |
152 | etebase_collection_list_response_destroy(col_list);
153 | col_list = etebase_collection_manager_list(col_mgr, COL_TYPE, fetch_options);
154 | assert_int_eq(0, etebase_collection_list_response_get_data_length(col_list));
155 |
156 | etebase_fetch_options_destroy(fetch_options);
157 | etebase_collection_list_response_destroy(col_list);
158 | }
159 |
160 | {
161 | EtebaseCollection *col2 = etebase_collection_manager_fetch(col_mgr, etebase_collection_get_uid(col), NULL);
162 | char content2[1000];
163 | intptr_t content2_size = etebase_collection_get_content(col2, &content2, sizeof(content2));
164 | fail_if(content2_size < 0);
165 | assert_int_eq(content2_size, strlen(content));
166 | content2[content2_size] = 0;
167 | assert_str_eq(content2, content);
168 |
169 | const char tmp[] = "Something else";
170 | etebase_collection_set_content(col2, tmp, strlen(tmp));
171 | etebase_collection_manager_transaction(col_mgr, col2, NULL);
172 |
173 | etebase_collection_destroy(col2);
174 | }
175 |
176 | EtebaseItemManager *item_mgr = etebase_collection_manager_get_item_manager(col_mgr, col);
177 | EtebaseItemMetadata *item_meta = etebase_item_metadata_new();
178 | etebase_item_metadata_set_item_type(item_meta, "Bla");
179 | const char item_content[] = "Something item";
180 | EtebaseItem *item = etebase_item_manager_create(item_mgr, item_meta, item_content, strlen(item_content));
181 | etebase_item_metadata_destroy(item_meta);
182 | fail_if(!strcmp("", etebase_item_get_uid(item)));
183 | fail_if(!etebase_item_get_etag(item));
184 |
185 | {
186 | char content2[1000];
187 | intptr_t content2_size = etebase_item_get_content(item, &content2, sizeof(content2));
188 | fail_if(content2_size < 0);
189 | assert_int_eq(content2_size, strlen(item_content));
190 | content2[content2_size] = 0;
191 | assert_str_eq(content2, item_content);
192 | }
193 |
194 | {
195 | const EtebaseItem *items[] = { item };
196 | fail_if(etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
197 | }
198 |
199 | {
200 | char *old_etag = strdup(etebase_item_get_etag(item));
201 | const char tmp[] = "Something item2";
202 | etebase_item_set_content(item, tmp, strlen(tmp));
203 | fail_if(!strcmp(old_etag, etebase_item_get_etag(item)));
204 | free(old_etag);
205 |
206 | const EtebaseItem *items[] = { item };
207 | fail_if(etebase_item_manager_transaction(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
208 |
209 | EtebaseItemListResponse *item_list = etebase_item_manager_list(item_mgr, NULL);
210 | fail_if(!item_list);
211 | uintptr_t list_len = etebase_item_list_response_get_data_length(item_list);
212 | assert_int_eq(1, list_len);
213 |
214 | const EtebaseItem *list_items[list_len];
215 | fail_if(etebase_item_list_response_get_data(item_list, list_items));
216 | EtebaseItem *item2 = etebase_item_clone(list_items[0]);
217 | etebase_item_destroy(item2);
218 |
219 | char content2[1000];
220 | intptr_t content2_size = etebase_item_get_content(list_items[0], &content2, sizeof(content2));
221 | fail_if(content2_size < 0);
222 | assert_int_eq(content2_size, strlen(tmp));
223 | content2[content2_size] = 0;
224 | assert_str_eq(content2, tmp);
225 |
226 | EtebaseFetchOptions *fetch_options = etebase_fetch_options_new();
227 | etebase_fetch_options_set_stoken(fetch_options, etebase_item_list_response_get_stoken(item_list));
228 | EtebaseItemListResponse *item_list2 = etebase_item_manager_list(item_mgr, fetch_options);
229 |
230 | uintptr_t list_len2 = etebase_item_list_response_get_data_length(item_list2);
231 | assert_int_eq(0, list_len2);
232 |
233 | etebase_fetch_options_destroy(fetch_options);
234 | etebase_item_list_response_destroy(item_list2);
235 | etebase_item_list_response_destroy(item_list);
236 | }
237 |
238 | etebase_account_logout(etebase);
239 |
240 | etebase_item_destroy(item);
241 | etebase_item_manager_destroy(item_mgr);
242 | etebase_collection_destroy(col);
243 | etebase_collection_manager_destroy(col_mgr);
244 | etebase_account_destroy(etebase);
245 | return 0;
246 | }
247 |
248 | int
249 | test_item_deps() {
250 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
251 | EtebaseAccount *etebase = etebase_account_restore(client, TEST_USER_SESSION, NULL, 0);
252 | etebase_client_destroy(client);
253 |
254 | etebase_account_force_server_url(etebase, get_test_url());
255 | etebase_account_fetch_token(etebase);
256 |
257 | EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase);
258 | EtebaseItemMetadata *col_meta = etebase_item_metadata_new();
259 | etebase_item_metadata_set_name(col_meta, "Name");
260 | EtebaseCollection *col = etebase_collection_manager_create(col_mgr, COL_TYPE, col_meta, "", 0);
261 | etebase_item_metadata_destroy(col_meta);
262 |
263 | etebase_collection_manager_upload(col_mgr, col, NULL);
264 |
265 | EtebaseItemManager *item_mgr = etebase_collection_manager_get_item_manager(col_mgr, col);
266 | EtebaseItemMetadata *item_meta = etebase_item_metadata_new();
267 | const char item_content[] = "Item 1";
268 | EtebaseItem *item1 = etebase_item_manager_create(item_mgr, item_meta, item_content, strlen(item_content));
269 | const char item_content2[] = "Item 2";
270 | EtebaseItem *item2 = etebase_item_manager_create(item_mgr, item_meta, item_content2, strlen(item_content2));
271 | etebase_item_metadata_destroy(item_meta);
272 |
273 | {
274 | const EtebaseItem *items[] = { item1, item2 };
275 | fail_if(etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
276 | }
277 |
278 | {
279 | const char *item1_uid = etebase_item_get_uid(item1);
280 | // -> On device B:
281 | EtebaseItem *item1 = etebase_item_manager_fetch(item_mgr, item1_uid, NULL);
282 | fail_if(!item1);
283 | const char tmp[] = "Something else for item1";
284 | etebase_item_set_content(item1, tmp, strlen(tmp));
285 | const EtebaseItem *items[] = { item1 };
286 | fail_if(etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
287 | etebase_item_destroy(item1);
288 | }
289 |
290 |
291 | {
292 | // -> On device A (using the previously saved collection)
293 | const char tmp[] = "New content for item 2";
294 | etebase_item_set_content(item2, tmp, strlen(tmp));
295 |
296 | // Will both fail because item1 changed
297 | const EtebaseItem *items[] = { item2 };
298 | const EtebaseItem *deps[] = { item1 };
299 | fail_if(!etebase_item_manager_transaction_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items),
300 | deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL));
301 | fail_if(!etebase_item_manager_batch_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items),
302 | deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL));
303 |
304 | // Can even use the item in both the list and deps in batch
305 | // Will fail because item1 changed on device B
306 |
307 | const EtebaseItem *items2[] = { item1, item2 };
308 | fail_if(!etebase_item_manager_batch_deps(item_mgr, items2, ETEBASE_UTILS_C_ARRAY_LEN(items2),
309 | deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL));
310 | }
311 |
312 | etebase_account_logout(etebase);
313 |
314 | etebase_item_destroy(item2);
315 | etebase_item_destroy(item1);
316 | etebase_item_manager_destroy(item_mgr);
317 | etebase_collection_destroy(col);
318 | etebase_collection_manager_destroy(col_mgr);
319 | etebase_account_destroy(etebase);
320 | return 0;
321 | }
322 |
323 | int
324 | test_bad_auth() {
325 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
326 | {
327 | EtebaseAccount *etebase = etebase_account_login(client, "non-existent", "passward");
328 | fail_if(etebase);
329 | assert_int_eq(ETEBASE_ERROR_CODE_UNAUTHORIZED, etebase_error_get_code());
330 | }
331 | {
332 | EtebaseAccount *etebase = etebase_account_login(client, "test_user", "bad-passward");
333 | fail_if(etebase);
334 | assert_int_eq(ETEBASE_ERROR_CODE_UNAUTHORIZED, etebase_error_get_code());
335 | }
336 |
337 | EtebaseAccount *etebase = etebase_account_restore(client, TEST_USER_SESSION, NULL, 0);
338 | etebase_client_destroy(client);
339 |
340 | etebase_account_force_server_url(etebase, get_test_url());
341 | etebase_account_fetch_token(etebase);
342 | etebase_account_logout(etebase);
343 |
344 | EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase);
345 |
346 | EtebaseCollectionListResponse *col_list = etebase_collection_manager_list(col_mgr, COL_TYPE, NULL);
347 | fail_if(col_list);
348 | assert_int_eq(ETEBASE_ERROR_CODE_UNAUTHORIZED, etebase_error_get_code());
349 |
350 | etebase_collection_manager_destroy(col_mgr);
351 | etebase_account_destroy(etebase);
352 | return 0;
353 | }
354 |
355 | int
356 | test_collection_transactions() {
357 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
358 | EtebaseAccount *etebase = etebase_account_restore(client, TEST_USER_SESSION, NULL, 0);
359 | etebase_client_destroy(client);
360 |
361 | etebase_account_force_server_url(etebase, get_test_url());
362 | etebase_account_fetch_token(etebase);
363 |
364 | EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase);
365 | EtebaseItemMetadata *col_meta = etebase_item_metadata_new();
366 | etebase_item_metadata_set_name(col_meta, "Name");
367 | EtebaseCollection *col = etebase_collection_manager_create(col_mgr, COL_TYPE, col_meta, "", 0);
368 | etebase_item_metadata_destroy(col_meta);
369 |
370 | etebase_collection_manager_upload(col_mgr, col, NULL);
371 |
372 | const char *col_uid = etebase_collection_get_uid(col);
373 | {
374 | // -> On device A:
375 | EtebaseCollection *col = etebase_collection_manager_fetch(col_mgr, col_uid, NULL);
376 |
377 |
378 | {
379 | // -> On device B:
380 | EtebaseCollection *col = etebase_collection_manager_fetch(col_mgr, col_uid, NULL);
381 | EtebaseItemMetadata *col_meta = etebase_collection_get_meta(col);
382 | etebase_item_metadata_set_name(col_meta, "New name");
383 | etebase_collection_set_meta(col, col_meta);
384 | etebase_item_metadata_destroy(col_meta);
385 |
386 | etebase_collection_manager_upload(col_mgr, col, NULL);
387 |
388 | etebase_collection_destroy(col);
389 | }
390 |
391 |
392 | // -> On device A (using the previously saved collection)
393 | EtebaseItemMetadata *col_meta = etebase_collection_get_meta(col);
394 | etebase_item_metadata_set_name(col_meta, "Another name");
395 | etebase_collection_set_meta(col, col_meta);
396 | etebase_item_metadata_destroy(col_meta);
397 |
398 | // Will fail
399 | fail_if(!etebase_collection_manager_transaction(col_mgr, col, NULL));
400 | // Will succeed
401 | fail_if(etebase_collection_manager_upload(col_mgr, col, NULL));
402 |
403 | etebase_collection_destroy(col);
404 | }
405 |
406 | // Using stoken
407 | {
408 | // -> On device A:
409 | EtebaseCollection *col = etebase_collection_manager_fetch(col_mgr, col_uid, NULL);
410 | const char *stoken = etebase_collection_get_stoken(col);
411 |
412 | {
413 | // -> On device B:
414 | EtebaseCollection *col = etebase_collection_manager_fetch(col_mgr, col_uid, NULL);
415 | EtebaseItemManager *item_mgr = etebase_collection_manager_get_item_manager(col_mgr, col);
416 | {
417 | EtebaseItemMetadata *item_meta = etebase_item_metadata_new();
418 | etebase_item_metadata_set_name(item_meta, "Name");
419 | EtebaseItem *item = etebase_item_manager_create(item_mgr, item_meta, NULL, 0);
420 | etebase_item_metadata_destroy(item_meta);
421 | {
422 | const EtebaseItem *items[] = { item };
423 | fail_if(etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
424 | }
425 | etebase_item_destroy(item);
426 | }
427 |
428 | etebase_item_manager_destroy(item_mgr);
429 | etebase_collection_destroy(col);
430 | }
431 |
432 | // -> On device A (using the previously saved collection)
433 | EtebaseItemMetadata *col_meta = etebase_collection_get_meta(col);
434 | etebase_item_metadata_set_name(col_meta, "Another name");
435 | etebase_collection_set_meta(col, col_meta);
436 | etebase_item_metadata_destroy(col_meta);
437 |
438 | // Will both fail
439 | EtebaseFetchOptions *fetch_options = etebase_fetch_options_new();
440 | etebase_fetch_options_set_stoken(fetch_options, stoken);
441 | fail_if(!etebase_collection_manager_transaction(col_mgr, col, fetch_options));
442 | fail_if(!etebase_collection_manager_upload(col_mgr, col, fetch_options));
443 | etebase_fetch_options_destroy(fetch_options);
444 | // Will both succeed
445 | fail_if(etebase_collection_manager_transaction(col_mgr, col, NULL));
446 | // Previous one fail_if(etebase_collection_manager_upload(col_mgr, col, NULL));
447 |
448 | etebase_collection_destroy(col);
449 | }
450 |
451 |
452 | etebase_account_logout(etebase);
453 |
454 | etebase_collection_destroy(col);
455 | etebase_collection_manager_destroy(col_mgr);
456 | etebase_account_destroy(etebase);
457 | return 0;
458 | }
459 |
460 | int
461 | test_items_transactions() {
462 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
463 | EtebaseAccount *etebase = etebase_account_restore(client, TEST_USER_SESSION, NULL, 0);
464 | etebase_client_destroy(client);
465 |
466 | etebase_account_force_server_url(etebase, get_test_url());
467 | etebase_account_fetch_token(etebase);
468 |
469 | EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase);
470 | EtebaseItemMetadata *col_meta = etebase_item_metadata_new();
471 | etebase_item_metadata_set_name(col_meta, "Name");
472 | EtebaseCollection *col = etebase_collection_manager_create(col_mgr, COL_TYPE, col_meta, "", 0);
473 | etebase_item_metadata_destroy(col_meta);
474 |
475 | etebase_collection_manager_upload(col_mgr, col, NULL);
476 | char *stoken;
477 | {
478 | EtebaseCollection *col2 = etebase_collection_manager_fetch(col_mgr, etebase_collection_get_uid(col), NULL);
479 | stoken = strdup(etebase_collection_get_stoken(col2));
480 | etebase_collection_destroy(col2);
481 | }
482 |
483 | EtebaseItemManager *item_mgr = etebase_collection_manager_get_item_manager(col_mgr, col);
484 |
485 | EtebaseItemMetadata *item_meta = etebase_item_metadata_new();
486 | etebase_item_metadata_set_name(item_meta, "Item 1");
487 | EtebaseItem *item1 = etebase_item_manager_create(item_mgr, item_meta, "", 0);
488 | etebase_item_metadata_set_name(item_meta, "Item 2");
489 | EtebaseItem *item2 = etebase_item_manager_create(item_mgr, item_meta, "", 0);
490 | etebase_item_metadata_destroy(item_meta);
491 |
492 | const EtebaseItem *items[] = { item1, item2 };
493 | fail_if(etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
494 |
495 | char *item1_uid = strdup(etebase_item_get_uid(item1));
496 | char *item2_uid = strdup(etebase_item_get_uid(item2));
497 | {
498 | // -> On device A:
499 | EtebaseItem *item1 = etebase_item_manager_fetch(item_mgr, item1_uid, NULL);
500 | EtebaseItem *item2 = etebase_item_manager_fetch(item_mgr, item2_uid, NULL);
501 |
502 | {
503 | // -> On device B:
504 | EtebaseItem *item1 = etebase_item_manager_fetch(item_mgr, item1_uid, NULL);
505 | const char tmp[] = "Something else for item 1";
506 | etebase_item_set_content(item1, tmp, strlen(tmp));
507 |
508 | const EtebaseItem *items[] = { item1 };
509 | etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL);
510 |
511 | etebase_item_destroy(item1);
512 | }
513 |
514 |
515 | // -> On device A (using the previously saved item)
516 | const char tmp[] = "New content for item 1";
517 | etebase_item_set_content(item1, tmp, strlen(tmp));
518 | const char tmp2[] = "New content for item 2";
519 | etebase_item_set_content(item2, tmp2, strlen(tmp2));
520 |
521 | // Will fail because item1 changed on device B
522 | const EtebaseItem *items[] = { item1, item2 };
523 | fail_if(!etebase_item_manager_transaction(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
524 | // Will succeed
525 | fail_if(etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
526 | // Will succeed because item2 hasn't changed on device B
527 | // const EtebaseItem *items2[] = { item2 };
528 | // fail_if(etebase_item_manager_transaction(item_mgr, items2, ETEBASE_UTILS_C_ARRAY_LEN(items2), NULL));
529 |
530 | etebase_item_destroy(item2);
531 | etebase_item_destroy(item1);
532 | }
533 |
534 | const char *item_uid = item1_uid;
535 | const char *another_item_uid = item2_uid;
536 | // Using stoken
537 | {
538 | // -> On device A:
539 | EtebaseItem *item = etebase_item_manager_fetch(item_mgr, item_uid, NULL);
540 |
541 | {
542 | // -> On device B:
543 | EtebaseItem *another_item = etebase_item_manager_fetch(item_mgr, another_item_uid, NULL);
544 | const char tmp[] = "content for another item";
545 | etebase_item_set_content(item1, tmp, strlen(tmp));
546 |
547 | const EtebaseItem *items[] = { another_item };
548 | etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL);
549 |
550 | etebase_item_destroy(another_item);
551 | }
552 |
553 |
554 | // -> On device A (using the previously saved item and stoken)
555 | const char tmp[] = "new secret content";
556 | etebase_item_set_content(item, tmp, strlen(tmp));
557 |
558 |
559 | // Will both fail
560 | EtebaseFetchOptions *fetch_options = etebase_fetch_options_new();
561 | etebase_fetch_options_set_stoken(fetch_options, stoken);
562 | const EtebaseItem *items[] = { item };
563 | fail_if(!etebase_item_manager_transaction(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), fetch_options));
564 | fail_if(!etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), fetch_options));
565 |
566 | etebase_fetch_options_destroy(fetch_options);
567 |
568 | // Will both succeed
569 | fail_if(etebase_item_manager_transaction(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
570 | // fail_if(etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
571 |
572 | etebase_item_destroy(item);
573 | }
574 |
575 | // Additional dependencies
576 | {
577 | // -> On device A:
578 | EtebaseItem *item1 = etebase_item_manager_fetch(item_mgr, item1_uid, NULL);
579 | EtebaseItem *item2 = etebase_item_manager_fetch(item_mgr, item2_uid, NULL);
580 |
581 |
582 | {
583 | // -> On device B:
584 | EtebaseItem *item1 = etebase_item_manager_fetch(item_mgr, item1_uid, NULL);
585 | const char tmp[] = "Something else for item 1";
586 | etebase_item_set_content(item1, tmp, strlen(tmp));
587 |
588 | const EtebaseItem *items[] = { item1 };
589 | etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL);
590 |
591 | etebase_item_destroy(item1);
592 | }
593 |
594 |
595 | // -> On device A (using the previously saved collection)
596 | const char tmp2[] = "New content for item 2";
597 | etebase_item_set_content(item2, tmp2, strlen(tmp2));
598 |
599 | // Will both fail because item1 changed
600 | {
601 | const EtebaseItem *items[] = { item2 };
602 | const EtebaseItem *deps[] = { item1 };
603 | fail_if(!etebase_item_manager_batch_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL));
604 | fail_if(!etebase_item_manager_transaction_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL));
605 | }
606 |
607 | // Can even use the item in both the list and deps in batch
608 | // Will fail because item1 changed on device B
609 | const EtebaseItem *items[] = { item1, item2 };
610 | const EtebaseItem *deps[] = { item1 };
611 | fail_if(!etebase_item_manager_batch_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL));
612 |
613 | etebase_item_destroy(item2);
614 | etebase_item_destroy(item1);
615 | }
616 |
617 | free(item2_uid);
618 | free(item1_uid);
619 |
620 | free(stoken);
621 |
622 | etebase_account_logout(etebase);
623 |
624 | etebase_item_destroy(item2);
625 | etebase_item_destroy(item1);
626 | etebase_item_manager_destroy(item_mgr);
627 | etebase_collection_destroy(col);
628 | etebase_collection_manager_destroy(col_mgr);
629 | etebase_account_destroy(etebase);
630 | return 0;
631 | }
632 |
633 | int
634 | test_collection_as_item() {
635 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
636 | EtebaseAccount *etebase = etebase_account_restore(client, TEST_USER_SESSION, NULL, 0);
637 | etebase_client_destroy(client);
638 |
639 | etebase_account_force_server_url(etebase, get_test_url());
640 | etebase_account_fetch_token(etebase);
641 |
642 | EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase);
643 | EtebaseItemMetadata *col_meta = etebase_item_metadata_new();
644 | etebase_item_metadata_set_name(col_meta, "Name");
645 | EtebaseCollection *col = etebase_collection_manager_create(col_mgr, COL_TYPE, col_meta, "", 0);
646 | etebase_item_metadata_destroy(col_meta);
647 |
648 | etebase_collection_manager_upload(col_mgr, col, NULL);
649 |
650 | EtebaseItemManager *item_mgr = etebase_collection_manager_get_item_manager(col_mgr, col);
651 |
652 | EtebaseItemMetadata *item_meta = etebase_item_metadata_new();
653 | etebase_item_metadata_set_name(item_meta, "Item 1");
654 | EtebaseItem *item1 = etebase_item_manager_create(item_mgr, item_meta, "", 0);
655 | etebase_item_metadata_set_name(item_meta, "Item 2");
656 | EtebaseItem *item2 = etebase_item_manager_create(item_mgr, item_meta, "", 0);
657 | etebase_item_metadata_destroy(item_meta);
658 |
659 | char *item1_uid = strdup(etebase_item_get_uid(item1));
660 | char *item2_uid = strdup(etebase_item_get_uid(item2));
661 | {
662 | // Get the item out of the collection
663 | EtebaseItem *col_item = etebase_collection_as_item(col);
664 |
665 | // The collection item can then be used like any other item:
666 | {
667 | const EtebaseItem *items[] = { col_item, item1 };
668 | const EtebaseItem *deps[] = { item2 };
669 | fail_if(!etebase_item_manager_transaction_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items),
670 | deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL));
671 | }
672 | {
673 | const EtebaseItem *items[] = { item1, item2 };
674 | const EtebaseItem *deps[] = { col_item };
675 | fail_if(etebase_item_manager_transaction_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items),
676 | deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL));
677 | }
678 | {
679 | const EtebaseItem *items[] = { col_item, item1 };
680 | fail_if(!etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
681 | }
682 |
683 | // In addition, these are true:
684 | assert_int_eq(etebase_collection_get_meta_raw(col, NULL, 0), etebase_item_get_meta_raw(col_item, NULL, 0));
685 | assert_int_eq(etebase_collection_get_content(col, NULL, 0), etebase_item_get_content(col_item, NULL, 0));
686 |
687 | etebase_item_destroy(col_item);
688 | }
689 |
690 | free(item2_uid);
691 | free(item1_uid);
692 |
693 | etebase_account_logout(etebase);
694 |
695 | etebase_item_destroy(item2);
696 | etebase_item_destroy(item1);
697 | etebase_item_manager_destroy(item_mgr);
698 | etebase_collection_destroy(col);
699 | etebase_collection_manager_destroy(col_mgr);
700 | etebase_account_destroy(etebase);
701 | return 0;
702 | }
703 |
704 | int
705 | test_item_revisions() {
706 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
707 | EtebaseAccount *etebase = etebase_account_restore(client, TEST_USER_SESSION, NULL, 0);
708 | etebase_client_destroy(client);
709 |
710 | etebase_account_force_server_url(etebase, get_test_url());
711 | etebase_account_fetch_token(etebase);
712 |
713 | EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase);
714 | EtebaseItemMetadata *col_meta = etebase_item_metadata_new();
715 | etebase_item_metadata_set_name(col_meta, "Name");
716 | EtebaseCollection *col = etebase_collection_manager_create(col_mgr, COL_TYPE, col_meta, "", 0);
717 | etebase_item_metadata_destroy(col_meta);
718 |
719 | etebase_collection_manager_upload(col_mgr, col, NULL);
720 |
721 | EtebaseItemManager *item_mgr = etebase_collection_manager_get_item_manager(col_mgr, col);
722 |
723 | EtebaseItemMetadata *item_meta = etebase_item_metadata_new();
724 | etebase_item_metadata_set_item_type(item_meta, "file");
725 | const char item_content[] = "First draft";
726 | EtebaseItem *item = etebase_item_manager_create(item_mgr, item_meta, item_content, strlen(item_content));
727 | etebase_item_metadata_destroy(item_meta);
728 |
729 | const EtebaseItem *items[] = { item };
730 | fail_if(etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
731 |
732 | {
733 | const char tmp[] = "Second draft";
734 | etebase_item_set_content(item, tmp, strlen(tmp));
735 |
736 | const EtebaseItem *items[] = { item };
737 | fail_if(etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL));
738 | }
739 |
740 | EtebaseItemRevisionsListResponse *revisions = etebase_item_manager_item_revisions(item_mgr, item, NULL);
741 |
742 | uintptr_t list_len = etebase_item_revisions_list_response_get_data_length(revisions);
743 | assert_int_eq(2, list_len);
744 |
745 | {
746 | // Revisions are normal items so we can use them as such
747 | const EtebaseItem *list_items[list_len];
748 | fail_if(etebase_item_revisions_list_response_get_data(revisions, list_items));
749 | char content2[100];
750 | intptr_t content2_size = etebase_item_get_content(list_items[1], &content2, sizeof(content2));
751 | content2[content2_size] = 0;
752 | assert_str_eq(content2, "First draft");
753 | }
754 |
755 | etebase_item_revisions_list_response_destroy(revisions);
756 |
757 | etebase_account_logout(etebase);
758 |
759 | etebase_item_destroy(item);
760 | etebase_item_manager_destroy(item_mgr);
761 | etebase_collection_destroy(col);
762 | etebase_collection_manager_destroy(col_mgr);
763 | etebase_account_destroy(etebase);
764 | return 0;
765 | }
766 |
767 | int
768 | test_basic_invitations() {
769 | EtebaseClient *client = etebase_client_new("libetebase-test", get_test_url());
770 | EtebaseAccount *etebase = etebase_account_restore(client, TEST_USER_SESSION, NULL, 0);
771 | etebase_client_destroy(client);
772 |
773 | etebase_account_force_server_url(etebase, get_test_url());
774 | etebase_account_fetch_token(etebase);
775 |
776 | EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase);
777 | EtebaseItemMetadata *col_meta = etebase_item_metadata_new();
778 | etebase_item_metadata_set_name(col_meta, "Name");
779 | EtebaseCollection *col = etebase_collection_manager_create(col_mgr, COL_TYPE, col_meta, "", 0);
780 | etebase_item_metadata_destroy(col_meta);
781 |
782 | etebase_collection_manager_upload(col_mgr, col, NULL);
783 |
784 | EtebaseCollectionInvitationManager *invitation_manager = etebase_account_get_invitation_manager(etebase);
785 |
786 | // Fetch their public key
787 | EtebaseUserProfile *user2 = etebase_invitation_manager_fetch_user_profile(invitation_manager, "test_user2");
788 | fail_if(!user2);
789 |
790 | // Verify user2.pubkey is indeed the pubkey you expect.
791 | // This is done in a secure channel (e.g. encrypted chat or in person)
792 |
793 | // Assuming the pubkey is as expected, send the invitation
794 | fail_if(etebase_invitation_manager_invite(invitation_manager, col, "test_user2", etebase_user_profile_get_pubkey(user2), etebase_user_profile_get_pubkey_size(user2), ETEBASE_COLLECTION_ACCESS_LEVEL_READ_ONLY));
795 |
796 | {
797 | EtebaseCollectionMemberManager *member_manager = etebase_collection_manager_get_member_manager(col_mgr, col);
798 |
799 | EtebaseMemberListResponse *members = etebase_collection_member_manager_list(member_manager, NULL);
800 |
801 | uintptr_t data_len = etebase_member_list_response_get_data_length(members);
802 | const EtebaseCollectionMember *data[data_len];
803 | etebase_member_list_response_get_data(members, data);
804 |
805 | // Print the users and their access levels
806 | const EtebaseCollectionMember *member = data[0];
807 | assert_str_eq("test_user", etebase_collection_member_get_username(member));
808 | assert_int_eq(ETEBASE_COLLECTION_ACCESS_LEVEL_ADMIN, etebase_collection_member_get_access_level(member));
809 |
810 | etebase_member_list_response_destroy(members);
811 | etebase_collection_member_manager_destroy(member_manager);
812 | }
813 |
814 | etebase_user_profile_destroy(user2);
815 | etebase_invitation_manager_destroy(invitation_manager);
816 |
817 | etebase_account_logout(etebase);
818 |
819 | etebase_collection_destroy(col);
820 | etebase_collection_manager_destroy(col_mgr);
821 | etebase_account_destroy(etebase);
822 | return 0;
823 | }
824 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "ansi_term"
7 | version = "0.12.1"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
10 | dependencies = [
11 | "winapi",
12 | ]
13 |
14 | [[package]]
15 | name = "atty"
16 | version = "0.2.14"
17 | source = "registry+https://github.com/rust-lang/crates.io-index"
18 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
19 | dependencies = [
20 | "hermit-abi",
21 | "libc",
22 | "winapi",
23 | ]
24 |
25 | [[package]]
26 | name = "autocfg"
27 | version = "1.1.0"
28 | source = "registry+https://github.com/rust-lang/crates.io-index"
29 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
30 |
31 | [[package]]
32 | name = "base64"
33 | version = "0.13.0"
34 | source = "registry+https://github.com/rust-lang/crates.io-index"
35 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
36 |
37 | [[package]]
38 | name = "bitflags"
39 | version = "1.3.2"
40 | source = "registry+https://github.com/rust-lang/crates.io-index"
41 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
42 |
43 | [[package]]
44 | name = "bumpalo"
45 | version = "3.9.1"
46 | source = "registry+https://github.com/rust-lang/crates.io-index"
47 | checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
48 |
49 | [[package]]
50 | name = "byteorder"
51 | version = "1.4.3"
52 | source = "registry+https://github.com/rust-lang/crates.io-index"
53 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
54 |
55 | [[package]]
56 | name = "bytes"
57 | version = "1.1.0"
58 | source = "registry+https://github.com/rust-lang/crates.io-index"
59 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
60 |
61 | [[package]]
62 | name = "cbindgen"
63 | version = "0.14.3"
64 | source = "registry+https://github.com/rust-lang/crates.io-index"
65 | checksum = "e6e03a705df2e735cc5486f104a48e25a8f72ae06eaea5b7753a81270ed00859"
66 | dependencies = [
67 | "clap",
68 | "heck",
69 | "log",
70 | "proc-macro2",
71 | "quote",
72 | "serde",
73 | "serde_json",
74 | "syn",
75 | "tempfile",
76 | "toml",
77 | ]
78 |
79 | [[package]]
80 | name = "cc"
81 | version = "1.0.73"
82 | source = "registry+https://github.com/rust-lang/crates.io-index"
83 | checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
84 |
85 | [[package]]
86 | name = "cfg-if"
87 | version = "1.0.0"
88 | source = "registry+https://github.com/rust-lang/crates.io-index"
89 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
90 |
91 | [[package]]
92 | name = "clap"
93 | version = "2.34.0"
94 | source = "registry+https://github.com/rust-lang/crates.io-index"
95 | checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
96 | dependencies = [
97 | "ansi_term",
98 | "atty",
99 | "bitflags",
100 | "strsim",
101 | "textwrap",
102 | "unicode-width",
103 | "vec_map",
104 | ]
105 |
106 | [[package]]
107 | name = "core-foundation"
108 | version = "0.9.3"
109 | source = "registry+https://github.com/rust-lang/crates.io-index"
110 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
111 | dependencies = [
112 | "core-foundation-sys",
113 | "libc",
114 | ]
115 |
116 | [[package]]
117 | name = "core-foundation-sys"
118 | version = "0.8.3"
119 | source = "registry+https://github.com/rust-lang/crates.io-index"
120 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
121 |
122 | [[package]]
123 | name = "crossbeam-channel"
124 | version = "0.5.4"
125 | source = "registry+https://github.com/rust-lang/crates.io-index"
126 | checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53"
127 | dependencies = [
128 | "cfg-if",
129 | "crossbeam-utils",
130 | ]
131 |
132 | [[package]]
133 | name = "crossbeam-deque"
134 | version = "0.8.1"
135 | source = "registry+https://github.com/rust-lang/crates.io-index"
136 | checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
137 | dependencies = [
138 | "cfg-if",
139 | "crossbeam-epoch",
140 | "crossbeam-utils",
141 | ]
142 |
143 | [[package]]
144 | name = "crossbeam-epoch"
145 | version = "0.9.8"
146 | source = "registry+https://github.com/rust-lang/crates.io-index"
147 | checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c"
148 | dependencies = [
149 | "autocfg",
150 | "cfg-if",
151 | "crossbeam-utils",
152 | "lazy_static",
153 | "memoffset",
154 | "scopeguard",
155 | ]
156 |
157 | [[package]]
158 | name = "crossbeam-utils"
159 | version = "0.8.8"
160 | source = "registry+https://github.com/rust-lang/crates.io-index"
161 | checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38"
162 | dependencies = [
163 | "cfg-if",
164 | "lazy_static",
165 | ]
166 |
167 | [[package]]
168 | name = "ed25519"
169 | version = "1.4.1"
170 | source = "registry+https://github.com/rust-lang/crates.io-index"
171 | checksum = "3d5c4b5e5959dc2c2b89918d8e2cc40fcdd623cef026ed09d2f0ee05199dc8e4"
172 | dependencies = [
173 | "signature",
174 | ]
175 |
176 | [[package]]
177 | name = "either"
178 | version = "1.6.1"
179 | source = "registry+https://github.com/rust-lang/crates.io-index"
180 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
181 |
182 | [[package]]
183 | name = "encoding_rs"
184 | version = "0.8.30"
185 | source = "registry+https://github.com/rust-lang/crates.io-index"
186 | checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df"
187 | dependencies = [
188 | "cfg-if",
189 | ]
190 |
191 | [[package]]
192 | name = "etebase"
193 | version = "0.5.3"
194 | source = "registry+https://github.com/rust-lang/crates.io-index"
195 | checksum = "dcbba1b6712a7e6f6c7a3b2c2aea88d4bd3fc3e3e1a642ebc4b8a97de6753a27"
196 | dependencies = [
197 | "libsodium-sys",
198 | "remove_dir_all 0.6.1",
199 | "reqwest",
200 | "rmp-serde",
201 | "serde",
202 | "serde_bytes",
203 | "serde_repr",
204 | "sodiumoxide",
205 | "url",
206 | ]
207 |
208 | [[package]]
209 | name = "fastrand"
210 | version = "1.7.0"
211 | source = "registry+https://github.com/rust-lang/crates.io-index"
212 | checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
213 | dependencies = [
214 | "instant",
215 | ]
216 |
217 | [[package]]
218 | name = "fnv"
219 | version = "1.0.7"
220 | source = "registry+https://github.com/rust-lang/crates.io-index"
221 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
222 |
223 | [[package]]
224 | name = "foreign-types"
225 | version = "0.3.2"
226 | source = "registry+https://github.com/rust-lang/crates.io-index"
227 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
228 | dependencies = [
229 | "foreign-types-shared",
230 | ]
231 |
232 | [[package]]
233 | name = "foreign-types-shared"
234 | version = "0.1.1"
235 | source = "registry+https://github.com/rust-lang/crates.io-index"
236 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
237 |
238 | [[package]]
239 | name = "form_urlencoded"
240 | version = "1.0.1"
241 | source = "registry+https://github.com/rust-lang/crates.io-index"
242 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
243 | dependencies = [
244 | "matches",
245 | "percent-encoding",
246 | ]
247 |
248 | [[package]]
249 | name = "futures-channel"
250 | version = "0.3.21"
251 | source = "registry+https://github.com/rust-lang/crates.io-index"
252 | checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
253 | dependencies = [
254 | "futures-core",
255 | ]
256 |
257 | [[package]]
258 | name = "futures-core"
259 | version = "0.3.21"
260 | source = "registry+https://github.com/rust-lang/crates.io-index"
261 | checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
262 |
263 | [[package]]
264 | name = "futures-io"
265 | version = "0.3.21"
266 | source = "registry+https://github.com/rust-lang/crates.io-index"
267 | checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
268 |
269 | [[package]]
270 | name = "futures-sink"
271 | version = "0.3.21"
272 | source = "registry+https://github.com/rust-lang/crates.io-index"
273 | checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
274 |
275 | [[package]]
276 | name = "futures-task"
277 | version = "0.3.21"
278 | source = "registry+https://github.com/rust-lang/crates.io-index"
279 | checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
280 |
281 | [[package]]
282 | name = "futures-util"
283 | version = "0.3.21"
284 | source = "registry+https://github.com/rust-lang/crates.io-index"
285 | checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
286 | dependencies = [
287 | "futures-core",
288 | "futures-io",
289 | "futures-task",
290 | "memchr",
291 | "pin-project-lite",
292 | "pin-utils",
293 | "slab",
294 | ]
295 |
296 | [[package]]
297 | name = "h2"
298 | version = "0.3.12"
299 | source = "registry+https://github.com/rust-lang/crates.io-index"
300 | checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b"
301 | dependencies = [
302 | "bytes",
303 | "fnv",
304 | "futures-core",
305 | "futures-sink",
306 | "futures-util",
307 | "http",
308 | "indexmap",
309 | "slab",
310 | "tokio",
311 | "tokio-util",
312 | "tracing",
313 | ]
314 |
315 | [[package]]
316 | name = "hashbrown"
317 | version = "0.11.2"
318 | source = "registry+https://github.com/rust-lang/crates.io-index"
319 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
320 |
321 | [[package]]
322 | name = "heck"
323 | version = "0.3.3"
324 | source = "registry+https://github.com/rust-lang/crates.io-index"
325 | checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
326 | dependencies = [
327 | "unicode-segmentation",
328 | ]
329 |
330 | [[package]]
331 | name = "hermit-abi"
332 | version = "0.1.19"
333 | source = "registry+https://github.com/rust-lang/crates.io-index"
334 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
335 | dependencies = [
336 | "libc",
337 | ]
338 |
339 | [[package]]
340 | name = "http"
341 | version = "0.2.6"
342 | source = "registry+https://github.com/rust-lang/crates.io-index"
343 | checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
344 | dependencies = [
345 | "bytes",
346 | "fnv",
347 | "itoa",
348 | ]
349 |
350 | [[package]]
351 | name = "http-body"
352 | version = "0.4.4"
353 | source = "registry+https://github.com/rust-lang/crates.io-index"
354 | checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
355 | dependencies = [
356 | "bytes",
357 | "http",
358 | "pin-project-lite",
359 | ]
360 |
361 | [[package]]
362 | name = "httparse"
363 | version = "1.6.0"
364 | source = "registry+https://github.com/rust-lang/crates.io-index"
365 | checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4"
366 |
367 | [[package]]
368 | name = "httpdate"
369 | version = "1.0.2"
370 | source = "registry+https://github.com/rust-lang/crates.io-index"
371 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
372 |
373 | [[package]]
374 | name = "hyper"
375 | version = "0.14.18"
376 | source = "registry+https://github.com/rust-lang/crates.io-index"
377 | checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2"
378 | dependencies = [
379 | "bytes",
380 | "futures-channel",
381 | "futures-core",
382 | "futures-util",
383 | "h2",
384 | "http",
385 | "http-body",
386 | "httparse",
387 | "httpdate",
388 | "itoa",
389 | "pin-project-lite",
390 | "socket2",
391 | "tokio",
392 | "tower-service",
393 | "tracing",
394 | "want",
395 | ]
396 |
397 | [[package]]
398 | name = "hyper-tls"
399 | version = "0.5.0"
400 | source = "registry+https://github.com/rust-lang/crates.io-index"
401 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
402 | dependencies = [
403 | "bytes",
404 | "hyper",
405 | "native-tls",
406 | "tokio",
407 | "tokio-native-tls",
408 | ]
409 |
410 | [[package]]
411 | name = "idna"
412 | version = "0.2.3"
413 | source = "registry+https://github.com/rust-lang/crates.io-index"
414 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
415 | dependencies = [
416 | "matches",
417 | "unicode-bidi",
418 | "unicode-normalization",
419 | ]
420 |
421 | [[package]]
422 | name = "indexmap"
423 | version = "1.8.1"
424 | source = "registry+https://github.com/rust-lang/crates.io-index"
425 | checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
426 | dependencies = [
427 | "autocfg",
428 | "hashbrown",
429 | ]
430 |
431 | [[package]]
432 | name = "instant"
433 | version = "0.1.12"
434 | source = "registry+https://github.com/rust-lang/crates.io-index"
435 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
436 | dependencies = [
437 | "cfg-if",
438 | ]
439 |
440 | [[package]]
441 | name = "ipnet"
442 | version = "2.4.0"
443 | source = "registry+https://github.com/rust-lang/crates.io-index"
444 | checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c"
445 |
446 | [[package]]
447 | name = "itoa"
448 | version = "1.0.1"
449 | source = "registry+https://github.com/rust-lang/crates.io-index"
450 | checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
451 |
452 | [[package]]
453 | name = "js-sys"
454 | version = "0.3.56"
455 | source = "registry+https://github.com/rust-lang/crates.io-index"
456 | checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
457 | dependencies = [
458 | "wasm-bindgen",
459 | ]
460 |
461 | [[package]]
462 | name = "lazy_static"
463 | version = "1.4.0"
464 | source = "registry+https://github.com/rust-lang/crates.io-index"
465 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
466 |
467 | [[package]]
468 | name = "libc"
469 | version = "0.2.121"
470 | source = "registry+https://github.com/rust-lang/crates.io-index"
471 | checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
472 |
473 | [[package]]
474 | name = "libetebase"
475 | version = "0.5.3"
476 | dependencies = [
477 | "cbindgen",
478 | "etebase",
479 | ]
480 |
481 | [[package]]
482 | name = "libsodium-sys"
483 | version = "0.2.7"
484 | source = "registry+https://github.com/rust-lang/crates.io-index"
485 | checksum = "6b779387cd56adfbc02ea4a668e704f729be8d6a6abd2c27ca5ee537849a92fd"
486 | dependencies = [
487 | "cc",
488 | "libc",
489 | "pkg-config",
490 | "walkdir",
491 | ]
492 |
493 | [[package]]
494 | name = "log"
495 | version = "0.4.16"
496 | source = "registry+https://github.com/rust-lang/crates.io-index"
497 | checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
498 | dependencies = [
499 | "cfg-if",
500 | ]
501 |
502 | [[package]]
503 | name = "matches"
504 | version = "0.1.9"
505 | source = "registry+https://github.com/rust-lang/crates.io-index"
506 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
507 |
508 | [[package]]
509 | name = "memchr"
510 | version = "2.4.1"
511 | source = "registry+https://github.com/rust-lang/crates.io-index"
512 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
513 |
514 | [[package]]
515 | name = "memoffset"
516 | version = "0.6.5"
517 | source = "registry+https://github.com/rust-lang/crates.io-index"
518 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
519 | dependencies = [
520 | "autocfg",
521 | ]
522 |
523 | [[package]]
524 | name = "mime"
525 | version = "0.3.16"
526 | source = "registry+https://github.com/rust-lang/crates.io-index"
527 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
528 |
529 | [[package]]
530 | name = "mio"
531 | version = "0.8.2"
532 | source = "registry+https://github.com/rust-lang/crates.io-index"
533 | checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
534 | dependencies = [
535 | "libc",
536 | "log",
537 | "miow",
538 | "ntapi",
539 | "wasi",
540 | "winapi",
541 | ]
542 |
543 | [[package]]
544 | name = "miow"
545 | version = "0.3.7"
546 | source = "registry+https://github.com/rust-lang/crates.io-index"
547 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
548 | dependencies = [
549 | "winapi",
550 | ]
551 |
552 | [[package]]
553 | name = "native-tls"
554 | version = "0.2.10"
555 | source = "registry+https://github.com/rust-lang/crates.io-index"
556 | checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
557 | dependencies = [
558 | "lazy_static",
559 | "libc",
560 | "log",
561 | "openssl",
562 | "openssl-probe",
563 | "openssl-sys",
564 | "schannel",
565 | "security-framework",
566 | "security-framework-sys",
567 | "tempfile",
568 | ]
569 |
570 | [[package]]
571 | name = "ntapi"
572 | version = "0.3.7"
573 | source = "registry+https://github.com/rust-lang/crates.io-index"
574 | checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
575 | dependencies = [
576 | "winapi",
577 | ]
578 |
579 | [[package]]
580 | name = "num-traits"
581 | version = "0.2.14"
582 | source = "registry+https://github.com/rust-lang/crates.io-index"
583 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
584 | dependencies = [
585 | "autocfg",
586 | ]
587 |
588 | [[package]]
589 | name = "num_cpus"
590 | version = "1.13.1"
591 | source = "registry+https://github.com/rust-lang/crates.io-index"
592 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
593 | dependencies = [
594 | "hermit-abi",
595 | "libc",
596 | ]
597 |
598 | [[package]]
599 | name = "once_cell"
600 | version = "1.10.0"
601 | source = "registry+https://github.com/rust-lang/crates.io-index"
602 | checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
603 |
604 | [[package]]
605 | name = "openssl"
606 | version = "0.10.38"
607 | source = "registry+https://github.com/rust-lang/crates.io-index"
608 | checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
609 | dependencies = [
610 | "bitflags",
611 | "cfg-if",
612 | "foreign-types",
613 | "libc",
614 | "once_cell",
615 | "openssl-sys",
616 | ]
617 |
618 | [[package]]
619 | name = "openssl-probe"
620 | version = "0.1.5"
621 | source = "registry+https://github.com/rust-lang/crates.io-index"
622 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
623 |
624 | [[package]]
625 | name = "openssl-sys"
626 | version = "0.9.72"
627 | source = "registry+https://github.com/rust-lang/crates.io-index"
628 | checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
629 | dependencies = [
630 | "autocfg",
631 | "cc",
632 | "libc",
633 | "pkg-config",
634 | "vcpkg",
635 | ]
636 |
637 | [[package]]
638 | name = "percent-encoding"
639 | version = "2.1.0"
640 | source = "registry+https://github.com/rust-lang/crates.io-index"
641 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
642 |
643 | [[package]]
644 | name = "pin-project-lite"
645 | version = "0.2.8"
646 | source = "registry+https://github.com/rust-lang/crates.io-index"
647 | checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
648 |
649 | [[package]]
650 | name = "pin-utils"
651 | version = "0.1.0"
652 | source = "registry+https://github.com/rust-lang/crates.io-index"
653 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
654 |
655 | [[package]]
656 | name = "pkg-config"
657 | version = "0.3.25"
658 | source = "registry+https://github.com/rust-lang/crates.io-index"
659 | checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
660 |
661 | [[package]]
662 | name = "proc-macro2"
663 | version = "1.0.36"
664 | source = "registry+https://github.com/rust-lang/crates.io-index"
665 | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
666 | dependencies = [
667 | "unicode-xid",
668 | ]
669 |
670 | [[package]]
671 | name = "quote"
672 | version = "1.0.17"
673 | source = "registry+https://github.com/rust-lang/crates.io-index"
674 | checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
675 | dependencies = [
676 | "proc-macro2",
677 | ]
678 |
679 | [[package]]
680 | name = "rayon"
681 | version = "1.5.1"
682 | source = "registry+https://github.com/rust-lang/crates.io-index"
683 | checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
684 | dependencies = [
685 | "autocfg",
686 | "crossbeam-deque",
687 | "either",
688 | "rayon-core",
689 | ]
690 |
691 | [[package]]
692 | name = "rayon-core"
693 | version = "1.9.1"
694 | source = "registry+https://github.com/rust-lang/crates.io-index"
695 | checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
696 | dependencies = [
697 | "crossbeam-channel",
698 | "crossbeam-deque",
699 | "crossbeam-utils",
700 | "lazy_static",
701 | "num_cpus",
702 | ]
703 |
704 | [[package]]
705 | name = "redox_syscall"
706 | version = "0.2.13"
707 | source = "registry+https://github.com/rust-lang/crates.io-index"
708 | checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
709 | dependencies = [
710 | "bitflags",
711 | ]
712 |
713 | [[package]]
714 | name = "remove_dir_all"
715 | version = "0.5.3"
716 | source = "registry+https://github.com/rust-lang/crates.io-index"
717 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
718 | dependencies = [
719 | "winapi",
720 | ]
721 |
722 | [[package]]
723 | name = "remove_dir_all"
724 | version = "0.6.1"
725 | source = "registry+https://github.com/rust-lang/crates.io-index"
726 | checksum = "d7b19f5c2df95a07275e7224924cc62f76f04525f4fda801473f85e325e81977"
727 | dependencies = [
728 | "log",
729 | "num_cpus",
730 | "rayon",
731 | "winapi",
732 | ]
733 |
734 | [[package]]
735 | name = "reqwest"
736 | version = "0.11.10"
737 | source = "registry+https://github.com/rust-lang/crates.io-index"
738 | checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb"
739 | dependencies = [
740 | "base64",
741 | "bytes",
742 | "encoding_rs",
743 | "futures-core",
744 | "futures-util",
745 | "h2",
746 | "http",
747 | "http-body",
748 | "hyper",
749 | "hyper-tls",
750 | "ipnet",
751 | "js-sys",
752 | "lazy_static",
753 | "log",
754 | "mime",
755 | "native-tls",
756 | "percent-encoding",
757 | "pin-project-lite",
758 | "serde",
759 | "serde_json",
760 | "serde_urlencoded",
761 | "tokio",
762 | "tokio-native-tls",
763 | "url",
764 | "wasm-bindgen",
765 | "wasm-bindgen-futures",
766 | "web-sys",
767 | "winreg",
768 | ]
769 |
770 | [[package]]
771 | name = "rmp"
772 | version = "0.8.10"
773 | source = "registry+https://github.com/rust-lang/crates.io-index"
774 | checksum = "4f55e5fa1446c4d5dd1f5daeed2a4fe193071771a2636274d0d7a3b082aa7ad6"
775 | dependencies = [
776 | "byteorder",
777 | "num-traits",
778 | ]
779 |
780 | [[package]]
781 | name = "rmp-serde"
782 | version = "1.0.0"
783 | source = "registry+https://github.com/rust-lang/crates.io-index"
784 | checksum = "f3eedffbfcc6a428f230c04baf8f59bd73c1781361e4286111fe900849aaddaf"
785 | dependencies = [
786 | "byteorder",
787 | "rmp",
788 | "serde",
789 | ]
790 |
791 | [[package]]
792 | name = "ryu"
793 | version = "1.0.9"
794 | source = "registry+https://github.com/rust-lang/crates.io-index"
795 | checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
796 |
797 | [[package]]
798 | name = "same-file"
799 | version = "1.0.6"
800 | source = "registry+https://github.com/rust-lang/crates.io-index"
801 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
802 | dependencies = [
803 | "winapi-util",
804 | ]
805 |
806 | [[package]]
807 | name = "schannel"
808 | version = "0.1.19"
809 | source = "registry+https://github.com/rust-lang/crates.io-index"
810 | checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
811 | dependencies = [
812 | "lazy_static",
813 | "winapi",
814 | ]
815 |
816 | [[package]]
817 | name = "scopeguard"
818 | version = "1.1.0"
819 | source = "registry+https://github.com/rust-lang/crates.io-index"
820 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
821 |
822 | [[package]]
823 | name = "security-framework"
824 | version = "2.6.1"
825 | source = "registry+https://github.com/rust-lang/crates.io-index"
826 | checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc"
827 | dependencies = [
828 | "bitflags",
829 | "core-foundation",
830 | "core-foundation-sys",
831 | "libc",
832 | "security-framework-sys",
833 | ]
834 |
835 | [[package]]
836 | name = "security-framework-sys"
837 | version = "2.6.1"
838 | source = "registry+https://github.com/rust-lang/crates.io-index"
839 | checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
840 | dependencies = [
841 | "core-foundation-sys",
842 | "libc",
843 | ]
844 |
845 | [[package]]
846 | name = "serde"
847 | version = "1.0.136"
848 | source = "registry+https://github.com/rust-lang/crates.io-index"
849 | checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
850 | dependencies = [
851 | "serde_derive",
852 | ]
853 |
854 | [[package]]
855 | name = "serde_bytes"
856 | version = "0.11.5"
857 | source = "registry+https://github.com/rust-lang/crates.io-index"
858 | checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9"
859 | dependencies = [
860 | "serde",
861 | ]
862 |
863 | [[package]]
864 | name = "serde_derive"
865 | version = "1.0.136"
866 | source = "registry+https://github.com/rust-lang/crates.io-index"
867 | checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
868 | dependencies = [
869 | "proc-macro2",
870 | "quote",
871 | "syn",
872 | ]
873 |
874 | [[package]]
875 | name = "serde_json"
876 | version = "1.0.79"
877 | source = "registry+https://github.com/rust-lang/crates.io-index"
878 | checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
879 | dependencies = [
880 | "itoa",
881 | "ryu",
882 | "serde",
883 | ]
884 |
885 | [[package]]
886 | name = "serde_repr"
887 | version = "0.1.7"
888 | source = "registry+https://github.com/rust-lang/crates.io-index"
889 | checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5"
890 | dependencies = [
891 | "proc-macro2",
892 | "quote",
893 | "syn",
894 | ]
895 |
896 | [[package]]
897 | name = "serde_urlencoded"
898 | version = "0.7.1"
899 | source = "registry+https://github.com/rust-lang/crates.io-index"
900 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
901 | dependencies = [
902 | "form_urlencoded",
903 | "itoa",
904 | "ryu",
905 | "serde",
906 | ]
907 |
908 | [[package]]
909 | name = "signature"
910 | version = "1.5.0"
911 | source = "registry+https://github.com/rust-lang/crates.io-index"
912 | checksum = "f054c6c1a6e95179d6f23ed974060dcefb2d9388bb7256900badad682c499de4"
913 |
914 | [[package]]
915 | name = "slab"
916 | version = "0.4.5"
917 | source = "registry+https://github.com/rust-lang/crates.io-index"
918 | checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
919 |
920 | [[package]]
921 | name = "socket2"
922 | version = "0.4.4"
923 | source = "registry+https://github.com/rust-lang/crates.io-index"
924 | checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
925 | dependencies = [
926 | "libc",
927 | "winapi",
928 | ]
929 |
930 | [[package]]
931 | name = "sodiumoxide"
932 | version = "0.2.7"
933 | source = "registry+https://github.com/rust-lang/crates.io-index"
934 | checksum = "e26be3acb6c2d9a7aac28482586a7856436af4cfe7100031d219de2d2ecb0028"
935 | dependencies = [
936 | "ed25519",
937 | "libc",
938 | "libsodium-sys",
939 | "serde",
940 | ]
941 |
942 | [[package]]
943 | name = "strsim"
944 | version = "0.8.0"
945 | source = "registry+https://github.com/rust-lang/crates.io-index"
946 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
947 |
948 | [[package]]
949 | name = "syn"
950 | version = "1.0.90"
951 | source = "registry+https://github.com/rust-lang/crates.io-index"
952 | checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f"
953 | dependencies = [
954 | "proc-macro2",
955 | "quote",
956 | "unicode-xid",
957 | ]
958 |
959 | [[package]]
960 | name = "tempfile"
961 | version = "3.3.0"
962 | source = "registry+https://github.com/rust-lang/crates.io-index"
963 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
964 | dependencies = [
965 | "cfg-if",
966 | "fastrand",
967 | "libc",
968 | "redox_syscall",
969 | "remove_dir_all 0.5.3",
970 | "winapi",
971 | ]
972 |
973 | [[package]]
974 | name = "textwrap"
975 | version = "0.11.0"
976 | source = "registry+https://github.com/rust-lang/crates.io-index"
977 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
978 | dependencies = [
979 | "unicode-width",
980 | ]
981 |
982 | [[package]]
983 | name = "tinyvec"
984 | version = "1.5.1"
985 | source = "registry+https://github.com/rust-lang/crates.io-index"
986 | checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
987 | dependencies = [
988 | "tinyvec_macros",
989 | ]
990 |
991 | [[package]]
992 | name = "tinyvec_macros"
993 | version = "0.1.0"
994 | source = "registry+https://github.com/rust-lang/crates.io-index"
995 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
996 |
997 | [[package]]
998 | name = "tokio"
999 | version = "1.17.0"
1000 | source = "registry+https://github.com/rust-lang/crates.io-index"
1001 | checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
1002 | dependencies = [
1003 | "bytes",
1004 | "libc",
1005 | "memchr",
1006 | "mio",
1007 | "num_cpus",
1008 | "pin-project-lite",
1009 | "socket2",
1010 | "winapi",
1011 | ]
1012 |
1013 | [[package]]
1014 | name = "tokio-native-tls"
1015 | version = "0.3.0"
1016 | source = "registry+https://github.com/rust-lang/crates.io-index"
1017 | checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
1018 | dependencies = [
1019 | "native-tls",
1020 | "tokio",
1021 | ]
1022 |
1023 | [[package]]
1024 | name = "tokio-util"
1025 | version = "0.6.9"
1026 | source = "registry+https://github.com/rust-lang/crates.io-index"
1027 | checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
1028 | dependencies = [
1029 | "bytes",
1030 | "futures-core",
1031 | "futures-sink",
1032 | "log",
1033 | "pin-project-lite",
1034 | "tokio",
1035 | ]
1036 |
1037 | [[package]]
1038 | name = "toml"
1039 | version = "0.5.8"
1040 | source = "registry+https://github.com/rust-lang/crates.io-index"
1041 | checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
1042 | dependencies = [
1043 | "serde",
1044 | ]
1045 |
1046 | [[package]]
1047 | name = "tower-service"
1048 | version = "0.3.1"
1049 | source = "registry+https://github.com/rust-lang/crates.io-index"
1050 | checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
1051 |
1052 | [[package]]
1053 | name = "tracing"
1054 | version = "0.1.32"
1055 | source = "registry+https://github.com/rust-lang/crates.io-index"
1056 | checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
1057 | dependencies = [
1058 | "cfg-if",
1059 | "pin-project-lite",
1060 | "tracing-core",
1061 | ]
1062 |
1063 | [[package]]
1064 | name = "tracing-core"
1065 | version = "0.1.23"
1066 | source = "registry+https://github.com/rust-lang/crates.io-index"
1067 | checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c"
1068 | dependencies = [
1069 | "lazy_static",
1070 | ]
1071 |
1072 | [[package]]
1073 | name = "try-lock"
1074 | version = "0.2.3"
1075 | source = "registry+https://github.com/rust-lang/crates.io-index"
1076 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
1077 |
1078 | [[package]]
1079 | name = "unicode-bidi"
1080 | version = "0.3.7"
1081 | source = "registry+https://github.com/rust-lang/crates.io-index"
1082 | checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
1083 |
1084 | [[package]]
1085 | name = "unicode-normalization"
1086 | version = "0.1.19"
1087 | source = "registry+https://github.com/rust-lang/crates.io-index"
1088 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
1089 | dependencies = [
1090 | "tinyvec",
1091 | ]
1092 |
1093 | [[package]]
1094 | name = "unicode-segmentation"
1095 | version = "1.9.0"
1096 | source = "registry+https://github.com/rust-lang/crates.io-index"
1097 | checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
1098 |
1099 | [[package]]
1100 | name = "unicode-width"
1101 | version = "0.1.9"
1102 | source = "registry+https://github.com/rust-lang/crates.io-index"
1103 | checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
1104 |
1105 | [[package]]
1106 | name = "unicode-xid"
1107 | version = "0.2.2"
1108 | source = "registry+https://github.com/rust-lang/crates.io-index"
1109 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
1110 |
1111 | [[package]]
1112 | name = "url"
1113 | version = "2.2.2"
1114 | source = "registry+https://github.com/rust-lang/crates.io-index"
1115 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
1116 | dependencies = [
1117 | "form_urlencoded",
1118 | "idna",
1119 | "matches",
1120 | "percent-encoding",
1121 | ]
1122 |
1123 | [[package]]
1124 | name = "vcpkg"
1125 | version = "0.2.15"
1126 | source = "registry+https://github.com/rust-lang/crates.io-index"
1127 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
1128 |
1129 | [[package]]
1130 | name = "vec_map"
1131 | version = "0.8.2"
1132 | source = "registry+https://github.com/rust-lang/crates.io-index"
1133 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
1134 |
1135 | [[package]]
1136 | name = "walkdir"
1137 | version = "2.3.2"
1138 | source = "registry+https://github.com/rust-lang/crates.io-index"
1139 | checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
1140 | dependencies = [
1141 | "same-file",
1142 | "winapi",
1143 | "winapi-util",
1144 | ]
1145 |
1146 | [[package]]
1147 | name = "want"
1148 | version = "0.3.0"
1149 | source = "registry+https://github.com/rust-lang/crates.io-index"
1150 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
1151 | dependencies = [
1152 | "log",
1153 | "try-lock",
1154 | ]
1155 |
1156 | [[package]]
1157 | name = "wasi"
1158 | version = "0.11.0+wasi-snapshot-preview1"
1159 | source = "registry+https://github.com/rust-lang/crates.io-index"
1160 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
1161 |
1162 | [[package]]
1163 | name = "wasm-bindgen"
1164 | version = "0.2.79"
1165 | source = "registry+https://github.com/rust-lang/crates.io-index"
1166 | checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
1167 | dependencies = [
1168 | "cfg-if",
1169 | "wasm-bindgen-macro",
1170 | ]
1171 |
1172 | [[package]]
1173 | name = "wasm-bindgen-backend"
1174 | version = "0.2.79"
1175 | source = "registry+https://github.com/rust-lang/crates.io-index"
1176 | checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
1177 | dependencies = [
1178 | "bumpalo",
1179 | "lazy_static",
1180 | "log",
1181 | "proc-macro2",
1182 | "quote",
1183 | "syn",
1184 | "wasm-bindgen-shared",
1185 | ]
1186 |
1187 | [[package]]
1188 | name = "wasm-bindgen-futures"
1189 | version = "0.4.29"
1190 | source = "registry+https://github.com/rust-lang/crates.io-index"
1191 | checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395"
1192 | dependencies = [
1193 | "cfg-if",
1194 | "js-sys",
1195 | "wasm-bindgen",
1196 | "web-sys",
1197 | ]
1198 |
1199 | [[package]]
1200 | name = "wasm-bindgen-macro"
1201 | version = "0.2.79"
1202 | source = "registry+https://github.com/rust-lang/crates.io-index"
1203 | checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
1204 | dependencies = [
1205 | "quote",
1206 | "wasm-bindgen-macro-support",
1207 | ]
1208 |
1209 | [[package]]
1210 | name = "wasm-bindgen-macro-support"
1211 | version = "0.2.79"
1212 | source = "registry+https://github.com/rust-lang/crates.io-index"
1213 | checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
1214 | dependencies = [
1215 | "proc-macro2",
1216 | "quote",
1217 | "syn",
1218 | "wasm-bindgen-backend",
1219 | "wasm-bindgen-shared",
1220 | ]
1221 |
1222 | [[package]]
1223 | name = "wasm-bindgen-shared"
1224 | version = "0.2.79"
1225 | source = "registry+https://github.com/rust-lang/crates.io-index"
1226 | checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
1227 |
1228 | [[package]]
1229 | name = "web-sys"
1230 | version = "0.3.56"
1231 | source = "registry+https://github.com/rust-lang/crates.io-index"
1232 | checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
1233 | dependencies = [
1234 | "js-sys",
1235 | "wasm-bindgen",
1236 | ]
1237 |
1238 | [[package]]
1239 | name = "winapi"
1240 | version = "0.3.9"
1241 | source = "registry+https://github.com/rust-lang/crates.io-index"
1242 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1243 | dependencies = [
1244 | "winapi-i686-pc-windows-gnu",
1245 | "winapi-x86_64-pc-windows-gnu",
1246 | ]
1247 |
1248 | [[package]]
1249 | name = "winapi-i686-pc-windows-gnu"
1250 | version = "0.4.0"
1251 | source = "registry+https://github.com/rust-lang/crates.io-index"
1252 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1253 |
1254 | [[package]]
1255 | name = "winapi-util"
1256 | version = "0.1.5"
1257 | source = "registry+https://github.com/rust-lang/crates.io-index"
1258 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
1259 | dependencies = [
1260 | "winapi",
1261 | ]
1262 |
1263 | [[package]]
1264 | name = "winapi-x86_64-pc-windows-gnu"
1265 | version = "0.4.0"
1266 | source = "registry+https://github.com/rust-lang/crates.io-index"
1267 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1268 |
1269 | [[package]]
1270 | name = "winreg"
1271 | version = "0.10.1"
1272 | source = "registry+https://github.com/rust-lang/crates.io-index"
1273 | checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
1274 | dependencies = [
1275 | "winapi",
1276 | ]
1277 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: © 2020 Etebase Authors
2 | // SPDX-License-Identifier: LGPL-2.1-only
3 |
4 | #![allow(non_camel_case_types)]
5 |
6 | use std::cell::RefCell;
7 | use std::os::raw::{c_char, c_void};
8 | use std::ffi::{CString, CStr};
9 | use std::path::PathBuf;
10 |
11 | use etebase::{
12 | DEFAULT_SERVER_URL,
13 |
14 | Client,
15 | User,
16 | Account,
17 |
18 | Collection,
19 | Item,
20 | ItemMetadata,
21 |
22 | CollectionAccessLevel,
23 | SignedInvitation,
24 | CollectionMember,
25 | RemovedCollection,
26 |
27 | UserProfile,
28 |
29 | fs_cache::FileSystemCache,
30 |
31 | error::Error,
32 | managers::{
33 | CollectionManager,
34 | ItemManager,
35 | CollectionInvitationManager,
36 | CollectionMemberManager,
37 | },
38 | };
39 |
40 | macro_rules! try_or_null {
41 | ($x:expr) => {
42 | match $x {
43 | Ok(val) => val,
44 | Err(err) => {
45 | update_last_error(Error::from(err));
46 | return std::ptr::null_mut();
47 | }
48 | };
49 | };
50 | }
51 |
52 | macro_rules! try_or_int {
53 | ($x:expr) => {
54 | match $x {
55 | Ok(val) => val,
56 | Err(err) => {
57 | update_last_error(Error::from(err));
58 | return -1;
59 | }
60 | };
61 | };
62 | }
63 |
64 | fn ptr_to_option(val: *const T) -> Option<*const T> {
65 | if val.is_null() {
66 | None
67 | } else {
68 | Some(val)
69 | }
70 | }
71 |
72 | thread_local! {
73 | static LAST_ERROR: RefCell