From c0d1c4d85f969d652508d63816f65315ae18cd7e Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" Date: Wed, 21 Feb 2024 17:40:43 +0000 Subject: Deploy mate-desktop/caja-dropbox to github.com/mate-desktop/caja-dropbox.git:gh-pages --- .../index.html | 97 + .../report-7ad019.html | 1225 +++++++++++ .../report-8893d3.html | 1225 +++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 849 ++++++++ .../1.html | 2169 +++++++++++++++++++ .../index.html | 126 ++ .../stats.html | 111 + .../style.css | 137 ++ .../index.html | 97 + .../report-58010e.html | 1225 +++++++++++ .../report-685866.html | 1225 +++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 849 ++++++++ .../1.html | 2169 +++++++++++++++++++ .../index.html | 126 ++ .../stats.html | 111 + .../style.css | 137 ++ .../index.html | 97 + .../report-0cf114.html | 1225 +++++++++++ .../report-63011c.html | 1225 +++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 2169 +++++++++++++++++++ .../index.html | 122 ++ .../stats.html | 108 + .../style.css | 137 ++ .../index.html | 97 + .../report-51813c.html | 1225 +++++++++++ .../report-b2c20b.html | 1225 +++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 2169 +++++++++++++++++++ .../index.html | 122 ++ .../stats.html | 108 + .../style.css | 137 ++ .../index.html | 94 + .../report-1b9128.html | 1553 ++++++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 2231 +++++++++++++++++++ .../index.html | 202 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 94 + .../report-1b9128.html | 1553 ++++++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 2231 +++++++++++++++++++ .../index.html | 202 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 94 + .../report-1b9128.html | 1553 ++++++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 2231 +++++++++++++++++++ .../index.html | 202 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 94 + .../report-1b9128.html | 1553 ++++++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 2231 +++++++++++++++++++ .../index.html | 202 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 94 + .../report-1b9128.html | 1553 ++++++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 2233 ++++++++++++++++++++ .../index.html | 202 ++ .../stats.html | 170 ++ .../style.css | 177 ++ .../index.html | 94 + .../report-1b9128.html | 1553 ++++++++++++++ .../scanview.css | 62 + .../sorttable.js | 492 +++++ .../0.html | 911 ++++++++ .../1.html | 335 +++ .../10.html | 1983 +++++++++++++++++ .../11.html | 345 +++ .../2.html | 367 ++++ .../3.html | 315 +++ .../4.html | 395 ++++ .../5.html | 2233 ++++++++++++++++++++ .../6.html | 463 ++++ .../7.html | 373 ++++ .../8.html | 389 ++++ .../9.html | 585 +++++ .../index.html | 274 +++ .../stats.html | 183 ++ .../style.css | 177 ++ CNAME | 1 + index.html | 47 + 99 files changed, 60744 insertions(+) create mode 100644 2021-05-29-193455-5826-1@8f5bcb5e8b30_master/index.html create mode 100644 2021-05-29-193455-5826-1@8f5bcb5e8b30_master/report-7ad019.html create mode 100644 2021-05-29-193455-5826-1@8f5bcb5e8b30_master/report-8893d3.html create mode 100644 2021-05-29-193455-5826-1@8f5bcb5e8b30_master/scanview.css create mode 100644 2021-05-29-193455-5826-1@8f5bcb5e8b30_master/sorttable.js create mode 100644 2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/0.html create mode 100644 2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/1.html create mode 100644 2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/index.html create mode 100644 2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/stats.html create mode 100644 2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/style.css create mode 100644 2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/index.html create mode 100644 2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/report-58010e.html create mode 100644 2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/report-685866.html create mode 100644 2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/scanview.css create mode 100644 2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/sorttable.js create mode 100644 2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/0.html create mode 100644 2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/1.html create mode 100644 2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/index.html create mode 100644 2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/stats.html create mode 100644 2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/style.css create mode 100644 2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/index.html create mode 100644 2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/report-0cf114.html create mode 100644 2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/report-63011c.html create mode 100644 2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/scanview.css create mode 100644 2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/sorttable.js create mode 100644 2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/0.html create mode 100644 2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/index.html create mode 100644 2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/stats.html create mode 100644 2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/style.css create mode 100644 2022-02-12-111711-5932-1@f4453b2d7fce_master/index.html create mode 100644 2022-02-12-111711-5932-1@f4453b2d7fce_master/report-51813c.html create mode 100644 2022-02-12-111711-5932-1@f4453b2d7fce_master/report-b2c20b.html create mode 100644 2022-02-12-111711-5932-1@f4453b2d7fce_master/scanview.css create mode 100644 2022-02-12-111711-5932-1@f4453b2d7fce_master/sorttable.js create mode 100644 2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/0.html create mode 100644 2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/index.html create mode 100644 2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/stats.html create mode 100644 2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/style.css create mode 100644 2022-10-29-140736-5910-1@8ec754ff8335_master/index.html create mode 100644 2022-10-29-140736-5910-1@8ec754ff8335_master/report-1b9128.html create mode 100644 2022-10-29-140736-5910-1@8ec754ff8335_master/scanview.css create mode 100644 2022-10-29-140736-5910-1@8ec754ff8335_master/sorttable.js create mode 100644 2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/0.html create mode 100644 2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/index.html create mode 100644 2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/stats.html create mode 100644 2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/style.css create mode 100644 2022-11-10-210649-5786-1@ea7b890d9702_master/index.html create mode 100644 2022-11-10-210649-5786-1@ea7b890d9702_master/report-1b9128.html create mode 100644 2022-11-10-210649-5786-1@ea7b890d9702_master/scanview.css create mode 100644 2022-11-10-210649-5786-1@ea7b890d9702_master/sorttable.js create mode 100644 2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/0.html create mode 100644 2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/index.html create mode 100644 2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/stats.html create mode 100644 2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/style.css create mode 100644 2022-11-11-213923-5771-1@21f8797d992b_master/index.html create mode 100644 2022-11-11-213923-5771-1@21f8797d992b_master/report-1b9128.html create mode 100644 2022-11-11-213923-5771-1@21f8797d992b_master/scanview.css create mode 100644 2022-11-11-213923-5771-1@21f8797d992b_master/sorttable.js create mode 100644 2022-11-11-213937-8071-cppcheck@21f8797d992b_master/0.html create mode 100644 2022-11-11-213937-8071-cppcheck@21f8797d992b_master/index.html create mode 100644 2022-11-11-213937-8071-cppcheck@21f8797d992b_master/stats.html create mode 100644 2022-11-11-213937-8071-cppcheck@21f8797d992b_master/style.css create mode 100644 2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/index.html create mode 100644 2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/report-1b9128.html create mode 100644 2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/scanview.css create mode 100644 2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/sorttable.js create mode 100644 2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/0.html create mode 100644 2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/index.html create mode 100644 2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/stats.html create mode 100644 2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/style.css create mode 100644 2023-04-16-220119-5762-1@a4dac3d0ebf8_master/index.html create mode 100644 2023-04-16-220119-5762-1@a4dac3d0ebf8_master/report-1b9128.html create mode 100644 2023-04-16-220119-5762-1@a4dac3d0ebf8_master/scanview.css create mode 100644 2023-04-16-220119-5762-1@a4dac3d0ebf8_master/sorttable.js create mode 100644 2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/0.html create mode 100644 2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/index.html create mode 100644 2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/stats.html create mode 100644 2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/style.css create mode 100644 2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/index.html create mode 100644 2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/report-1b9128.html create mode 100644 2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/scanview.css create mode 100644 2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/sorttable.js create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/0.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/1.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/10.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/11.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/2.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/3.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/4.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/5.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/6.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/7.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/8.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/9.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/index.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/stats.html create mode 100644 2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/style.css create mode 100644 CNAME create mode 100644 index.html diff --git a/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/index.html b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/index.html new file mode 100644 index 0000000..7da8101 --- /dev/null +++ b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/index.html @@ -0,0 +1,97 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@e4f2a4aebe6d
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 12.0.0 (Fedora 12.0.0-0.3.rc1.fc34) +
Date:Sat May 29 19:34:55 2021
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs2
Logic error
Cast from non-struct type to struct type2
+

Reports

+ + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/report-7ad019.html b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/report-7ad019.html new file mode 100644 index 0000000..297d58f --- /dev/null +++ b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/report-7ad019.html @@ -0,0 +1,1225 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir /rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -o /rootdir/html-report/2021-05-29-193455-5826-1 -x c dropbox-command-client.c +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/report-8893d3.html b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/report-8893d3.html new file mode 100644 index 0000000..b670096 --- /dev/null +++ b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/report-8893d3.html @@ -0,0 +1,1225 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir /rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -o /rootdir/html-report/2021-05-29-193455-5826-1 -x c dropbox-command-client.c +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/scanview.css b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/sorttable.js b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2021-05-29-193455-5826-1@8f5bcb5e8b30_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox-hooks.c
+ * Implements connection handling and C interface for the Dropbox hook socket.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <string.h>
+
+#include <glib.h>
+
+#include "g-util.h"
+#include "async-io-coroutine.h"
+#include "dropbox-client-util.h"
+#include "caja-dropbox-hooks.h"
+
+typedef struct {
+  DropboxUpdateHook hook;
+  gpointer ud;
+} HookData;
+
+static gboolean
+try_to_connect(CajaDropboxHookserv *hookserv);
+
+static gboolean
+handle_hook_server_input(GIOChannel *chan,
+			 GIOCondition cond,
+			 CajaDropboxHookserv *hookserv) {
+  /*debug_enter(); */
+
+  /* we have some sweet macros defined that allow us to write this
+     async event handler like a microthread yeahh, watch out for context */
+  CRBEGIN(hookserv->hhsi.line);
+  while (1) {
+    hookserv->hhsi.command_args =
+      g_hash_table_new_full((GHashFunc) g_str_hash,
+			    (GEqualFunc) g_str_equal,
+			    (GDestroyNotify) g_free,
+			    (GDestroyNotify) g_strfreev);
+    hookserv->hhsi.numargs = 0;
+
+    /* read the command name */
+    {
+      gchar *line;
+      CRREADLINE(hookserv->hhsi.line, chan, line);
+      hookserv->hhsi.command_name = dropbox_client_util_desanitize(line);<--- Uninitialized variable: line
+      g_free(line);
+    }
+
+    /*debug("got a hook name: %s", hookserv->hhsi.command_name); */
+
+    /* now read each arg line (until a certain limit) until we receive "done" */
+    while (1) {
+      gchar *line;
+
+      /* if too many arguments, this connection seems malicious */
+      if (hookserv->hhsi.numargs >= 20) {<--- Assuming condition is false
+	CRHALT;
+      }
+
+      CRREADLINE(hookserv->hhsi.line, chan, line);
+
+      if (strcmp("done", line) == 0) {<--- Uninitialized variable: line
+	g_free(line);
+	break;
+      }
+      else {
+	gboolean parse_result;
+
+	parse_result =
+	  dropbox_client_util_command_parse_arg(line,
+						hookserv->hhsi.command_args);
+	g_free(line);
+
+	if (FALSE == parse_result) {
+	  debug("bad parse");
+	  CRHALT;
+	}
+      }
+
+      hookserv->hhsi.numargs += 1;
+    }
+
+    {
+      HookData *hd;
+      hd = (HookData *)
+	g_hash_table_lookup(hookserv->dispatch_table,
+			    hookserv->hhsi.command_name);
+      if (hd != NULL) {
+	(hd->hook)(hookserv->hhsi.command_args, hd->ud);
+      }
+    }
+
+    g_free(hookserv->hhsi.command_name);
+    g_hash_table_unref(hookserv->hhsi.command_args);
+    hookserv->hhsi.command_name = NULL;
+    hookserv->hhsi.command_args = NULL;
+  }
+  CREND;
+}
+
+static void
+watch_killer(CajaDropboxHookserv *hookserv) {
+  debug("hook client disconnected");
+
+  hookserv->connected = FALSE;
+
+  g_hook_list_invoke(&(hookserv->ondisconnect_hooklist), FALSE);
+
+  /* we basically just have to free the memory allocated in the
+     handle_hook_server_init ctx */
+  if (hookserv->hhsi.command_name != NULL) {
+    g_free(hookserv->hhsi.command_name);
+    hookserv->hhsi.command_name = NULL;
+  }
+
+  if (hookserv->hhsi.command_args != NULL) {
+    g_hash_table_unref(hookserv->hhsi.command_args);
+    hookserv->hhsi.command_args = NULL;
+  }
+
+  g_io_channel_unref(hookserv->chan);
+  hookserv->chan = NULL;
+  hookserv->event_source = 0;
+  hookserv->socket = 0;
+
+  /* lol we also have to start a new connection */
+  try_to_connect(hookserv);
+}
+
+static gboolean
+try_to_connect(CajaDropboxHookserv *hookserv) {
+  /* create socket */
+  hookserv->socket = socket(PF_UNIX, SOCK_STREAM, 0);
+
+  /* set native non-blocking, for connect timeout */
+  {
+    int flags;
+
+    if ((flags = fcntl(hookserv->socket, F_GETFL, 0)) < 0) {
+      goto FAIL_CLEANUP;
+    }
+
+    if (fcntl(hookserv->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
+      goto FAIL_CLEANUP;
+    }
+  }
+
+  /* connect to server, might fail of course */
+  {
+    struct sockaddr_un addr;
+    socklen_t addr_len;
+
+    /* intialize address structure */
+    addr.sun_family = AF_UNIX;
+    g_snprintf(addr.sun_path,
+	       sizeof(addr.sun_path),
+	       "%s/.dropbox/iface_socket",
+	       g_get_home_dir());
+    addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
+
+    /* if there was an error we have to try again later */
+    if (connect(hookserv->socket, (struct sockaddr *) &addr, addr_len) < 0) {
+      if (errno == EINPROGRESS) {
+	fd_set writers;
+	struct timeval tv = {1, 0};
+        FD_ZERO(&writers);
+	FD_SET(hookserv->socket, &writers);
+
+	/* if nothing was ready after 3 seconds, fail out homie */
+	if (select(hookserv->socket+1, NULL, &writers, NULL, &tv) == 0) {
+	  goto FAIL_CLEANUP;
+	}
+
+	if (connect(hookserv->socket, (struct sockaddr *) &addr, addr_len) < 0) {
+	  debug("couldn't connect to hook server after 1 second");
+	  goto FAIL_CLEANUP;
+	}
+      }
+      else {
+	goto FAIL_CLEANUP;
+      }
+    }
+  }
+
+  /* lol sometimes i write funny codez */
+  if (FALSE) {
+  FAIL_CLEANUP:
+    close(hookserv->socket);
+    g_timeout_add_seconds(1, (GSourceFunc) try_to_connect, hookserv);
+    return FALSE;
+  }
+
+  /* great we connected!, let's create the channel and wait on it */
+  hookserv->chan = g_io_channel_unix_new(hookserv->socket);
+  g_io_channel_set_line_term(hookserv->chan, "\n", -1);
+  g_io_channel_set_close_on_unref(hookserv->chan, TRUE);
+
+  /*debug("create channel"); */
+
+  /* Set non-blocking ;) (again just in case) */
+  {
+    GIOFlags flags;
+    GIOStatus iostat;
+
+    flags = g_io_channel_get_flags(hookserv->chan);
+    iostat = g_io_channel_set_flags(hookserv->chan, flags | G_IO_FLAG_NONBLOCK,
+				    NULL);
+    if (iostat == G_IO_STATUS_ERROR) {
+      g_io_channel_unref(hookserv->chan);
+      g_timeout_add_seconds(1, (GSourceFunc) try_to_connect, hookserv);
+      return FALSE;
+    }
+  }
+
+  /*debug("set non blocking"); */
+
+  /* this is fun, async io watcher */
+  hookserv->hhsi.line = 0;
+  hookserv->hhsi.command_args = NULL;
+  hookserv->hhsi.command_name = NULL;
+  hookserv->event_source =
+    g_io_add_watch_full(hookserv->chan, G_PRIORITY_DEFAULT,
+			G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+			(GIOFunc) handle_hook_server_input, hookserv,
+			(GDestroyNotify) watch_killer);
+
+  debug("hook client connected");
+  hookserv->connected = TRUE;
+  g_hook_list_invoke(&(hookserv->onconnect_hooklist), FALSE);
+
+  /*debug("added watch");*/
+  return FALSE;
+}
+
+/* should only be called in glib main loop */
+/* returns a gboolean because it is a GSourceFunc */
+gboolean caja_dropbox_hooks_force_reconnect(CajaDropboxHookserv *hookserv) {
+  debug_enter();
+
+  if (hookserv->connected == FALSE) {
+    return FALSE;
+  }
+
+  debug("forcing hook to reconnect");
+
+  g_assert(hookserv->event_source >= 0);
+
+  if (hookserv->event_source > 0) {
+    g_source_remove(hookserv->event_source);
+  }
+  else if (hookserv->event_source == 0) {
+    debug("event source was zero!!!!!");
+  }
+
+  return FALSE;
+}
+
+gboolean
+caja_dropbox_hooks_is_connected(CajaDropboxHookserv *hookserv) {
+  return hookserv->connected;
+}
+
+void
+caja_dropbox_hooks_setup(CajaDropboxHookserv *hookserv) {
+  hookserv->dispatch_table = g_hash_table_new_full((GHashFunc) g_str_hash,
+						   (GEqualFunc) g_str_equal,
+						   g_free, g_free);
+  hookserv->connected = FALSE;
+
+  g_hook_list_init(&(hookserv->ondisconnect_hooklist), sizeof(GHook));
+  g_hook_list_init(&(hookserv->onconnect_hooklist), sizeof(GHook));
+}
+
+void
+caja_dropbox_hooks_add_on_disconnect_hook(CajaDropboxHookserv *hookserv,
+					      DropboxHookClientConnectHook dhcch,
+					      gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(hookserv->ondisconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(hookserv->ondisconnect_hooklist), newhook);
+}
+
+void
+caja_dropbox_hooks_add_on_connect_hook(CajaDropboxHookserv *hookserv,
+					   DropboxHookClientConnectHook dhcch,
+					   gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(hookserv->onconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(hookserv->onconnect_hooklist), newhook);
+}
+
+void caja_dropbox_hooks_add(CajaDropboxHookserv *ndhs,
+				const gchar *hook_name,
+				DropboxUpdateHook hook, gpointer ud) {
+  HookData *hd;
+  hd = g_new(HookData, 1);
+  hd->hook = hook;
+  hd->ud = ud;
+  g_hash_table_insert(ndhs->dispatch_table, g_strdup(hook_name), hd);
+}
+
+void
+caja_dropbox_hooks_start(CajaDropboxHookserv *hookserv) {
+  try_to_connect(hookserv);
+}
+
+
+
+
+ + + diff --git a/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/1.html b/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/1.html new file mode 100644 index 0000000..9978714 --- /dev/null +++ b/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/1.html @@ -0,0 +1,2169 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-info-provider.h>
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)<--- Assuming that condition '!emblem_paths_response' is not redundant
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+
+
+
+ + + diff --git a/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/index.html b/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/index.html new file mode 100644 index 0000000..c2b791a --- /dev/null +++ b/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/index.html @@ -0,0 +1,126 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
0missingIncludeSysteminformationCppcheck cannot find all the include files (use --check-config for details)
src/caja-dropbox-hooks.c
69uninitvar457errorUninitialized variable: line
86uninitvar457errorUninitialized variable: line
src/caja-dropbox.c
312variableScope398styleThe scope of the variable 'file' can be reduced.
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
+
+
+ + + diff --git a/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/stats.html b/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/stats.html new file mode 100644 index 0000000..c448fd4 --- /dev/null +++ b/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/stats.html @@ -0,0 +1,111 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+

Top 10 files for error severity, total findings: 2
+   2  src/caja-dropbox-hooks.c
+

+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 3
+   3  src/caja-dropbox.c
+

+ +
+
+ + + diff --git a/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/style.css b/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/style.css new file mode 100644 index 0000000..07125f4 --- /dev/null +++ b/2021-05-29-193513-5696-cppcheck@8f5bcb5e8b30_master/style.css @@ -0,0 +1,137 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +.header { + border-bottom: thin solid #aaa; +} + +.footer { + border-top: thin solid #aaa; + font-size: 90%; + margin-top: 5px; +} + +.footer ul { + list-style-type: none; + padding-left: 0; +} + +.footer > p { + margin: 4px; +} + +.wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +#menu, +#menu_index { + text-align: left; + width: 350px; + height: 90vh; + min-height: 200px; + overflow: auto; + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 0 15px 15px 15px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +#content, +#content_index { + background-color: #fff; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + padding: 0 15px 15px 15px; + width: calc(100% - 350px); + height: 100%; + overflow-x: auto; +} + +#filename { + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + z-index: 10; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.d-none { + display: none; +} diff --git a/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/index.html b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/index.html new file mode 100644 index 0000000..25d999c --- /dev/null +++ b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/index.html @@ -0,0 +1,97 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@ac58bb3bdfde
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 12.0.0 (Fedora 12.0.0-2.fc34) +
Date:Sat Jun 19 23:30:12 2021
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs2
Logic error
Cast from non-struct type to struct type2
+

Reports

+ + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/report-58010e.html b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/report-58010e.html new file mode 100644 index 0000000..2a41cc8 --- /dev/null +++ b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/report-58010e.html @@ -0,0 +1,1225 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir /rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -o /rootdir/html-report/2021-06-19-233012-5833-1 -x c dropbox-command-client.c +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/report-685866.html b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/report-685866.html new file mode 100644 index 0000000..75fb396 --- /dev/null +++ b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/report-685866.html @@ -0,0 +1,1225 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir /rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -o /rootdir/html-report/2021-06-19-233012-5833-1 -x c dropbox-command-client.c +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/scanview.css b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/sorttable.js b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2021-06-19-233012-5833-1@1dd58e57ff8d_v1.25.0/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox-hooks.c
+ * Implements connection handling and C interface for the Dropbox hook socket.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <string.h>
+
+#include <glib.h>
+
+#include "g-util.h"
+#include "async-io-coroutine.h"
+#include "dropbox-client-util.h"
+#include "caja-dropbox-hooks.h"
+
+typedef struct {
+  DropboxUpdateHook hook;
+  gpointer ud;
+} HookData;
+
+static gboolean
+try_to_connect(CajaDropboxHookserv *hookserv);
+
+static gboolean
+handle_hook_server_input(GIOChannel *chan,
+			 GIOCondition cond,
+			 CajaDropboxHookserv *hookserv) {
+  /*debug_enter(); */
+
+  /* we have some sweet macros defined that allow us to write this
+     async event handler like a microthread yeahh, watch out for context */
+  CRBEGIN(hookserv->hhsi.line);
+  while (1) {
+    hookserv->hhsi.command_args =
+      g_hash_table_new_full((GHashFunc) g_str_hash,
+			    (GEqualFunc) g_str_equal,
+			    (GDestroyNotify) g_free,
+			    (GDestroyNotify) g_strfreev);
+    hookserv->hhsi.numargs = 0;
+
+    /* read the command name */
+    {
+      gchar *line;
+      CRREADLINE(hookserv->hhsi.line, chan, line);
+      hookserv->hhsi.command_name = dropbox_client_util_desanitize(line);<--- Uninitialized variable: line
+      g_free(line);
+    }
+
+    /*debug("got a hook name: %s", hookserv->hhsi.command_name); */
+
+    /* now read each arg line (until a certain limit) until we receive "done" */
+    while (1) {
+      gchar *line;
+
+      /* if too many arguments, this connection seems malicious */
+      if (hookserv->hhsi.numargs >= 20) {<--- Assuming condition is false
+	CRHALT;
+      }
+
+      CRREADLINE(hookserv->hhsi.line, chan, line);
+
+      if (strcmp("done", line) == 0) {<--- Uninitialized variable: line
+	g_free(line);
+	break;
+      }
+      else {
+	gboolean parse_result;
+
+	parse_result =
+	  dropbox_client_util_command_parse_arg(line,
+						hookserv->hhsi.command_args);
+	g_free(line);
+
+	if (FALSE == parse_result) {
+	  debug("bad parse");
+	  CRHALT;
+	}
+      }
+
+      hookserv->hhsi.numargs += 1;
+    }
+
+    {
+      HookData *hd;
+      hd = (HookData *)
+	g_hash_table_lookup(hookserv->dispatch_table,
+			    hookserv->hhsi.command_name);
+      if (hd != NULL) {
+	(hd->hook)(hookserv->hhsi.command_args, hd->ud);
+      }
+    }
+
+    g_free(hookserv->hhsi.command_name);
+    g_hash_table_unref(hookserv->hhsi.command_args);
+    hookserv->hhsi.command_name = NULL;
+    hookserv->hhsi.command_args = NULL;
+  }
+  CREND;
+}
+
+static void
+watch_killer(CajaDropboxHookserv *hookserv) {
+  debug("hook client disconnected");
+
+  hookserv->connected = FALSE;
+
+  g_hook_list_invoke(&(hookserv->ondisconnect_hooklist), FALSE);
+
+  /* we basically just have to free the memory allocated in the
+     handle_hook_server_init ctx */
+  if (hookserv->hhsi.command_name != NULL) {
+    g_free(hookserv->hhsi.command_name);
+    hookserv->hhsi.command_name = NULL;
+  }
+
+  if (hookserv->hhsi.command_args != NULL) {
+    g_hash_table_unref(hookserv->hhsi.command_args);
+    hookserv->hhsi.command_args = NULL;
+  }
+
+  g_io_channel_unref(hookserv->chan);
+  hookserv->chan = NULL;
+  hookserv->event_source = 0;
+  hookserv->socket = 0;
+
+  /* lol we also have to start a new connection */
+  try_to_connect(hookserv);
+}
+
+static gboolean
+try_to_connect(CajaDropboxHookserv *hookserv) {
+  /* create socket */
+  hookserv->socket = socket(PF_UNIX, SOCK_STREAM, 0);
+
+  /* set native non-blocking, for connect timeout */
+  {
+    int flags;
+
+    if ((flags = fcntl(hookserv->socket, F_GETFL, 0)) < 0) {
+      goto FAIL_CLEANUP;
+    }
+
+    if (fcntl(hookserv->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
+      goto FAIL_CLEANUP;
+    }
+  }
+
+  /* connect to server, might fail of course */
+  {
+    struct sockaddr_un addr;
+    socklen_t addr_len;
+
+    /* intialize address structure */
+    addr.sun_family = AF_UNIX;
+    g_snprintf(addr.sun_path,
+	       sizeof(addr.sun_path),
+	       "%s/.dropbox/iface_socket",
+	       g_get_home_dir());
+    addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
+
+    /* if there was an error we have to try again later */
+    if (connect(hookserv->socket, (struct sockaddr *) &addr, addr_len) < 0) {
+      if (errno == EINPROGRESS) {
+	fd_set writers;
+	struct timeval tv = {1, 0};
+        FD_ZERO(&writers);
+	FD_SET(hookserv->socket, &writers);
+
+	/* if nothing was ready after 3 seconds, fail out homie */
+	if (select(hookserv->socket+1, NULL, &writers, NULL, &tv) == 0) {
+	  goto FAIL_CLEANUP;
+	}
+
+	if (connect(hookserv->socket, (struct sockaddr *) &addr, addr_len) < 0) {
+	  debug("couldn't connect to hook server after 1 second");
+	  goto FAIL_CLEANUP;
+	}
+      }
+      else {
+	goto FAIL_CLEANUP;
+      }
+    }
+  }
+
+  /* lol sometimes i write funny codez */
+  if (FALSE) {
+  FAIL_CLEANUP:
+    close(hookserv->socket);
+    g_timeout_add_seconds(1, (GSourceFunc) try_to_connect, hookserv);
+    return FALSE;
+  }
+
+  /* great we connected!, let's create the channel and wait on it */
+  hookserv->chan = g_io_channel_unix_new(hookserv->socket);
+  g_io_channel_set_line_term(hookserv->chan, "\n", -1);
+  g_io_channel_set_close_on_unref(hookserv->chan, TRUE);
+
+  /*debug("create channel"); */
+
+  /* Set non-blocking ;) (again just in case) */
+  {
+    GIOFlags flags;
+    GIOStatus iostat;
+
+    flags = g_io_channel_get_flags(hookserv->chan);
+    iostat = g_io_channel_set_flags(hookserv->chan, flags | G_IO_FLAG_NONBLOCK,
+				    NULL);
+    if (iostat == G_IO_STATUS_ERROR) {
+      g_io_channel_unref(hookserv->chan);
+      g_timeout_add_seconds(1, (GSourceFunc) try_to_connect, hookserv);
+      return FALSE;
+    }
+  }
+
+  /*debug("set non blocking"); */
+
+  /* this is fun, async io watcher */
+  hookserv->hhsi.line = 0;
+  hookserv->hhsi.command_args = NULL;
+  hookserv->hhsi.command_name = NULL;
+  hookserv->event_source =
+    g_io_add_watch_full(hookserv->chan, G_PRIORITY_DEFAULT,
+			G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+			(GIOFunc) handle_hook_server_input, hookserv,
+			(GDestroyNotify) watch_killer);
+
+  debug("hook client connected");
+  hookserv->connected = TRUE;
+  g_hook_list_invoke(&(hookserv->onconnect_hooklist), FALSE);
+
+  /*debug("added watch");*/
+  return FALSE;
+}
+
+/* should only be called in glib main loop */
+/* returns a gboolean because it is a GSourceFunc */
+gboolean caja_dropbox_hooks_force_reconnect(CajaDropboxHookserv *hookserv) {
+  debug_enter();
+
+  if (hookserv->connected == FALSE) {
+    return FALSE;
+  }
+
+  debug("forcing hook to reconnect");
+
+  g_assert(hookserv->event_source >= 0);
+
+  if (hookserv->event_source > 0) {
+    g_source_remove(hookserv->event_source);
+  }
+  else if (hookserv->event_source == 0) {
+    debug("event source was zero!!!!!");
+  }
+
+  return FALSE;
+}
+
+gboolean
+caja_dropbox_hooks_is_connected(CajaDropboxHookserv *hookserv) {
+  return hookserv->connected;
+}
+
+void
+caja_dropbox_hooks_setup(CajaDropboxHookserv *hookserv) {
+  hookserv->dispatch_table = g_hash_table_new_full((GHashFunc) g_str_hash,
+						   (GEqualFunc) g_str_equal,
+						   g_free, g_free);
+  hookserv->connected = FALSE;
+
+  g_hook_list_init(&(hookserv->ondisconnect_hooklist), sizeof(GHook));
+  g_hook_list_init(&(hookserv->onconnect_hooklist), sizeof(GHook));
+}
+
+void
+caja_dropbox_hooks_add_on_disconnect_hook(CajaDropboxHookserv *hookserv,
+					      DropboxHookClientConnectHook dhcch,
+					      gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(hookserv->ondisconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(hookserv->ondisconnect_hooklist), newhook);
+}
+
+void
+caja_dropbox_hooks_add_on_connect_hook(CajaDropboxHookserv *hookserv,
+					   DropboxHookClientConnectHook dhcch,
+					   gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(hookserv->onconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(hookserv->onconnect_hooklist), newhook);
+}
+
+void caja_dropbox_hooks_add(CajaDropboxHookserv *ndhs,
+				const gchar *hook_name,
+				DropboxUpdateHook hook, gpointer ud) {
+  HookData *hd;
+  hd = g_new(HookData, 1);
+  hd->hook = hook;
+  hd->ud = ud;
+  g_hash_table_insert(ndhs->dispatch_table, g_strdup(hook_name), hd);
+}
+
+void
+caja_dropbox_hooks_start(CajaDropboxHookserv *hookserv) {
+  try_to_connect(hookserv);
+}
+
+
+
+
+ + + diff --git a/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/1.html b/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/1.html new file mode 100644 index 0000000..9978714 --- /dev/null +++ b/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/1.html @@ -0,0 +1,2169 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-info-provider.h>
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)<--- Assuming that condition '!emblem_paths_response' is not redundant
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+
+
+
+ + + diff --git a/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/index.html b/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/index.html new file mode 100644 index 0000000..c2b791a --- /dev/null +++ b/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/index.html @@ -0,0 +1,126 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
0missingIncludeSysteminformationCppcheck cannot find all the include files (use --check-config for details)
src/caja-dropbox-hooks.c
69uninitvar457errorUninitialized variable: line
86uninitvar457errorUninitialized variable: line
src/caja-dropbox.c
312variableScope398styleThe scope of the variable 'file' can be reduced.
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
+
+
+ + + diff --git a/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/stats.html b/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/stats.html new file mode 100644 index 0000000..c448fd4 --- /dev/null +++ b/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/stats.html @@ -0,0 +1,111 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+

Top 10 files for error severity, total findings: 2
+   2  src/caja-dropbox-hooks.c
+

+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 3
+   3  src/caja-dropbox.c
+

+ +
+
+ + + diff --git a/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/style.css b/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/style.css new file mode 100644 index 0000000..07125f4 --- /dev/null +++ b/2021-06-19-233030-5559-cppcheck@1dd58e57ff8d_v1.25.0/style.css @@ -0,0 +1,137 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +.header { + border-bottom: thin solid #aaa; +} + +.footer { + border-top: thin solid #aaa; + font-size: 90%; + margin-top: 5px; +} + +.footer ul { + list-style-type: none; + padding-left: 0; +} + +.footer > p { + margin: 4px; +} + +.wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +#menu, +#menu_index { + text-align: left; + width: 350px; + height: 90vh; + min-height: 200px; + overflow: auto; + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 0 15px 15px 15px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +#content, +#content_index { + background-color: #fff; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + padding: 0 15px 15px 15px; + width: calc(100% - 350px); + height: 100%; + overflow-x: auto; +} + +#filename { + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + z-index: 10; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.d-none { + display: none; +} diff --git a/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/index.html b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/index.html new file mode 100644 index 0000000..3379de5 --- /dev/null +++ b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/index.html @@ -0,0 +1,97 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@69e851c1c553
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 12.0.0 (Fedora 12.0.0-2.fc34) +
Date:Fri Aug 6 19:09:01 2021
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs2
Logic error
Cast from non-struct type to struct type2
+

Reports

+ + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/report-0cf114.html b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/report-0cf114.html new file mode 100644 index 0000000..9db5635 --- /dev/null +++ b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/report-0cf114.html @@ -0,0 +1,1225 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir /rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -o /rootdir/html-report/2021-08-06-190901-5809-1 -x c dropbox-command-client.c +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/report-63011c.html b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/report-63011c.html new file mode 100644 index 0000000..a3c208b --- /dev/null +++ b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/report-63011c.html @@ -0,0 +1,1225 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir /rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -o /rootdir/html-report/2021-08-06-190901-5809-1 -x c dropbox-command-client.c +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/scanview.css b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/sorttable.js b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2021-08-06-190901-5809-1@8eef4a81e9cc_v1.26.0/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-info-provider.h>
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)<--- Assuming that condition '!emblem_paths_response' is not redundant
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+
+
+
+ + + diff --git a/2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/index.html b/2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/index.html new file mode 100644 index 0000000..303d30f --- /dev/null +++ b/2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/index.html @@ -0,0 +1,122 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+ + + + + + + + + + +
LineIdCWESeverityMessage
0missingIncludeSysteminformationCppcheck cannot find all the include files (use --check-config for details)
src/caja-dropbox.c
312variableScope398styleThe scope of the variable 'file' can be reduced.
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
+
+
+ + + diff --git a/2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/stats.html b/2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/stats.html new file mode 100644 index 0000000..5007565 --- /dev/null +++ b/2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/stats.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 3
+   3  src/caja-dropbox.c
+

+ +
+
+ + + diff --git a/2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/style.css b/2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/style.css new file mode 100644 index 0000000..07125f4 --- /dev/null +++ b/2021-08-06-190918-5051-cppcheck@8eef4a81e9cc_v1.26.0/style.css @@ -0,0 +1,137 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +.header { + border-bottom: thin solid #aaa; +} + +.footer { + border-top: thin solid #aaa; + font-size: 90%; + margin-top: 5px; +} + +.footer ul { + list-style-type: none; + padding-left: 0; +} + +.footer > p { + margin: 4px; +} + +.wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +#menu, +#menu_index { + text-align: left; + width: 350px; + height: 90vh; + min-height: 200px; + overflow: auto; + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 0 15px 15px 15px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +#content, +#content_index { + background-color: #fff; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + padding: 0 15px 15px 15px; + width: calc(100% - 350px); + height: 100%; + overflow-x: auto; +} + +#filename { + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + z-index: 10; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.d-none { + display: none; +} diff --git a/2022-02-12-111711-5932-1@f4453b2d7fce_master/index.html b/2022-02-12-111711-5932-1@f4453b2d7fce_master/index.html new file mode 100644 index 0000000..2af4432 --- /dev/null +++ b/2022-02-12-111711-5932-1@f4453b2d7fce_master/index.html @@ -0,0 +1,97 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@20d74a68e41b
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 13.0.0 (Fedora 13.0.0-3.fc35) +
Date:Sat Feb 12 11:17:11 2022
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs2
Logic error
Cast from non-struct type to struct type2
+

Reports

+ + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2022-02-12-111711-5932-1@f4453b2d7fce_master/report-51813c.html b/2022-02-12-111711-5932-1@f4453b2d7fce_master/report-51813c.html new file mode 100644 index 0000000..e07aa85 --- /dev/null +++ b/2022-02-12-111711-5932-1@f4453b2d7fce_master/report-51813c.html @@ -0,0 +1,1225 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib64/clang/13.0.0 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-02-12-111711-5932-1 -x c dropbox-command-client.c +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2022-02-12-111711-5932-1@f4453b2d7fce_master/report-b2c20b.html b/2022-02-12-111711-5932-1@f4453b2d7fce_master/report-b2c20b.html new file mode 100644 index 0000000..ce01b1a --- /dev/null +++ b/2022-02-12-111711-5932-1@f4453b2d7fce_master/report-b2c20b.html @@ -0,0 +1,1225 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib64/clang/13.0.0 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-02-12-111711-5932-1 -x c dropbox-command-client.c +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2022-02-12-111711-5932-1@f4453b2d7fce_master/scanview.css b/2022-02-12-111711-5932-1@f4453b2d7fce_master/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2022-02-12-111711-5932-1@f4453b2d7fce_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2022-02-12-111711-5932-1@f4453b2d7fce_master/sorttable.js b/2022-02-12-111711-5932-1@f4453b2d7fce_master/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2022-02-12-111711-5932-1@f4453b2d7fce_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + + +
+ +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-info-provider.h>
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)<--- Assuming that condition '!emblem_paths_response' is not redundant
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+
+
+
+ + + diff --git a/2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/index.html b/2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/index.html new file mode 100644 index 0000000..5a6d450 --- /dev/null +++ b/2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/index.html @@ -0,0 +1,122 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+ + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeSysteminformationCppcheck cannot find all the include files (use --check-config for details)
src/caja-dropbox.c
312variableScope398styleThe scope of the variable 'file' can be reduced.
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
+
+
+ + + diff --git a/2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/stats.html b/2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/stats.html new file mode 100644 index 0000000..d32b0c2 --- /dev/null +++ b/2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/stats.html @@ -0,0 +1,108 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + + +
+ +
+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 3
+   3  src/caja-dropbox.c
+

+ +
+
+ + + diff --git a/2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/style.css b/2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/style.css new file mode 100644 index 0000000..07125f4 --- /dev/null +++ b/2022-02-12-111726-5833-cppcheck@f4453b2d7fce_master/style.css @@ -0,0 +1,137 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + margin: 0; + width: auto; +} + +h1 { + margin: 10px; +} + +.header { + border-bottom: thin solid #aaa; +} + +.footer { + border-top: thin solid #aaa; + font-size: 90%; + margin-top: 5px; +} + +.footer ul { + list-style-type: none; + padding-left: 0; +} + +.footer > p { + margin: 4px; +} + +.wrapper { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; +} + +#menu, +#menu_index { + text-align: left; + width: 350px; + height: 90vh; + min-height: 200px; + overflow: auto; + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 0 15px 15px 15px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +#content, +#content_index { + background-color: #fff; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + padding: 0 15px 15px 15px; + width: calc(100% - 350px); + height: 100%; + overflow-x: auto; +} + +#filename { + margin-left: 10px; + font-size: 12px; + z-index: 1; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + z-index: 10; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.d-none { + display: none; +} diff --git a/2022-10-29-140736-5910-1@8ec754ff8335_master/index.html b/2022-10-29-140736-5910-1@8ec754ff8335_master/index.html new file mode 100644 index 0000000..b9d2aab --- /dev/null +++ b/2022-10-29-140736-5910-1@8ec754ff8335_master/index.html @@ -0,0 +1,94 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@b9260aaaf731
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 14.0.5 (Fedora 14.0.5-1.fc36) +
Date:Sat Oct 29 14:07:36 2022
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs1
Logic error
Cast from non-struct type to struct type1
+

Reports

+ + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2022-10-29-140736-5910-1@8ec754ff8335_master/report-1b9128.html b/2022-10-29-140736-5910-1@8ec754ff8335_master/report-1b9128.html new file mode 100644 index 0000000..7e828b7 --- /dev/null +++ b/2022-10-29-140736-5910-1@8ec754ff8335_master/report-1b9128.html @@ -0,0 +1,1553 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib64/clang/14.0.5 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/lib64/clang/14.0.5/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-10-29-140736-5910-1 -x c dropbox-command-client.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2022-10-29-140736-5910-1@8ec754ff8335_master/scanview.css b/2022-10-29-140736-5910-1@8ec754ff8335_master/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2022-10-29-140736-5910-1@8ec754ff8335_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2022-10-29-140736-5910-1@8ec754ff8335_master/sorttable.js b/2022-10-29-140736-5910-1@8ec754ff8335_master/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2022-10-29-140736-5910-1@8ec754ff8335_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-info-provider.h>
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+
+
+ +
+ + diff --git a/2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/index.html b/2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/index.html new file mode 100644 index 0000000..2c87aae --- /dev/null +++ b/2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/index.html @@ -0,0 +1,202 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeSysteminformationCppcheck cannot find all the include files (use --check-config for details)
src/caja-dropbox.c
312variableScope398styleThe scope of the variable 'file' can be reduced.
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
+
+ +
+ + diff --git a/2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/stats.html b/2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/stats.html new file mode 100644 index 0000000..6f8dab3 --- /dev/null +++ b/2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 3
+   3  src/caja-dropbox.c
+

+ +
+ +
+ + diff --git a/2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/style.css b/2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/style.css new file mode 100644 index 0000000..3897bfa --- /dev/null +++ b/2022-10-29-140751-4046-cppcheck@8ec754ff8335_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2022-11-10-210649-5786-1@ea7b890d9702_master/index.html b/2022-11-10-210649-5786-1@ea7b890d9702_master/index.html new file mode 100644 index 0000000..a971656 --- /dev/null +++ b/2022-11-10-210649-5786-1@ea7b890d9702_master/index.html @@ -0,0 +1,94 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@64b88840efdc
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 14.0.5 (Fedora 14.0.5-1.fc36) +
Date:Thu Nov 10 21:06:49 2022
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs1
Logic error
Cast from non-struct type to struct type1
+

Reports

+ + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2022-11-10-210649-5786-1@ea7b890d9702_master/report-1b9128.html b/2022-11-10-210649-5786-1@ea7b890d9702_master/report-1b9128.html new file mode 100644 index 0000000..d66f387 --- /dev/null +++ b/2022-11-10-210649-5786-1@ea7b890d9702_master/report-1b9128.html @@ -0,0 +1,1553 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib64/clang/14.0.5 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/lib64/clang/14.0.5/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-11-10-210649-5786-1 -x c dropbox-command-client.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2022-11-10-210649-5786-1@ea7b890d9702_master/scanview.css b/2022-11-10-210649-5786-1@ea7b890d9702_master/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2022-11-10-210649-5786-1@ea7b890d9702_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2022-11-10-210649-5786-1@ea7b890d9702_master/sorttable.js b/2022-11-10-210649-5786-1@ea7b890d9702_master/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2022-11-10-210649-5786-1@ea7b890d9702_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-info-provider.h>
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+
+
+ +
+ + diff --git a/2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/index.html b/2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/index.html new file mode 100644 index 0000000..2c87aae --- /dev/null +++ b/2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/index.html @@ -0,0 +1,202 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeSysteminformationCppcheck cannot find all the include files (use --check-config for details)
src/caja-dropbox.c
312variableScope398styleThe scope of the variable 'file' can be reduced.
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
+
+ +
+ + diff --git a/2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/stats.html b/2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/stats.html new file mode 100644 index 0000000..6f8dab3 --- /dev/null +++ b/2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 3
+   3  src/caja-dropbox.c
+

+ +
+ +
+ + diff --git a/2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/style.css b/2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/style.css new file mode 100644 index 0000000..3897bfa --- /dev/null +++ b/2022-11-10-210705-2471-cppcheck@ea7b890d9702_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2022-11-11-213923-5771-1@21f8797d992b_master/index.html b/2022-11-11-213923-5771-1@21f8797d992b_master/index.html new file mode 100644 index 0000000..9aa730f --- /dev/null +++ b/2022-11-11-213923-5771-1@21f8797d992b_master/index.html @@ -0,0 +1,94 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@eac87768ab40
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 14.0.5 (Fedora 14.0.5-1.fc36) +
Date:Fri Nov 11 21:39:23 2022
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs1
Logic error
Cast from non-struct type to struct type1
+

Reports

+ + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2022-11-11-213923-5771-1@21f8797d992b_master/report-1b9128.html b/2022-11-11-213923-5771-1@21f8797d992b_master/report-1b9128.html new file mode 100644 index 0000000..7f2820e --- /dev/null +++ b/2022-11-11-213923-5771-1@21f8797d992b_master/report-1b9128.html @@ -0,0 +1,1553 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib64/clang/14.0.5 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/lib64/clang/14.0.5/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-11-11-213923-5771-1 -x c dropbox-command-client.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2022-11-11-213923-5771-1@21f8797d992b_master/scanview.css b/2022-11-11-213923-5771-1@21f8797d992b_master/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2022-11-11-213923-5771-1@21f8797d992b_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2022-11-11-213923-5771-1@21f8797d992b_master/sorttable.js b/2022-11-11-213923-5771-1@21f8797d992b_master/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2022-11-11-213923-5771-1@21f8797d992b_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-info-provider.h>
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+
+
+ +
+ + diff --git a/2022-11-11-213937-8071-cppcheck@21f8797d992b_master/index.html b/2022-11-11-213937-8071-cppcheck@21f8797d992b_master/index.html new file mode 100644 index 0000000..2c87aae --- /dev/null +++ b/2022-11-11-213937-8071-cppcheck@21f8797d992b_master/index.html @@ -0,0 +1,202 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeSysteminformationCppcheck cannot find all the include files (use --check-config for details)
src/caja-dropbox.c
312variableScope398styleThe scope of the variable 'file' can be reduced.
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
+
+ +
+ + diff --git a/2022-11-11-213937-8071-cppcheck@21f8797d992b_master/stats.html b/2022-11-11-213937-8071-cppcheck@21f8797d992b_master/stats.html new file mode 100644 index 0000000..6f8dab3 --- /dev/null +++ b/2022-11-11-213937-8071-cppcheck@21f8797d992b_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 3
+   3  src/caja-dropbox.c
+

+ +
+ +
+ + diff --git a/2022-11-11-213937-8071-cppcheck@21f8797d992b_master/style.css b/2022-11-11-213937-8071-cppcheck@21f8797d992b_master/style.css new file mode 100644 index 0000000..3897bfa --- /dev/null +++ b/2022-11-11-213937-8071-cppcheck@21f8797d992b_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/index.html b/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/index.html new file mode 100644 index 0000000..52f6867 --- /dev/null +++ b/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/index.html @@ -0,0 +1,94 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@6c22e919ed41
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 14.0.5 (Fedora 14.0.5-1.fc36) +
Date:Fri Nov 11 21:39:51 2022
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs1
Logic error
Cast from non-struct type to struct type1
+

Reports

+ + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/report-1b9128.html b/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/report-1b9128.html new file mode 100644 index 0000000..51b8943 --- /dev/null +++ b/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/report-1b9128.html @@ -0,0 +1,1553 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib64/clang/14.0.5 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/lib64/clang/14.0.5/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2022-11-11-213951-5768-1 -x c dropbox-command-client.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/scanview.css b/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/sorttable.js b/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2022-11-11-213951-5768-1@21f8797d992b_v1.27.0/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-info-provider.h>
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+
+
+ +
+ + diff --git a/2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/index.html b/2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/index.html new file mode 100644 index 0000000..2c87aae --- /dev/null +++ b/2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/index.html @@ -0,0 +1,202 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeSysteminformationCppcheck cannot find all the include files (use --check-config for details)
src/caja-dropbox.c
312variableScope398styleThe scope of the variable 'file' can be reduced.
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
+
+ +
+ + diff --git a/2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/stats.html b/2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/stats.html new file mode 100644 index 0000000..6f8dab3 --- /dev/null +++ b/2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 3
+   3  src/caja-dropbox.c
+

+ +
+ +
+ + diff --git a/2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/style.css b/2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/style.css new file mode 100644 index 0000000..3897bfa --- /dev/null +++ b/2022-11-11-214007-0694-cppcheck@21f8797d992b_v1.27.0/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/index.html b/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/index.html new file mode 100644 index 0000000..0258968 --- /dev/null +++ b/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/index.html @@ -0,0 +1,94 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@6d47ab0c0f2d
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 15.0.7 (Fedora 15.0.7-2.fc37) +
Date:Sun Apr 16 22:01:19 2023
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs1
Logic error
Cast from non-struct type to struct type1
+

Reports

+ + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/report-1b9128.html b/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/report-1b9128.html new file mode 100644 index 0000000..a8f1c14 --- /dev/null +++ b/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/report-1b9128.html @@ -0,0 +1,1553 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/lib64/clang/15.0.7 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/at-spi-2.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/12/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-04-16-220119-5762-1 -x c dropbox-command-client.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *)__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/scanview.css b/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/sorttable.js b/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2023-04-16-220119-5762-1@a4dac3d0ebf8_master/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
+967
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <libcaja-extension/caja-extension-types.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-info-provider.h>
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+    NULL
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+ +
+ +
+ + diff --git a/2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/index.html b/2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/index.html new file mode 100644 index 0000000..eb0d005 --- /dev/null +++ b/2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/index.html @@ -0,0 +1,202 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+ + + + + + + + + + + + + +
LineIdCWESeverityMessage
missingIncludeSysteminformationCppcheck cannot find all the include files (use --check-config for details)
src/caja-dropbox.c
312variableScope398styleThe scope of the variable 'file' can be reduced.
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
+
+ +
+ + diff --git a/2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/stats.html b/2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/stats.html new file mode 100644 index 0000000..18955b2 --- /dev/null +++ b/2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/stats.html @@ -0,0 +1,170 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 3
+   3  src/caja-dropbox.c
+

+ +
+ +
+ + diff --git a/2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/style.css b/2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/style.css new file mode 100644 index 0000000..3897bfa --- /dev/null +++ b/2023-04-16-220134-7625-cppcheck@a4dac3d0ebf8_master/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/index.html b/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/index.html new file mode 100644 index 0000000..ff737ba --- /dev/null +++ b/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/index.html @@ -0,0 +1,94 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@2be86dfdc62c
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 17.0.6 (Fedora 17.0.6-2.fc39) +
Date:Wed Feb 21 17:39:34 2024
+

Bug Summary

+ + + + +
Bug TypeQuantityDisplay?
All Bugs1
Logic error
Cast from non-struct type to struct type1
+

Reports

+ + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typedropbox-command-client.cdropbox_command_client_force_reconnect7461View Report
+ + diff --git a/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/report-1b9128.html b/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/report-1b9128.html new file mode 100644 index 0000000..4d17cc4 --- /dev/null +++ b/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/report-1b9128.html @@ -0,0 +1,1553 @@ + + + +dropbox-command-client.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:dropbox-command-client.c
Warning:line 746, column 41
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dropbox-command-client.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/src -resource-dir /usr/bin/../lib/clang/17 -D HAVE_CONFIG_H -I . -I .. -I .. -I .. -D DATADIR="/usr/share" -D EMBLEMDIR="/usr/share/caja-dropbox/emblems" -I /usr/include/caja -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/cairo -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/atk-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/at-spi2-atk/2.0 -I /usr/include/cloudproviders -I /usr/include/at-spi-2.0 -I /usr/include/blkid -I /usr/include/gio-unix-2.0 -I /usr/include/libmount -I /usr/include/pixman-1 -I /usr/include/libxml2 -I /usr/include/fribidi -I /usr/include/sysprof-6 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-6 -D G_DISABLE_ASSERT -D G_DISABLE_CHECKS -D PIC -internal-isystem /usr/bin/../lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/src -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-02-21-173934-5699-1 -x c dropbox-command-client.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright 2008 Evenflow, Inc.
3 *
4 * dropbox-command-client.c
5 * Implements connection handling and C interface for the Dropbox command socket.
6 *
7 * This file is part of caja-dropbox.
8 *
9 * caja-dropbox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * caja-dropbox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with caja-dropbox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <sys/un.h>
27#include <errno(*__errno_location ()).h>
28#include <unistd.h>
29#include <fcntl.h>
30
31#include <stdarg.h>
32#include <string.h>
33
34#include <glib.h>
35
36#include "g-util.h"
37#include "dropbox-client-util.h"
38#include "dropbox-command-client.h"
39#include "caja-dropbox.h"
40#include "caja-dropbox-hooks.h"
41
42/* TODO: make this asynchronous ;) */
43
44/*
45 this is a tiny hack, necessitated by the fact that
46 finish_file info command is in caja_dropbox,
47 this can be cleaned up once the file_info_command isn't a special
48 case anylonger
49*/
50gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
51
52typedef struct {
53 DropboxCommandClient *dcc;
54 guint connect_attempt;
55} ConnectionAttempt;
56
57typedef struct {
58 DropboxCommandClientConnectionAttemptHook h;
59 gpointer ud;
60} DropboxCommandClientConnectionAttempt;
61
62typedef struct {
63 DropboxGeneralCommand *dgc;
64 GHashTable *response;
65} DropboxGeneralCommandResponse;
66
67static gboolean
68on_connect(DropboxCommandClient *dcc) {
69 g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE(0));
70 return FALSE(0);
71}
72
73static gboolean
74on_disconnect(DropboxCommandClient *dcc) {
75 g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE(0));
76 return FALSE(0);
77}
78
79static gboolean
80on_connection_attempt(ConnectionAttempt *ca) {
81 GList *ll;
82
83 for (ll = ca->dcc->ca_hooklist; ll != NULL((void*)0); ll = g_list_next(ll)((ll) ? (((GList *)(ll))->next) : ((void*)0))) {
84 DropboxCommandClientConnectionAttempt *dccca =
85 (DropboxCommandClientConnectionAttempt *)(ll->data);
86 dccca->h(ca->connect_attempt, dccca->ud);
87 }
88
89 g_free(ca);
90
91 return FALSE(0);
92}
93
94static gboolean
95receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
96 GError **err) {
97 GIOStatus iostat;
98 GError *tmp_error = NULL((void*)0);
99 guint numargs = 0;
100
101 while (1) {
102 gchar *line;
103 gsize term_pos;
104
105 /* if we are getting too many args, connection could be malicious */
106 if (numargs >= 20) {
107 g_set_error(err,
108 g_quark_from_static_string("malicious connection"),
109 0, "malicious connection");
110 return FALSE(0);
111 }
112
113 /* get the string */
114 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
115 &term_pos, &tmp_error);
116 if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL((void*)0)) {
117 g_free(line);
118 if (tmp_error != NULL((void*)0)) {
119 g_propagate_error(err, tmp_error);
120 }
121 return FALSE(0);
122 }
123 else if (iostat == G_IO_STATUS_EOF) {
124 g_free(line);
125 g_set_error(err,
126 g_quark_from_static_string("connection closed"),
127 0, "connection closed");
128 return FALSE(0);
129 }
130
131 *(line+term_pos) = '\0';
132
133 if (strcmp("done", line) == 0) {
134 g_free(line);
135 break;
136 }
137 else {
138 gboolean parse_result;
139
140 parse_result = dropbox_client_util_command_parse_arg(line, return_table);
141 g_free(line);
142
143 if (FALSE(0) == parse_result) {
144 g_set_error(err,
145 g_quark_from_static_string("parse error"),
146 0, "parse error");
147 return FALSE(0);
148 }
149 }
150
151 numargs += 1;
152 }
153
154 return TRUE(!(0));
155}
156
157/*
158 sends a command to the dropbox server
159 returns an hash of the return values
160
161 in theory, this should disconnection errors
162 but it doesn't matter right now, any error is a sufficient
163 condition to disconnect
164*/
165static GHashTable *
166send_command_to_db(GIOChannel *chan, const gchar *command_name,
167 GHashTable *args, GError **err) {
168 GError *tmp_error = NULL((void*)0);
169 GIOStatus iostat;
170 gsize bytes_trans;
171 gchar *line;
172
173 g_assert(chan != NULL)do { (void) 0; } while (0);
174 g_assert(command_name != NULL)do { (void) 0; } while (0);
175
176
177#define WRITE_OR_DIE_SANI(s,l) { \
178 gchar *sani_s; \
179 sani_s = dropbox_client_util_sanitize(s); \
180 iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans, \
181 &tmp_error); \
182 g_free(sani_s); \
183 if (iostat == G_IO_STATUS_ERROR || \
184 iostat == G_IO_STATUS_AGAIN) { \
185 if (tmp_error != NULL((void*)0)) { \
186 g_propagate_error(err, tmp_error); \
187 } \
188 return NULL((void*)0); \
189 } \
190 }
191
192#define WRITE_OR_DIE(s,l) { \
193 iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans, \
194 &tmp_error); \
195 if (iostat == G_IO_STATUS_ERROR || \
196 iostat == G_IO_STATUS_AGAIN) { \
197 if (tmp_error != NULL((void*)0)) { \
198 g_propagate_error(err, tmp_error); \
199 } \
200 return NULL((void*)0); \
201 } \
202 }
203
204 /* send command to server */
205 WRITE_OR_DIE_SANI(command_name, -1);
206 WRITE_OR_DIE("\n", -1);
207
208 if (args != NULL((void*)0)) {
209 GList *keys, *li;
210
211 keys = g_hash_table_get_keys(args);
212
213 for (li = keys; li != NULL((void*)0); li = g_list_next(li)((li) ? (((GList *)(li))->next) : ((void*)0))) {
214 int i;
215 gchar **value;
216
217 WRITE_OR_DIE_SANI((gchar *) li->data, -1);
218
219 value = g_hash_table_lookup(args, li->data);
220 for (i = 0; value[i] != NULL((void*)0); i++) {
221 WRITE_OR_DIE("\t", -1);
222 WRITE_OR_DIE_SANI(value[i], -1);
223 }
224 WRITE_OR_DIE("\n", -1);
225 }
226
227 g_list_free(keys);
228 }
229
230 WRITE_OR_DIE("done\n", -1);
231
232#undef WRITE_OR_DIE
233#undef WRITE_OR_DIE_SANI
234
235 g_io_channel_flush(chan, &tmp_error);
236 if (tmp_error != NULL((void*)0)) {
237 g_propagate_error(err, tmp_error);
238 return NULL((void*)0);
239 }
240
241 /* now we have to read the data */
242 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
243 NULL((void*)0), &tmp_error);
244 if (iostat == G_IO_STATUS_ERROR) {
245 g_assert(line == NULL)do { (void) 0; } while (0);
246 g_propagate_error(err, tmp_error);
247 return NULL((void*)0);
248 }
249 else if (iostat == G_IO_STATUS_AGAIN) {
250 g_assert(line == NULL)do { (void) 0; } while (0);
251 g_set_error(err,
252 g_quark_from_static_string("dropbox command connection timed out"),
253 0,
254 "dropbox command connection timed out");
255 return NULL((void*)0);
256 }
257 else if (iostat == G_IO_STATUS_EOF) {
258 g_assert(line == NULL)do { (void) 0; } while (0);
259 g_set_error(err,
260 g_quark_from_static_string("dropbox command connection closed"),
261 0,
262 "dropbox command connection closed");
263 return NULL((void*)0);
264 }
265
266 /* if the response was okay */
267 if (strncmp(line, "ok\n", 3) == 0) {
268 GHashTable *return_table =
269 g_hash_table_new_full((GHashFunc) g_str_hash,
270 (GEqualFunc) g_str_equal,
271 (GDestroyNotify) g_free,
272 (GDestroyNotify) g_strfreev);
273
274 g_free(line);
275 line = NULL((void*)0);
276
277 receive_args_until_done(chan, return_table, &tmp_error);
278 if (tmp_error != NULL((void*)0)) {
279 g_hash_table_destroy(return_table);
280 g_propagate_error(err, tmp_error);
281 return NULL((void*)0);
282 }
283
284 return return_table;
285 }
286 /* otherwise */
287 else {
288 /* read errors off until we get done */
289 do {
290 g_free(line);
291 line = NULL((void*)0);
292
293 /* clear string */
294 iostat = g_io_channel_read_line(chan, &line, NULL((void*)0),
295 NULL((void*)0), &tmp_error);
296 if (iostat == G_IO_STATUS_ERROR) {
297 g_assert(line == NULL)do { (void) 0; } while (0);
298 g_propagate_error(err, tmp_error);
299 return NULL((void*)0);
300 }
301 else if (iostat == G_IO_STATUS_AGAIN) {
302 g_assert(line == NULL)do { (void) 0; } while (0);
303 g_set_error(err,
304 g_quark_from_static_string("dropbox command connection timed out"),
305 0,
306 "dropbox command connection timed out");
307 return NULL((void*)0);
308
309 }
310 else if (iostat == G_IO_STATUS_EOF) {
311 g_assert(line == NULL)do { (void) 0; } while (0);
312 g_set_error(err,
313 g_quark_from_static_string("dropbox command connection closed"),
314 0,
315 "dropbox command connection closed");
316 return NULL((void*)0);
317 }
318
319 /* we got our line */
320 } while (strncmp(line, "done\n", 5) != 0);
321
322 g_free(line);
323 return NULL((void*)0);
324 }
325}
326
327static void
328do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
329 /* we need to send two requests to dropbox:
330 file status, and folder_tags */
331 GError *tmp_gerr = NULL((void*)0);
332 DropboxFileInfoCommandResponse *dficr;
333 GHashTable *file_status_response = NULL((void*)0), *args, *folder_tag_response = NULL((void*)0), *emblems_response = NULL((void*)0);
334 gchar *filename = NULL((void*)0);
335
336 {
337 gchar *filename_un, *uri;
338 uri = caja_file_info_get_uri(dfic->file);
339 filename_un = uri ? g_filename_from_uri(uri, NULL((void*)0), NULL((void*)0)): NULL((void*)0);
340 g_free(uri);
341 if (filename_un) {
342 filename = g_filename_to_utf8(filename_un, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
343 g_free(filename_un);
344 if (filename == NULL((void*)0)) {
345 /* oooh, filename wasn't correctly encoded. mark as */
346 debug("file wasn't correctly encoded %s", filename_un)do {} while(0);
347 }
348 }
349 }
350
351 if (filename == NULL((void*)0)) {
352 /* We couldn't get the filename. Just return empty. */
353 goto exit;
354 }
355
356 args = g_hash_table_new_full((GHashFunc) g_str_hash,
357 (GEqualFunc) g_str_equal,
358 (GDestroyNotify) g_free,
359 (GDestroyNotify) g_strfreev);
360 {
361 gchar **path_arg;
362 path_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
363 path_arg[0] = g_strdup(filename)g_strdup_inline (filename);
364 path_arg[1] = NULL((void*)0);
365 g_hash_table_insert(args, g_strdup("path")g_strdup_inline ("path"), path_arg);
366 }
367
368 emblems_response = send_command_to_db(chan, "get_emblems", args, NULL((void*)0));
369 if (emblems_response) {
370 /* Don't need to do the other calls. */
371 g_hash_table_unref(args);
372 goto exit;
373 }
374
375 /* send status command to server */
376 file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
377 args, &tmp_gerr);
378 g_hash_table_unref(args);
379 args = NULL((void*)0);
380 if (tmp_gerr != NULL((void*)0)) {
381 g_free(filename);
382 g_assert(file_status_response == NULL)do { (void) 0; } while (0);
383 g_propagate_error(gerr, tmp_gerr);
384 return;
385 }
386
387 if (caja_file_info_is_directory(dfic->file)) {
388 args = g_hash_table_new_full((GHashFunc) g_str_hash,
389 (GEqualFunc) g_str_equal,
390 (GDestroyNotify) g_free,
391 (GDestroyNotify) g_strfreev);
392 {
393 gchar **paths_arg;
394 paths_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
395 paths_arg[0] = g_strdup(filename)g_strdup_inline (filename);
396 paths_arg[1] = NULL((void*)0);
397 g_hash_table_insert(args, g_strdup("path")g_strdup_inline ("path"), paths_arg);
398 }
399
400 folder_tag_response =
401 send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
402 g_hash_table_unref(args);
403 args = NULL((void*)0);
404 if (tmp_gerr != NULL((void*)0)) {
405 if (file_status_response != NULL((void*)0))
406 g_hash_table_destroy(file_status_response);
407 g_assert(folder_tag_response == NULL)do { (void) 0; } while (0);
408 g_propagate_error(gerr, tmp_gerr);
409 return;
410 }
411 }
412
413 /* great server responded perfectly,
414 now let's get this request done,
415 ...in the glib main loop */
416exit:
417 dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
418 dficr->dfic = dfic;
419 dficr->folder_tag_response = folder_tag_response;
420 dficr->file_status_response = file_status_response;
421 dficr->emblems_response = emblems_response;
422 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
423
424 g_free(filename);
425
426 return;
427}
428
429static gboolean
430finish_general_command(DropboxGeneralCommandResponse *dgcr) {
431 if (dgcr->dgc->handler != NULL((void*)0)) {
432 dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
433 }
434
435 if (dgcr->response != NULL((void*)0)) {
436 g_hash_table_unref(dgcr->response);
437 }
438
439 g_free(dgcr->dgc->command_name);
440 if (dgcr->dgc->command_args != NULL((void*)0)) {
441 g_hash_table_unref(dgcr->dgc->command_args);
442 }
443 g_free(dgcr->dgc);
444 g_free(dgcr);
445
446 return FALSE(0);
447}
448
449static void
450do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
451 GError **gerr) {
452 GError *tmp_gerr = NULL((void*)0);
453 GHashTable *response;
454
455 /* send status command to server */
456 response = send_command_to_db(chan, dcac->command_name,
457 dcac->command_args, &tmp_gerr);
458 if (tmp_gerr != NULL((void*)0)) {
459 g_assert(response == NULL)do { (void) 0; } while (0);
460 g_propagate_error(gerr, tmp_gerr);
461 return;
462 }
463
464 /* great, the server did the command perfectly,
465 now call the handler with the response */
466 {
467 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
468 dgcr->dgc = dcac;
469 dgcr->response = response;
470 finish_general_command(dgcr);
471 }
472
473 return;
474}
475
476static gboolean
477check_connection(GIOChannel *chan) {
478 gchar fake_buf[4096];
479 gsize bytes_read;
480 GError *tmp_error = NULL((void*)0);
481 GIOFlags flags;
482 GIOStatus ret, iostat;
483
484 flags = g_io_channel_get_flags(chan);
485
486 /* set non-blocking */
487 ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL((void*)0));
488 if (ret == G_IO_STATUS_ERROR) {
489 return FALSE(0);
490 }
491
492 iostat = g_io_channel_read_chars(chan, fake_buf,
493 sizeof(fake_buf),
494 &bytes_read, &tmp_error);
495
496 ret = g_io_channel_set_flags(chan, flags, NULL((void*)0));
497 if (ret == G_IO_STATUS_ERROR) {
498 return FALSE(0);
499 }
500
501 /* this makes us disconnect from bad servers
502 (those that send us information without us asking for it) */
503 return iostat == G_IO_STATUS_AGAIN;
504}
505
506static gpointer
507dropbox_command_client_thread(DropboxCommandClient *data);
508
509static void
510end_request(DropboxCommand *dc) {
511 if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
512 switch (dc->request_type) {
513 case GET_FILE_INFO: {
514 DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
515 DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1)(DropboxFileInfoCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxFileInfoCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
516 dficr->dfic = dfic;
517 dficr->file_status_response = NULL((void*)0);
518 dficr->emblems_response = NULL((void*)0);
519 g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
520 }
521 break;
522 case GENERAL_COMMAND: {
523 DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
524 DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1)(DropboxGeneralCommandResponse *) (__extension__ ({ gsize __n
= (gsize) (1); gsize __s = sizeof (DropboxGeneralCommandResponse
); gpointer __p; if (__s == 1) __p = g_malloc0 (__n); else if
(__builtin_constant_p (__n) && (__s == 0 || __n <=
(9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc0 (__n
* __s); else __p = g_malloc0_n (__n, __s); __p; }))
;
525 dgcr->dgc = dgc;
526 dgcr->response = NULL((void*)0);
527 finish_general_command(dgcr);
528 }
529 break;
530 default:
531 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
532 break;
533 }
534 }
535}
536
537
538static gpointer
539dropbox_command_client_thread(DropboxCommandClient *dcc) {
540 struct sockaddr_un addr;
541 socklen_t addr_len;
542 int connection_attempts = 1;
543
544 /* intialize address structure */
545 addr.sun_family = AF_UNIX1;
546 g_snprintf(addr.sun_path,
547 sizeof(addr.sun_path),
548 "%s/.dropbox/command_socket",
549 g_get_home_dir());
550 addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
551
552 while (1) {
553 GIOChannel *chan = NULL((void*)0);
554 GError *gerr = NULL((void*)0);
555 int sock;
556 gboolean failflag = TRUE(!(0));
557
558 do {
559 int flags;
560
561 if (0 > (sock = socket(PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0))) {
562 /* WTF */
563 break;
564 }
565
566 /* set timeout on socket, to protect against
567 bad servers */
568 {
569 struct timeval tv = {3, 0};
570 if (0 > setsockopt(sock, SOL_SOCKET1, SO_RCVTIMEO20,
571 &tv, sizeof(struct timeval)) ||
572 0 > setsockopt(sock, SOL_SOCKET1, SO_SNDTIMEO21,
573 &tv, sizeof(struct timeval))) {
574 /* debug("setsockopt failed"); */
575 break;
576 }
577 }
578
579 /* set native non-blocking, for connect timeout */
580 {
581 if ((flags = fcntl(sock, F_GETFL3, 0)) < 0 ||
582 fcntl(sock, F_SETFL4, flags | O_NONBLOCK04000) < 0) {
583 /* debug("fcntl failed"); */
584 break;
585 }
586 }
587
588 /* if there was an error we have to try again later */
589 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
590 if (errno(*__errno_location ()) == EINPROGRESS115) {
591 fd_set writers;
592 struct timeval tv = {1, 0};
593
594 FD_ZERO(&writers)do { unsigned int __i; fd_set *__arr = (&writers); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
595 FD_SET(sock, &writers)((void) (((&writers)->__fds_bits)[((sock) / (8 * (int)
sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((sock) %
(8 * (int) sizeof (__fd_mask)))))))
;
596
597 /* if nothing was ready after 3 seconds, fail out homie */
598 if (select(sock+1, NULL((void*)0), &writers, NULL((void*)0), &tv) == 0) {
599 /* debug("connection timeout"); */
600 break;
601 }
602
603 if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
604 /* debug("couldn't connect to command server after 1 second"); */
605 break;
606 }
607 }
608 /* errno != EINPROGRESS */
609 else {
610 /* debug("bad connection"); */
611 break;
612 }
613 }
614
615 /* set back to blocking */
616 if (fcntl(sock, F_SETFL4, flags) < 0) {
617 /* debug("fcntl2 failed"); */
618 break;
619 }
620
621 failflag = FALSE(0);
622 } while (0);
623
624 if (failflag) {
625 ConnectionAttempt *ca = g_new(ConnectionAttempt, 1)(ConnectionAttempt *) (__extension__ ({ gsize __n = (gsize) (
1); gsize __s = sizeof (ConnectionAttempt); gpointer __p; if (
__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
626 ca->dcc = dcc;
627 ca->connect_attempt = connection_attempts;
628 g_idle_add((GSourceFunc) on_connection_attempt, ca);
629 if (sock >= 0) {
630 close(sock);
631 }
632 g_usleep(G_USEC_PER_SEC1000000);
633 connection_attempts++;
634 continue;
635 }
636 else {
637 connection_attempts = 0;
638 }
639
640 /* connected */
641 debug("command client connected")do {} while(0);
642
643 chan = g_io_channel_unix_new(sock);
644 g_io_channel_set_close_on_unref(chan, TRUE(!(0)));
645 g_io_channel_set_line_term(chan, "\n", -1);
646
647#define SET_CONNECTED_STATE(s) { \
648 g_mutex_lock(&(dcc->command_connected_mutex)); \
649 dcc->command_connected = s; \
650 g_mutex_unlock(&(dcc->command_connected_mutex)); \
651 }
652
653 SET_CONNECTED_STATE(TRUE(!(0)));
654
655 g_idle_add((GSourceFunc) on_connect, dcc);
656
657 while (1) {
658 DropboxCommand *dc;
659
660 while (1) {
661
662 /* get a request from caja */
663 dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC1000000 / 10);
664 if (dc != NULL((void*)0)) {
665 break;
666 }
667 else {
668 if (check_connection(chan) == FALSE(0)) {
669 goto BADCONNECTION;
670 }
671 }
672 }
673
674 /* this pointer should be unique */
675 if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
676 debug("got a reset request")do {} while(0);
677 goto BADCONNECTION;
678 }
679
680 switch (dc->request_type) {
681 case GET_FILE_INFO: {
682 debug("doing file info command")do {} while(0);
683 do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
684 }
685 break;
686 case GENERAL_COMMAND: {
687 debug("doing general command")do {} while(0);
688 do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
689 }
690 break;
691 default:
692 g_assert_not_reached()do { (void) 0; __builtin_unreachable (); } while (0);
693 break;
694 }
695
696 debug("done.")do {} while(0);
697
698 if (gerr != NULL((void*)0)) {
699 // debug("COMMAND ERROR*****************************");
700 /* mark this request as never to be completed */
701 end_request(dc);
702
703 debug("command error: %s", gerr->message)do {} while(0);
704
705 g_error_free(gerr);
706 BADCONNECTION:
707 /* grab all the rest of the data off the async queue and mark it
708 never to be completed, who knows how long we'll be disconnected */
709 while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL((void*)0)) {
710 end_request(dc);
711 }
712
713 g_io_channel_unref(chan);
714
715 SET_CONNECTED_STATE(FALSE(0));
716
717 /* call the disconnect handler */
718 g_idle_add((GSourceFunc) on_disconnect, dcc);
719
720 break;
721 }
722 }
723
724#undef SET_CONNECTED_STATE
725 }
726
727 return NULL((void*)0);
728}
729
730/* thread safe */
731gboolean
732dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
733 gboolean command_connected;
734
735 g_mutex_lock(&(dcc->command_connected_mutex));
736 command_connected = dcc->command_connected;
737 g_mutex_unlock(&(dcc->command_connected_mutex));
738
739 return command_connected;
740}
741
742/* thread safe */
743void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
744 if (dropbox_command_client_is_connected(dcc) == TRUE(!(0))) {
745 debug("forcing command to reconnect")do {} while(0);
746 dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
747 }
748}
749
750/* thread safe */
751void
752dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
753 g_async_queue_push(dcc->command_queue, dc);
754}
755
756/* should only be called once on initialization */
757void
758dropbox_command_client_setup(DropboxCommandClient *dcc) {
759 dcc->command_queue = g_async_queue_new();
760 g_mutex_init(&(dcc->command_connected_mutex));
761 dcc->command_connected = FALSE(0);
762 dcc->ca_hooklist = NULL((void*)0);
763
764 g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
765 g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
766}
767
768void
769dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
770 DropboxCommandClientConnectHook dhcch,
771 gpointer ud) {
772 GHook *newhook;
773
774 newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
775 newhook->func = dhcch;
776 newhook->data = ud;
777
778 g_hook_append(&(dcc->ondisconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->ondisconnect_hooklist)),
((void*)0), (newhook))
;
779}
780
781void
782dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
783 DropboxCommandClientConnectHook dhcch,
784 gpointer ud) {
785 GHook *newhook;
786
787 newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
788 newhook->func = dhcch;
789 newhook->data = ud;
790
791 g_hook_append(&(dcc->onconnect_hooklist), newhook)g_hook_insert_before ((&(dcc->onconnect_hooklist)), ((
void*)0), (newhook))
;
792}
793
794void
795dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
796 DropboxCommandClientConnectionAttemptHook dhcch,
797 gpointer ud) {
798 DropboxCommandClientConnectionAttempt *newhook;
799
800 debug("shouldn't be here...")do {} while(0);
801
802 newhook = g_new(DropboxCommandClientConnectionAttempt, 1)(DropboxCommandClientConnectionAttempt *) (__extension__ ({ gsize
__n = (gsize) (1); gsize __s = sizeof (DropboxCommandClientConnectionAttempt
); gpointer __p; if (__s == 1) __p = g_malloc (__n); else if (
__builtin_constant_p (__n) && (__s == 0 || __n <= (
9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc (__n * __s
); else __p = g_malloc_n (__n, __s); __p; }))
;
803 newhook->h = dhcch;
804 newhook->ud = ud;
805
806 dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
807}
808
809/* should only be called once on initialization */
810void
811dropbox_command_client_start(DropboxCommandClient *dcc) {
812 /* setup the connect to the command server */
813 debug("starting command thread")do {} while(0);
814 g_thread_new(NULL((void*)0), (GThreadFunc) dropbox_command_client_thread, dcc);
815}
816
817/* thread safe */
818void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
819 const char *command) {
820 DropboxGeneralCommand *dgc;
821
822 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
823
824 dgc->dc.request_type = GENERAL_COMMAND;
825 dgc->command_name = g_strdup(command)g_strdup_inline (command);
826 dgc->command_args = NULL((void*)0);
827 dgc->handler = NULL((void*)0);
828 dgc->handler_ud = NULL((void*)0);
829
830 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
831}
832
833/* thread safe */
834/* this is the C API, there is another send_command_to_db
835 that is more the actual over the wire command */
836void dropbox_command_client_send_command(DropboxCommandClient *dcc,
837 CajaDropboxCommandResponseHandler h,
838 gpointer ud,
839 const char *command, ...) {
840 va_list ap;
841 DropboxGeneralCommand *dgc;
842 gchar *na;
843 va_start(ap, command)__builtin_va_start(ap, command);
844
845 dgc = g_new(DropboxGeneralCommand, 1)(DropboxGeneralCommand *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (DropboxGeneralCommand); gpointer __p
; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
846 dgc->dc.request_type = GENERAL_COMMAND;
847 dgc->command_name = g_strdup(command)g_strdup_inline (command);
848 dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
849 (GEqualFunc) g_str_equal,
850 (GDestroyNotify) g_free,
851 (GDestroyNotify) g_strfreev);
852 /*
853 * NB: The handler is called in the DropboxCommandClient Thread. If you need
854 * it in the main thread you must call g_idle_add in the callback.
855 */
856 dgc->handler = h;
857 dgc->handler_ud = ud;
858
859 while ((na = va_arg(ap, char *)__builtin_va_arg(ap, char *)) != NULL((void*)0)) {
860 gchar **is_active_arg;
861
862 is_active_arg = g_new(gchar *, 2)(gchar * *) (__extension__ ({ gsize __n = (gsize) (2); gsize __s
= sizeof (gchar *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
863
864 g_hash_table_insert(dgc->command_args,
865 g_strdup(na)g_strdup_inline (na), is_active_arg);
866
867 is_active_arg[0] = g_strdup(va_arg(ap, char *))g_strdup_inline (__builtin_va_arg(ap, char *));
868 is_active_arg[1] = NULL((void*)0);
869 }
870 va_end(ap)__builtin_va_end(ap);
871
872 dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
873}
diff --git a/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/scanview.css b/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/scanview.css new file mode 100644 index 0000000..cf8a5a6 --- /dev/null +++ b/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/sorttable.js b/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/sorttable.js new file mode 100644 index 0000000..32faa07 --- /dev/null +++ b/2024-02-21-173934-5699-1@c39dc324eb09_v1.28.0/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write(" + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox-hooks.c
+ * Implements connection handling and C interface for the Dropbox hook socket.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/types.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <sys/socket.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <sys/un.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <errno.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <unistd.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <fcntl.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include <string.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "g-util.h"
+#include "async-io-coroutine.h"
+#include "dropbox-client-util.h"
+#include "caja-dropbox-hooks.h"
+
+typedef struct {
+  DropboxUpdateHook hook;
+  gpointer ud;
+} HookData;
+
+static gboolean
+try_to_connect(CajaDropboxHookserv *hookserv);
+
+static gboolean
+handle_hook_server_input(GIOChannel *chan,
+			 GIOCondition cond,
+			 CajaDropboxHookserv *hookserv) {
+  /*debug_enter(); */
+
+  /* we have some sweet macros defined that allow us to write this
+     async event handler like a microthread yeahh, watch out for context */
+  CRBEGIN(hookserv->hhsi.line);
+  while (1) {
+    hookserv->hhsi.command_args =
+      g_hash_table_new_full((GHashFunc) g_str_hash,
+			    (GEqualFunc) g_str_equal,
+			    (GDestroyNotify) g_free,
+			    (GDestroyNotify) g_strfreev);
+    hookserv->hhsi.numargs = 0;
+
+    /* read the command name */
+    {
+      gchar *line;
+      CRREADLINE(hookserv->hhsi.line, chan, line);
+      hookserv->hhsi.command_name = dropbox_client_util_desanitize(line);
+      g_free(line);
+    }
+
+    /*debug("got a hook name: %s", hookserv->hhsi.command_name); */
+
+    /* now read each arg line (until a certain limit) until we receive "done" */
+    while (1) {
+      gchar *line;
+
+      /* if too many arguments, this connection seems malicious */
+      if (hookserv->hhsi.numargs >= 20) {
+	CRHALT;
+      }
+
+      CRREADLINE(hookserv->hhsi.line, chan, line);
+
+      if (strcmp("done", line) == 0) {
+	g_free(line);
+	break;
+      }
+      else {
+	gboolean parse_result;
+
+	parse_result =
+	  dropbox_client_util_command_parse_arg(line,
+						hookserv->hhsi.command_args);
+	g_free(line);
+
+	if (FALSE == parse_result) {
+	  debug("bad parse");
+	  CRHALT;
+	}
+      }
+
+      hookserv->hhsi.numargs += 1;
+    }
+
+    {
+      HookData *hd;
+      hd = (HookData *)
+	g_hash_table_lookup(hookserv->dispatch_table,
+			    hookserv->hhsi.command_name);
+      if (hd != NULL) {
+	(hd->hook)(hookserv->hhsi.command_args, hd->ud);
+      }
+    }
+
+    g_free(hookserv->hhsi.command_name);
+    g_hash_table_unref(hookserv->hhsi.command_args);
+    hookserv->hhsi.command_name = NULL;
+    hookserv->hhsi.command_args = NULL;
+  }
+  CREND;
+}
+
+static void
+watch_killer(CajaDropboxHookserv *hookserv) {
+  debug("hook client disconnected");
+
+  hookserv->connected = FALSE;
+
+  g_hook_list_invoke(&(hookserv->ondisconnect_hooklist), FALSE);
+
+  /* we basically just have to free the memory allocated in the
+     handle_hook_server_init ctx */
+  if (hookserv->hhsi.command_name != NULL) {
+    g_free(hookserv->hhsi.command_name);
+    hookserv->hhsi.command_name = NULL;
+  }
+
+  if (hookserv->hhsi.command_args != NULL) {
+    g_hash_table_unref(hookserv->hhsi.command_args);
+    hookserv->hhsi.command_args = NULL;
+  }
+
+  g_io_channel_unref(hookserv->chan);
+  hookserv->chan = NULL;
+  hookserv->event_source = 0;
+  hookserv->socket = 0;
+
+  /* lol we also have to start a new connection */
+  try_to_connect(hookserv);
+}
+
+static gboolean
+try_to_connect(CajaDropboxHookserv *hookserv) {
+  /* create socket */
+  hookserv->socket = socket(PF_UNIX, SOCK_STREAM, 0);
+
+  /* set native non-blocking, for connect timeout */
+  {
+    int flags;
+
+    if ((flags = fcntl(hookserv->socket, F_GETFL, 0)) < 0) {
+      goto FAIL_CLEANUP;
+    }
+
+    if (fcntl(hookserv->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
+      goto FAIL_CLEANUP;
+    }
+  }
+
+  /* connect to server, might fail of course */
+  {
+    struct sockaddr_un addr;
+    socklen_t addr_len;
+
+    /* intialize address structure */
+    addr.sun_family = AF_UNIX;
+    g_snprintf(addr.sun_path,
+	       sizeof(addr.sun_path),
+	       "%s/.dropbox/iface_socket",
+	       g_get_home_dir());
+    addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
+
+    /* if there was an error we have to try again later */
+    if (connect(hookserv->socket, (struct sockaddr *) &addr, addr_len) < 0) {
+      if (errno == EINPROGRESS) {
+	fd_set writers;
+	struct timeval tv = {1, 0};
+        FD_ZERO(&writers);
+	FD_SET(hookserv->socket, &writers);
+
+	/* if nothing was ready after 3 seconds, fail out homie */
+	if (select(hookserv->socket+1, NULL, &writers, NULL, &tv) == 0) {
+	  goto FAIL_CLEANUP;
+	}
+
+	if (connect(hookserv->socket, (struct sockaddr *) &addr, addr_len) < 0) {
+	  debug("couldn't connect to hook server after 1 second");
+	  goto FAIL_CLEANUP;
+	}
+      }
+      else {
+	goto FAIL_CLEANUP;
+      }
+    }
+  }
+
+  /* lol sometimes i write funny codez */
+  if (FALSE) {
+  FAIL_CLEANUP:
+    close(hookserv->socket);
+    g_timeout_add_seconds(1, (GSourceFunc) try_to_connect, hookserv);
+    return FALSE;
+  }
+
+  /* great we connected!, let's create the channel and wait on it */
+  hookserv->chan = g_io_channel_unix_new(hookserv->socket);
+  g_io_channel_set_line_term(hookserv->chan, "\n", -1);
+  g_io_channel_set_close_on_unref(hookserv->chan, TRUE);
+
+  /*debug("create channel"); */
+
+  /* Set non-blocking ;) (again just in case) */
+  {
+    GIOFlags flags;
+    GIOStatus iostat;
+
+    flags = g_io_channel_get_flags(hookserv->chan);
+    iostat = g_io_channel_set_flags(hookserv->chan, flags | G_IO_FLAG_NONBLOCK,
+				    NULL);
+    if (iostat == G_IO_STATUS_ERROR) {
+      g_io_channel_unref(hookserv->chan);
+      g_timeout_add_seconds(1, (GSourceFunc) try_to_connect, hookserv);
+      return FALSE;
+    }
+  }
+
+  /*debug("set non blocking"); */
+
+  /* this is fun, async io watcher */
+  hookserv->hhsi.line = 0;
+  hookserv->hhsi.command_args = NULL;
+  hookserv->hhsi.command_name = NULL;
+  hookserv->event_source =
+    g_io_add_watch_full(hookserv->chan, G_PRIORITY_DEFAULT,
+			G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+			(GIOFunc) handle_hook_server_input, hookserv,
+			(GDestroyNotify) watch_killer);
+
+  debug("hook client connected");
+  hookserv->connected = TRUE;
+  g_hook_list_invoke(&(hookserv->onconnect_hooklist), FALSE);
+
+  /*debug("added watch");*/
+  return FALSE;
+}
+
+/* should only be called in glib main loop */
+/* returns a gboolean because it is a GSourceFunc */
+gboolean caja_dropbox_hooks_force_reconnect(CajaDropboxHookserv *hookserv) {
+  debug_enter();
+
+  if (hookserv->connected == FALSE) {
+    return FALSE;
+  }
+
+  debug("forcing hook to reconnect");
+
+  g_assert(hookserv->event_source >= 0);
+
+  if (hookserv->event_source > 0) {
+    g_source_remove(hookserv->event_source);
+  }
+  else if (hookserv->event_source == 0) {
+    debug("event source was zero!!!!!");
+  }
+
+  return FALSE;
+}
+
+gboolean
+caja_dropbox_hooks_is_connected(CajaDropboxHookserv *hookserv) {<--- Parameter 'hookserv' can be declared as pointer to const
+  return hookserv->connected;
+}
+
+void
+caja_dropbox_hooks_setup(CajaDropboxHookserv *hookserv) {
+  hookserv->dispatch_table = g_hash_table_new_full((GHashFunc) g_str_hash,
+						   (GEqualFunc) g_str_equal,
+						   g_free, g_free);
+  hookserv->connected = FALSE;
+
+  g_hook_list_init(&(hookserv->ondisconnect_hooklist), sizeof(GHook));
+  g_hook_list_init(&(hookserv->onconnect_hooklist), sizeof(GHook));
+}
+
+void
+caja_dropbox_hooks_add_on_disconnect_hook(CajaDropboxHookserv *hookserv,
+					      DropboxHookClientConnectHook dhcch,
+					      gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(hookserv->ondisconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(hookserv->ondisconnect_hooklist), newhook);
+}
+
+void
+caja_dropbox_hooks_add_on_connect_hook(CajaDropboxHookserv *hookserv,
+					   DropboxHookClientConnectHook dhcch,
+					   gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(hookserv->onconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(hookserv->onconnect_hooklist), newhook);
+}
+
+void caja_dropbox_hooks_add(CajaDropboxHookserv *ndhs,
+				const gchar *hook_name,
+				DropboxUpdateHook hook, gpointer ud) {
+  HookData *hd;
+  hd = g_new(HookData, 1);
+  hd->hook = hook;
+  hd->ud = ud;
+  g_hash_table_insert(ndhs->dispatch_table, g_strdup(hook_name), hd);
+}
+
+void
+caja_dropbox_hooks_start(CajaDropboxHookserv *hookserv) {
+  try_to_connect(hookserv);
+}
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/1.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/1.html new file mode 100644 index 0000000..7709acb --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/1.html @@ -0,0 +1,335 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * g-util.h
+ * Helper macros.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef G_UTIL_H
+#define G_UTIL_H
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <glib/gprintf.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+G_BEGIN_DECLS
+
+#ifdef ND_DEBUG
+
+#define debug_enter() {g_print("Entering "); g_print(__FUNCTION__); g_printf("\n");}
+#define debug(format, ...) {g_print(__FUNCTION__); g_print(": "); \
+    g_printf(format, ## __VA_ARGS__); g_print("\n");}
+#define debug_return(v) {g_print("Exiting "); g_print(__FUNCTION__); g_printf("\n"); return v;}
+
+#else
+
+#define debug_enter() do {} while(0)
+#define debug(format, ...) do {} while(0)
+#define debug_return(v) do {} while(0)
+
+#endif
+
+G_END_DECLS
+
+#endif
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/10.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/10.html new file mode 100644 index 0000000..12dd722 --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/10.html @@ -0,0 +1,1983 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * dropbox-command-client.c
+ * Implements connection handling and C interface for the Dropbox command socket.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <sys/types.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <sys/socket.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <sys/un.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <errno.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <unistd.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <fcntl.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include <stdarg.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <string.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "g-util.h"
+#include "dropbox-client-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+/* TODO: make this asynchronous ;) */
+
+/*
+  this is a tiny hack, necessitated by the fact that
+  finish_file info command is in caja_dropbox,
+  this can be cleaned up once the file_info_command isn't a special
+  case anylonger
+*/
+gboolean caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *);
+
+typedef struct {
+  DropboxCommandClient *dcc;
+  guint connect_attempt;
+} ConnectionAttempt;
+
+typedef struct {
+  DropboxCommandClientConnectionAttemptHook h;
+  gpointer ud;
+} DropboxCommandClientConnectionAttempt;
+
+typedef struct {
+  DropboxGeneralCommand *dgc;
+  GHashTable *response;
+} DropboxGeneralCommandResponse;
+
+static gboolean
+on_connect(DropboxCommandClient *dcc) {
+  g_hook_list_invoke(&(dcc->onconnect_hooklist), FALSE);
+  return FALSE;
+}
+
+static gboolean
+on_disconnect(DropboxCommandClient *dcc) {
+  g_hook_list_invoke(&(dcc->ondisconnect_hooklist), FALSE);
+  return FALSE;
+}
+
+static gboolean
+on_connection_attempt(ConnectionAttempt *ca) {
+  GList *ll;
+
+  for (ll = ca->dcc->ca_hooklist; ll != NULL; ll = g_list_next(ll)) {
+    DropboxCommandClientConnectionAttempt *dccca =
+      (DropboxCommandClientConnectionAttempt *)(ll->data);
+    dccca->h(ca->connect_attempt, dccca->ud);
+  }
+
+  g_free(ca);
+
+  return FALSE;
+}
+
+static gboolean
+receive_args_until_done(GIOChannel *chan, GHashTable *return_table,
+			GError **err) {
+  GIOStatus iostat;
+  GError *tmp_error = NULL;
+  guint numargs = 0;
+
+  while (1) {
+    gchar *line;
+    gsize term_pos;
+
+    /* if we are getting too many args, connection could be malicious */
+    if (numargs >= 20) {
+      g_set_error(err,
+		  g_quark_from_static_string("malicious connection"),
+		  0, "malicious connection");
+      return FALSE;
+    }
+
+    /* get the string */
+    iostat = g_io_channel_read_line(chan, &line, NULL,
+				    &term_pos, &tmp_error);
+    if (iostat == G_IO_STATUS_ERROR || tmp_error != NULL) {
+      g_free(line);
+      if (tmp_error != NULL) {
+	g_propagate_error(err, tmp_error);
+      }
+      return FALSE;
+    }
+    else if (iostat == G_IO_STATUS_EOF) {
+      g_free(line);
+      g_set_error(err,
+		  g_quark_from_static_string("connection closed"),
+		  0, "connection closed");
+      return FALSE;
+    }
+
+    *(line+term_pos) = '\0';
+
+    if (strcmp("done", line) == 0) {
+      g_free(line);
+      break;
+    }
+    else {
+      gboolean parse_result;
+
+      parse_result = dropbox_client_util_command_parse_arg(line, return_table);
+      g_free(line);
+
+      if (FALSE == parse_result) {
+	g_set_error(err,
+		    g_quark_from_static_string("parse error"),
+		    0, "parse error");
+	return FALSE;
+      }
+    }
+
+    numargs += 1;
+  }
+
+  return TRUE;
+}
+
+/*
+  sends a command to the dropbox server
+  returns an hash of the return values
+
+  in theory, this should disconnection errors
+  but it doesn't matter right now, any error is a sufficient
+  condition to disconnect
+*/
+static GHashTable *
+send_command_to_db(GIOChannel *chan, const gchar *command_name,
+		   GHashTable *args, GError **err) {
+  GError *tmp_error = NULL;
+  GIOStatus iostat;
+  gsize bytes_trans;
+  gchar *line;
+
+  g_assert(chan != NULL);
+  g_assert(command_name != NULL);
+
+
+#define WRITE_OR_DIE_SANI(s,l) {					\
+    gchar *sani_s;							\
+    sani_s = dropbox_client_util_sanitize(s);				\
+    iostat = g_io_channel_write_chars(chan, sani_s,l, &bytes_trans,	\
+				      &tmp_error);			\
+    g_free(sani_s);							\
+    if (iostat == G_IO_STATUS_ERROR ||					\
+	iostat == G_IO_STATUS_AGAIN) {					\
+      if (tmp_error != NULL) {						\
+	g_propagate_error(err, tmp_error);				\
+      }									\
+      return NULL;							\
+    }									\
+  }
+
+#define WRITE_OR_DIE(s,l) {						\
+    iostat = g_io_channel_write_chars(chan, s,l, &bytes_trans,		\
+				      &tmp_error);			\
+    if (iostat == G_IO_STATUS_ERROR ||					\
+	iostat == G_IO_STATUS_AGAIN) {					\
+      if (tmp_error != NULL) {						\
+	g_propagate_error(err, tmp_error);				\
+      }									\
+      return NULL;							\
+    }									\
+  }
+
+  /* send command to server */
+  WRITE_OR_DIE_SANI(command_name, -1);
+  WRITE_OR_DIE("\n", -1);
+
+  if (args != NULL) {
+    GList *keys, *li;
+
+    keys = g_hash_table_get_keys(args);
+
+    for (li = keys; li != NULL; li = g_list_next(li)) {
+      int i;
+      gchar **value;
+
+      WRITE_OR_DIE_SANI((gchar *) li->data, -1);
+
+      value = g_hash_table_lookup(args, li->data);
+      for (i = 0; value[i] != NULL; i++) {
+	WRITE_OR_DIE("\t", -1);
+	WRITE_OR_DIE_SANI(value[i], -1);
+      }
+      WRITE_OR_DIE("\n", -1);
+    }
+
+    g_list_free(keys);
+  }
+
+  WRITE_OR_DIE("done\n", -1);
+
+#undef WRITE_OR_DIE
+#undef WRITE_OR_DIE_SANI
+
+  g_io_channel_flush(chan, &tmp_error);
+  if (tmp_error != NULL) {
+    g_propagate_error(err, tmp_error);
+    return NULL;
+  }
+
+  /* now we have to read the data */
+  iostat = g_io_channel_read_line(chan, &line, NULL,
+				  NULL, &tmp_error);
+  if (iostat == G_IO_STATUS_ERROR) {
+    g_assert(line == NULL);
+    g_propagate_error(err, tmp_error);
+    return NULL;
+  }
+  else if (iostat == G_IO_STATUS_AGAIN) {
+    g_assert(line == NULL);
+    g_set_error(err,
+		g_quark_from_static_string("dropbox command connection timed out"),
+		0,
+		"dropbox command connection timed out");
+    return NULL;
+  }
+  else if (iostat == G_IO_STATUS_EOF) {
+    g_assert(line == NULL);
+    g_set_error(err,
+		g_quark_from_static_string("dropbox command connection closed"),
+		0,
+		"dropbox command connection closed");
+    return NULL;
+  }
+
+  /* if the response was okay */
+  if (strncmp(line, "ok\n", 3) == 0) {
+    GHashTable *return_table =
+      g_hash_table_new_full((GHashFunc) g_str_hash,
+			    (GEqualFunc) g_str_equal,
+			    (GDestroyNotify) g_free,
+			    (GDestroyNotify) g_strfreev);
+
+    g_free(line);
+    line = NULL;
+
+    receive_args_until_done(chan, return_table, &tmp_error);
+    if (tmp_error != NULL) {
+      g_hash_table_destroy(return_table);
+      g_propagate_error(err, tmp_error);
+      return NULL;
+    }
+
+    return return_table;
+  }
+  /* otherwise */
+  else {
+    /* read errors off until we get done */
+    do {
+      g_free(line);
+      line = NULL;
+
+      /* clear string */
+      iostat = g_io_channel_read_line(chan, &line, NULL,
+				      NULL, &tmp_error);
+      if (iostat == G_IO_STATUS_ERROR) {
+	g_assert(line == NULL);
+	g_propagate_error(err, tmp_error);
+	return NULL;
+      }
+      else if (iostat == G_IO_STATUS_AGAIN) {
+	g_assert(line == NULL);
+	g_set_error(err,
+		    g_quark_from_static_string("dropbox command connection timed out"),
+		    0,
+		    "dropbox command connection timed out");
+	return NULL;
+
+      }
+      else if (iostat == G_IO_STATUS_EOF) {
+	g_assert(line == NULL);
+	g_set_error(err,
+		    g_quark_from_static_string("dropbox command connection closed"),
+		    0,
+		    "dropbox command connection closed");
+	return NULL;
+      }
+
+      /* we got our line */
+    } while (strncmp(line, "done\n", 5) != 0);
+
+    g_free(line);
+    return NULL;
+  }
+}
+
+static void
+do_file_info_command(GIOChannel *chan, DropboxFileInfoCommand *dfic, GError **gerr) {
+  /* we need to send two requests to dropbox:
+     file status, and folder_tags */
+  GError *tmp_gerr = NULL;
+  DropboxFileInfoCommandResponse *dficr;
+  GHashTable *file_status_response = NULL, *args, *folder_tag_response = NULL, *emblems_response = NULL;
+  gchar *filename = NULL;
+
+  {
+    gchar *filename_un, *uri;
+    uri = caja_file_info_get_uri(dfic->file);
+    filename_un = uri ? g_filename_from_uri(uri, NULL, NULL): NULL;
+    g_free(uri);
+    if (filename_un) {
+      filename = g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL);
+      g_free(filename_un);
+      if (filename == NULL) {
+        /* oooh, filename wasn't correctly encoded. mark as  */
+	debug("file wasn't correctly encoded %s", filename_un);
+      }
+    }
+  }
+
+  if (filename == NULL) {
+    /* We couldn't get the filename.  Just return empty. */
+    goto exit;
+  }
+
+  args = g_hash_table_new_full((GHashFunc) g_str_hash,
+			       (GEqualFunc) g_str_equal,
+			       (GDestroyNotify) g_free,
+			       (GDestroyNotify) g_strfreev);
+  {
+    gchar **path_arg;
+    path_arg = g_new(gchar *, 2);
+    path_arg[0] = g_strdup(filename);
+    path_arg[1] = NULL;
+    g_hash_table_insert(args, g_strdup("path"), path_arg);
+  }
+
+  emblems_response = send_command_to_db(chan, "get_emblems", args, NULL);
+  if (emblems_response) {
+      /* Don't need to do the other calls. */
+      g_hash_table_unref(args);
+      goto exit;
+  }
+
+  /* send status command to server */
+  file_status_response = send_command_to_db(chan, "icon_overlay_file_status",
+					    args, &tmp_gerr);
+  g_hash_table_unref(args);
+  args = NULL;
+  if (tmp_gerr != NULL) {
+    g_free(filename);
+    g_assert(file_status_response == NULL);
+    g_propagate_error(gerr, tmp_gerr);
+    return;
+  }
+
+  if (caja_file_info_is_directory(dfic->file)) {
+    args = g_hash_table_new_full((GHashFunc) g_str_hash,
+				 (GEqualFunc) g_str_equal,
+				 (GDestroyNotify) g_free,
+				 (GDestroyNotify) g_strfreev);
+    {
+      gchar **paths_arg;
+      paths_arg = g_new(gchar *, 2);
+      paths_arg[0] = g_strdup(filename);
+      paths_arg[1] = NULL;
+      g_hash_table_insert(args, g_strdup("path"), paths_arg);
+    }
+
+    folder_tag_response =
+      send_command_to_db(chan, "get_folder_tag", args, &tmp_gerr);
+    g_hash_table_unref(args);
+    args = NULL;
+    if (tmp_gerr != NULL) {
+      if (file_status_response != NULL)
+	g_hash_table_destroy(file_status_response);
+      g_assert(folder_tag_response == NULL);
+      g_propagate_error(gerr, tmp_gerr);
+      return;
+    }
+  }
+
+  /* great server responded perfectly,
+     now let's get this request done,
+     ...in the glib main loop */
+exit:
+  dficr = g_new0(DropboxFileInfoCommandResponse, 1);
+  dficr->dfic = dfic;
+  dficr->folder_tag_response = folder_tag_response;
+  dficr->file_status_response = file_status_response;
+  dficr->emblems_response = emblems_response;
+  g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
+
+  g_free(filename);
+
+  return;
+}
+
+static gboolean
+finish_general_command(DropboxGeneralCommandResponse *dgcr) {
+  if (dgcr->dgc->handler != NULL) {
+    dgcr->dgc->handler(dgcr->response, dgcr->dgc->handler_ud);
+  }
+
+  if (dgcr->response != NULL) {
+    g_hash_table_unref(dgcr->response);
+  }
+
+  g_free(dgcr->dgc->command_name);
+  if (dgcr->dgc->command_args != NULL) {
+    g_hash_table_unref(dgcr->dgc->command_args);
+  }
+  g_free(dgcr->dgc);
+  g_free(dgcr);
+
+  return FALSE;
+}
+
+static void
+do_general_command(GIOChannel *chan, DropboxGeneralCommand *dcac,
+		   GError **gerr) {
+  GError *tmp_gerr = NULL;
+  GHashTable *response;
+
+  /* send status command to server */
+  response = send_command_to_db(chan, dcac->command_name,
+				dcac->command_args, &tmp_gerr);
+  if (tmp_gerr != NULL) {
+    g_assert(response == NULL);
+    g_propagate_error(gerr, tmp_gerr);
+    return;
+  }
+
+  /* great, the server did the command perfectly,
+     now call the handler with the response */
+  {
+    DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1);
+    dgcr->dgc = dcac;
+    dgcr->response = response;
+    finish_general_command(dgcr);
+  }
+
+  return;
+}
+
+static gboolean
+check_connection(GIOChannel *chan) {
+  gchar fake_buf[4096];
+  gsize bytes_read;
+  GError *tmp_error = NULL;
+  GIOFlags flags;
+  GIOStatus ret, iostat;
+
+  flags = g_io_channel_get_flags(chan);
+
+  /* set non-blocking */
+  ret = g_io_channel_set_flags(chan, flags | G_IO_FLAG_NONBLOCK, NULL);
+  if (ret == G_IO_STATUS_ERROR) {
+    return FALSE;
+  }
+
+  iostat = g_io_channel_read_chars(chan, fake_buf,
+				   sizeof(fake_buf),
+				   &bytes_read, &tmp_error);
+
+  ret = g_io_channel_set_flags(chan, flags, NULL);
+  if (ret == G_IO_STATUS_ERROR) {
+    return FALSE;
+  }
+
+  /* this makes us disconnect from bad servers
+     (those that send us information without us asking for it) */
+  return iostat == G_IO_STATUS_AGAIN;
+}
+
+static gpointer
+dropbox_command_client_thread(DropboxCommandClient *data);
+
+static void
+end_request(DropboxCommand *dc) {
+  if ((gpointer (*)(DropboxCommandClient *data)) dc != &dropbox_command_client_thread) {
+    switch (dc->request_type) {
+    case GET_FILE_INFO: {
+      DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) dc;
+      DropboxFileInfoCommandResponse *dficr = g_new0(DropboxFileInfoCommandResponse, 1);
+      dficr->dfic = dfic;
+      dficr->file_status_response = NULL;
+      dficr->emblems_response = NULL;
+      g_idle_add((GSourceFunc) caja_dropbox_finish_file_info_command, dficr);
+    }
+      break;
+    case GENERAL_COMMAND: {
+      DropboxGeneralCommand *dgc = (DropboxGeneralCommand *) dc;
+      DropboxGeneralCommandResponse *dgcr = g_new0(DropboxGeneralCommandResponse, 1);
+      dgcr->dgc = dgc;
+      dgcr->response = NULL;
+      finish_general_command(dgcr);
+    }
+      break;
+    default:
+      g_assert_not_reached();
+      break;
+    }
+  }
+}
+
+
+static gpointer
+dropbox_command_client_thread(DropboxCommandClient *dcc) {
+  struct sockaddr_un addr;
+  socklen_t addr_len;
+  int connection_attempts = 1;
+
+  /* intialize address structure */
+  addr.sun_family = AF_UNIX;
+  g_snprintf(addr.sun_path,
+	     sizeof(addr.sun_path),
+	     "%s/.dropbox/command_socket",
+	     g_get_home_dir());
+  addr_len = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path);
+
+  while (1) {
+    GIOChannel *chan = NULL;
+    GError *gerr = NULL;
+    int sock;
+    gboolean failflag = TRUE;
+
+    do {
+      int flags;
+
+      if (0 > (sock = socket(PF_UNIX, SOCK_STREAM, 0))) {
+	/* WTF */
+	break;
+      }
+
+      /* set timeout on socket, to protect against
+	 bad servers */
+      {
+	struct timeval tv = {3, 0};
+	if (0 > setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
+			   &tv, sizeof(struct timeval)) ||
+	    0 > setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
+			   &tv, sizeof(struct timeval))) {
+	  /* debug("setsockopt failed"); */
+	  break;
+	}
+      }
+
+      /* set native non-blocking, for connect timeout */
+      {
+	if ((flags = fcntl(sock, F_GETFL, 0)) < 0 ||
+	    fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
+	  /* debug("fcntl failed"); */
+	  break;
+	}
+      }
+
+      /* if there was an error we have to try again later */
+      if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
+	if (errno == EINPROGRESS) {
+	  fd_set writers;
+	  struct timeval tv = {1, 0};
+
+	  FD_ZERO(&writers);
+	  FD_SET(sock, &writers);
+
+	  /* if nothing was ready after 3 seconds, fail out homie */
+	  if (select(sock+1, NULL, &writers, NULL, &tv) == 0) {
+	    /* debug("connection timeout"); */
+	    break;
+	  }
+
+	  if (connect(sock, (struct sockaddr *) &addr, addr_len) < 0) {
+	    /*	    debug("couldn't connect to command server after 1 second"); */
+	    break;
+	  }
+	}
+	/* errno != EINPROGRESS */
+	else {
+	  /*	  debug("bad connection"); */
+	  break;
+	}
+      }
+
+      /* set back to blocking */
+      if (fcntl(sock, F_SETFL, flags) < 0) {
+	/* debug("fcntl2 failed"); */
+	break;
+      }
+
+      failflag = FALSE;
+    } while (0);
+
+    if (failflag) {
+      ConnectionAttempt *ca = g_new(ConnectionAttempt, 1);
+      ca->dcc = dcc;
+      ca->connect_attempt = connection_attempts;
+      g_idle_add((GSourceFunc) on_connection_attempt, ca);
+      if (sock >= 0) {
+	close(sock);
+      }
+      g_usleep(G_USEC_PER_SEC);
+      connection_attempts++;
+      continue;
+    }
+    else {
+      connection_attempts = 0;
+    }
+
+    /* connected */
+    debug("command client connected");
+
+    chan = g_io_channel_unix_new(sock);
+    g_io_channel_set_close_on_unref(chan, TRUE);
+    g_io_channel_set_line_term(chan, "\n", -1);
+
+#define SET_CONNECTED_STATE(s)     {			\
+      g_mutex_lock(&(dcc->command_connected_mutex));	\
+      dcc->command_connected = s;			\
+      g_mutex_unlock(&(dcc->command_connected_mutex));	\
+    }
+
+    SET_CONNECTED_STATE(TRUE);
+
+    g_idle_add((GSourceFunc) on_connect, dcc);
+
+    while (1) {
+      DropboxCommand *dc;
+
+      while (1) {
+
+	/* get a request from caja */
+	dc = g_async_queue_timeout_pop(dcc->command_queue, G_USEC_PER_SEC / 10);
+	if (dc != NULL) {
+	  break;
+	}
+	else {
+	  if (check_connection(chan) == FALSE) {
+	    goto BADCONNECTION;
+	  }
+	}
+      }
+
+      /* this pointer should be unique */
+      if ((gpointer (*)(DropboxCommandClient *data)) dc == &dropbox_command_client_thread) {
+	debug("got a reset request");
+	goto BADCONNECTION;
+      }
+
+      switch (dc->request_type) {
+      case GET_FILE_INFO: {
+	debug("doing file info command");
+	do_file_info_command(chan, (DropboxFileInfoCommand *) dc, &gerr);
+      }
+	break;
+      case GENERAL_COMMAND: {
+	debug("doing general command");
+	do_general_command(chan, (DropboxGeneralCommand *) dc, &gerr);
+      }
+	break;
+      default:
+	g_assert_not_reached();
+	break;
+      }
+
+      debug("done.");
+
+      if (gerr != NULL) {
+	//	debug("COMMAND ERROR*****************************");
+	/* mark this request as never to be completed */
+	end_request(dc);
+
+	debug("command error: %s", gerr->message);
+
+	g_error_free(gerr);
+      BADCONNECTION:
+	/* grab all the rest of the data off the async queue and mark it
+	   never to be completed, who knows how long we'll be disconnected */
+	while ((dc = g_async_queue_try_pop(dcc->command_queue)) != NULL) {
+	  end_request(dc);
+	}
+
+	g_io_channel_unref(chan);
+
+	SET_CONNECTED_STATE(FALSE);
+
+	/* call the disconnect handler */
+	g_idle_add((GSourceFunc) on_disconnect, dcc);
+
+	break;
+      }
+    }
+
+#undef SET_CONNECTED_STATE
+  }
+
+  return NULL;
+}
+
+/* thread safe */
+gboolean
+dropbox_command_client_is_connected(DropboxCommandClient *dcc) {
+  gboolean command_connected;
+
+  g_mutex_lock(&(dcc->command_connected_mutex));
+  command_connected = dcc->command_connected;
+  g_mutex_unlock(&(dcc->command_connected_mutex));
+
+  return command_connected;
+}
+
+/* thread safe */
+void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc) {
+  if (dropbox_command_client_is_connected(dcc) == TRUE) {
+    debug("forcing command to reconnect");
+    dropbox_command_client_request(dcc, (DropboxCommand *) &dropbox_command_client_thread);
+  }
+}
+
+/* thread safe */
+void
+dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc) {
+  g_async_queue_push(dcc->command_queue, dc);
+}
+
+/* should only be called once on initialization */
+void
+dropbox_command_client_setup(DropboxCommandClient *dcc) {
+  dcc->command_queue = g_async_queue_new();
+  g_mutex_init(&(dcc->command_connected_mutex));
+  dcc->command_connected = FALSE;
+  dcc->ca_hooklist = NULL;
+
+  g_hook_list_init(&(dcc->ondisconnect_hooklist), sizeof(GHook));
+  g_hook_list_init(&(dcc->onconnect_hooklist), sizeof(GHook));
+}
+
+void
+dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
+					      DropboxCommandClientConnectHook dhcch,
+					      gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(dcc->ondisconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(dcc->ondisconnect_hooklist), newhook);
+}
+
+void
+dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
+					   DropboxCommandClientConnectHook dhcch,
+					   gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(dcc->onconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(dcc->onconnect_hooklist), newhook);
+}
+
+void
+dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
+						   DropboxCommandClientConnectionAttemptHook dhcch,
+						   gpointer ud) {
+  DropboxCommandClientConnectionAttempt *newhook;
+
+  debug("shouldn't be here...");
+
+  newhook = g_new(DropboxCommandClientConnectionAttempt, 1);
+  newhook->h = dhcch;
+  newhook->ud = ud;
+
+  dcc->ca_hooklist = g_list_append(dcc->ca_hooklist, newhook);
+}
+
+/* should only be called once on initialization */
+void
+dropbox_command_client_start(DropboxCommandClient *dcc) {
+  /* setup the connect to the command server */
+  debug("starting command thread");
+  g_thread_new(NULL, (GThreadFunc) dropbox_command_client_thread, dcc);
+}
+
+/* thread safe */
+void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
+					 const char *command) {
+  DropboxGeneralCommand *dgc;
+
+  dgc = g_new(DropboxGeneralCommand, 1);
+
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup(command);
+  dgc->command_args = NULL;
+  dgc->handler = NULL;
+  dgc->handler_ud = NULL;
+
+  dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
+}
+
+/* thread safe */
+/* this is the C API, there is another send_command_to_db
+   that is more the actual over the wire command */
+void dropbox_command_client_send_command(DropboxCommandClient *dcc,
+					 CajaDropboxCommandResponseHandler h,
+					 gpointer ud,
+					 const char *command, ...) {
+  va_list ap;
+  DropboxGeneralCommand *dgc;
+  gchar *na;
+  va_start(ap, command);
+
+  dgc = g_new(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup(command);
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  /*
+   * NB: The handler is called in the DropboxCommandClient Thread.  If you need
+   * it in the main thread you must call g_idle_add in the callback.
+   */
+  dgc->handler = h;
+  dgc->handler_ud = ud;
+
+  while ((na = va_arg(ap, char *)) != NULL) {
+    gchar **is_active_arg;
+
+    is_active_arg = g_new(gchar *, 2);
+
+    g_hash_table_insert(dgc->command_args,
+			g_strdup(na), is_active_arg);
+
+    is_active_arg[0] = g_strdup(va_arg(ap, char *));
+    is_active_arg[1] = NULL;
+  }
+  va_end(ap);
+
+  dropbox_command_client_request(dcc, (DropboxCommand *) dgc);
+}
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/11.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/11.html new file mode 100644 index 0000000..4256be3 --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/11.html @@ -0,0 +1,345 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * dropbox.c
+ * Caja module registering functions for the Dropbox extension.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#endif
+
+#include <glib-object.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "caja-dropbox.h"
+
+static GType type_list[1];
+
+void
+caja_module_initialize (GTypeModule *module) {
+  g_print ("Initializing %s\n", PACKAGE_STRING);
+
+  caja_dropbox_register_type (module);
+  type_list[0] = CAJA_TYPE_DROPBOX;
+
+  dropbox_use_operation_in_progress_workaround = TRUE;
+}
+
+void
+caja_module_shutdown (void) {
+  g_print ("Shutting down dropbox extension\n");
+}
+
+void
+caja_module_list_types (const GType **types,
+                            int *num_types) {
+  *types = type_list;
+  *num_types = G_N_ELEMENTS (type_list);
+}
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/2.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/2.html new file mode 100644 index 0000000..9bceebc --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/2.html @@ -0,0 +1,367 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * async-io-coroutine.h
+ * Macros to simplify writing coroutines for the glib main loop.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef ASYNC_IO_COROUTINE_H
+#define ASYNC_IO_COROUTINE_H
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+G_BEGIN_DECLS
+
+#define CRBEGIN(pos) switch (pos) { case 0:
+#define CREND } return FALSE
+#define CRYIELD(pos) do { pos = __LINE__; return TRUE; case __LINE__:;} while (0)
+#define CRHALT return FALSE
+
+#define CRREADLINE(pos, chan, where)                             \
+  while (1) {							\
+    gchar *__line;						\
+    gsize __line_length, __newline_pos;				\
+    GIOStatus __iostat;							\
+    									\
+    __iostat = g_io_channel_read_line(chan, &__line,			\
+				      &__line_length,			\
+				      &__newline_pos, NULL);		\
+    if (__iostat == G_IO_STATUS_AGAIN) {				\
+      CRYIELD(pos);                                                \
+    }									\
+    else if (__iostat == G_IO_STATUS_NORMAL) {				\
+      *(__line + __newline_pos) = '\0';				\
+      where = __line;						\
+      break;							\
+    }								\
+    else if (__iostat == G_IO_STATUS_EOF ||			\
+	     __iostat == G_IO_STATUS_ERROR) {			\
+      CRHALT;							\
+    }								\
+    else {							\
+      g_assert_not_reached();					\
+      CRHALT;							\
+    }								\
+  }
+
+G_END_DECLS
+
+#endif
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/3.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/3.html new file mode 100644 index 0000000..1d5b7f7 --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/3.html @@ -0,0 +1,315 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * dropbox-client-util.h
+ * Header file for dropbox-client-util.c
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DROPBOX_CLIENT_UTIL_H
+#define DROPBOX_CLIENT_UTIL_H
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+G_BEGIN_DECLS
+
+gchar *dropbox_client_util_sanitize(const gchar *a);
+gchar *dropbox_client_util_desanitize(const gchar *a);
+
+gboolean
+dropbox_client_util_command_parse_arg(const gchar *line, GHashTable *return_table);
+
+G_END_DECLS
+
+#endif
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/4.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/4.html new file mode 100644 index 0000000..674a040 --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/4.html @@ -0,0 +1,395 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox-hooks.h
+ * Header file for caja-dropbox-hooks.c
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CAJA_DROPBOX_HOOKS_H
+#define CAJA_DROPBOX_HOOKS_H
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+G_BEGIN_DECLS
+
+typedef void (*DropboxUpdateHook)(GHashTable *, gpointer);
+typedef void (*DropboxHookClientConnectHook)(gpointer);
+
+typedef struct {
+  GIOChannel *chan;
+  int socket;
+  struct {
+    int line;
+    gchar *command_name;
+    GHashTable *command_args;
+    int numargs;
+  } hhsi;
+  gboolean connected;
+  guint event_source;
+  GHashTable *dispatch_table;
+  GHookList ondisconnect_hooklist;
+  GHookList onconnect_hooklist;
+} CajaDropboxHookserv;
+
+void
+caja_dropbox_hooks_setup(CajaDropboxHookserv *);
+
+void
+caja_dropbox_hooks_start(CajaDropboxHookserv *);
+
+gboolean
+caja_dropbox_hooks_is_connected(CajaDropboxHookserv *);
+
+gboolean
+caja_dropbox_hooks_force_reconnect(CajaDropboxHookserv *);
+
+void
+caja_dropbox_hooks_add(CajaDropboxHookserv *ndhs,
+			   const gchar *hook_name,
+			   DropboxUpdateHook hook, gpointer ud);
+void
+caja_dropbox_hooks_add_on_disconnect_hook(CajaDropboxHookserv *hookserv,
+					      DropboxHookClientConnectHook dhcch,
+					      gpointer ud);
+
+void
+caja_dropbox_hooks_add_on_connect_hook(CajaDropboxHookserv *hookserv,
+					   DropboxHookClientConnectHook dhcch,
+					   gpointer ud);
+
+
+G_END_DECLS
+
+#endif
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/5.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/5.html new file mode 100644 index 0000000..4c8f51f --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/5.html @@ -0,0 +1,2233 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
+967
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.c
+ * Implements the Caja extension API for Dropbox.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> /* for GETTEXT_PACKAGE */<--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#endif
+
+#include <sys/types.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <sys/socket.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <sys/un.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <errno.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <unistd.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <ctype.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <glib/gprintf.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <glib-object.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <gtk/gtk.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include <libcaja-extension/caja-extension-types.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <libcaja-extension/caja-menu-provider.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <libcaja-extension/caja-info-provider.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox.h"
+#include "caja-dropbox-hooks.h"
+
+static char *emblems[] = {"dropbox-uptodate", "dropbox-syncing", "dropbox-unsyncable"};
+gchar *DEFAULT_EMBLEM_PATHS[2] = { EMBLEMDIR , NULL };
+
+gboolean dropbox_use_operation_in_progress_workaround;
+
+static GType dropbox_type = 0;
+
+/*
+  Simplifies a path by removing navigation elements such as '.' and '..'
+
+  Arguments:
+    - path: input path to be canonicalized
+
+  Returns:
+    Canonicalized path if input path is valid.
+    NULL otherwise.
+*/
+static gchar *
+canonicalize_path(gchar *path) {
+  int i, j = 0;
+  gchar *toret = NULL;
+  gchar **cpy, **elts;
+
+  g_assert(path != NULL);
+  g_assert(path[0] == '/');
+
+  elts = g_strsplit(path, "/", 0);
+  cpy = g_new(gchar *, g_strv_length(elts)+1);
+  cpy[j++] = "/";
+  for (i = 0; elts[i] != NULL; i++) {
+    if (strcmp(elts[i], "..") == 0) {
+      if (j > 0) {
+        j--;
+      }
+      else {
+        // Input path has too many parent directory references and is invalid
+        toret = NULL;
+        goto exit;
+      }
+    }
+    else if (strcmp(elts[i], ".") != 0 && elts[i][0] != '\0') {
+      cpy[j++] = elts[i];
+    }
+  }
+
+  cpy[j] = NULL;
+  toret = g_build_filenamev(cpy);
+
+exit:
+  g_free(cpy);
+  g_strfreev(elts);
+
+  return toret;
+}
+
+static void
+reset_file(CajaFileInfo *file) {
+  debug("resetting file %p", (void *) file);
+  caja_file_info_invalidate_extension_info(file);
+}
+
+static gboolean
+reset_all_files(CajaDropbox *cvs) {
+  /* Only run this on the main loop or you'll cause problems. */
+
+  /* this works because you can call a function pointer with
+     more arguments than it takes */
+  g_hash_table_foreach(cvs->obj2filename, (GHFunc) reset_file, NULL);
+  return FALSE;
+}
+
+
+static void
+when_file_dies(CajaDropbox *cvs, CajaFileInfo *address) {
+  gchar *filename;
+
+  filename = g_hash_table_lookup(cvs->obj2filename, address);
+
+  /* we never got a change to view this file */
+  if (filename == NULL) {
+    return;
+  }
+
+  /* too chatty */
+  /*  debug("removing %s <-> 0x%p", filename, address); */
+
+  g_hash_table_remove(cvs->filename2obj, filename);
+  g_hash_table_remove(cvs->obj2filename, address);
+}
+
+static void
+changed_cb(CajaFileInfo *file, CajaDropbox *cvs) {
+  /* check if this file's path has changed, if so update the hash and invalidate
+     the file */
+  gchar *filename, *pfilename;
+  gchar *filename2;
+  gchar *uri;
+
+  uri = caja_file_info_get_uri(file);
+  pfilename = g_filename_from_uri(uri, NULL, NULL);
+  filename = pfilename ? canonicalize_path(pfilename) : NULL;
+
+  /* Canonicalization will only null-out a non-null filename if it is invalid */
+  g_assert((pfilename == NULL && filename == NULL) || (pfilename != NULL && filename != NULL));
+
+  filename2 =  g_hash_table_lookup(cvs->obj2filename, file);
+
+  g_free(pfilename);
+  g_free(uri);
+
+  /* if filename2 is NULL we've never seen this file in update_file_info */
+  if (filename2 == NULL) {
+    g_free(filename);
+    return;
+  }
+
+  if (filename == NULL) {
+      /* A file has moved to offline storage. Lets remove it from our tables. */
+      g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+      g_hash_table_remove(cvs->filename2obj, filename2);
+      g_hash_table_remove(cvs->obj2filename, file);
+      g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+      reset_file(file);
+      return;
+  }
+
+  /* this is a hack, because caja doesn't do this for us, for some reason
+     the file's path has changed */
+  if (strcmp(filename, filename2) != 0) {
+    debug("shifty old: %s, new %s", filename2, filename);
+
+    /* gotta do this first, the call after this frees filename2 */
+    g_hash_table_remove(cvs->filename2obj, filename2);
+
+    g_hash_table_replace(cvs->obj2filename, file, g_strdup(filename));
+
+    {
+      CajaFileInfo *f2;
+      /* we shouldn't have another mapping from filename to an object */
+      f2 = g_hash_table_lookup(cvs->filename2obj, filename);
+      if (f2 != NULL) {
+	/* lets fix it if it's true, just remove the mapping */
+	g_hash_table_remove(cvs->filename2obj, filename);
+	g_hash_table_remove(cvs->obj2filename, f2);
+      }
+    }
+
+    g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+    reset_file(file);
+  }
+
+  g_free(filename);
+}
+
+static CajaOperationResult
+caja_dropbox_update_file_info(CajaInfoProvider     *provider,
+                                  CajaFileInfo         *file,
+                                  GClosure                 *update_complete,
+                                  CajaOperationHandle **handle) {
+  CajaDropbox *cvs;
+
+  cvs = CAJA_DROPBOX(provider);
+
+  /* this code adds this file object to our two-way hash of file objects
+     so we can shell touch these files later */
+  {
+    gchar *pfilename, *uri;
+
+    uri = caja_file_info_get_uri(file);
+    pfilename = g_filename_from_uri(uri, NULL, NULL);
+    g_free(uri);
+    if (pfilename == NULL) {
+      return CAJA_OPERATION_COMPLETE;
+    }
+    else {
+      int cmp = 0;
+      gchar *stored_filename;
+      gchar *filename;
+
+      filename = canonicalize_path(pfilename);
+      g_free(pfilename);
+      if (filename == NULL) {
+        /* pfilename path was invalid if canonicalize operation nulled it out */
+        return CAJA_OPERATION_FAILED;
+      }
+      stored_filename = g_hash_table_lookup(cvs->obj2filename, file);
+
+      /* don't worry about the dup checks, gcc is smart enough to optimize this
+	 GCSE ftw */
+      if ((stored_filename != NULL && (cmp = strcmp(stored_filename, filename)) != 0) ||
+	  stored_filename == NULL) {
+
+	if (stored_filename != NULL && cmp != 0) {
+	  /* this happens when the filename changes name on a file obj
+	     but changed_cb isn't called */
+	  g_object_weak_unref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	  g_hash_table_remove(cvs->obj2filename, file);
+	  g_hash_table_remove(cvs->filename2obj, stored_filename);
+	  g_signal_handlers_disconnect_by_func(file, G_CALLBACK(changed_cb), cvs);
+	}
+	else if (stored_filename == NULL) {
+	  CajaFileInfo *f2;
+
+	  if ((f2 = g_hash_table_lookup(cvs->filename2obj, filename)) != NULL) {
+	    /* if the filename exists in the filename2obj hash
+	       but the file obj doesn't exist in the obj2filename hash:
+
+	       this happens when caja allocates another file object
+	       for a filename without first deleting the original file object
+
+	       just remove the association to the older file object, it's obsolete
+	    */
+	    g_object_weak_unref(G_OBJECT(f2), (GWeakNotify) when_file_dies, cvs);
+	    g_signal_handlers_disconnect_by_func(f2, G_CALLBACK(changed_cb), cvs);
+	    g_hash_table_remove(cvs->filename2obj, filename);
+	    g_hash_table_remove(cvs->obj2filename, f2);
+	  }
+	}
+
+	/* too chatty */
+	/* debug("adding %s <-> 0x%p", filename, file);*/
+	g_object_weak_ref(G_OBJECT(file), (GWeakNotify) when_file_dies, cvs);
+	g_hash_table_insert(cvs->filename2obj, g_strdup(filename), file);
+	g_hash_table_insert(cvs->obj2filename, file, g_strdup(filename));
+	g_signal_connect(file, "changed", G_CALLBACK(changed_cb), cvs);
+      }
+
+      g_free(filename);
+    }
+  }
+
+  if (dropbox_client_is_connected(&(cvs->dc)) == FALSE ||
+      caja_file_info_is_gone(file)) {
+    return CAJA_OPERATION_COMPLETE;
+  }
+
+  {
+    DropboxFileInfoCommand *dfic = g_new0(DropboxFileInfoCommand, 1);
+
+    dfic->cancelled = FALSE;
+    dfic->provider = provider;
+    dfic->dc.request_type = GET_FILE_INFO;
+    dfic->update_complete = g_closure_ref(update_complete);
+    dfic->file = g_object_ref(file);
+
+    dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dfic);
+
+    *handle = (CajaOperationHandle *) dfic;
+
+    return dropbox_use_operation_in_progress_workaround
+      ? CAJA_OPERATION_COMPLETE
+      : CAJA_OPERATION_IN_PROGRESS;
+  }
+}
+
+static void
+handle_shell_touch(GHashTable *args, CajaDropbox *cvs) {
+  gchar **path;
+
+  //  debug_enter();
+
+  if ((path = g_hash_table_lookup(args, "path")) != NULL &&
+      path[0][0] == '/') {
+    CajaFileInfo *file;
+    gchar *filename;
+
+    filename = canonicalize_path(path[0]);
+    if (filename != NULL) {
+      debug("shell touch for %s", filename);
+
+      file = g_hash_table_lookup(cvs->filename2obj, filename);
+
+      if (file != NULL) {
+        debug("gonna reset %s", filename);
+        reset_file(file);
+      }
+      g_free(filename);
+    }
+  }
+
+  return;
+}
+
+gboolean
+caja_dropbox_finish_file_info_command(DropboxFileInfoCommandResponse *dficr) {
+
+  //debug_enter();
+  CajaOperationResult result = CAJA_OPERATION_FAILED;
+
+  if (!dficr->dfic->cancelled) {
+    gchar **status = NULL;
+    gboolean isdir;
+
+    isdir = caja_file_info_is_directory(dficr->dfic->file) ;
+
+    /* if we have emblems just use them. */
+    if (dficr->emblems_response != NULL &&
+	(status = g_hash_table_lookup(dficr->emblems_response, "emblems")) != NULL) {
+      int i;
+      for ( i = 0; status[i] != NULL; i++) {
+	  if (status[i][0])
+	    caja_file_info_add_emblem(dficr->dfic->file, status[i]);
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+    /* if the file status command went okay */
+    else if ((dficr->file_status_response != NULL &&
+	(status =
+	 g_hash_table_lookup(dficr->file_status_response, "status")) != NULL) &&
+	((isdir == TRUE &&
+	  dficr->folder_tag_response != NULL) || isdir == FALSE)) {
+      gchar **tag = NULL;
+
+      /* set the tag emblem */
+      if (isdir &&
+	  (tag = g_hash_table_lookup(dficr->folder_tag_response, "tag")) != NULL) {
+	if (strcmp("public", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "web");
+	}
+	else if (strcmp("shared", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "people");
+	}
+	else if (strcmp("photos", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "photos");
+	}
+	else if (strcmp("sandbox", tag[0]) == 0) {
+	  caja_file_info_add_emblem(dficr->dfic->file, "star");
+	}
+      }
+
+      /* set the status emblem */
+      {
+	int emblem_code = 0;
+
+	if (strcmp("up to date", status[0]) == 0) {
+	  emblem_code = 1;
+	}
+	else if (strcmp("syncing", status[0]) == 0) {
+	  emblem_code = 2;
+	}
+	else if (strcmp("unsyncable", status[0]) == 0) {
+	  emblem_code = 3;
+	}
+
+	if (emblem_code > 0) {
+	  /*
+	    debug("%s to %s", emblems[emblem_code-1],
+	    g_filename_from_uri(caja_file_info_get_uri(dficr->dfic->file),
+	    NULL, NULL));
+	  */
+	  caja_file_info_add_emblem(dficr->dfic->file, emblems[emblem_code-1]);
+	}
+      }
+      result = CAJA_OPERATION_COMPLETE;
+    }
+  }
+
+  /* complete the info request */
+  if (!dropbox_use_operation_in_progress_workaround) {
+      caja_info_provider_update_complete_invoke(dficr->dfic->update_complete,
+						    dficr->dfic->provider,
+						    (CajaOperationHandle*) dficr->dfic,
+						    result);
+  }
+
+  /* destroy the objects we created */
+  if (dficr->file_status_response != NULL)
+    g_hash_table_unref(dficr->file_status_response);
+  if (dficr->folder_tag_response != NULL)
+    g_hash_table_unref(dficr->folder_tag_response);
+  if (dficr->emblems_response != NULL)
+    g_hash_table_unref(dficr->emblems_response);
+
+  /* unref the objects we didn't create */
+  g_closure_unref(dficr->dfic->update_complete);
+  g_object_unref(dficr->dfic->file);
+
+  /* now free the structs */
+  g_free(dficr->dfic);
+  g_free(dficr);
+
+  return FALSE;
+}
+
+static void
+caja_dropbox_cancel_update(CajaInfoProvider     *provider,
+                               CajaOperationHandle  *handle) {
+  DropboxFileInfoCommand *dfic = (DropboxFileInfoCommand *) handle;
+  dfic->cancelled = TRUE;
+  return;
+}
+
+static void
+menu_item_cb(CajaMenuItem *item,
+	     CajaDropbox *cvs) {
+  gchar *verb;
+  GList *files;
+  DropboxGeneralCommand *dcac;
+
+  dcac = g_new(DropboxGeneralCommand, 1);
+
+  /* maybe these would be better passed in a container
+     struct used as the userdata pointer, oh well this
+     is how dave camp does it */
+  files = g_object_get_data(G_OBJECT(item), "caja_dropbox_files");
+  verb = g_object_get_data(G_OBJECT(item), "caja_dropbox_verb");
+
+  dcac->dc.request_type = GENERAL_COMMAND;
+
+  /* build the argument list */
+  dcac->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					     (GEqualFunc) g_str_equal,
+					     (GDestroyNotify) g_free,
+					     (GDestroyNotify) g_strfreev);
+  {
+    gchar **arglist;
+    guint i;
+    GList *li;
+
+    arglist = g_new0(gchar *,g_list_length(files) + 1);
+
+    for (li = files, i = 0; li != NULL; li = g_list_next(li)) {
+      char *uri = caja_file_info_get_uri(CAJA_FILE_INFO(li->data));
+      char *path = g_filename_from_uri(uri, NULL, NULL);
+      g_free(uri);
+      if (!path)
+	continue;
+      arglist[i] = path;
+      i++;
+    }
+
+    g_hash_table_insert(dcac->command_args,
+			g_strdup("paths"),
+			arglist);
+  }
+
+  {
+    gchar **arglist;
+    arglist = g_new(gchar *, 2);
+    arglist[0] = g_strdup(verb);
+    arglist[1] = NULL;
+    g_hash_table_insert(dcac->command_args, g_strdup("verb"), arglist);
+  }
+
+  dcac->command_name = g_strdup("icon_overlay_context_action");
+  dcac->handler = NULL;
+  dcac->handler_ud = NULL;
+
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dcac);
+}
+
+static char from_hex(gchar ch) {
+    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+// decode in --> out, but dont fill more than n chars into out
+// returns len of out if thing went well, -1 if n wasn't big enough
+// can be used in place (whoa!)
+int GhettoURLDecode(gchar* out, gchar* in, int n) {
+  char *out_initial;<--- Variable 'out_initial' can be declared as pointer to const
+
+  for(out_initial = out; out-out_initial < n && *in != '\0'; out++) {
+    if (*in == '%') {
+      if ((in[1] != '\0') && (in[2] != '\0')) {
+        *out = from_hex(in[1]) << 4 | from_hex(in[2]);
+        in += 3;
+      }
+      else {
+        // Input string isn't well-formed
+        return -1;
+      }
+    }
+    else {
+      *out = *in;
+      in++;
+    }
+  }
+
+  if (out-out_initial < n) {
+    *out = '\0';
+    return out-out_initial;
+  }
+  return -1;
+}
+
+static int
+caja_dropbox_parse_menu(gchar			**options,
+			    CajaMenu		*menu,
+			    GString			*old_action_string,
+			    GList			*toret,
+			    CajaMenuProvider	*provider,
+			    GList			*files)
+{
+  int ret = 0;
+  int i;
+
+  for ( i = 0; options[i] != NULL; i++) {
+    gchar **option_info = g_strsplit(options[i], "~", 3);
+    /* if this is a valid string */
+    if (option_info[0] == NULL || option_info[1] == NULL ||
+	option_info[2] == NULL || option_info[3] != NULL) {
+	g_strfreev(option_info);
+	continue;
+    }
+
+    gchar* item_name = option_info[0];
+    gchar* item_inner = option_info[1];
+    gchar* verb = option_info[2];
+
+    GhettoURLDecode(item_name, item_name, strlen(item_name));
+    GhettoURLDecode(verb, verb, strlen(verb));
+    GhettoURLDecode(item_inner, item_inner, strlen(item_inner));
+
+    // If the inner section has a menu in it then we create a submenu.  The verb will be ignored.
+    // Otherwise add the verb to our map and add the menu item to the list.
+    if (strchr(item_inner, '~') != NULL) {
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gchar **suboptions = g_strsplit(item_inner, "|", -1);
+      CajaMenuItem *item;
+      CajaMenu *submenu = caja_menu_new();
+
+      g_string_append(new_action_string, item_name);
+      g_string_append(new_action_string, "::");
+
+      ret += caja_dropbox_parse_menu(suboptions, submenu, new_action_string,
+					 toret, provider, files);
+
+      item = caja_menu_item_new(new_action_string->str,
+				    item_name, "", NULL);
+      caja_menu_item_set_submenu(item, submenu);
+      caja_menu_append_item(menu, item);
+
+      g_strfreev(suboptions);
+      g_object_unref(item);
+      g_object_unref(submenu);
+      g_string_free(new_action_string, TRUE);
+    } else {
+      CajaMenuItem *item;
+      GString *new_action_string = g_string_new(old_action_string->str);
+      gboolean grayed_out = FALSE;
+
+      g_string_append(new_action_string, verb);
+
+      if (item_name[0] == '!') {
+	  item_name++;
+	  grayed_out = TRUE;
+      }
+
+      item = caja_menu_item_new(new_action_string->str, item_name, item_inner, NULL);
+
+      caja_menu_append_item(menu, item);
+      /* add the file metadata to this item */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_files",
+			      caja_file_info_list_copy (files),
+			      (GDestroyNotify) caja_file_info_list_free);
+      /* add the verb metadata */
+      g_object_set_data_full (G_OBJECT(item), "caja_dropbox_verb",
+			      g_strdup(verb),
+			      (GDestroyNotify) g_free);
+      g_signal_connect (item, "activate", G_CALLBACK (menu_item_cb), provider);
+
+      if (grayed_out) {
+	GValue sensitive = { 0 };
+	g_value_init (&sensitive, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&sensitive, FALSE);
+	g_object_set_property (G_OBJECT(item), "sensitive", &sensitive);
+      }
+
+      g_object_unref(item);
+      g_string_free(new_action_string, TRUE);
+      ret++;
+    }
+    g_strfreev(option_info);
+  }
+  return ret;
+}
+
+static void
+get_file_items_callback(GHashTable *response, gpointer ud)
+{
+  GAsyncQueue *reply_queue = ud;
+
+  /* queue_push doesn't accept NULL as a value so we create an empty hash table
+   * if we got no response. */
+  g_async_queue_push(reply_queue, response ? g_hash_table_ref(response) :
+		     g_hash_table_new((GHashFunc) g_str_hash, (GEqualFunc) g_str_equal));
+  g_async_queue_unref(reply_queue);
+}
+
+
+static GList *
+caja_dropbox_get_file_items(CajaMenuProvider *provider,
+                                GtkWidget            *window,
+				GList                *files)
+{
+  /*
+   * 1. Convert files to filenames.
+   */
+  int file_count = g_list_length(files);
+
+  if (file_count < 1)
+    return NULL;
+
+  gchar **paths = g_new0(gchar *, file_count + 1);
+  int i = 0;
+  GList* elem;
+
+  for (elem = files; elem; elem = elem->next, i++) {
+    gchar *uri = caja_file_info_get_uri(elem->data);
+    gchar *filename_un = uri ? g_filename_from_uri(uri, NULL, NULL) : NULL;
+    gchar *filename = filename_un ? g_filename_to_utf8(filename_un, -1, NULL, NULL, NULL) : NULL;
+
+    g_free(uri);
+    g_free(filename_un);
+
+    if (filename == NULL) {
+      /* oooh, filename wasn't correctly encoded, or isn't a local file.  */
+      g_strfreev(paths);
+      return NULL;
+    }
+
+    paths[i] = filename;
+  }
+
+  GAsyncQueue *reply_queue = g_async_queue_new_full((GDestroyNotify)g_hash_table_unref);
+
+  /*
+   * 2. Create a DropboxGeneralCommand to call "icon_overlay_context_options"
+   */
+
+  DropboxGeneralCommand *dgc = g_new0(DropboxGeneralCommand, 1);
+  dgc->dc.request_type = GENERAL_COMMAND;
+  dgc->command_name = g_strdup("icon_overlay_context_options");
+  dgc->command_args = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) g_strfreev);
+  g_hash_table_insert(dgc->command_args, g_strdup("paths"), paths);
+  dgc->handler = get_file_items_callback;
+  dgc->handler_ud = g_async_queue_ref(reply_queue);
+
+  /*
+   * 3. Queue it up for the helper thread to run it.
+   */
+  CajaDropbox *cvs = CAJA_DROPBOX(provider);
+  dropbox_command_client_request(&(cvs->dc.dcc), (DropboxCommand *) dgc);
+
+  /*
+   * 4. We have to block until it's done because caja expects a reply.  But we will
+   * only block for 50 ms for a reply.
+   */
+
+  GHashTable *context_options_response = g_async_queue_timeout_pop(reply_queue, 50000);
+  g_async_queue_unref(reply_queue);
+
+  if (!context_options_response) {
+      return NULL;
+  }
+
+  /*
+   * 5. Parse the reply.
+   */
+
+  char **options = g_hash_table_lookup(context_options_response, "options");
+  GList *toret = NULL;
+
+  if (options && *options && **options)  {
+    /* build the menu */
+    CajaMenuItem *root_item;
+    CajaMenu *root_menu;
+
+    root_menu = caja_menu_new();
+    root_item = caja_menu_item_new("CajaDropbox::root_item",
+				       "Dropbox", "Dropbox Options", "dropbox");
+
+    toret = g_list_append(toret, root_item);
+    GString *action_string = g_string_new("CajaDropbox::");
+
+    if (!caja_dropbox_parse_menu(options, root_menu, action_string,
+				     toret, provider, files)) {
+	g_object_unref(toret);
+	toret = NULL;
+    }
+
+    caja_menu_item_set_submenu(root_item, root_menu);
+
+    g_string_free(action_string, TRUE);
+    g_object_unref(root_menu);
+  }
+
+  g_hash_table_unref(context_options_response);
+
+  return toret;
+}
+
+gboolean
+add_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list;
+  int i;
+
+  GtkIconTheme *theme = gtk_icon_theme_get_default();
+
+  if (emblem_paths_response &&<--- Condition 'emblem_paths_response' is always true
+      (emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path"))) {
+      for (i = 0; emblem_paths_list[i] != NULL; i++) {
+	if (emblem_paths_list[i][0])
+	  gtk_icon_theme_append_search_path(theme, emblem_paths_list[i]);
+      }
+  }
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+gboolean
+remove_emblem_paths(GHashTable* emblem_paths_response)
+{
+  /* Only run this on the main loop or you'll cause problems. */
+  if (!emblem_paths_response)
+    return FALSE;
+
+  gchar **emblem_paths_list = g_hash_table_lookup(emblem_paths_response, "path");
+  if (!emblem_paths_list)
+      goto exit;
+
+  // We need to remove the old paths.
+  GtkIconTheme * icon_theme = gtk_icon_theme_get_default();
+  gchar ** paths;
+  gint path_count;
+
+  gtk_icon_theme_get_search_path(icon_theme, &paths, &path_count);
+
+  gint i, j, out = 0;
+  gboolean found = FALSE;
+  for (i = 0; i < path_count; i++) {
+      gboolean keep = TRUE;
+      for (j = 0; emblem_paths_list[j] != NULL; j++) {
+	  if (emblem_paths_list[j][0]) {
+	      if (!g_strcmp0(paths[i], emblem_paths_list[j])) {
+		  found = TRUE;
+		  keep = FALSE;
+		  g_free(paths[i]);
+		  break;
+	      }
+	  }
+      }
+      if (keep) {
+	  paths[out] = paths[i];
+	  out++;
+      }
+  }
+
+  /* If we found one we need to reset the path to
+     accomodate the changes */
+  if (found) {
+    paths[out] = NULL; /* Clear the last one */
+    gtk_icon_theme_set_search_path(icon_theme, (const gchar **)paths, out);
+  }
+
+  g_strfreev(paths);
+exit:
+  g_hash_table_unref(emblem_paths_response);
+  return FALSE;
+}
+
+void get_emblem_paths_cb(GHashTable *emblem_paths_response, CajaDropbox *cvs)
+{
+  if (!emblem_paths_response) {
+      emblem_paths_response = g_hash_table_new((GHashFunc) g_str_hash,
+					       (GEqualFunc) g_str_equal);
+      g_hash_table_insert(emblem_paths_response, "path", DEFAULT_EMBLEM_PATHS);
+  } else {
+      /* Increase the ref so that finish_general_command doesn't delete it. */
+      g_hash_table_ref(emblem_paths_response);
+  }
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  if (cvs->emblem_paths) {
+    g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+    cvs->emblem_paths = NULL;
+  }
+  cvs->emblem_paths = emblem_paths_response;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+
+  g_idle_add((GSourceFunc) add_emblem_paths, g_hash_table_ref(emblem_paths_response));
+  g_idle_add((GSourceFunc) reset_all_files, cvs);
+}
+
+static void
+on_connect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  dropbox_command_client_send_command(&(cvs->dc.dcc),
+				      (CajaDropboxCommandResponseHandler) get_emblem_paths_cb,
+				      cvs, "get_emblem_paths", NULL);
+}
+
+static void
+on_disconnect(CajaDropbox *cvs) {
+  reset_all_files(cvs);
+
+  g_mutex_lock(&(cvs->emblem_paths_mutex));
+  /* This call will free the data too. */
+  g_idle_add((GSourceFunc) remove_emblem_paths, cvs->emblem_paths);
+  cvs->emblem_paths = NULL;
+  g_mutex_unlock(&(cvs->emblem_paths_mutex));
+}
+
+
+static void
+caja_dropbox_menu_provider_iface_init (CajaMenuProviderIface *iface) {
+  iface->get_file_items = caja_dropbox_get_file_items;
+  return;
+}
+
+static void
+caja_dropbox_info_provider_iface_init (CajaInfoProviderIface *iface) {
+  iface->update_file_info = caja_dropbox_update_file_info;
+  iface->cancel_update = caja_dropbox_cancel_update;
+  return;
+}
+
+static void
+caja_dropbox_instance_init (CajaDropbox *cvs) {
+  cvs->filename2obj = g_hash_table_new_full((GHashFunc) g_str_hash,
+					    (GEqualFunc) g_str_equal,
+					    (GDestroyNotify) g_free,
+					    (GDestroyNotify) NULL);
+  cvs->obj2filename = g_hash_table_new_full((GHashFunc) g_direct_hash,
+					    (GEqualFunc) g_direct_equal,
+					    (GDestroyNotify) NULL,
+					    (GDestroyNotify) g_free);
+  g_mutex_init(&(cvs->emblem_paths_mutex));
+  cvs->emblem_paths = NULL;
+
+  /* setup the connection obj*/
+  dropbox_client_setup(&(cvs->dc));
+
+  /* our hooks */
+  caja_dropbox_hooks_add(&(cvs->dc.hookserv), "shell_touch",
+			     (DropboxUpdateHook) handle_shell_touch, cvs);
+
+  /* add connection handlers */
+  dropbox_client_add_on_connect_hook(&(cvs->dc),
+				     (DropboxClientConnectHook) on_connect,
+				     cvs);
+  dropbox_client_add_on_disconnect_hook(&(cvs->dc),
+					(DropboxClientConnectHook) on_disconnect,
+					cvs);
+
+  /* now start the connection */
+  debug("about to start client connection");
+  dropbox_client_start(&(cvs->dc));
+
+  return;
+}
+
+static void
+caja_dropbox_class_init (CajaDropboxClass *class) {
+}
+
+static void
+caja_dropbox_class_finalize (CajaDropboxClass *class) {
+  debug("just checking");
+  /* kill threads here? */
+}
+
+GType
+caja_dropbox_get_type (void) {
+  return dropbox_type;
+}
+
+void
+caja_dropbox_register_type (GTypeModule *module) {
+  static const GTypeInfo info = {
+    sizeof (CajaDropboxClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) caja_dropbox_class_init,
+    (GClassFinalizeFunc) caja_dropbox_class_finalize,
+    NULL,
+    sizeof (CajaDropbox),
+    0,
+    (GInstanceInitFunc) caja_dropbox_instance_init,
+    NULL
+  };
+
+  static const GInterfaceInfo menu_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_menu_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  static const GInterfaceInfo info_provider_iface_info = {
+    (GInterfaceInitFunc) caja_dropbox_info_provider_iface_init,
+    NULL,
+    NULL
+  };
+
+  dropbox_type =
+    g_type_module_register_type(module,
+				G_TYPE_OBJECT,
+				"CajaDropbox",
+				&info, 0);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_MENU_PROVIDER,
+			       &menu_provider_iface_info);
+
+  g_type_module_add_interface (module,
+			       dropbox_type,
+			       CAJA_TYPE_INFO_PROVIDER,
+			       &info_provider_iface_info);
+}
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/6.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/6.html new file mode 100644 index 0000000..dad17e8 --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/6.html @@ -0,0 +1,463 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * dropbox-command-client.h
+ * Header file for caja-dropbox-command.c
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DROPBOX_COMMAND_CLIENT_H
+#define DROPBOX_COMMAND_CLIENT_H
+
+#include <libcaja-extension/caja-info-provider.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <libcaja-extension/caja-file-info.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+G_BEGIN_DECLS
+
+/* command structs */
+typedef enum {GET_FILE_INFO, GENERAL_COMMAND} CajaDropboxRequestType;
+
+typedef struct {
+  CajaDropboxRequestType request_type;
+} DropboxCommand;
+
+typedef struct {
+  DropboxCommand dc;
+  CajaInfoProvider *provider;
+  GClosure *update_complete;
+  CajaFileInfo *file;
+  gboolean cancelled;
+} DropboxFileInfoCommand;
+
+typedef struct {
+  DropboxFileInfoCommand *dfic;
+  GHashTable *file_status_response;
+  GHashTable *folder_tag_response;
+  GHashTable *emblems_response;
+} DropboxFileInfoCommandResponse;
+
+typedef void (*CajaDropboxCommandResponseHandler)(GHashTable *, gpointer);
+
+typedef struct {
+  DropboxCommand dc;
+  gchar *command_name;
+  GHashTable *command_args;
+  CajaDropboxCommandResponseHandler handler;
+  gpointer handler_ud;
+} DropboxGeneralCommand;
+
+typedef void (*DropboxCommandClientConnectionAttemptHook)(guint, gpointer);
+typedef GHookFunc DropboxCommandClientConnectHook;
+
+typedef struct {
+  GMutex command_connected_mutex;
+  gboolean command_connected;
+  GAsyncQueue *command_queue;
+  GList *ca_hooklist;
+  GHookList onconnect_hooklist;
+  GHookList ondisconnect_hooklist;
+} DropboxCommandClient;
+
+gboolean dropbox_command_client_is_connected(DropboxCommandClient *dcc);
+
+void dropbox_command_client_force_reconnect(DropboxCommandClient *dcc);
+
+void
+dropbox_command_client_request(DropboxCommandClient *dcc, DropboxCommand *dc);
+
+void
+dropbox_command_client_setup(DropboxCommandClient *dcc);
+
+void
+dropbox_command_client_start(DropboxCommandClient *dcc);
+
+void dropbox_command_client_send_simple_command(DropboxCommandClient *dcc,
+						const char *command);
+
+void dropbox_command_client_send_command(DropboxCommandClient *dcc,
+					 CajaDropboxCommandResponseHandler h,
+					 gpointer ud,
+					 const char *command, ...);
+void
+dropbox_command_client_add_on_connect_hook(DropboxCommandClient *dcc,
+					   DropboxCommandClientConnectHook dhcch,
+					   gpointer ud);
+
+void
+dropbox_command_client_add_on_disconnect_hook(DropboxCommandClient *dcc,
+					      DropboxCommandClientConnectHook dhcch,
+					      gpointer ud);
+
+void
+dropbox_command_client_add_connection_attempt_hook(DropboxCommandClient *dcc,
+						   DropboxCommandClientConnectionAttemptHook dhcch,
+						   gpointer ud);
+
+G_END_DECLS
+
+#endif
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/7.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/7.html new file mode 100644 index 0000000..4730b8e --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/7.html @@ -0,0 +1,373 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * caja-dropbox.h
+ * Header file for caja-dropbox.c
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef CAJA_DROPBOX_H
+#define CAJA_DROPBOX_H
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include <glib-object.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include <libcaja-extension/caja-info-provider.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "dropbox-command-client.h"
+#include "caja-dropbox-hooks.h"
+#include "dropbox-client.h"
+
+G_BEGIN_DECLS
+
+/* Declarations for the dropbox extension object.  This object will be
+ * instantiated by caja.  It implements the GInterfaces
+ * exported by libcaja. */
+
+#define CAJA_TYPE_DROPBOX	  (caja_dropbox_get_type ())
+#define CAJA_DROPBOX(o)	  (G_TYPE_CHECK_INSTANCE_CAST ((o), CAJA_TYPE_DROPBOX, CajaDropbox))
+#define CAJA_IS_DROPBOX(o)	  (G_TYPE_CHECK_INSTANCE_TYPE ((o), CAJA_TYPE_DROPBOX))
+typedef struct _CajaDropbox      CajaDropbox;
+typedef struct _CajaDropboxClass CajaDropboxClass;
+
+struct _CajaDropbox {
+  GObject parent_slot;
+  GHashTable *filename2obj;
+  GHashTable *obj2filename;
+  GMutex emblem_paths_mutex;
+  GHashTable *emblem_paths;
+  DropboxClient dc;
+};
+
+struct _CajaDropboxClass {
+	GObjectClass parent_slot;
+};
+
+GType caja_dropbox_get_type(void);
+void  caja_dropbox_register_type(GTypeModule *module);
+
+extern gboolean dropbox_use_operation_in_progress_workaround;
+
+G_END_DECLS
+
+#endif
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/8.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/8.html new file mode 100644 index 0000000..52dd132 --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/8.html @@ -0,0 +1,389 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * dropbox-client.h
+ * Header file for dropbox-client.c
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DROPBOX_CLIENT_H
+#define DROPBOX_CLIENT_H
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+#include "dropbox-command-client.h"
+#include "caja-dropbox-hooks.h"
+
+G_BEGIN_DECLS
+
+typedef struct {
+  DropboxCommandClient dcc;
+  CajaDropboxHookserv hookserv;
+  GHookList onconnect_hooklist;
+  GHookList ondisconnect_hooklist;
+  gboolean hook_connect_called;
+  gboolean command_connect_called;
+  gboolean hook_disconnect_called;
+  gboolean command_disconnect_called;
+} DropboxClient;
+
+typedef void (*DropboxClientConnectionAttemptHook)(guint, gpointer);
+typedef GHookFunc DropboxClientConnectHook;
+
+void
+dropbox_client_setup(DropboxClient *dc);
+
+void
+dropbox_client_start(DropboxClient *dc);
+
+gboolean
+dropbox_client_is_connected(DropboxClient *dc);
+
+void
+dropbox_client_force_reconnect(DropboxClient *dc);
+
+void
+dropbox_client_add_on_connect_hook(DropboxClient *dc,
+				   DropboxClientConnectHook dhcch,
+				   gpointer ud);
+
+void
+dropbox_client_add_on_disconnect_hook(DropboxClient *dc,
+				      DropboxClientConnectHook dhcch,
+				      gpointer ud);
+
+void
+dropbox_client_add_connection_attempt_hook(DropboxClient *dc,
+					   DropboxClientConnectionAttemptHook dhcch,
+					   gpointer ud);
+
+G_END_DECLS
+
+#endif
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/9.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/9.html new file mode 100644 index 0000000..8b00d3e --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/9.html @@ -0,0 +1,585 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
/*
+ * Copyright 2008 Evenflow, Inc.
+ *
+ * dropbox-client.c
+ * Implements connection handling and C interface for interfacing with the Dropbox daemon.
+ *
+ * This file is part of caja-dropbox.
+ *
+ * caja-dropbox is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * caja-dropbox is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with caja-dropbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <glib.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+#include "g-util.h"
+#include "dropbox-command-client.h"
+#include "caja-dropbox-hooks.h"
+#include "dropbox-client.h"
+
+static void
+hook_on_connect(DropboxClient *dc) {
+  dc->hook_connect_called = TRUE;
+
+  if (dc->command_connect_called) {
+    debug("client connection");
+    g_hook_list_invoke(&(dc->onconnect_hooklist), FALSE);
+    /* reset flags */
+    dc->hook_connect_called = dc->command_connect_called = FALSE;
+  }
+}
+
+static void
+command_on_connect(DropboxClient *dc) {
+  dc->command_connect_called = TRUE;
+
+  if (dc->hook_connect_called) {
+    debug("client connection");
+    g_hook_list_invoke(&(dc->onconnect_hooklist), FALSE);
+    /* reset flags */
+    dc->hook_connect_called = dc->command_connect_called = FALSE;
+  }
+}
+
+static void
+command_on_disconnect(DropboxClient *dc) {
+  dc->command_disconnect_called = TRUE;
+
+  if (dc->hook_disconnect_called) {
+    debug("client disconnect");
+    g_hook_list_invoke(&(dc->ondisconnect_hooklist), FALSE);
+    /* reset flags */
+    dc->hook_disconnect_called = dc->command_disconnect_called = FALSE;
+  }
+  else {
+    caja_dropbox_hooks_force_reconnect(&(dc->hookserv));
+  }
+}
+
+static void
+hook_on_disconnect(DropboxClient *dc) {
+  dc->hook_disconnect_called = TRUE;
+
+  if (dc->command_disconnect_called) {
+    debug("client disconnect");
+    g_hook_list_invoke(&(dc->ondisconnect_hooklist), FALSE);
+    /* reset flags */
+    dc->hook_disconnect_called = dc->command_disconnect_called = FALSE;
+  }
+  else {
+    dropbox_command_client_force_reconnect(&(dc->dcc));
+  }
+}
+
+gboolean
+dropbox_client_is_connected(DropboxClient *dc) {
+  return (dropbox_command_client_is_connected(&(dc->dcc)) &&
+	  caja_dropbox_hooks_is_connected(&(dc->hookserv)));
+}
+
+void
+dropbox_client_force_reconnect(DropboxClient *dc) {
+  if (dropbox_client_is_connected(dc) == TRUE) {
+    debug("forcing client to reconnect");
+    dropbox_command_client_force_reconnect(&(dc->dcc));
+    caja_dropbox_hooks_force_reconnect(&(dc->hookserv));
+  }
+}
+
+/* should only be called once on initialization */
+void
+dropbox_client_setup(DropboxClient *dc) {
+  caja_dropbox_hooks_setup(&(dc->hookserv));
+  dropbox_command_client_setup(&(dc->dcc));
+
+  g_hook_list_init(&(dc->ondisconnect_hooklist), sizeof(GHook));
+  g_hook_list_init(&(dc->onconnect_hooklist), sizeof(GHook));
+
+  dc->hook_disconnect_called = dc->command_disconnect_called = FALSE;
+  dc->hook_connect_called = dc->command_connect_called = FALSE;
+
+  caja_dropbox_hooks_add_on_connect_hook(&(dc->hookserv),
+					     (DropboxHookClientConnectHook)
+					     hook_on_connect, dc);
+
+  dropbox_command_client_add_on_connect_hook(&(dc->dcc),
+					     (DropboxCommandClientConnectHook)
+					     command_on_connect, dc);
+
+  caja_dropbox_hooks_add_on_disconnect_hook(&(dc->hookserv),
+						(DropboxHookClientConnectHook)
+						hook_on_disconnect, dc);
+
+  dropbox_command_client_add_on_disconnect_hook(&(dc->dcc),
+						(DropboxCommandClientConnectHook)
+						command_on_disconnect, dc);
+}
+
+/* not thread safe */
+void
+dropbox_client_add_on_disconnect_hook(DropboxClient *dc,
+				      DropboxClientConnectHook dhcch,
+				      gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(dc->ondisconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(dc->ondisconnect_hooklist), newhook);
+}
+
+/* not thread safe */
+void
+dropbox_client_add_on_connect_hook(DropboxClient *dc,
+				   DropboxClientConnectHook dhcch,
+				   gpointer ud) {
+  GHook *newhook;
+
+  newhook = g_hook_alloc(&(dc->onconnect_hooklist));
+  newhook->func = dhcch;
+  newhook->data = ud;
+
+  g_hook_append(&(dc->onconnect_hooklist), newhook);
+}
+
+/* not thread safe */
+void
+dropbox_client_add_connection_attempt_hook(DropboxClient *dc,
+					   DropboxClientConnectionAttemptHook dhcch,
+					   gpointer ud) {
+  debug("shouldn't be here...");
+
+  dropbox_command_client_add_connection_attempt_hook(&(dc->dcc),
+						     dhcch, ud);
+}
+
+/* should only be called once on initialization */
+void
+dropbox_client_start(DropboxClient *dc) {
+  debug("starting connections");
+  caja_dropbox_hooks_start(&(dc->hookserv));
+  dropbox_command_client_start(&(dc->dcc));
+}
+
+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/index.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/index.html new file mode 100644 index 0000000..3d20314 --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/index.html @@ -0,0 +1,274 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LineIdCWESeverityMessage
checkersReportinformationActive checkers: 106/592 (use --checkers-report=<filename> to see details)
src/async-io-coroutine.h
27missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
src/caja-dropbox-hooks.c
24missingIncludeSysteminformationInclude file: <sys/types.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
25missingIncludeSysteminformationInclude file: <sys/socket.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
26missingIncludeSysteminformationInclude file: <sys/un.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
27missingIncludeSysteminformationInclude file: <errno.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <unistd.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
29missingIncludeSysteminformationInclude file: <fcntl.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
31missingIncludeSysteminformationInclude file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
33missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
283constParameterPointer398styleParameter 'hookserv' can be declared as pointer to const
src/caja-dropbox-hooks.h
27missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
src/caja-dropbox.c
25missingIncludeSysteminformationInclude file: <config.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <sys/types.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
29missingIncludeSysteminformationInclude file: <sys/socket.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
30missingIncludeSysteminformationInclude file: <sys/un.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
31missingIncludeSysteminformationInclude file: <errno.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
32missingIncludeSysteminformationInclude file: <unistd.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
33missingIncludeSysteminformationInclude file: <ctype.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
35missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
36missingIncludeSysteminformationInclude file: <glib/gprintf.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
37missingIncludeSysteminformationInclude file: <glib-object.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
38missingIncludeSysteminformationInclude file: <gtk/gtk.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
40missingIncludeSysteminformationInclude file: <libcaja-extension/caja-extension-types.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
41missingIncludeSysteminformationInclude file: <libcaja-extension/caja-menu-provider.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
42missingIncludeSysteminformationInclude file: <libcaja-extension/caja-info-provider.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
312variableScope398styleThe scope of the variable 'file' can be reduced.
508constVariablePointer398styleVariable 'out_initial' can be declared as pointer to const
752variableScope398styleThe scope of the variable 'i' can be reduced.
756knownConditionTrueFalse571styleCondition 'emblem_paths_response' is always true
847varFuncNullUB475portabilityPassing NULL after the last typed argument to a variadic function leads to undefined behaviour.
src/caja-dropbox.h
27missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <glib-object.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
30missingIncludeSysteminformationInclude file: <libcaja-extension/caja-info-provider.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
src/dropbox-client-util.h
27missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
src/dropbox-client.c
24missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
src/dropbox-client.h
27missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
src/dropbox-command-client.c
24missingIncludeSysteminformationInclude file: <sys/types.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
25missingIncludeSysteminformationInclude file: <sys/socket.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
26missingIncludeSysteminformationInclude file: <sys/un.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
27missingIncludeSysteminformationInclude file: <errno.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <unistd.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
29missingIncludeSysteminformationInclude file: <fcntl.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
31missingIncludeSysteminformationInclude file: <stdarg.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
32missingIncludeSysteminformationInclude file: <string.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
34missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
src/dropbox-command-client.h
27missingIncludeSysteminformationInclude file: <libcaja-extension/caja-info-provider.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <libcaja-extension/caja-file-info.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
src/dropbox.c
25missingIncludeSysteminformationInclude file: <config.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <glib-object.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
src/g-util.h
27missingIncludeSysteminformationInclude file: <glib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
28missingIncludeSysteminformationInclude file: <glib/gprintf.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
+
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/stats.html b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/stats.html new file mode 100644 index 0000000..738f644 --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/stats.html @@ -0,0 +1,183 @@ + + + + + + Cppcheck - HTML report - caja-dropbox + + + + + +
+ + + +
+

Top 10 files for portability severity, total findings: 1
+   1  src/caja-dropbox.c
+

+

Top 10 files for style severity, total findings: 5
+   4  src/caja-dropbox.c
+   1  src/caja-dropbox-hooks.c
+

+

Top 10 files for information severity, total findings: 45
+   14  src/caja-dropbox.c
+   9   src/dropbox-command-client.c
+   8   src/caja-dropbox-hooks.c
+   3   src/caja-dropbox.h
+   2   src/g-util.h
+   2   src/dropbox.c
+   2   src/dropbox-command-client.h
+   1   src/dropbox-client.h
+   1   src/dropbox-client.c
+   1   src/dropbox-client-util.h
+

+ +
+ +
+ + diff --git a/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/style.css b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/style.css new file mode 100644 index 0000000..3897bfa --- /dev/null +++ b/2024-02-21-173952-0547-cppcheck@c39dc324eb09_v1.28.0/style.css @@ -0,0 +1,177 @@ + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 13px; + line-height: 1.5; + height: 100%; + margin: 0; +} + +#wrapper { + position: fixed; + height: 100vh; + width: 100vw; + display: grid; + grid-template-rows: fit-content(8rem) auto fit-content(8rem); + grid-template-columns: fit-content(25%) 1fr; + grid-template-areas: + "header header" + "menu content" + "footer footer"; +} + +h1 { + margin: 0 0 8px -2px; + font-size: 175%; +} + +.header { + padding: 0 0 5px 15px; + grid-area: header; + border-bottom: thin solid #aaa; +} + +.footer { + grid-area: footer; + border-top: thin solid #aaa; + font-size: 85%; + +} + +.footer > p { + margin: 4px; +} + +#menu, +#menu_index { + grid-area: menu; + text-align: left; + overflow: auto; + padding: 0 23px 15px 15px; + border-right: thin solid #aaa; + min-width: 200px; +} + +#menu > a { + display: block; + margin-left: 10px; + font-size: 12px; +} + +#content, +#content_index { + grid-area: content; + padding: 0px 5px 15px 15px; + overflow: auto; +} + +label { + white-space: nowrap; +} + +label.checkBtn.disabled { + color: #606060; + background: #e0e0e0; + font-style: italic; +} + +label.checkBtn, input[type="text"] { + border: 1px solid grey; + border-radius: 4px; + box-shadow: 1px 1px inset; + padding: 1px 5px; +} + +label.checkBtn { + white-space: nowrap; + background: #ccddff; +} + +label.unchecked { + background: #eff8ff; + box-shadow: 1px 1px 1px; +} + +label.checkBtn:hover, label.unchecked:hover{ + box-shadow: 0 0 2px; +} + +label.disabled:hover { + box-shadow: 1px 1px inset; +} + +label.checkBtn > input { + display:none; +} + +.summaryTable { + width: 100%; +} + +table.summaryTable td { padding: 0 5px 0 5px; } + +.statHeader, .severityHeader { + font-weight: bold; +} + +.warning { + background-color: #ffffa7; +} + +.error { + background-color: #ffb7b7; +} + +.error2 { + background-color: #faa; + display: inline-block; + margin-left: 4px; +} + +.inconclusive { + background-color: #b6b6b4; +} + +.inconclusive2 { + background-color: #b6b6b4; + display: inline-block; + margin-left: 4px; +} + +.verbose { + display: inline-block; + vertical-align: top; + cursor: help; +} + +.verbose .content { + display: none; + position: absolute; + padding: 10px; + margin: 4px; + max-width: 40%; + white-space: pre-wrap; + border: 1px solid #000; + background-color: #ffffcc; + cursor: auto; +} + +.highlight .hll { + padding: 1px; +} + +.highlighttable { + background-color: #fff; + position: relative; + margin: -10px; +} + +.linenos { + border-right: thin solid #aaa; + color: #d3d3d3; + padding-right: 6px; +} + +.id-filtered, .severity-filtered, .file-filtered, .tool-filtered, .text-filtered { + visibility: collapse; +} diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..835e76d --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +caja-dropbox.mate-desktop.dev diff --git a/index.html b/index.html new file mode 100644 index 0000000..67b72d6 --- /dev/null +++ b/index.html @@ -0,0 +1,47 @@ + + + + + + caja-dropbox Code Analyzer results + + +

+ mate-desktop/caja-dropbox Static analyzer results +

+ GitHub + Build Status +
+Commit: c39dc324eb09843f607a1c6d04ae17c7694d1d13
+Compare:
+Branch: v1.28.0
+Time: 2024-02-21 17:39:52+00:00
+Messages:
+
+release 1.28.0
+
+
+ + + -- cgit v1.2.1