mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Merge branch 'master' into Fix_ClangWarnings
This commit is contained in:
commit
9102a698e4
661
LICENSE.AGPL.txt
Normal file
661
LICENSE.AGPL.txt
Normal file
@ -0,0 +1,661 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
@ -8,7 +8,7 @@ Build Status
|
||||
| Platform | Build Status |
|
||||
| :------------- | :------------- |
|
||||
| GNU/Linux, MacOS, (via travis-ci) | [![Build Status](https://travis-ci.org/RetroShare/RetroShare.svg?branch=master)](https://travis-ci.org/RetroShare/RetroShare) |
|
||||
| Windows, `MSys2` (via appveyor) | [![Build status](https://ci.appveyor.com/api/projects/status/github/RetroShare/RetroShare?svg=true)](https://ci.appveyor.com/project/G10h4ck/retroshare-u4lmn) |
|
||||
| Windows, `MSys2` (via appveyor) | [![Build status](https://ci.appveyor.com/api/projects/status/github/RetroShare/RetroShare?svg=true)](https://ci.appveyor.com/project/RetroShare58622/retroshare) |
|
||||
|
||||
Compilation on Windows
|
||||
----------------------------
|
||||
|
@ -85,7 +85,8 @@ environment:
|
||||
# - cmd: echo This is batch again
|
||||
# - cmd: set MY_VAR=12345
|
||||
install:
|
||||
- git submodule update --init
|
||||
# We cannot get OBS submodule as it use illegal folder name for windows.
|
||||
#- git submodule update --init
|
||||
# Configuring MSys2
|
||||
- set PATH=C:\msys64\usr\bin;%PATH%
|
||||
- set PATH=C:\msys64\mingw32\bin;%PATH%
|
||||
@ -195,11 +196,13 @@ after_build:
|
||||
- windeployqt %RS_DEPLOY%\retroshare.exe
|
||||
|
||||
- copy C:\msys64\mingw32\bin\libbz2*.dll %RS_DEPLOY%\
|
||||
- copy C:\msys64\mingw32\bin\libeay32.dll %RS_DEPLOY%\
|
||||
#- copy C:\msys64\mingw32\bin\libeay32.dll %RS_DEPLOY%\
|
||||
- copy C:\OpenSSL-Win32\libeay32.dll %RS_DEPLOY%\
|
||||
- copy C:\msys64\mingw32\bin\libminiupnpc.dll %RS_DEPLOY%\
|
||||
- copy C:\msys64\mingw32\bin\libsqlcipher*.dll %RS_DEPLOY%\
|
||||
- copy C:\msys64\mingw32\bin\libsqlite3*.dll %RS_DEPLOY%\
|
||||
- copy C:\msys64\mingw32\bin\ssleay32.dll %RS_DEPLOY%\
|
||||
#- copy C:\msys64\mingw32\bin\ssleay32.dll %RS_DEPLOY%\
|
||||
- copy C:\OpenSSL-Win32\ssleay32.dll %RS_DEPLOY%\
|
||||
- copy C:\msys64\mingw32\bin\zlib*.dll %RS_DEPLOY%\
|
||||
- copy C:\msys64\mingw32\bin\libgcc_s_dw2*.dll %RS_DEPLOY%\
|
||||
- copy C:\msys64\mingw32\bin\libstdc*.dll %RS_DEPLOY%\
|
||||
|
@ -133,12 +133,7 @@ void HashStorage::data_tick()
|
||||
|
||||
if(!mChanged) // otherwise it might prevent from saving the hash cache
|
||||
{
|
||||
std::cerr << "Stopping hashing thread." << std::endl;
|
||||
shutdown();
|
||||
mRunning = false ;
|
||||
mTotalSizeToHash = 0;
|
||||
mTotalFilesToHash = 0;
|
||||
std::cerr << "done." << std::endl;
|
||||
stopHashThread();
|
||||
}
|
||||
|
||||
RsServer::notify()->notifyHashingInfo(NOTIFY_HASHTYPE_FINISH, "") ;
|
||||
@ -262,10 +257,12 @@ bool HashStorage::requestHash(const std::string& full_path,uint64_t size,rstime_
|
||||
it->second.time_stamp = now ;
|
||||
|
||||
#ifdef WINDOWS_SYS
|
||||
if(it->second.time_stamp != (uint64_t)mod_time)
|
||||
if(it->second.modf_stamp != (uint64_t)mod_time)
|
||||
{
|
||||
std::cerr << "(WW) detected a 1 hour shift in file modification time. This normally happens to many files at once, when daylight saving time shifts (file=\"" << full_path << "\")." << std::endl;
|
||||
it->second.time_stamp = (uint64_t)mod_time;
|
||||
it->second.modf_stamp = (uint64_t)mod_time;
|
||||
mChanged = true;
|
||||
startHashThread();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -301,6 +298,13 @@ bool HashStorage::requestHash(const std::string& full_path,uint64_t size,rstime_
|
||||
mTotalSizeToHash += size ;
|
||||
++mTotalFilesToHash;
|
||||
|
||||
startHashThread();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void HashStorage::startHashThread()
|
||||
{
|
||||
if(!mRunning)
|
||||
{
|
||||
mRunning = true ;
|
||||
@ -308,10 +312,21 @@ bool HashStorage::requestHash(const std::string& full_path,uint64_t size,rstime_
|
||||
mHashCounter = 0;
|
||||
mTotalHashedSize = 0;
|
||||
|
||||
start("fs hash cache") ;
|
||||
start("fs hash cache") ;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
void HashStorage::stopHashThread()
|
||||
{
|
||||
if (mRunning)
|
||||
{
|
||||
std::cerr << "Stopping hashing thread." << std::endl;
|
||||
shutdown();
|
||||
mRunning = false ;
|
||||
mTotalSizeToHash = 0;
|
||||
mTotalFilesToHash = 0;
|
||||
std::cerr << "done." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void HashStorage::clean()
|
||||
|
@ -97,6 +97,9 @@ private:
|
||||
*/
|
||||
void clean() ;
|
||||
|
||||
void startHashThread();
|
||||
void stopHashThread();
|
||||
|
||||
// loading/saving the entire hash database to a file
|
||||
|
||||
void locked_save() ;
|
||||
|
@ -692,22 +692,40 @@ void p3GxsTunnelService::receiveTurtleData(const RsTurtleGenericTunnelItem *gite
|
||||
(void) direction;
|
||||
#endif
|
||||
|
||||
const RsTurtleGenericDataItem *item = dynamic_cast<const RsTurtleGenericDataItem*>(gitem) ;
|
||||
void *data_bytes;
|
||||
uint32_t data_size ;
|
||||
bool accept_fast_items = false;
|
||||
|
||||
if(item == NULL)
|
||||
const RsTurtleGenericFastDataItem *fitem = dynamic_cast<const RsTurtleGenericFastDataItem*>(gitem) ;
|
||||
|
||||
if(fitem != NULL)
|
||||
{
|
||||
std::cerr << "(EE) item is not a data item. That is an error." << std::endl;
|
||||
return ;
|
||||
data_bytes = fitem->data_bytes ;
|
||||
data_size = fitem->data_size ;
|
||||
accept_fast_items = true;
|
||||
}
|
||||
// Call the AES crypto module
|
||||
else
|
||||
{
|
||||
const RsTurtleGenericDataItem *item = dynamic_cast<const RsTurtleGenericDataItem*>(gitem) ;
|
||||
|
||||
if(item == NULL)
|
||||
{
|
||||
std::cerr << "(EE) item is not a data item. That is an error." << std::endl;
|
||||
return ;
|
||||
}
|
||||
data_bytes = item->data_bytes ;
|
||||
data_size = item->data_size ;
|
||||
}
|
||||
|
||||
// Call the AES crypto module
|
||||
// - the IV is the first 8 bytes of item->data_bytes
|
||||
|
||||
if(item->data_size < 8)
|
||||
if(data_size < 8)
|
||||
{
|
||||
std::cerr << "(EE) item encrypted data stream is too small: size = " << item->data_size << std::endl;
|
||||
std::cerr << "(EE) item encrypted data stream is too small: size = " << data_size << std::endl;
|
||||
return ;
|
||||
}
|
||||
if(*((uint64_t*)item->data_bytes) != 0) // WTF?? we should use flags
|
||||
if(*((uint64_t*)data_bytes) != 0) // WTF?? we should use flags
|
||||
{
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
std::cerr << " Item is encrypted." << std::endl;
|
||||
@ -715,7 +733,7 @@ void p3GxsTunnelService::receiveTurtleData(const RsTurtleGenericTunnelItem *gite
|
||||
|
||||
// if cannot decrypt, it means the key is wrong. We need to re-negociate a new key.
|
||||
|
||||
handleEncryptedData((uint8_t*)item->data_bytes,item->data_size,hash,virtual_peer_id) ;
|
||||
handleEncryptedData((uint8_t*)data_bytes,data_size,hash,virtual_peer_id,accept_fast_items) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -725,8 +743,8 @@ void p3GxsTunnelService::receiveTurtleData(const RsTurtleGenericTunnelItem *gite
|
||||
|
||||
// Now try deserialise the decrypted data to make an RsItem out of it.
|
||||
//
|
||||
uint32_t pktsize = item->data_size-8;
|
||||
RsItem *citem = RsGxsTunnelSerialiser().deserialise(&((uint8_t*)item->data_bytes)[8],&pktsize) ;
|
||||
uint32_t pktsize = data_size-8;
|
||||
RsItem *citem = RsGxsTunnelSerialiser().deserialise(&((uint8_t*)data_bytes)[8],&pktsize) ;
|
||||
|
||||
if(citem == NULL)
|
||||
{
|
||||
@ -752,7 +770,11 @@ void p3GxsTunnelService::receiveTurtleData(const RsTurtleGenericTunnelItem *gite
|
||||
|
||||
// This function encrypts the given data and adds a MAC and an IV into a serialised memory chunk that is then sent through the tunnel.
|
||||
|
||||
#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004
|
||||
bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id,bool accepts_fast_items)
|
||||
#else
|
||||
bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id)
|
||||
#endif
|
||||
{
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
std::cerr << "p3GxsTunnelService::handleEncryptedDataItem()" << std::endl;
|
||||
@ -795,6 +817,16 @@ bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t
|
||||
std::cerr << "(EE) no tunnel data for tunnel ID=" << tunnel_id << ". This is a bug." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004
|
||||
if(accepts_fast_items)
|
||||
{
|
||||
if(!it2->second.accepts_fast_turtle_items)
|
||||
std::cerr << "(II) received probe for Fast track turtle items for tunnel VPID " << it2->second.virtual_peer_id << ": switching to Fast items mode." << std::endl;
|
||||
|
||||
it2->second.accepts_fast_turtle_items = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(aes_key,it2->second.aes_key,GXS_TUNNEL_AES_KEY_SIZE) ;
|
||||
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
@ -1291,36 +1323,79 @@ bool p3GxsTunnelService::locked_sendEncryptedTunnelData(RsGxsTunnelItem *item)
|
||||
|
||||
// make a TurtleGenericData item out of it:
|
||||
//
|
||||
RsTurtleGenericDataItem *gitem = new RsTurtleGenericDataItem ;
|
||||
|
||||
gitem->data_size = encrypted_size + GXS_TUNNEL_ENCRYPTION_IV_SIZE + GXS_TUNNEL_ENCRYPTION_HMAC_SIZE ;
|
||||
gitem->data_bytes = rs_malloc(gitem->data_size) ;
|
||||
uint32_t data_size = encrypted_size + GXS_TUNNEL_ENCRYPTION_IV_SIZE + GXS_TUNNEL_ENCRYPTION_HMAC_SIZE ;
|
||||
void *data_bytes = rs_malloc(data_size) ;
|
||||
|
||||
if(gitem->data_bytes == NULL)
|
||||
if(data_bytes == NULL)
|
||||
return false ;
|
||||
|
||||
memcpy(& ((uint8_t*)gitem->data_bytes)[0] ,&IV,8) ;
|
||||
memcpy(& ((uint8_t*)data_bytes)[0] ,&IV,8) ;
|
||||
|
||||
unsigned int md_len = GXS_TUNNEL_ENCRYPTION_HMAC_SIZE ;
|
||||
HMAC(EVP_sha1(),aes_key,GXS_TUNNEL_AES_KEY_SIZE,encrypted_data,encrypted_size,&(((uint8_t*)gitem->data_bytes)[GXS_TUNNEL_ENCRYPTION_IV_SIZE]),&md_len) ;
|
||||
HMAC(EVP_sha1(),aes_key,GXS_TUNNEL_AES_KEY_SIZE,encrypted_data,encrypted_size,&(((uint8_t*)data_bytes)[GXS_TUNNEL_ENCRYPTION_IV_SIZE]),&md_len) ;
|
||||
|
||||
memcpy(& (((uint8_t*)gitem->data_bytes)[GXS_TUNNEL_ENCRYPTION_HMAC_SIZE+GXS_TUNNEL_ENCRYPTION_IV_SIZE]),encrypted_data,encrypted_size) ;
|
||||
memcpy(& (((uint8_t*)data_bytes)[GXS_TUNNEL_ENCRYPTION_HMAC_SIZE+GXS_TUNNEL_ENCRYPTION_IV_SIZE]),encrypted_data,encrypted_size) ;
|
||||
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
std::cerr << " Using IV: " << std::hex << IV << std::dec << std::endl;
|
||||
std::cerr << " Using Key: " << RsUtil::BinToHex((char*)aes_key,GXS_TUNNEL_AES_KEY_SIZE) ; std::cerr << std::endl;
|
||||
std::cerr << " hmac: " << RsUtil::BinToHex((char*)gitem->data_bytes,GXS_TUNNEL_ENCRYPTION_HMAC_SIZE) << std::endl;
|
||||
std::cerr << " hmac: " << RsUtil::BinToHex((char*)data_bytes,GXS_TUNNEL_ENCRYPTION_HMAC_SIZE) << std::endl;
|
||||
#endif
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
std::cerr << "GxsTunnelService::sendEncryptedTunnelData(): Sending encrypted data to virtual peer: " << virtual_peer_id << std::endl;
|
||||
std::cerr << " gitem->data_size = " << gitem->data_size << std::endl;
|
||||
std::cerr << " serialised data = " << RsUtil::BinToHex((unsigned char*)gitem->data_bytes,gitem->data_size,100) ;
|
||||
std::cerr << " data_size = " << data_size << std::endl;
|
||||
std::cerr << " serialised data = " << RsUtil::BinToHex((unsigned char*)data_bytes,data_size,100) ;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
mTurtle->sendTurtleData(virtual_peer_id,gitem) ;
|
||||
|
||||
return true ;
|
||||
// We send the item through the turtle tunnel. We do that using the new 'fast' item type if the tunnel accepts it, and using the old slow one otherwise.
|
||||
// Still if the tunnel hasn't been probed, we duplicate the packet using the new fast item format. The packet being received twice on the other side will
|
||||
// be discarded with a warning.
|
||||
// Note that because the data is deleted by sendTurtleData(), we need to send all packets at the end, and properly duplicate the data when needed.
|
||||
|
||||
#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004
|
||||
RsTurtleGenericFastDataItem *gitem = new RsTurtleGenericFastDataItem;
|
||||
gitem->data_bytes = data_bytes;
|
||||
gitem->data_size = data_size ;
|
||||
#else
|
||||
RsTurtleGenericDataItem *gitem = NULL;
|
||||
RsTurtleGenericFastDataItem *gitem2 = NULL;
|
||||
|
||||
if(!it->second.accepts_fast_turtle_items)
|
||||
{
|
||||
std::cerr << "Sending old format (slow) item for packet IV=" << std::hex << IV << std::dec << " in tunnel VPID=" << it->second.virtual_peer_id << std::endl;
|
||||
gitem = new RsTurtleGenericDataItem ;
|
||||
|
||||
gitem->data_bytes = data_bytes;
|
||||
gitem->data_size = data_size ;
|
||||
}
|
||||
|
||||
if(it->second.accepts_fast_turtle_items || !it->second.already_probed_for_fast_items)
|
||||
{
|
||||
std::cerr << "Sending new format (fast) item for packet IV=" << std::hex << IV << std::dec << " in tunnel VPID=" << it->second.virtual_peer_id << std::endl;
|
||||
gitem2 = new RsTurtleGenericFastDataItem ;
|
||||
|
||||
if(gitem != NULL) // duplicate the data because it was already sent in gitem.
|
||||
{
|
||||
gitem2->data_bytes = rs_malloc(data_size);
|
||||
gitem2->data_size = data_size ;
|
||||
memcpy(gitem2->data_bytes,data_bytes,data_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
gitem2->data_bytes = data_bytes;
|
||||
gitem2->data_size = data_size ;
|
||||
}
|
||||
|
||||
it->second.already_probed_for_fast_items = true;
|
||||
|
||||
}
|
||||
if(gitem2) mTurtle->sendTurtleData(virtual_peer_id,gitem2) ;
|
||||
#endif
|
||||
if(gitem) mTurtle->sendTurtleData(virtual_peer_id,gitem) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool p3GxsTunnelService::requestSecuredTunnel(const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, RsGxsTunnelId &tunnel_id, uint32_t service_id, uint32_t& error_code)
|
||||
|
@ -128,14 +128,12 @@ public:
|
||||
// Creates the invite if the public key of the distant peer is available.
|
||||
// Om success, stores the invite in the map above, so that we can respond to tunnel requests.
|
||||
//
|
||||
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t service_id,uint32_t& error_code) ;
|
||||
|
||||
virtual bool closeExistingTunnel(const RsGxsTunnelId &tunnel_id,uint32_t service_id) ;
|
||||
virtual bool getTunnelsInfo(std::vector<GxsTunnelInfo>& infos);
|
||||
virtual bool getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info);
|
||||
virtual bool sendData(const RsGxsTunnelId& tunnel_id,uint32_t service_id,const uint8_t *data,uint32_t size) ;
|
||||
|
||||
virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) ;
|
||||
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t service_id,uint32_t& error_code) override ;
|
||||
virtual bool closeExistingTunnel(const RsGxsTunnelId &tunnel_id,uint32_t service_id) override ;
|
||||
virtual bool getTunnelsInfo(std::vector<GxsTunnelInfo>& infos) override ;
|
||||
virtual bool getTunnelInfo(const RsGxsTunnelId& tunnel_id,GxsTunnelInfo& info) override ;
|
||||
virtual bool sendData(const RsGxsTunnelId& tunnel_id,uint32_t service_id,const uint8_t *data,uint32_t size) override ;
|
||||
virtual bool registerClientService(uint32_t service_id,RsGxsTunnelClientService *service) override ;
|
||||
|
||||
// derived from p3service
|
||||
|
||||
@ -150,6 +148,9 @@ private:
|
||||
{
|
||||
public:
|
||||
GxsTunnelPeerInfo() : last_contact(0), last_keep_alive_sent(0), status(0), direction(0)
|
||||
#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004
|
||||
,accepts_fast_turtle_items(false)
|
||||
#endif
|
||||
{
|
||||
memset(aes_key, 0, GXS_TUNNEL_AES_KEY_SIZE);
|
||||
|
||||
@ -158,20 +159,24 @@ private:
|
||||
}
|
||||
|
||||
rstime_t last_contact ; // used to keep track of working connexion
|
||||
rstime_t last_keep_alive_sent ; // last time we sent a keep alive packet.
|
||||
rstime_t last_keep_alive_sent ; // last time we sent a keep alive packet.
|
||||
|
||||
unsigned char aes_key[GXS_TUNNEL_AES_KEY_SIZE] ;
|
||||
|
||||
uint32_t status ; // info: do we have a tunnel ?
|
||||
RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel.
|
||||
RsGxsId to_gxs_id; // gxs id we're talking to
|
||||
RsGxsId own_gxs_id ; // gxs id we're using to talk.
|
||||
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
|
||||
TurtleFileHash hash ; // hash that is last used. This is necessary for handling tunnel establishment
|
||||
std::set<uint32_t> client_services ;// services that used this tunnel
|
||||
std::map<uint64_t,rstime_t> received_data_prints ; // list of recently received messages, to avoid duplicates. Kept for 20 mins at most.
|
||||
uint32_t total_sent ;
|
||||
uint32_t total_received ;
|
||||
uint32_t status ; // info: do we have a tunnel ?
|
||||
RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel.
|
||||
RsGxsId to_gxs_id; // gxs id we're talking to
|
||||
RsGxsId own_gxs_id ; // gxs id we're using to talk.
|
||||
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
|
||||
TurtleFileHash hash ; // hash that is last used. This is necessary for handling tunnel establishment
|
||||
std::set<uint32_t> client_services ; // services that used this tunnel
|
||||
std::map<uint64_t,rstime_t> received_data_prints ; // list of recently received messages, to avoid duplicates. Kept for 20 mins at most.
|
||||
uint32_t total_sent ; // total data sent to this peer
|
||||
uint32_t total_received ; // total data received by this peer
|
||||
#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004
|
||||
bool accepts_fast_turtle_items; // does the tunnel accept RsTurtleGenericFastDataItem type?
|
||||
bool already_probed_for_fast_items; // has the tunnel been probed already? If not, a fast item will be sent
|
||||
#endif
|
||||
};
|
||||
|
||||
class GxsTunnelDHInfo
|
||||
@ -243,7 +248,11 @@ private:
|
||||
bool locked_sendEncryptedTunnelData(RsGxsTunnelItem *item) ;
|
||||
bool locked_sendClearTunnelData(RsGxsTunnelDHPublicKeyItem *item); // this limits the usage to DH items. Others should be encrypted!
|
||||
|
||||
bool handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id) ;
|
||||
#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_004
|
||||
bool handleEncryptedData(const uint8_t *data_bytes, uint32_t data_size, const TurtleFileHash& hash, const RsPeerId& virtual_peer_id, bool accepts_fast_items) ;
|
||||
#else
|
||||
bool handleEncryptedData(const uint8_t *data_bytes, uint32_t data_size, const TurtleFileHash& hash, const RsPeerId& virtual_peer_id) ;
|
||||
#endif
|
||||
|
||||
// local data
|
||||
|
||||
|
@ -185,9 +185,10 @@ class NetInterface;
|
||||
**/
|
||||
class PQInterface: public RateInterface
|
||||
{
|
||||
public:
|
||||
explicit PQInterface(const RsPeerId &id) :peerId(id) { return; }
|
||||
virtual ~PQInterface() { return; }
|
||||
public:
|
||||
explicit PQInterface(const RsPeerId &id) :
|
||||
traf_in(0), traf_out(0), peerId(id) {}
|
||||
virtual ~PQInterface() {}
|
||||
|
||||
/*!
|
||||
* allows user to send RsItems to a particular facility (file, network)
|
||||
@ -228,6 +229,22 @@ class PQInterface: public RateInterface
|
||||
const sockaddr_storage & /*remote_peer_address*/)
|
||||
{ return 0; }
|
||||
|
||||
virtual uint64_t getTraffic(bool in)
|
||||
{
|
||||
uint64_t ret = 0;
|
||||
if (in)
|
||||
{
|
||||
ret = traf_in;
|
||||
traf_in = 0;
|
||||
return ret;
|
||||
}
|
||||
ret = traf_out;
|
||||
traf_out = 0;
|
||||
return ret;
|
||||
}
|
||||
uint64_t traf_in;
|
||||
uint64_t traf_out;
|
||||
|
||||
private:
|
||||
|
||||
RsPeerId peerId;
|
||||
|
@ -83,6 +83,8 @@ pqihandler::pqihandler() : coreMtx("pqihandler")
|
||||
rateMax_in = 0.01;
|
||||
rateTotal_in = 0.0 ;
|
||||
rateTotal_out = 0.0 ;
|
||||
traffInSum = 0;
|
||||
traffOutSum = 0;
|
||||
last_m = time(NULL) ;
|
||||
nb_ticks = 0 ;
|
||||
mLastRateCapUpdate = 0 ;
|
||||
@ -371,6 +373,9 @@ int pqihandler::UpdateRates()
|
||||
{
|
||||
SearchModule *mod = (it -> second);
|
||||
float crate_in = mod -> pqi -> getRate(true);
|
||||
|
||||
traffInSum += mod -> pqi -> getTraffic(true);
|
||||
traffOutSum += mod -> pqi -> getTraffic(false);
|
||||
|
||||
#ifdef PQI_HDL_DEBUG_UR
|
||||
if(crate_in > 0.0)
|
||||
@ -540,4 +545,8 @@ void pqihandler::locked_StoreCurrentRates(float in, float out)
|
||||
rateTotal_out = out;
|
||||
}
|
||||
|
||||
|
||||
void pqihandler::GetTraffic(uint64_t &in, uint64_t &out)
|
||||
{
|
||||
in = traffInSum;
|
||||
out = traffOutSum;
|
||||
}
|
||||
|
@ -87,6 +87,10 @@ class pqihandler: public P3Interface, public pqiPublisher
|
||||
int ExtractRates(std::map<RsPeerId, RsBwRates> &ratemap, RsBwRates &totals);
|
||||
int ExtractTrafficInfo(std::list<RSTrafficClue> &out_lst, std::list<RSTrafficClue> &in_lst);
|
||||
|
||||
uint64_t traffInSum;
|
||||
uint64_t traffOutSum;
|
||||
void GetTraffic(uint64_t &in, uint64_t &out);
|
||||
|
||||
protected:
|
||||
/* check to be overloaded by those that can
|
||||
* generates warnings otherwise
|
||||
|
@ -637,6 +637,13 @@ float pqiperson::getRate(bool in)
|
||||
return activepqi -> getRate(in);
|
||||
}
|
||||
|
||||
uint64_t pqiperson::getTraffic(bool in)
|
||||
{
|
||||
if ((!active) || (activepqi == NULL))
|
||||
return 0;
|
||||
return activepqi -> getTraffic(in);
|
||||
}
|
||||
|
||||
void pqiperson::setMaxRate(bool in, float val)
|
||||
{
|
||||
RS_STACK_MUTEX(mPersonMtx);
|
||||
|
@ -143,6 +143,7 @@ public:
|
||||
virtual int getQueueSize(bool in);
|
||||
virtual void getRates(RsBwRates &rates);
|
||||
virtual float getRate(bool in);
|
||||
virtual uint64_t getTraffic(bool in);
|
||||
virtual void setMaxRate(bool in, float val);
|
||||
virtual void setRateCap(float val_in, float val_out);
|
||||
virtual int gatherStatistics(std::list<RSTrafficClue>& outqueue_lst,
|
||||
|
@ -216,6 +216,7 @@ float pqistreamer::getRate(bool b)
|
||||
RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/
|
||||
return RateInterface::getRate(b) ;
|
||||
}
|
||||
|
||||
void pqistreamer::setMaxRate(bool b,float f)
|
||||
{
|
||||
RsStackMutex stack(mStreamerMtx); /**** LOCKED MUTEX ****/
|
||||
@ -1226,7 +1227,7 @@ void pqistreamer::outSentBytes_locked(uint32_t outb)
|
||||
mTotalSent += outb;
|
||||
mCurrSent += outb;
|
||||
mAvgSentCount += outb;
|
||||
|
||||
PQInterface::traf_out += outb;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1243,7 +1244,7 @@ void pqistreamer::inReadBytes_locked(uint32_t inb)
|
||||
mTotalRead += inb;
|
||||
mCurrRead += inb;
|
||||
mAvgReadCount += inb;
|
||||
|
||||
PQInterface::traf_in += inb;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -409,6 +409,7 @@ public:
|
||||
* @return returns 1 on succes and 0 otherwise
|
||||
*/
|
||||
virtual int GetCurrentDataRates( float &inKb, float &outKb ) = 0;
|
||||
virtual int GetTrafficSum( uint64_t &inb, uint64_t &outb ) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -4,7 +4,7 @@
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright (C) 2012 Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -33,6 +33,8 @@
|
||||
#include "serialiser/rsserializable.h"
|
||||
#include "retroshare/rsturtle.h"
|
||||
#include "util/rsdeprecate.h"
|
||||
#include "retroshare/rsgxscircles.h"
|
||||
#include "util/rsmemory.h"
|
||||
|
||||
class RsGxsChannels;
|
||||
|
||||
@ -102,34 +104,114 @@ public:
|
||||
/**
|
||||
* @brief Create channel. Blocking API.
|
||||
* @jsonapi{development}
|
||||
* @param[inout] channel Channel data (name, description...)
|
||||
* @return false on error, true otherwise
|
||||
* @param[in] name Name of the channel
|
||||
* @param[in] description Description of the channel
|
||||
* @param[in] thumbnail Optional image to show as channel thumbnail.
|
||||
* @param[in] authorId Optional id of the author. Leave empty for an
|
||||
* anonymous channel.
|
||||
* @param[in] circleType Optional visibility rule, default public.
|
||||
* @param[in] circleId If the channel is not public specify the id of
|
||||
* the circle who can see the channel. Depending on
|
||||
* the value you pass for
|
||||
* circleType this should be be an external circle
|
||||
* if EXTERNAL is passed, a local friend group id
|
||||
* if NODES_GROUP is passed, empty otherwise.
|
||||
* @param[out] channelId Optional storage for the id of the created
|
||||
* channel, meaningful only if creations succeeds.
|
||||
* @param[out] errorMessage Optional storage for error messsage, meaningful
|
||||
* only if creation fail.
|
||||
* @return False on error, true otherwise.
|
||||
*/
|
||||
virtual bool createChannel(RsGxsChannelGroup& channel) = 0;
|
||||
virtual bool createChannelV2(
|
||||
const std::string& name,
|
||||
const std::string& description,
|
||||
const RsGxsImage& thumbnail = RsGxsImage(),
|
||||
const RsGxsId& authorId = RsGxsId(),
|
||||
RsGxsCircleType circleType = RsGxsCircleType::PUBLIC,
|
||||
const RsGxsCircleId& circleId = RsGxsCircleId(),
|
||||
RsGxsGroupId& channelId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId),
|
||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* @brief Add a comment on a post or on another comment
|
||||
* @brief Add a comment on a post or on another comment. Blocking API.
|
||||
* @jsonapi{development}
|
||||
* @param[inout] comment
|
||||
* @param[in] channelId Id of the channel in which the comment is to be
|
||||
* posted
|
||||
* @param[in] threadId Id of the post (that is a thread) in the channel
|
||||
* where the comment is placed
|
||||
* @param[in] parentId Id of the parent of the comment that is either a
|
||||
* channel post Id or the Id of another comment.
|
||||
* @param[in] authorId Id of the author of the comment
|
||||
* @param[in] comment UTF-8 string containing the comment itself
|
||||
* @param[out] commentMessageId Optional storage for the id of the comment
|
||||
* that was created, meaningful only on success.
|
||||
* @param[out] errorMessage Optional storage for error message, meaningful
|
||||
* only on failure.
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool createComment(RsGxsComment& comment) = 0;
|
||||
virtual bool createCommentV2(
|
||||
const RsGxsGroupId& channelId,
|
||||
const RsGxsMessageId& threadId,
|
||||
const RsGxsMessageId& parentId,
|
||||
const RsGxsId& authorId,
|
||||
const std::string& comment,
|
||||
RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* @brief Create channel post. Blocking API.
|
||||
* @jsonapi{development}
|
||||
* @param[inout] post
|
||||
* @param[in] channelId Id of the channel where to put the post. Beware
|
||||
* you need publish rights on that channel to post.
|
||||
* @param[in] title Title of the post
|
||||
* @param[in] mBody Text content of the post
|
||||
* @param[in] files Optional list of attached files. These are
|
||||
* supposed to be already shared,
|
||||
* @see ExtraFileHash() below otherwise.
|
||||
* @param[in] thumbnail Optional thumbnail image for the post.
|
||||
* @param[in] origPostId If this is supposed to replace an already
|
||||
* existent post, the id of the old post. If left
|
||||
* blank a new post will be created.
|
||||
* @param[out] postId Optional storage for the id of the created post,
|
||||
* meaningful only on success.
|
||||
* @param[out] errorMessage Optional storage for the error message,
|
||||
* meaningful only on failure.
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool createPost(RsGxsChannelPost& post) = 0;
|
||||
virtual bool createPostV2(
|
||||
const RsGxsGroupId& channelId, const std::string& title,
|
||||
const std::string& mBody,
|
||||
const std::list<RsGxsFile>& files = std::list<RsGxsFile>(),
|
||||
const RsGxsImage& thumbnail = RsGxsImage(),
|
||||
const RsGxsMessageId& origPostId = RsGxsMessageId(),
|
||||
RsGxsMessageId& postId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0;
|
||||
|
||||
/**
|
||||
* @brief createVote
|
||||
* @brief Create a vote
|
||||
* @jsonapi{development}
|
||||
* @param[inout] vote
|
||||
* @param[in] channelId Id of the channel where to vote
|
||||
* @param[in] postId Id of the channel post of which a comment is
|
||||
* voted.
|
||||
* @param[in] commentId Id of the comment that is voted
|
||||
* @param[in] authorId Id of the author. Needs to be of an owned
|
||||
* identity.
|
||||
* @param[in] vote Vote value, either RsGxsVoteType::DOWN or
|
||||
* RsGxsVoteType::UP
|
||||
* @param[out] voteId Optional storage for the id of the created vote,
|
||||
* meaningful only on success.
|
||||
* @param[out] errorMessage Optional storage for error message, meaningful
|
||||
* only on failure.
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
virtual bool createVote(RsGxsVote& vote) = 0;
|
||||
virtual bool createVoteV2(
|
||||
const RsGxsGroupId& channelId, const RsGxsMessageId& postId,
|
||||
const RsGxsMessageId& commentId, const RsGxsId& authorId,
|
||||
RsGxsVoteType vote,
|
||||
RsGxsMessageId& voteId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string) ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Edit channel details.
|
||||
@ -315,6 +397,16 @@ public:
|
||||
/* Following functions are deprecated as they expose internal functioning
|
||||
* semantic, instead of a safe to use API */
|
||||
|
||||
/**
|
||||
* @brief Create channel. Blocking API.
|
||||
* @jsonapi{development}
|
||||
* @deprecated { substituted by createChannelV2 }
|
||||
* @param[inout] channel Channel data (name, description...)
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
RS_DEPRECATED_FOR(createChannelV2)
|
||||
virtual bool createChannel(RsGxsChannelGroup& channel) = 0;
|
||||
|
||||
RS_DEPRECATED_FOR(getChannelsInfo)
|
||||
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsChannelGroup> &groups) = 0;
|
||||
|
||||
@ -372,9 +464,29 @@ public:
|
||||
* @param[in] group Channel data (name, description...)
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
RS_DEPRECATED_FOR(createChannel)
|
||||
RS_DEPRECATED_FOR(createChannelV2)
|
||||
virtual bool createGroup(uint32_t& token, RsGxsChannelGroup& group) = 0;
|
||||
|
||||
/**
|
||||
* @brief Add a comment on a post or on another comment
|
||||
* @jsonapi{development}
|
||||
* @deprecated
|
||||
* @param[inout] comment
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
RS_DEPRECATED_FOR(createCommentV2)
|
||||
virtual bool createComment(RsGxsComment& comment) = 0;
|
||||
|
||||
/**
|
||||
* @brief Create channel post. Blocking API.
|
||||
* @jsonapi{development}
|
||||
* @deprecated
|
||||
* @param[inout] post
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
RS_DEPRECATED_FOR(createPostV2)
|
||||
virtual bool createPost(RsGxsChannelPost& post) = 0;
|
||||
|
||||
/**
|
||||
* @brief Request post creation.
|
||||
* The action is performed asyncronously, so it could fail in a subsequent
|
||||
@ -385,9 +497,19 @@ public:
|
||||
* @param[in] post
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
RS_DEPRECATED
|
||||
RS_DEPRECATED_FOR(createPostV2)
|
||||
virtual bool createPost(uint32_t& token, RsGxsChannelPost& post) = 0;
|
||||
|
||||
/**
|
||||
* @brief createVote
|
||||
* @jsonapi{development}
|
||||
* @deprecated
|
||||
* @param[inout] vote
|
||||
* @return false on error, true otherwise
|
||||
*/
|
||||
RS_DEPRECATED_FOR(createVoteV2)
|
||||
virtual bool createVote(RsGxsVote& vote) = 0;
|
||||
|
||||
/**
|
||||
* @brief Request channel change.
|
||||
* The action is performed asyncronously, so it could fail in a subsequent
|
||||
|
@ -42,24 +42,35 @@ class RsGxsCircles;
|
||||
*/
|
||||
extern RsGxsCircles* rsGxsCircles;
|
||||
|
||||
enum class RsGxsCircleType : uint32_t // 32 bit overkill, just for retrocompat
|
||||
{
|
||||
UNKNOWN = 0, /// Used to detect uninizialized values.
|
||||
PUBLIC = 1, /// Public distribution
|
||||
EXTERNAL = 2, /// Restricted to an external circle
|
||||
|
||||
// TODO: convert to enum
|
||||
/// The meaning of the different circle types is:
|
||||
static const uint32_t GXS_CIRCLE_TYPE_UNKNOWN = 0x0000 ; /// Used to detect uninizialized values.
|
||||
static const uint32_t GXS_CIRCLE_TYPE_PUBLIC = 0x0001 ; // not restricted to a circle
|
||||
static const uint32_t GXS_CIRCLE_TYPE_EXTERNAL = 0x0002 ; // restricted to an external circle, made of RsGxsId
|
||||
static const uint32_t GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY = 0x0003 ; // restricted to a subset of friend nodes of a given RS node given by a RsPgpId list
|
||||
static const uint32_t GXS_CIRCLE_TYPE_LOCAL = 0x0004 ; // not distributed at all
|
||||
static const uint32_t GXS_CIRCLE_TYPE_EXT_SELF = 0x0005 ; // self-restricted. Not used, except at creation time when the circle ID isn't known yet. Set to EXTERNAL afterwards.
|
||||
static const uint32_t GXS_CIRCLE_TYPE_YOUR_EYES_ONLY = 0x0006 ; // distributed to nodes signed by your own PGP key only.
|
||||
/** Restricted to a group of friend nodes, the administrator of the circle
|
||||
* behave as a hub for them */
|
||||
NODES_GROUP = 3,
|
||||
|
||||
LOCAL = 4, /// not distributed at all
|
||||
|
||||
/** Self-restricted. Used only at creation time of self-restricted circles
|
||||
* when the circle id isn't known yet. Once the circle id is known the type
|
||||
* is set to EXTERNAL, and the external circle id is set to the id of the
|
||||
* circle itself.
|
||||
*/
|
||||
EXT_SELF = 5,
|
||||
|
||||
/// distributed to nodes signed by your own PGP key only.
|
||||
YOUR_EYES_ONLY = 6
|
||||
};
|
||||
|
||||
// TODO: convert to enum class
|
||||
static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST = 0x0001 ;// user is validated by circle admin
|
||||
static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED = 0x0002 ;// user has subscribed the group
|
||||
static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_KEY_AVAILABLE = 0x0004 ;// key is available, so we can encrypt for this circle
|
||||
static const uint32_t GXS_EXTERNAL_CIRCLE_FLAGS_ALLOWED = 0x0007 ;// user is allowed. Combines all flags above.
|
||||
|
||||
static const uint32_t GXS_CIRCLE_FLAGS_IS_EXTERNAL = 0x0008 ;// user is allowed
|
||||
|
||||
|
||||
struct RsGxsCircleGroup : RsSerializable
|
||||
{
|
||||
@ -110,8 +121,9 @@ struct RsGxsCircleMsg : RsSerializable
|
||||
struct RsGxsCircleDetails : RsSerializable
|
||||
{
|
||||
RsGxsCircleDetails() :
|
||||
mCircleType(GXS_CIRCLE_TYPE_EXTERNAL), mAmIAllowed(false) {}
|
||||
~RsGxsCircleDetails() {}
|
||||
mCircleType(static_cast<uint32_t>(RsGxsCircleType::EXTERNAL)),
|
||||
mAmIAllowed(false) {}
|
||||
~RsGxsCircleDetails() override {}
|
||||
|
||||
RsGxsCircleId mCircleId;
|
||||
std::string mCircleName;
|
||||
@ -264,3 +276,34 @@ public:
|
||||
RS_DEPRECATED_FOR("editCircle, inviteIdsToCircle")
|
||||
virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group) = 0;
|
||||
};
|
||||
|
||||
|
||||
/// @deprecated Used to detect uninizialized values.
|
||||
RS_DEPRECATED_FOR("RsGxsCircleType::UNKNOWN")
|
||||
static const uint32_t GXS_CIRCLE_TYPE_UNKNOWN = 0x0000;
|
||||
|
||||
/// @deprecated not restricted to a circle
|
||||
RS_DEPRECATED_FOR("RsGxsCircleType::PUBLIC")
|
||||
static const uint32_t GXS_CIRCLE_TYPE_PUBLIC = 0x0001;
|
||||
|
||||
/// @deprecated restricted to an external circle, made of RsGxsId
|
||||
RS_DEPRECATED_FOR("RsGxsCircleType::EXTERNAL")
|
||||
static const uint32_t GXS_CIRCLE_TYPE_EXTERNAL = 0x0002;
|
||||
|
||||
/// @deprecated restricted to a subset of friend nodes of a given RS node given
|
||||
/// by a RsPgpId list
|
||||
RS_DEPRECATED_FOR("RsGxsCircleType::NODES_GROUP")
|
||||
static const uint32_t GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY = 0x0003;
|
||||
|
||||
/// @deprecated not distributed at all
|
||||
RS_DEPRECATED_FOR("RsGxsCircleType::LOCAL")
|
||||
static const uint32_t GXS_CIRCLE_TYPE_LOCAL = 0x0004;
|
||||
|
||||
/// @deprecated self-restricted. Not used, except at creation time when the
|
||||
/// circle ID isn't known yet. Set to EXTERNAL afterwards.
|
||||
RS_DEPRECATED_FOR("RsGxsCircleType::EXT_SELF")
|
||||
static const uint32_t GXS_CIRCLE_TYPE_EXT_SELF = 0x0005;
|
||||
|
||||
/// @deprecated distributed to nodes signed by your own PGP key only.
|
||||
RS_DEPRECATED_FOR("RsGxsCircleType::YOUR_EYES_ONLY")
|
||||
static const uint32_t GXS_CIRCLE_TYPE_YOUR_EYES_ONLY = 0x0006;
|
||||
|
@ -19,11 +19,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#ifndef RETROSHARE_GXS_COMMON_OBJS_INTERFACE_H
|
||||
#define RETROSHARE_GXS_COMMON_OBJS_INTERFACE_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
@ -79,10 +77,12 @@ struct RsGxsImage : RsSerializable
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define GXS_VOTE_NONE 0x0000
|
||||
#define GXS_VOTE_DOWN 0x0001
|
||||
#define GXS_VOTE_UP 0x0002
|
||||
enum class RsGxsVoteType : uint32_t
|
||||
{
|
||||
NONE = 0, /// Used to detect unset vote?
|
||||
DOWN = 1, /// Negative vote
|
||||
UP = 2 /// Positive vote
|
||||
};
|
||||
|
||||
|
||||
// Status Flags to indicate Voting....
|
||||
@ -181,7 +181,11 @@ struct RsGxsCommentService
|
||||
std::pair<RsGxsGroupId, RsGxsMessageId>& msgId ) = 0;
|
||||
};
|
||||
|
||||
/// @deprecated use RsGxsVoteType::NONE instead @see RsGxsVoteType
|
||||
#define GXS_VOTE_NONE 0x0000
|
||||
|
||||
/// @deprecated use RsGxsVoteType::DOWN instead @see RsGxsVoteType
|
||||
#define GXS_VOTE_DOWN 0x0001
|
||||
|
||||
#endif
|
||||
|
||||
/// @deprecated use RsGxsVoteType::UP instead @see RsGxsVoteType
|
||||
#define GXS_VOTE_UP 0x0002
|
||||
|
@ -52,14 +52,15 @@ namespace GXS_SERV {
|
||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_MASK = 0x0000ff00;
|
||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_NONE = 0x00000000;
|
||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG = 0x00000100; // Anti-spam feature. Allows to ask higher reputation to anonymous IDs
|
||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_REQUIRED = 0x00000200;
|
||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN = 0x00000400;
|
||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_REQUIRED = 0x00000200; // unused
|
||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN = 0x00000400; // ???
|
||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES = 0x00000800; // not used anymore
|
||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN = 0x00001000; // Anti-spam feature. Allows to ask higher reputation to unknown IDs and anonymous IDs
|
||||
|
||||
// These are *not used*
|
||||
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_MASK = 0x000000ff;
|
||||
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED = 0x00000001;
|
||||
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED = 0x00000002;
|
||||
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED = 0x00000002; // unused
|
||||
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_THREADHEAD = 0x00000004;
|
||||
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_NONEREQ = 0x00000008;
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2011 by Christopher Evi-Parker *
|
||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -20,9 +20,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef RSGXSIFACEIMPL_H
|
||||
#define RSGXSIFACEIMPL_H
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
@ -292,19 +290,51 @@ protected:
|
||||
* Useful for blocking API implementation.
|
||||
* @param[in] token token associated to the request caller is waiting for
|
||||
* @param[in] maxWait maximum waiting time in milliseconds
|
||||
* @param[in] checkEvery time in millisecond between status checks
|
||||
*/
|
||||
RsTokenService::GxsRequestStatus waitToken(
|
||||
uint32_t token,
|
||||
std::chrono::milliseconds maxWait = std::chrono::milliseconds(500) )
|
||||
std::chrono::milliseconds maxWait = std::chrono::milliseconds(500),
|
||||
std::chrono::milliseconds checkEvery = std::chrono::milliseconds(2))
|
||||
{
|
||||
#if defined(__ANDROID__) && (__ANDROID_API__ < 24)
|
||||
auto wkStartime = std::chrono::steady_clock::now();
|
||||
int maxWorkAroundCnt = 10;
|
||||
LLwaitTokenBeginLabel:
|
||||
#endif
|
||||
auto timeout = std::chrono::steady_clock::now() + maxWait;
|
||||
auto st = requestStatus(token);
|
||||
while( !(st == RsTokenService::FAILED || st >= RsTokenService::COMPLETE)
|
||||
&& std::chrono::steady_clock::now() < timeout )
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
std::this_thread::sleep_for(checkEvery);
|
||||
st = requestStatus(token);
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__) && (__ANDROID_API__ < 24)
|
||||
/* Work around for very slow/old android devices, we don't expect this
|
||||
* to be necessary on newer devices. If it take unreasonably long
|
||||
* something worser is already happening elsewere and we return anyway.
|
||||
*/
|
||||
if( st > RsTokenService::FAILED && st < RsTokenService::COMPLETE
|
||||
&& maxWorkAroundCnt-- > 0 )
|
||||
{
|
||||
maxWait *= 10;
|
||||
checkEvery *= 3;
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Slow Android device "
|
||||
<< " workaround st: " << st
|
||||
<< " maxWorkAroundCnt: " << maxWorkAroundCnt
|
||||
<< " maxWait: " << maxWait.count()
|
||||
<< " checkEvery: " << checkEvery.count() << std::endl;
|
||||
goto LLwaitTokenBeginLabel;
|
||||
}
|
||||
std::cerr << __PRETTY_FUNCTION__ << " lasted: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now() - wkStartime ).count()
|
||||
<< "ms" << std::endl;
|
||||
|
||||
#endif
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
@ -312,5 +342,3 @@ private:
|
||||
RsGxsIface& mGxs;
|
||||
RsTokenService& mTokenService;
|
||||
};
|
||||
|
||||
#endif // RSGXSIFACEIMPL_H
|
||||
|
@ -563,8 +563,8 @@ public:
|
||||
/**
|
||||
* @brief MessageToTrash
|
||||
* @jsonapi{development}
|
||||
* @param[in] msgId
|
||||
* @param[in] bTrash
|
||||
* @param[in] msgId Id of the message to mode to trash box
|
||||
* @param[in] bTrash Move to trash if true, otherwise remove from trash
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool MessageToTrash(const std::string &msgId, bool bTrash) = 0;
|
||||
|
@ -44,6 +44,7 @@ class RsPostedGroup
|
||||
|
||||
RsGroupMetaData mMeta;
|
||||
std::string mDescription;
|
||||
RsGxsImage mGroupImage;
|
||||
|
||||
};
|
||||
|
||||
|
@ -121,15 +121,14 @@ public:
|
||||
|
||||
enum GxsRequestStatus : uint8_t
|
||||
{
|
||||
FAILED,
|
||||
PENDING,
|
||||
PARTIAL,
|
||||
COMPLETE,
|
||||
DONE, /// Once all data has been retrived
|
||||
CANCELLED
|
||||
FAILED = 0,
|
||||
PENDING = 1,
|
||||
PARTIAL = 2,
|
||||
COMPLETE = 3,
|
||||
DONE = 4, /// Once all data has been retrived
|
||||
CANCELLED = 5
|
||||
};
|
||||
|
||||
|
||||
RsTokenService() {}
|
||||
virtual ~RsTokenService() {}
|
||||
|
||||
|
@ -31,21 +31,22 @@ const uint8_t QOS_PRIORITY_TOP = 9 ;
|
||||
|
||||
// Turtle traffic
|
||||
//
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_OPEN_TUNNEL = 6 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_TUNNEL_OK = 6 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_OPEN_TUNNEL = 6 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_TUNNEL_OK = 6 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_SEARCH_REQUEST = 6 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_REQUEST = 5 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_CRC_REQUEST = 5 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_CHUNK_CRC_REQUEST= 5 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_REQUEST = 5 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_CRC_REQUEST = 5 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_CHUNK_CRC_REQUEST= 5 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST = 5 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT = 3 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_DATA = 3 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT = 3 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_DATA = 3 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_CRC = 3 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_CHUNK_CRC = 5 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FILE_MAP = 3 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_ITEM = 3 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA= 3 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_DATA = 5 ;
|
||||
const uint8_t QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA= 7 ;
|
||||
|
||||
// File transfer
|
||||
//
|
||||
|
@ -44,7 +44,15 @@ void RsGxsPostedPostItem::serial_process(RsGenericSerializer::SerializeJob j,RsG
|
||||
|
||||
void RsGxsPostedGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR ,mGroup.mDescription,"mGroup.mDescription") ;
|
||||
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR ,mDescription,"mDescription") ;
|
||||
|
||||
if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize)
|
||||
return ;
|
||||
|
||||
if((j == RsGenericSerializer::SIZE_ESTIMATE || j == RsGenericSerializer::SERIALIZE) && mGroupImage.empty())
|
||||
return ;
|
||||
|
||||
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,mGroupImage,"mGroupImage") ;
|
||||
}
|
||||
|
||||
RsItem *RsGxsPostedSerialiser::create_item(uint16_t service_id,uint8_t item_subtype) const
|
||||
@ -109,6 +117,42 @@ void RsGxsPostedPostItem::clear()
|
||||
}
|
||||
void RsGxsPostedGroupItem::clear()
|
||||
{
|
||||
mGroup.mDescription.clear();
|
||||
mDescription.clear();
|
||||
mGroupImage.TlvClear();
|
||||
}
|
||||
|
||||
bool RsGxsPostedGroupItem::fromPostedGroup(RsPostedGroup &group, bool moveImage)
|
||||
{
|
||||
clear();
|
||||
meta = group.mMeta;
|
||||
mDescription = group.mDescription;
|
||||
|
||||
if (moveImage)
|
||||
{
|
||||
mGroupImage.binData.bin_data = group.mGroupImage.mData;
|
||||
mGroupImage.binData.bin_len = group.mGroupImage.mSize;
|
||||
group.mGroupImage.shallowClear();
|
||||
}
|
||||
else
|
||||
{
|
||||
mGroupImage.binData.setBinData(group.mGroupImage.mData, group.mGroupImage.mSize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsGxsPostedGroupItem::toPostedGroup(RsPostedGroup &group, bool moveImage)
|
||||
{
|
||||
group.mMeta = meta;
|
||||
group.mDescription = mDescription;
|
||||
if (moveImage)
|
||||
{
|
||||
group.mGroupImage.take((uint8_t *) mGroupImage.binData.bin_data, mGroupImage.binData.bin_len);
|
||||
// mGroupImage doesn't have a ShallowClear at the moment!
|
||||
mGroupImage.binData.TlvShallowClear();
|
||||
}
|
||||
else
|
||||
{
|
||||
group.mGroupImage.copy((uint8_t *) mGroupImage.binData.bin_data, mGroupImage.binData.bin_len);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -42,8 +42,12 @@ public:
|
||||
|
||||
virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
|
||||
RsPostedGroup mGroup;
|
||||
// use conversion functions to transform:
|
||||
bool fromPostedGroup(RsPostedGroup &group, bool moveImage);
|
||||
bool toPostedGroup(RsPostedGroup &group, bool moveImage);
|
||||
|
||||
std::string mDescription;
|
||||
RsTlvImage mGroupImage;
|
||||
|
||||
};
|
||||
|
||||
|
@ -560,4 +560,8 @@ int p3ServerConfig::GetCurrentDataRates( float &inKb, float &outKb )
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int p3ServerConfig::GetTrafficSum(uint64_t &inb, uint64_t &outb )
|
||||
{
|
||||
mPqiHandler->GetTraffic(inb, outb);
|
||||
return 1;
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ virtual bool setOperatingMode(const std::string &opModeStr);
|
||||
virtual int SetMaxDataRates( int downKb, int upKb );
|
||||
virtual int GetMaxDataRates( int &downKb, int &upKb );
|
||||
virtual int GetCurrentDataRates( float &inKb, float &outKb );
|
||||
virtual int GetTrafficSum( uint64_t &inb, uint64_t &outb );
|
||||
|
||||
/********************* ABOVE is RsConfig Interface *******/
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright (C) 2012 Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -31,12 +31,14 @@
|
||||
|
||||
#include "retroshare/rsgxsflags.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
|
||||
#include "rsserver/p3face.h"
|
||||
#include "retroshare/rsnotify.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
// For Dummy Msgs.
|
||||
#include "util/rsrandom.h"
|
||||
@ -1055,26 +1057,145 @@ bool p3GxsChannels::getChannelContent( const RsGxsGroupId& channelId,
|
||||
return getPostData(token, posts, comments);
|
||||
}
|
||||
|
||||
bool p3GxsChannels::createChannel(RsGxsChannelGroup& channel)
|
||||
bool p3GxsChannels::createChannelV2(
|
||||
const std::string& name, const std::string& description,
|
||||
const RsGxsImage& thumbnail, const RsGxsId& authorId,
|
||||
RsGxsCircleType circleType, const RsGxsCircleId& circleId,
|
||||
RsGxsGroupId& channelId, std::string& errorMessage )
|
||||
{
|
||||
// do some checks
|
||||
|
||||
if( circleType != RsGxsCircleType::PUBLIC
|
||||
&& circleType != RsGxsCircleType::EXTERNAL
|
||||
&& circleType != RsGxsCircleType::NODES_GROUP
|
||||
&& circleType != RsGxsCircleType::LOCAL
|
||||
&& circleType != RsGxsCircleType::YOUR_EYES_ONLY)
|
||||
{
|
||||
errorMessage = "circleType has invalid value";
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(circleType)
|
||||
{
|
||||
case RsGxsCircleType::EXTERNAL:
|
||||
if(circleId.isNull())
|
||||
{
|
||||
errorMessage = "circleType is EXTERNAL but circleId is null";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case RsGxsCircleType::NODES_GROUP:
|
||||
{
|
||||
RsGroupInfo ginfo;
|
||||
|
||||
if(!rsPeers->getGroupInfo(RsNodeGroupId(circleId), ginfo))
|
||||
{
|
||||
errorMessage = "circleType is NODES_GROUP but circleId does not "
|
||||
"correspond to an actual group of friends";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if(!circleId.isNull())
|
||||
{
|
||||
errorMessage = "circleType requires a null circleId, but a non "
|
||||
"null circleId (";
|
||||
errorMessage += circleId.toStdString();
|
||||
errorMessage += ") was supplied";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a consistent channel group meta from the information supplied
|
||||
RsGxsChannelGroup channel;
|
||||
|
||||
channel.mMeta.mGroupName = name;
|
||||
channel.mMeta.mAuthorId = authorId;
|
||||
channel.mMeta.mCircleType = static_cast<uint32_t>(circleType);
|
||||
|
||||
channel.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ
|
||||
| GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED;
|
||||
|
||||
channel.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC;
|
||||
|
||||
channel.mMeta.mCircleId.clear();
|
||||
channel.mMeta.mInternalCircle.clear();
|
||||
|
||||
switch(circleType)
|
||||
{
|
||||
case RsGxsCircleType::NODES_GROUP:
|
||||
channel.mMeta.mInternalCircle = circleId; break;
|
||||
case RsGxsCircleType::EXTERNAL:
|
||||
channel.mMeta.mCircleId = circleId; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Create the channel
|
||||
channel.mDescription = description;
|
||||
channel.mImage = thumbnail;
|
||||
|
||||
uint32_t token;
|
||||
if(!createGroup(token, channel))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! Failed creating group."
|
||||
errorMessage = "Failed creating GXS group.";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(waitToken(token) != RsTokenService::COMPLETE)
|
||||
// wait for the group creation to complete.
|
||||
RsTokenService::GxsRequestStatus wSt =
|
||||
waitToken( token, std::chrono::milliseconds(5000),
|
||||
std::chrono::milliseconds(20) );
|
||||
if(wSt != RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed."
|
||||
errorMessage = "GXS operation waitToken failed with: "
|
||||
+ std::to_string(wSt);
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated "
|
||||
errorMessage = "Failure getting updated group data.";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
channelId = channel.mMeta.mGroupId;
|
||||
|
||||
#ifdef RS_DEEP_SEARCH
|
||||
DeepSearch::indexChannelGroup(channel);
|
||||
#endif // RS_DEEP_SEARCH
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3GxsChannels::createChannel(RsGxsChannelGroup& channel)
|
||||
{
|
||||
uint32_t token;
|
||||
if(!createGroup(token, channel))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating group."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(waitToken(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting updated "
|
||||
<< " group data." << std::endl;
|
||||
return false;
|
||||
}
|
||||
@ -1086,53 +1207,121 @@ bool p3GxsChannels::createChannel(RsGxsChannelGroup& channel)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3GxsChannels::createComment(RsGxsComment& comment)
|
||||
bool p3GxsChannels::createVoteV2(
|
||||
const RsGxsGroupId& channelId, const RsGxsMessageId& postId,
|
||||
const RsGxsMessageId& commentId, const RsGxsId& authorId,
|
||||
RsGxsVoteType tVote, RsGxsMessageId& voteId, std::string& errorMessage )
|
||||
{
|
||||
uint32_t token;
|
||||
if(!createNewComment(token, comment))
|
||||
std::vector<RsGxsChannelGroup> channelsInfo;
|
||||
if(!getChannelsInfo(std::list<RsGxsGroupId>({channelId}),channelsInfo))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! Failed creating comment."
|
||||
<< std::endl;
|
||||
errorMessage = "Channel with Id " + channelId.toStdString()
|
||||
+ " does not exist.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(commentId.isNull())
|
||||
{
|
||||
errorMessage = "You cannot vote on null comment "
|
||||
+ commentId.toStdString();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<RsGxsMessageId> s({commentId});
|
||||
std::vector<RsGxsChannelPost> posts;
|
||||
std::vector<RsGxsComment> comments;
|
||||
|
||||
if(!getChannelContent(channelId, s, posts, comments))
|
||||
{
|
||||
errorMessage = "You cannot vote on comment "
|
||||
+ commentId.toStdString() + " of channel with Id "
|
||||
+ channelId.toStdString()
|
||||
+ ": this comment does not exists locally!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// is the ID a comment ID or a post ID?
|
||||
// It should be comment => should have a parent ID
|
||||
if(posts.front().mMeta.mParentId.isNull())
|
||||
{
|
||||
errorMessage = "You cannot vote on channel message "
|
||||
+ commentId.toStdString() + " of channel with Id "
|
||||
+ channelId.toStdString()
|
||||
+ ": given id refers to a post, not a comment!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( tVote != RsGxsVoteType::NONE
|
||||
&& tVote != RsGxsVoteType::UP
|
||||
&& tVote != RsGxsVoteType::DOWN )
|
||||
{
|
||||
errorMessage = "Your vote to channel with Id "
|
||||
+ channelId.toStdString() + " has wrong vote type. "
|
||||
+ " Only RsGxsVoteType::NONE, RsGxsVoteType::UP, "
|
||||
+ "RsGxsVoteType::DOWN are accepted.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!rsIdentity->isOwnId(authorId))
|
||||
{
|
||||
errorMessage = "You cannot vote to channel with Id "
|
||||
+ channelId.toStdString() + " with identity "
|
||||
+ authorId.toStdString() + " because it is not yours.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the vote
|
||||
RsGxsVote vote;
|
||||
vote.mMeta.mGroupId = channelId;
|
||||
vote.mMeta.mThreadId = postId;
|
||||
vote.mMeta.mParentId = commentId;
|
||||
vote.mMeta.mAuthorId = authorId;
|
||||
vote.mVoteType = static_cast<uint32_t>(tVote);
|
||||
|
||||
uint32_t token;
|
||||
if(!createNewVote(token, vote))
|
||||
{
|
||||
errorMessage = "Error! Failed creating vote.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(waitToken(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed."
|
||||
<< std::endl;
|
||||
errorMessage = "GXS operation failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!RsGenExchange::getPublishedMsgMeta(token, comment.mMeta))
|
||||
if(!RsGenExchange::getPublishedMsgMeta(token, vote.mMeta))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting generated "
|
||||
<< " comment data." << std::endl;
|
||||
errorMessage = "Failure getting generated vote data.";
|
||||
return false;
|
||||
}
|
||||
|
||||
voteId = vote.mMeta.mMsgId;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @deprecated use createVoteV2 instead
|
||||
bool p3GxsChannels::createVote(RsGxsVote& vote)
|
||||
{
|
||||
uint32_t token;
|
||||
if(!createNewVote(token, vote))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! Failed creating vote."
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating vote."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(waitToken(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed."
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!RsGenExchange::getPublishedMsgMeta(token, vote.mMeta))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting generated "
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting generated "
|
||||
<< " vote data." << std::endl;
|
||||
return false;
|
||||
}
|
||||
@ -1145,21 +1334,21 @@ bool p3GxsChannels::editChannel(RsGxsChannelGroup& channel)
|
||||
uint32_t token;
|
||||
if(!updateGroup(token, channel))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! Failed updating group."
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! Failed updating group."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(waitToken(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! GXS operation failed."
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!RsGenExchange::getPublishedGroupMeta(token, channel.mMeta))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated "
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting updated "
|
||||
<< " group data." << std::endl;
|
||||
return false;
|
||||
}
|
||||
@ -1171,11 +1360,64 @@ bool p3GxsChannels::editChannel(RsGxsChannelGroup& channel)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3GxsChannels::createPost(RsGxsChannelPost& post)
|
||||
bool p3GxsChannels::createPostV2(
|
||||
const RsGxsGroupId& channelId, const std::string& title,
|
||||
const std::string& body, const std::list<RsGxsFile>& files,
|
||||
const RsGxsImage& thumbnail, const RsGxsMessageId& origPostId,
|
||||
RsGxsMessageId& postId, std::string& errorMessage )
|
||||
{
|
||||
// Do some checks
|
||||
|
||||
std::vector<RsGxsChannelGroup> channelsInfo;
|
||||
|
||||
if(!getChannelsInfo(std::list<RsGxsGroupId>({channelId}),channelsInfo))
|
||||
{
|
||||
errorMessage = "Channel with Id " + channelId.toStdString() +
|
||||
" does not exist.";
|
||||
return false;
|
||||
}
|
||||
|
||||
const RsGxsChannelGroup& cg(*channelsInfo.begin());
|
||||
|
||||
if(!(cg.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_PUBLISH))
|
||||
{
|
||||
errorMessage = "You cannot post to channel with Id " +
|
||||
channelId.toStdString() + ": missing publish rights!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!origPostId.isNull())
|
||||
{
|
||||
std::set<RsGxsMessageId> s({origPostId});
|
||||
std::vector<RsGxsChannelPost> posts;
|
||||
std::vector<RsGxsComment> comments;
|
||||
|
||||
if(!getChannelContent(channelId,s,posts,comments))
|
||||
{
|
||||
errorMessage = "You cannot edit post " + origPostId.toStdString()
|
||||
+ " of channel with Id " + channelId.toStdString()
|
||||
+ ": this post does not exist locally!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the post
|
||||
RsGxsChannelPost post;
|
||||
|
||||
post.mMeta.mGroupId = channelId;
|
||||
post.mMeta.mOrigMsgId = origPostId;
|
||||
post.mMeta.mMsgName = title;
|
||||
|
||||
post.mMsg = body;
|
||||
post.mFiles = files;
|
||||
post.mThumbnail = thumbnail;
|
||||
|
||||
uint32_t token;
|
||||
if( !createPost(token, post)
|
||||
|| waitToken(token) != RsTokenService::COMPLETE ) return false;
|
||||
if(!createPost(token, post) || waitToken(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
errorMessage = "GXS operation failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(RsGenExchange::getPublishedMsgMeta(token,post.mMeta))
|
||||
{
|
||||
@ -1183,12 +1425,150 @@ bool p3GxsChannels::createPost(RsGxsChannelPost& post)
|
||||
DeepSearch::indexChannelPost(post);
|
||||
#endif // RS_DEEP_SEARCH
|
||||
|
||||
postId = post.mMeta.mMsgId;
|
||||
return true;
|
||||
}
|
||||
|
||||
errorMessage = "Failed to retrive created post metadata";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool p3GxsChannels::createCommentV2(const RsGxsGroupId& channelId,
|
||||
const RsGxsMessageId& threadId,
|
||||
const RsGxsMessageId& parentId,
|
||||
const RsGxsId& authorId,
|
||||
const std::string& comment,
|
||||
RsGxsMessageId& commentMessageId,
|
||||
std::string& errorMessage)
|
||||
{
|
||||
std::vector<RsGxsChannelGroup> channelsInfo;
|
||||
if(!getChannelsInfo(std::list<RsGxsGroupId>({channelId}),channelsInfo))
|
||||
{
|
||||
errorMessage = "Channel with Id " + channelId.toStdString()
|
||||
+ " does not exist.";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<RsGxsChannelPost> posts;
|
||||
std::vector<RsGxsComment> comments;
|
||||
|
||||
if(!getChannelContent( // does the post thread exist?
|
||||
channelId,std::set<RsGxsMessageId>({threadId}), posts, comments ))
|
||||
{
|
||||
errorMessage = "You cannot comment post " + threadId.toStdString() +
|
||||
" of channel with Id " + channelId.toStdString() +
|
||||
": this post does not exists locally!";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// check that the post thread Id is actually that of a post thread
|
||||
if(posts.size() != 1 || !posts[0].mMeta.mParentId.isNull())
|
||||
{
|
||||
errorMessage = "You cannot comment post " + threadId.toStdString() +
|
||||
" of channel with Id " + channelId.toStdString() +
|
||||
": supplied threadId is not a thread, or parentMsgId is not a" +
|
||||
" comment!";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!parentId.isNull())
|
||||
if(!getChannelContent( // does the post thread exist?
|
||||
channelId,std::set<RsGxsMessageId>({parentId}),posts,comments ))
|
||||
{
|
||||
errorMessage = "You cannot comment post " + parentId.toStdString() +
|
||||
": supplied parent comment Id is not a comment!";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
else if(comments.size() != 1 || comments[0].mMeta.mParentId.isNull())
|
||||
{ // is the comment parent actually a comment?
|
||||
errorMessage = "You cannot comment post " + parentId.toStdString()
|
||||
+ " of channel with Id " + channelId.toStdString() +
|
||||
": supplied mParentMsgId is not a comment Id!";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!rsIdentity->isOwnId(authorId)) // is the voter ID actually ours?
|
||||
{
|
||||
errorMessage = "You cannot comment to channel with Id " +
|
||||
channelId.toStdString() + " with identity " +
|
||||
authorId.toStdString() + " because it is not yours.";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now create the comment
|
||||
RsGxsComment cmt;
|
||||
cmt.mMeta.mGroupId = channelId;
|
||||
cmt.mMeta.mThreadId = threadId;
|
||||
cmt.mMeta.mParentId = parentId;
|
||||
cmt.mMeta.mAuthorId = authorId;
|
||||
cmt.mComment = comment;
|
||||
|
||||
uint32_t token;
|
||||
if(!createNewComment(token, cmt))
|
||||
{
|
||||
errorMessage = "Failed creating comment.";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(waitToken(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
errorMessage = "GXS operation failed.";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!RsGenExchange::getPublishedMsgMeta(token, cmt.mMeta))
|
||||
{
|
||||
errorMessage = "Failure getting created comment data.";
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
commentMessageId = cmt.mMeta.mMsgId;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3GxsChannels::createComment(RsGxsComment& comment) // deprecated
|
||||
{
|
||||
uint32_t token;
|
||||
if(!createNewComment(token, comment))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating comment."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(waitToken(token) != RsTokenService::COMPLETE)
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed."
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!RsGenExchange::getPublishedMsgMeta(token, comment.mMeta))
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! Failure getting generated "
|
||||
<< " comment data." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3GxsChannels::subscribeToChannel(
|
||||
const RsGxsGroupId& groupId, bool subscribe )
|
||||
{
|
||||
@ -1428,13 +1808,31 @@ bool p3GxsChannels::updateGroup(uint32_t &token, RsGxsChannelGroup &group)
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @deprecated use createPostV2 instead
|
||||
bool p3GxsChannels::createPost(RsGxsChannelPost& post)
|
||||
{
|
||||
uint32_t token;
|
||||
if( !createPost(token, post)
|
||||
|| waitToken(token) != RsTokenService::COMPLETE ) return false;
|
||||
|
||||
if(RsGenExchange::getPublishedMsgMeta(token,post.mMeta))
|
||||
{
|
||||
#ifdef RS_DEEP_SEARCH
|
||||
DeepSearch::indexChannelPost(post);
|
||||
#endif // RS_DEEP_SEARCH
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool p3GxsChannels::createPost(uint32_t &token, RsGxsChannelPost &msg)
|
||||
{
|
||||
#ifdef GXSCHANNELS_DEBUG
|
||||
std::cerr << "p3GxsChannels::createChannelPost() GroupId: " << msg.mMeta.mGroupId;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << __PRETTY_FUNCTION__ << " GroupId: " << msg.mMeta.mGroupId
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
RsGxsChannelPostItem* msgItem = new RsGxsChannelPostItem();
|
||||
@ -1976,7 +2374,7 @@ bool p3GxsChannels::turtleChannelRequest(
|
||||
{
|
||||
if(channelId.isNull())
|
||||
{
|
||||
std::cerr << __PRETTY_FUNCTION__ << "Error! channelId can't be null!"
|
||||
std::cerr << __PRETTY_FUNCTION__ << " Error! channelId can't be null!"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright (C) 2012 Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -20,14 +20,14 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#ifndef P3_GXSCHANNELS_SERVICE_HEADER
|
||||
#define P3_GXSCHANNELS_SERVICE_HEADER
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "retroshare/rsgxschannels.h"
|
||||
#include "services/p3gxscommon.h"
|
||||
#include "gxs/rsgenexchange.h"
|
||||
#include "gxs/gxstokenqueue.h"
|
||||
#include "util/rsmemory.h"
|
||||
|
||||
#include "util/rstickevent.h"
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
class SSGxsChannelGroup
|
||||
{
|
||||
public:
|
||||
@ -191,23 +192,64 @@ virtual bool ExtraFileRemove(const RsFileHash &hash);
|
||||
std::vector<RsGxsComment>& comments );
|
||||
|
||||
/// Implementation of @see RsGxsChannels::getContentSummaries
|
||||
virtual bool getContentSummaries( const RsGxsGroupId& channelId,
|
||||
std::vector<RsMsgMetaData>& summaries );
|
||||
virtual bool getContentSummaries(
|
||||
const RsGxsGroupId& channelId,
|
||||
std::vector<RsMsgMetaData>& summaries ) override;
|
||||
|
||||
/// Implementation of @see RsGxsChannels::createChannel
|
||||
virtual bool createChannel(RsGxsChannelGroup& channel);
|
||||
/// Implementation of @see RsGxsChannels::createChannelV2
|
||||
virtual bool createChannelV2(
|
||||
const std::string& name, const std::string& description,
|
||||
const RsGxsImage& thumbnail = RsGxsImage(),
|
||||
const RsGxsId& authorId = RsGxsId(),
|
||||
RsGxsCircleType circleType = RsGxsCircleType::PUBLIC,
|
||||
const RsGxsCircleId& circleId = RsGxsCircleId(),
|
||||
RsGxsGroupId& channelId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId),
|
||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||
) override;
|
||||
|
||||
/// @deprecated Implementation of @see RsGxsChannels::createComment
|
||||
RS_DEPRECATED_FOR(createCommentV2)
|
||||
virtual bool createComment(RsGxsComment& comment) override;
|
||||
|
||||
/// Implementation of @see RsGxsChannels::createComment
|
||||
virtual bool createComment(RsGxsComment& comment);
|
||||
virtual bool createCommentV2(
|
||||
const RsGxsGroupId& channelId, const RsGxsMessageId& threadId,
|
||||
const RsGxsMessageId& parentId, const RsGxsId& authorId,
|
||||
const std::string& comment,
|
||||
RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||
) override;
|
||||
|
||||
/// Implementation of @see RsGxsChannels::editChannel
|
||||
virtual bool editChannel(RsGxsChannelGroup& channel);
|
||||
virtual bool editChannel(RsGxsChannelGroup& channel) override;
|
||||
|
||||
/// Implementation of @see RsGxsChannels::createPost
|
||||
virtual bool createPost(RsGxsChannelPost& post);
|
||||
/// @deprecated Implementation of @see RsGxsChannels::createPost
|
||||
RS_DEPRECATED_FOR(createPostV2)
|
||||
virtual bool createPost(RsGxsChannelPost& post) override;
|
||||
|
||||
/// Implementation of @see RsGxsChannels::createVote
|
||||
virtual bool createVote(RsGxsVote& vote);
|
||||
/// Implementation of @see RsGxsChannels::createPostV2
|
||||
bool createPostV2(
|
||||
const RsGxsGroupId& channelId, const std::string& title,
|
||||
const std::string& body,
|
||||
const std::list<RsGxsFile>& files = std::list<RsGxsFile>(),
|
||||
const RsGxsImage& thumbnail = RsGxsImage(),
|
||||
const RsGxsMessageId& origPostId = RsGxsMessageId(),
|
||||
RsGxsMessageId& postId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||
) override;
|
||||
|
||||
/// @deprecated Implementation of @see RsGxsChannels::createVote
|
||||
RS_DEPRECATED_FOR(createVoteV2)
|
||||
virtual bool createVote(RsGxsVote& vote) override;
|
||||
|
||||
/// Implementation of @see RsGxsChannels::createVoteV2
|
||||
virtual bool createVoteV2(
|
||||
const RsGxsGroupId& channelId, const RsGxsMessageId& postId,
|
||||
const RsGxsMessageId& commentId, const RsGxsId& authorId,
|
||||
RsGxsVoteType vote,
|
||||
RsGxsMessageId& voteId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||
) override;
|
||||
|
||||
/// Implementation of @see RsGxsChannels::subscribeToChannel
|
||||
virtual bool subscribeToChannel( const RsGxsGroupId &groupId,
|
||||
@ -219,6 +261,10 @@ virtual bool ExtraFileRemove(const RsFileHash &hash);
|
||||
virtual bool shareChannelKeys(
|
||||
const RsGxsGroupId& channelId, const std::set<RsPeerId>& peers );
|
||||
|
||||
/// Implementation of @see RsGxsChannels::createChannel
|
||||
RS_DEPRECATED_FOR(createChannelV2)
|
||||
virtual bool createChannel(RsGxsChannelGroup& channel) override;
|
||||
|
||||
protected:
|
||||
// Overloaded from GxsTokenQueue for Request callbacks.
|
||||
virtual void handleResponse(uint32_t token, uint32_t req_type);
|
||||
@ -263,9 +309,11 @@ bool generateGroup(uint32_t &token, std::string groupName);
|
||||
class ChannelDummyRef
|
||||
{
|
||||
public:
|
||||
ChannelDummyRef() { return; }
|
||||
ChannelDummyRef(const RsGxsGroupId &grpId, const RsGxsMessageId &threadId, const RsGxsMessageId &msgId)
|
||||
:mGroupId(grpId), mThreadId(threadId), mMsgId(msgId) { return; }
|
||||
ChannelDummyRef() {}
|
||||
ChannelDummyRef(
|
||||
const RsGxsGroupId &grpId, const RsGxsMessageId &threadId,
|
||||
const RsGxsMessageId &msgId ) :
|
||||
mGroupId(grpId), mThreadId(threadId), mMsgId(msgId) {}
|
||||
|
||||
RsGxsGroupId mGroupId;
|
||||
RsGxsMessageId mThreadId;
|
||||
@ -309,5 +357,3 @@ bool generateGroup(uint32_t &token, std::string groupName);
|
||||
/// Cleanup mSearchCallbacksMap and mDistantChannelsCallbacksMap
|
||||
void cleanTimedOutCallbacks();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -79,9 +79,8 @@ bool p3Posted::getGroupData(const uint32_t &token, std::vector<RsPostedGroup> &g
|
||||
RsGxsPostedGroupItem* item = dynamic_cast<RsGxsPostedGroupItem*>(*vit);
|
||||
if (item)
|
||||
{
|
||||
RsPostedGroup grp = item->mGroup;
|
||||
item->mGroup.mMeta = item->meta;
|
||||
grp.mMeta = item->mGroup.mMeta;
|
||||
RsPostedGroup grp;
|
||||
item->toPostedGroup(grp, true);
|
||||
delete item;
|
||||
groups.push_back(grp);
|
||||
}
|
||||
@ -265,8 +264,8 @@ bool p3Posted::createGroup(uint32_t &token, RsPostedGroup &group)
|
||||
std::cerr << "p3Posted::createGroup()" << std::endl;
|
||||
|
||||
RsGxsPostedGroupItem* grpItem = new RsGxsPostedGroupItem();
|
||||
grpItem->mGroup = group;
|
||||
grpItem->meta = group.mMeta;
|
||||
grpItem->fromPostedGroup(group, true);
|
||||
|
||||
|
||||
RsGenExchange::publishGroup(token, grpItem);
|
||||
return true;
|
||||
@ -278,8 +277,8 @@ bool p3Posted::updateGroup(uint32_t &token, RsPostedGroup &group)
|
||||
std::cerr << "p3Posted::updateGroup()" << std::endl;
|
||||
|
||||
RsGxsPostedGroupItem* grpItem = new RsGxsPostedGroupItem();
|
||||
grpItem->mGroup = group;
|
||||
grpItem->meta = group.mMeta;
|
||||
grpItem->fromPostedGroup(group, true);
|
||||
|
||||
|
||||
RsGenExchange::updateGroup(token, grpItem);
|
||||
return true;
|
||||
|
@ -77,18 +77,18 @@ void TS_dumpState() ;
|
||||
// - The total number of TR per second emmited from self will be MAX_TUNNEL_REQS_PER_SECOND / TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 0.5
|
||||
// - I updated forward probabilities to higher values, and min them to 1/nb_connected_friends to prevent blocking tunnels.
|
||||
//
|
||||
static const rstime_t TUNNEL_REQUESTS_LIFE_TIME = 240 ; /// life time for tunnel requests in the cache.
|
||||
static const rstime_t SEARCH_REQUESTS_LIFE_TIME = 240 ; /// life time for search requests in the cache
|
||||
static const rstime_t REGULAR_TUNNEL_DIGGING_TIME = 300 ; /// maximum interval between two tunnel digging campaigns.
|
||||
static const rstime_t MAXIMUM_TUNNEL_IDLE_TIME = 60 ; /// maximum life time of an unused tunnel.
|
||||
static const rstime_t EMPTY_TUNNELS_DIGGING_TIME = 50 ; /// look into tunnels regularly every 50 sec.
|
||||
static const rstime_t TUNNEL_SPEED_ESTIMATE_LAPSE = 5 ; /// estimate tunnel speed every 5 seconds
|
||||
static const rstime_t TUNNEL_CLEANING_LAPS_TIME = 10 ; /// clean tunnels every 10 secs
|
||||
static const rstime_t TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 2 ; /// Tunnel management calls every 2 secs.
|
||||
static const uint32_t MAX_TUNNEL_REQS_PER_SECOND = 1 ; /// maximum number of tunnel requests issued per second. Was 0.5 before
|
||||
static const uint32_t MAX_ALLOWED_SR_IN_CACHE = 120 ; /// maximum number of search requests allowed in cache. That makes 2 per sec.
|
||||
static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_FILES =5000 ; /// maximum number of search results forwarded back to the source.
|
||||
static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_DEFAULT= 100 ; /// default maximum number of search results forwarded back source.
|
||||
static const rstime_t TUNNEL_REQUESTS_LIFE_TIME = 240 ; /// life time for tunnel requests in the cache.
|
||||
static const rstime_t SEARCH_REQUESTS_LIFE_TIME = 240 ; /// life time for search requests in the cache
|
||||
static const rstime_t REGULAR_TUNNEL_DIGGING_TIME = 300 ; /// maximum interval between two tunnel digging campaigns.
|
||||
static const rstime_t MAXIMUM_TUNNEL_IDLE_TIME = 60 ; /// maximum life time of an unused tunnel.
|
||||
static const rstime_t EMPTY_TUNNELS_DIGGING_TIME = 50 ; /// look into tunnels regularly every 50 sec.
|
||||
static const rstime_t TUNNEL_SPEED_ESTIMATE_LAPSE = 5 ; /// estimate tunnel speed every 5 seconds
|
||||
static const rstime_t TUNNEL_CLEANING_LAPS_TIME = 10 ; /// clean tunnels every 10 secs
|
||||
static const rstime_t TIME_BETWEEN_TUNNEL_MANAGEMENT_CALLS = 2 ; /// Tunnel management calls every 2 secs.
|
||||
static const uint32_t MAX_TUNNEL_REQS_PER_SECOND = 1 ; /// maximum number of tunnel requests issued per second. Was 0.5 before
|
||||
static const uint32_t MAX_ALLOWED_SR_IN_CACHE = 120 ; /// maximum number of search requests allowed in cache. That makes 2 per sec.
|
||||
static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_FILES =5000 ; /// maximum number of search results forwarded back to the source.
|
||||
static const uint32_t TURTLE_SEARCH_RESULT_MAX_HITS_DEFAULT = 100 ; /// default maximum number of search results forwarded back source.
|
||||
|
||||
static const float depth_peer_probability[7] = { 1.0f,0.99f,0.9f,0.7f,0.6f,0.5,0.4f } ;
|
||||
|
||||
|
@ -53,6 +53,7 @@ RsItem *RsTurtleSerialiser::create_item(uint16_t service,uint8_t item_subtype) c
|
||||
case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : return new RsTurtleOpenTunnelItem();
|
||||
case RS_TURTLE_SUBTYPE_TUNNEL_OK : return new RsTurtleTunnelOkItem();
|
||||
case RS_TURTLE_SUBTYPE_GENERIC_DATA : return new RsTurtleGenericDataItem();
|
||||
case RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA : return new RsTurtleGenericFastDataItem();
|
||||
case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST : return new RsTurtleGenericSearchRequestItem();
|
||||
case RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT : return new RsTurtleGenericSearchResultItem();
|
||||
|
||||
@ -244,8 +245,12 @@ void RsTurtleTunnelOkItem::serial_process(RsGenericSerializer::SerializeJob j,Rs
|
||||
void RsTurtleGenericDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process<uint32_t>(j,ctx,tunnel_id ,"tunnel_id") ;
|
||||
|
||||
RsTypeSerializer::TlvMemBlock_proxy prox(data_bytes,data_size) ;
|
||||
|
||||
RsTypeSerializer::serial_process(j,ctx,prox,"data bytes") ;
|
||||
}
|
||||
void RsTurtleGenericFastDataItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process<uint32_t>(j,ctx,tunnel_id ,"tunnel_id") ;
|
||||
RsTypeSerializer::TlvMemBlock_proxy prox(data_bytes,data_size) ;
|
||||
RsTypeSerializer::serial_process(j,ctx,prox,"data bytes") ;
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST = 0x11 ;
|
||||
// const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST = 0x13 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC = 0x14 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST = 0x15 ;
|
||||
const uint8_t RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA = 0x16 ;
|
||||
|
||||
|
||||
class TurtleSearchRequestInfo ;
|
||||
@ -331,6 +332,28 @@ class RsTurtleGenericDataItem: public RsTurtleGenericTunnelItem
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
};
|
||||
|
||||
// Same, but with a fact priority. Can rather be used for e.g. distant chat.
|
||||
//
|
||||
class RsTurtleGenericFastDataItem: public RsTurtleGenericTunnelItem
|
||||
{
|
||||
public:
|
||||
RsTurtleGenericFastDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA), data_size(0), data_bytes(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA);}
|
||||
virtual ~RsTurtleGenericFastDataItem() { if(data_bytes != NULL) free(data_bytes) ; }
|
||||
|
||||
virtual bool shouldStampTunnel() const { return true ; }
|
||||
|
||||
uint32_t data_size ;
|
||||
void *data_bytes ;
|
||||
|
||||
void clear()
|
||||
{
|
||||
free(data_bytes) ;
|
||||
data_bytes = NULL ;
|
||||
data_size = 0;
|
||||
}
|
||||
protected:
|
||||
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
};
|
||||
/***********************************************************************************/
|
||||
/* Turtle Serialiser class */
|
||||
/***********************************************************************************/
|
||||
|
@ -3,7 +3,8 @@
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2012-2012 by Cyril Soler <csoler@users.sourceforge.net> *
|
||||
* Copyright 2012 Cyril Soler <csoler@users.sourceforge.net> *
|
||||
* Copyright 2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -21,9 +22,45 @@
|
||||
*******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <util/stacktrace.h>
|
||||
#include <memory>
|
||||
|
||||
#include "util/stacktrace.h"
|
||||
|
||||
/**
|
||||
* @brief Shorthand macro to declare optional functions output parameters
|
||||
* To define an optional output paramether use the following syntax
|
||||
*
|
||||
\code{.cpp}
|
||||
bool myFunnyFunction(
|
||||
int mandatoryParamether,
|
||||
BigType& myOptionalOutput = RS_DEFAULT_STORAGE_PARAM(BigType) )
|
||||
\endcode
|
||||
*
|
||||
* The function caller then can call myFunnyFunction either passing
|
||||
* myOptionalOutput parameter or not.
|
||||
* @see RsGxsChannels methods for real usage examples.
|
||||
*
|
||||
* @details
|
||||
* When const references are used to pass function parameters it is easy do make
|
||||
* those params optional by defining a default value in the function
|
||||
* declaration, because a temp is accepted as default parameter in those cases.
|
||||
* It is not as simple when one want to make optional a non-const reference
|
||||
* parameter that is usually used as output, in that case as a temp is in theory
|
||||
* not acceptable.
|
||||
* Yet it is possible to overcome that limitation with the following trick:
|
||||
* If not passed as parameter the storage for the output parameter can be
|
||||
* dinamically allocated directly by the function call, to avoid leaking memory
|
||||
* on each function call the pointer to that storage is made unique so once the
|
||||
* function returns it goes out of scope and is automatically deleted.
|
||||
* About performance overhead: std::unique_ptr have very good performance and
|
||||
* modern compilers may be even able to avoid the dynamic allocation in this
|
||||
* case, any way the allocation would only happen if the parameter is not
|
||||
* passed, so any effect on performace would happen only in case where the
|
||||
* function is called without the parameter.
|
||||
*/
|
||||
#define RS_DEFAULT_STORAGE_PARAM(Type) *std::unique_ptr<Type>(new Type)
|
||||
|
||||
void *rs_malloc(size_t size) ;
|
||||
|
||||
|
@ -201,7 +201,7 @@ void RsThread::start(const std::string &threadName)
|
||||
if(threadName.length() > 15)
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
THREAD_DEBUG << "RsThread::start called with to long name '" << name << "' truncating..." << std::endl;
|
||||
THREAD_DEBUG << "RsThread::start called with to long name '" << threadName << "' truncating..." << std::endl;
|
||||
#endif
|
||||
RS_pthread_setname_np(mTid, threadName.substr(0, 15).c_str());
|
||||
} else {
|
||||
|
@ -329,13 +329,15 @@ void SearchDialog::searchResultWidgetCustomPopupMenu( QPoint /*point*/ )
|
||||
QMenu contextMnu(this) ;
|
||||
|
||||
contextMnu.addAction(QIcon(IMAGE_START), tr("Download"), this, SLOT(download())) ;
|
||||
contextMnu.addAction(QIcon(IMAGE_BANFILE), tr("Mark as bad"), this, SLOT(ban())) ;
|
||||
contextMnu.addSeparator();//--------------------------------------
|
||||
|
||||
contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyResultLink())) ;
|
||||
contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Send RetroShare Link"), this, SLOT(sendLinkTo())) ;
|
||||
contextMnu.addSeparator();//--------------------------------------
|
||||
|
||||
contextMnu.addAction(QIcon(IMAGE_BANFILE), tr("Mark as bad"), this, SLOT(ban())) ;
|
||||
contextMnu.addSeparator();//--------------------------------------
|
||||
|
||||
QMenu collectionMenu(tr("Collection"), this);
|
||||
collectionMenu.setIcon(QIcon(IMAGE_LIBRARY));
|
||||
collectionMenu.addAction(collCreateAct);
|
||||
|
@ -1878,6 +1878,7 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
if (isOwnId)
|
||||
{
|
||||
mStateHelper->setWidgetEnabled(ui->ownOpinion_CB, false);
|
||||
mStateHelper->setWidgetEnabled(ui->autoBanIdentities_CB, false);
|
||||
ui->editIdentity->setEnabled(true);
|
||||
ui->removeIdentity->setEnabled(true);
|
||||
ui->chatIdentity->setEnabled(false);
|
||||
@ -1887,6 +1888,7 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
{
|
||||
// No Reputation yet!
|
||||
mStateHelper->setWidgetEnabled(ui->ownOpinion_CB, true);
|
||||
mStateHelper->setWidgetEnabled(ui->autoBanIdentities_CB, true);
|
||||
ui->editIdentity->setEnabled(false);
|
||||
ui->removeIdentity->setEnabled(false);
|
||||
ui->chatIdentity->setEnabled(true);
|
||||
@ -2086,7 +2088,7 @@ void IdDialog::modifyReputation()
|
||||
case 2: op = RsOpinion::POSITIVE; break;
|
||||
default:
|
||||
std::cerr << "Wrong value from opinion combobox. Bug??" << std::endl;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
rsReputations->setOwnOpinion(id,op);
|
||||
|
||||
|
@ -117,7 +117,7 @@
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/icons/help_64.png</normaloff>:/icons/help_64.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
@ -284,7 +284,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1372</width>
|
||||
<height>1000</height>
|
||||
<height>999</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="scrollAreaWidgetContentsVLayout">
|
||||
@ -562,7 +562,11 @@ border-image: url(:/images/closepressed.png)
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_Type"/>
|
||||
<widget class="QLineEdit" name="lineEdit_Type">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_Nickname">
|
||||
@ -646,7 +650,11 @@ p, li { white-space: pre-wrap; }
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEdit_LastUsed"/>
|
||||
<widget class="QLineEdit" name="lineEdit_LastUsed">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_Type">
|
||||
@ -891,7 +899,11 @@ p, li { white-space: pre-wrap; }
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLineEdit" name="lineEdit_PublishTS"/>
|
||||
<widget class="QLineEdit" name="lineEdit_PublishTS">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -1087,8 +1099,8 @@ p, li { white-space: pre-wrap; }
|
||||
<tabstop>idTreeWidget</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../icons.qrc"/>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="../icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "gui/FileTransfer/SearchDialog.h"
|
||||
#include "gui/FileTransfer/SharedFilesDialog.h"
|
||||
#include "gui/FileTransfer/TransfersDialog.h"
|
||||
#include "MessagesDialog.h"
|
||||
#include "gui/msgs/MessagesDialog.h"
|
||||
#include "PluginsPage.h"
|
||||
#include "NewsFeed.h"
|
||||
#include "ShareManager.h"
|
||||
@ -730,9 +730,12 @@ void MainWindow::updateStatus()
|
||||
float downKb = 0;
|
||||
float upKb = 0;
|
||||
rsConfig->GetCurrentDataRates(downKb, upKb);
|
||||
uint64_t down = 0;
|
||||
uint64_t up = 0;
|
||||
rsConfig->GetTrafficSum(down, up);
|
||||
|
||||
if (ratesstatus)
|
||||
ratesstatus->getRatesStatus(downKb, upKb);
|
||||
ratesstatus->getRatesStatus(downKb, down, upKb, up);
|
||||
|
||||
if(torstatus)
|
||||
torstatus->getTorStatus();
|
||||
|
@ -35,6 +35,7 @@ public:
|
||||
PostedGroupInfoData() : RsUserdata() {}
|
||||
|
||||
public:
|
||||
QMap<RsGxsGroupId, QIcon> mIcon;
|
||||
QMap<RsGxsGroupId, QString> mDescription;
|
||||
};
|
||||
|
||||
@ -102,17 +103,17 @@ QString PostedDialog::icon(IconType type)
|
||||
case ICON_NEW:
|
||||
return ":/icons/png/add.png";
|
||||
case ICON_YOUR_GROUP:
|
||||
return ":/icons/png/feedreader.png";
|
||||
return "";
|
||||
case ICON_SUBSCRIBED_GROUP:
|
||||
return ":/icons/png/feed-subscribed.png";
|
||||
return "";
|
||||
case ICON_POPULAR_GROUP:
|
||||
return ":/icons/png/feed-popular.png";
|
||||
return "";
|
||||
case ICON_OTHER_GROUP:
|
||||
return ":/icons/png/feed-other.png";
|
||||
case ICON_SEARCH:
|
||||
return ":/images/find.png";
|
||||
case ICON_DEFAULT:
|
||||
return "";
|
||||
return ":/icons/png/posted.png";
|
||||
}
|
||||
|
||||
return "";
|
||||
@ -161,6 +162,12 @@ void PostedDialog::loadGroupSummaryToken(const uint32_t &token, std::list<RsGrou
|
||||
for (groupIt = groups.begin(); groupIt != groups.end(); ++groupIt) {
|
||||
RsPostedGroup &group = *groupIt;
|
||||
groupInfo.push_back(group.mMeta);
|
||||
|
||||
if (group.mGroupImage.mData != NULL) {
|
||||
QPixmap image;
|
||||
image.loadFromData(group.mGroupImage.mData, group.mGroupImage.mSize, "PNG");
|
||||
postedData->mIcon[group.mMeta.mGroupId] = image;
|
||||
}
|
||||
|
||||
if (!group.mDescription.empty()) {
|
||||
postedData->mDescription[group.mMeta.mGroupId] = QString::fromUtf8(group.mDescription.c_str());
|
||||
@ -183,4 +190,9 @@ void PostedDialog::groupInfoToGroupItemInfo(const RsGroupMetaData &groupInfo, Gr
|
||||
if (descriptionIt != postedData->mDescription.end()) {
|
||||
groupItemInfo.description = descriptionIt.value();
|
||||
}
|
||||
|
||||
QMap<RsGxsGroupId, QIcon>::const_iterator iconIt = postedData->mIcon.find(groupInfo.mGroupId);
|
||||
if (iconIt != postedData->mIcon.end()) {
|
||||
groupItemInfo.icon = iconIt.value();
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
#include <QBuffer>
|
||||
|
||||
#include "PostedGroupDialog.h"
|
||||
|
||||
@ -25,7 +26,7 @@
|
||||
|
||||
const uint32_t PostedCreateEnabledFlags = (
|
||||
GXS_GROUP_FLAGS_NAME |
|
||||
// GXS_GROUP_FLAGS_ICON |
|
||||
GXS_GROUP_FLAGS_ICON |
|
||||
GXS_GROUP_FLAGS_DESCRIPTION |
|
||||
GXS_GROUP_FLAGS_DISTRIBUTION |
|
||||
// GXS_GROUP_FLAGS_PUBLISHSIGN |
|
||||
@ -90,14 +91,31 @@ QPixmap PostedGroupDialog::serviceImage()
|
||||
return QPixmap(":/icons/png/posted.png");
|
||||
}
|
||||
|
||||
void PostedGroupDialog::preparePostedGroup(RsPostedGroup &group, const RsGroupMetaData &meta)
|
||||
{
|
||||
group.mMeta = meta;
|
||||
group.mDescription = getDescription().toUtf8().constData();
|
||||
|
||||
QPixmap pixmap = getLogo();
|
||||
|
||||
if (!pixmap.isNull()) {
|
||||
QByteArray ba;
|
||||
QBuffer buffer(&ba);
|
||||
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
pixmap.save(&buffer, "PNG"); // writes image into ba in PNG format
|
||||
|
||||
group.mGroupImage.copy((uint8_t *) ba.data(), ba.size());
|
||||
} else {
|
||||
group.mGroupImage.clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool PostedGroupDialog::service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta)
|
||||
{
|
||||
// Specific Function.
|
||||
RsPostedGroup grp;
|
||||
grp.mMeta = meta;
|
||||
grp.mDescription = getDescription().toStdString();
|
||||
std::cerr << "PostedGroupDialog::service_CreateGroup() storing to Queue";
|
||||
std::cerr << std::endl;
|
||||
preparePostedGroup(grp, meta);
|
||||
|
||||
rsPosted->createGroup(token, grp);
|
||||
|
||||
@ -107,8 +125,7 @@ bool PostedGroupDialog::service_CreateGroup(uint32_t &token, const RsGroupMetaDa
|
||||
bool PostedGroupDialog::service_EditGroup(uint32_t &token, RsGroupMetaData &editedMeta)
|
||||
{
|
||||
RsPostedGroup grp;
|
||||
grp.mMeta = editedMeta;
|
||||
grp.mDescription = getDescription().toUtf8().constData();
|
||||
preparePostedGroup(grp, editedMeta);
|
||||
|
||||
std::cerr << "PostedGroupDialog::service_EditGroup() submitting changes";
|
||||
std::cerr << std::endl;
|
||||
@ -140,8 +157,18 @@ bool PostedGroupDialog::service_loadGroup(uint32_t token, Mode /*mode*/, RsGroup
|
||||
std::cerr << "PostedGroupDialog::service_loadGroup() Unfinished Loading";
|
||||
std::cerr << std::endl;
|
||||
|
||||
groupMetaData = groups[0].mMeta;
|
||||
description = QString::fromUtf8(groups[0].mDescription.c_str());
|
||||
const RsPostedGroup &group = groups[0];
|
||||
groupMetaData = group.mMeta;
|
||||
description = QString::fromUtf8(group.mDescription.c_str());
|
||||
|
||||
if (group.mGroupImage.mData) {
|
||||
QPixmap pixmap;
|
||||
if (pixmap.loadFromData(group.mGroupImage.mData, group.mGroupImage.mSize, "PNG")) {
|
||||
setLogo(pixmap);
|
||||
}
|
||||
} else {
|
||||
setLogo(QPixmap(":/icons/png/posted.png"));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ protected:
|
||||
virtual bool service_CreateGroup(uint32_t &token, const RsGroupMetaData &meta);
|
||||
virtual bool service_loadGroup(uint32_t token, Mode mode, RsGroupMetaData& groupMetaData, QString &description);
|
||||
virtual bool service_EditGroup(uint32_t &token, RsGroupMetaData &editedMeta);
|
||||
|
||||
private:
|
||||
void preparePostedGroup(RsPostedGroup &group, const RsGroupMetaData &meta);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -109,7 +109,18 @@ void PostedItem::setup()
|
||||
|
||||
QAction *CopyLinkAction = new QAction(QIcon(""),tr("Copy RetroShare Link"), this);
|
||||
connect(CopyLinkAction, SIGNAL(triggered()), this, SLOT(copyMessageLink()));
|
||||
|
||||
|
||||
|
||||
int S = QFontMetricsF(font()).height() ;
|
||||
|
||||
ui->voteUpButton->setIconSize(QSize(S*1.5,S*1.5));
|
||||
ui->voteDownButton->setIconSize(QSize(S*1.5,S*1.5));
|
||||
ui->commentButton->setIconSize(QSize(S*1.5,S*1.5));
|
||||
ui->expandButton->setIconSize(QSize(S*1.5,S*1.5));
|
||||
ui->notesButton->setIconSize(QSize(S*1.5,S*1.5));
|
||||
ui->readButton->setIconSize(QSize(S*1.5,S*1.5));
|
||||
ui->shareButton->setIconSize(QSize(S*1.5,S*1.5));
|
||||
|
||||
QMenu *menu = new QMenu();
|
||||
menu->addAction(CopyLinkAction);
|
||||
ui->shareButton->setMenu(menu);
|
||||
@ -235,20 +246,25 @@ void PostedItem::fill()
|
||||
return;
|
||||
}
|
||||
|
||||
QPixmap sqpixmap2 = QPixmap(":/images/thumb-default.png");
|
||||
|
||||
mInFill = true;
|
||||
|
||||
int desired_height = 1.5*(ui->voteDownButton->height() + ui->voteUpButton->height() + ui->scoreLabel->height());
|
||||
int desired_width = sqpixmap2.width()*desired_height/(float)sqpixmap2.height();
|
||||
|
||||
if(mPost.mImage.mData != NULL)
|
||||
{
|
||||
QPixmap pixmap;
|
||||
pixmap.loadFromData(mPost.mImage.mData, mPost.mImage.mSize, "PNG");
|
||||
// Wiping data - as its been passed to thumbnail.
|
||||
|
||||
QPixmap sqpixmap = pixmap.scaled(800, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
ui->pictureLabel->setPixmap(sqpixmap);
|
||||
|
||||
ui->thumbnailLabel->setPixmap(pixmap);
|
||||
}else
|
||||
QPixmap sqpixmap = pixmap.scaled(desired_width,desired_height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||
ui->thumbnailLabel->setPixmap(sqpixmap);
|
||||
ui->pictureLabel->setPixmap(pixmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
//ui->thumbnailLabel->setFixedSize(desired_width,desired_height);
|
||||
ui->expandButton->setDisabled(true);
|
||||
}
|
||||
|
||||
@ -290,7 +306,7 @@ void PostedItem::fill()
|
||||
urlstr += QString(" </span></a>");
|
||||
|
||||
QString siteurl = url.scheme() + "://" + url.host();
|
||||
sitestr = QString("<a href=\"%1\" ><span style=\" text-decoration: underline; color:#2255AA;\"> %2 </span></a>").arg(siteurl).arg(siteurl);
|
||||
sitestr = QString("<a href=\"%1\" ><span style=\" text-decoration: underline; color:#0079d3;\"> %2 </span></a>").arg(siteurl).arg(siteurl);
|
||||
|
||||
ui->titleLabel->setText(urlstr);
|
||||
}else
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>617</width>
|
||||
<height>190</height>
|
||||
<width>825</width>
|
||||
<height>337</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -67,6 +67,12 @@
|
||||
</property>
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<widget class="QFrame" name="voteFrame">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>37</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
@ -100,12 +106,6 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Vote up</string>
|
||||
</property>
|
||||
@ -116,12 +116,6 @@
|
||||
<iconset resource="Posted_images.qrc">
|
||||
<normaloff>:/images/up-arrow.png</normaloff>:/images/up-arrow.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -161,12 +155,6 @@
|
||||
<iconset resource="Posted_images.qrc">
|
||||
<normaloff>:/images/down-arrow.png</normaloff>:/images/down-arrow.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -198,6 +186,12 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="thumbnailLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
@ -312,7 +306,7 @@
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
@ -371,25 +365,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="siteBoldLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Site</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="siteLabel">
|
||||
<property name="sizePolicy">
|
||||
@ -426,6 +401,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="buttonHLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@ -705,8 +683,8 @@
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="Posted_images.qrc"/>
|
||||
<include location="../images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -26,8 +26,12 @@
|
||||
#include "PostedCreatePostDialog.h"
|
||||
#include "PostedItem.h"
|
||||
#include "gui/common/UIStateHelper.h"
|
||||
#include "gui/RetroShareLink.h"
|
||||
#include "util/HandleRichText.h"
|
||||
#include "util/DateTime.h"
|
||||
|
||||
#include <retroshare/rsposted.h>
|
||||
#include "retroshare/rsgxscircles.h"
|
||||
|
||||
#define POSTED_DEFAULT_LISTING_LENGTH 10
|
||||
#define POSTED_MAX_INDEX 10000
|
||||
@ -65,12 +69,19 @@ PostedListWidget::PostedListWidget(const RsGxsGroupId &postedId, QWidget *parent
|
||||
|
||||
/* fill in the available OwnIds for signing */
|
||||
ui->idChooser->loadIds(IDCHOOSER_ID_REQUIRED, RsGxsId());
|
||||
|
||||
int S = QFontMetricsF(font()).height() ;
|
||||
|
||||
ui->submitPostButton->setIconSize(QSize(S*1.5,S*1.5));
|
||||
ui->comboBox->setIconSize(QSize(S*1.5,S*1.5));
|
||||
|
||||
connect(ui->submitPostButton, SIGNAL(clicked()), this, SLOT(newPost()));
|
||||
|
||||
ui->subscribeToolButton->setToolTip(tr( "<p>Subscribing to the links will gather \
|
||||
available posts from your subscribed friends, and make the \
|
||||
links visible to all other friends.</p><p>Afterwards you can unsubscribe from the context menu of the links list at left.</p>"));
|
||||
|
||||
ui->infoframe->hide();
|
||||
|
||||
/* load settings */
|
||||
processSettings(true);
|
||||
@ -293,6 +304,67 @@ void PostedListWidget::insertPostedDetails(const RsPostedGroup &group)
|
||||
mStateHelper->setWidgetEnabled(ui->submitPostButton, IS_GROUP_SUBSCRIBED(group.mMeta.mSubscribeFlags));
|
||||
ui->subscribeToolButton->setSubscribed(IS_GROUP_SUBSCRIBED(group.mMeta.mSubscribeFlags));
|
||||
ui->subscribeToolButton->setHidden(IS_GROUP_SUBSCRIBED(group.mMeta.mSubscribeFlags)) ;
|
||||
|
||||
RetroShareLink link;
|
||||
|
||||
if (IS_GROUP_SUBSCRIBED(group.mMeta.mSubscribeFlags)) {
|
||||
|
||||
ui->infoframe->hide();
|
||||
|
||||
} else {
|
||||
|
||||
ui->infoPosts->setText(QString::number(group.mMeta.mVisibleMsgCount));
|
||||
|
||||
if(group.mMeta.mLastPost==0)
|
||||
ui->infoLastPost->setText(tr("Never"));
|
||||
else
|
||||
|
||||
ui->infoLastPost->setText(DateTime::formatLongDateTime(group.mMeta.mLastPost));
|
||||
|
||||
QString formatDescription = QString::fromUtf8(group.mDescription.c_str());
|
||||
|
||||
unsigned int formatFlag = RSHTML_FORMATTEXT_EMBED_LINKS;
|
||||
|
||||
formatDescription = RsHtml().formatText(NULL, formatDescription, formatFlag);
|
||||
|
||||
ui->infoDescription->setText(formatDescription);
|
||||
|
||||
ui->infoAdministrator->setId(group.mMeta.mAuthorId) ;
|
||||
|
||||
link = RetroShareLink::createMessage(group.mMeta.mAuthorId, "");
|
||||
ui->infoAdministrator->setText(link.toHtml());
|
||||
|
||||
QString distrib_string ( "[unknown]" );
|
||||
|
||||
switch(group.mMeta.mCircleType)
|
||||
{
|
||||
case GXS_CIRCLE_TYPE_PUBLIC: distrib_string = tr("Public") ;
|
||||
break ;
|
||||
case GXS_CIRCLE_TYPE_EXTERNAL:
|
||||
{
|
||||
RsGxsCircleDetails det ;
|
||||
|
||||
// !! What we need here is some sort of CircleLabel, which loads the circle and updates the label when done.
|
||||
|
||||
if(rsGxsCircles->getCircleDetails(group.mMeta.mCircleId,det))
|
||||
distrib_string = tr("Restricted to members of circle \"")+QString::fromUtf8(det.mCircleName.c_str()) +"\"";
|
||||
else
|
||||
distrib_string = tr("Restricted to members of circle ")+QString::fromStdString(group.mMeta.mCircleId.toStdString()) ;
|
||||
}
|
||||
break ;
|
||||
case GXS_CIRCLE_TYPE_YOUR_EYES_ONLY: distrib_string = tr("Your eyes only");
|
||||
break ;
|
||||
case GXS_CIRCLE_TYPE_LOCAL: distrib_string = tr("You and your friend nodes");
|
||||
break ;
|
||||
default:
|
||||
std::cerr << "(EE) badly initialised group distribution ID = " << group.mMeta.mCircleType << std::endl;
|
||||
}
|
||||
|
||||
ui->infoDistribution->setText(distrib_string);
|
||||
|
||||
ui->infoframe->show();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*********************** **** **** **** ***********************/
|
||||
|
@ -205,6 +205,186 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="infoframe">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="infoGroupBox">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Topic Details</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Administrator:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="infoPostsLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Posts:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="infoLastPostLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Last Post:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QTextBrowser" name="infoDescription">
|
||||
<property name="html">
|
||||
<string notr="true"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Description</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="infoDescriptionLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="GxsIdLabel" name="infoAdministrator">
|
||||
<property name="text">
|
||||
<string>unknown</string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="infoPosts">
|
||||
<property name="text">
|
||||
<string notr="true">0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="infoLastPost">
|
||||
<property name="text">
|
||||
<string notr="true">unknown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Distribution:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="infoDistribution">
|
||||
<property name="text">
|
||||
<string>unknown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
@ -258,6 +438,11 @@
|
||||
<extends>QComboBox</extends>
|
||||
<header>gui/gxs/GxsIdChooser.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>GxsIdLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>gui/gxs/GxsIdLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../images.qrc"/>
|
||||
|
@ -291,7 +291,7 @@ bool ChatLobbyUserNotify::checkWord(QString message, QString word)
|
||||
&& (!word.isEmpty())) {
|
||||
QString eow=" ~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="; // end of word
|
||||
bool bFirstCharEOW = (nFound==0)?true:(eow.indexOf(message.at(nFound-1)) != -1);
|
||||
bool bLastCharEOW = ((nFound+word.length()-1) < message.length())
|
||||
bool bLastCharEOW = (nFound+word.length() < message.length())
|
||||
?(eow.indexOf(message.at(nFound+word.length())) != -1)
|
||||
:true;
|
||||
bFound = (bFirstCharEOW && bLastCharEOW);
|
||||
|
@ -134,14 +134,23 @@ void PostedGroupItem::fill()
|
||||
// ui->nameLabel->setText(groupName());
|
||||
|
||||
ui->descLabel->setText(QString::fromUtf8(mGroup.mDescription.c_str()));
|
||||
|
||||
//TODO - nice icon for subscribed group
|
||||
if (IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) {
|
||||
ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png"));
|
||||
|
||||
if (mGroup.mGroupImage.mData != NULL) {
|
||||
QPixmap postedImage;
|
||||
postedImage.loadFromData(mGroup.mGroupImage.mData, mGroup.mGroupImage.mSize, "PNG");
|
||||
ui->logoLabel->setPixmap(QPixmap(postedImage));
|
||||
} else {
|
||||
ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png"));
|
||||
}
|
||||
|
||||
|
||||
//TODO - nice icon for subscribed group
|
||||
// if (IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) {
|
||||
// ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png"));
|
||||
// } else {
|
||||
// ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png"));
|
||||
// }
|
||||
|
||||
if (IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) {
|
||||
ui->subscribeButton->setEnabled(false);
|
||||
} else {
|
||||
|
@ -49,6 +49,15 @@ GxsCommentDialog::GxsCommentDialog(QWidget *parent, RsTokenService *token_servic
|
||||
connect(ui->refreshButton, SIGNAL(clicked()), this, SLOT(refresh()));
|
||||
connect(ui->idChooser, SIGNAL(currentIndexChanged( int )), this, SLOT(voterSelectionChanged( int )));
|
||||
connect(ui->idChooser, SIGNAL(idsLoaded()), this, SLOT(idChooserReady()));
|
||||
|
||||
connect(ui->sortBox, SIGNAL(currentIndexChanged(int)), this, SLOT(sortComments(int)));
|
||||
|
||||
// default sort method "HOT".
|
||||
ui->treeWidget->sortByColumn(4, Qt::DescendingOrder);
|
||||
|
||||
int S = QFontMetricsF(font()).height() ;
|
||||
|
||||
ui->sortBox->setIconSize(QSize(S*1.5,S*1.5));
|
||||
}
|
||||
|
||||
GxsCommentDialog::~GxsCommentDialog()
|
||||
@ -141,3 +150,22 @@ void GxsCommentDialog::setCommentHeader(QWidget *header)
|
||||
ui->notesBrowser->setPlainText(QString::fromStdString(mCurrentPost.mNotes));
|
||||
#endif
|
||||
}
|
||||
|
||||
void GxsCommentDialog::sortComments(int i)
|
||||
{
|
||||
|
||||
switch(i)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
ui->treeWidget->sortByColumn(4, Qt::DescendingOrder);
|
||||
break;
|
||||
case 1:
|
||||
ui->treeWidget->sortByColumn(2, Qt::DescendingOrder);
|
||||
break;
|
||||
case 2:
|
||||
ui->treeWidget->sortByColumn(3, Qt::DescendingOrder);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ private slots:
|
||||
void refresh();
|
||||
void idChooserReady();
|
||||
void voterSelectionChanged( int index );
|
||||
void sortComments(int);
|
||||
|
||||
private:
|
||||
RsGxsGroupId mGrpId;
|
||||
|
@ -13,8 +13,8 @@
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="GxsCommentDialogVLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="GxsCommentDialogGLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="postFrame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
@ -24,59 +24,63 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="postFrameVLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="toolBarHLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="hotSortButton">
|
||||
<property name="text">
|
||||
<string>Hot</string>
|
||||
<widget class="QComboBox" name="sortBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">sort by</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="autoExclusive">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="newSortButton">
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoExclusive">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="topSortButton">
|
||||
<property name="text">
|
||||
<string>Top</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="autoExclusive">
|
||||
<bool>true</bool>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hot</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/flame.png</normaloff>:/icons/png/flame.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/new.png</normaloff>:/icons/png/new.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Top</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/top.png</normaloff>:/icons/png/top.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@ -111,8 +115,11 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<item row="2" column="0">
|
||||
<widget class="GxsCommentTreeWidget" name="treeWidget">
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Comment</string>
|
||||
@ -164,6 +171,8 @@
|
||||
<header>gui/gxs/GxsCommentTreeWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "gui/gxs/GxsCommentTreeWidget.h"
|
||||
#include "gui/gxs/GxsCreateCommentDialog.h"
|
||||
#include "gui/gxs/GxsIdTreeWidgetItem.h"
|
||||
#include "gui/common/RSTreeWidgetItem.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -45,6 +46,7 @@
|
||||
#define PCITEM_COLUMN_PARENTID 8
|
||||
#define PCITEM_COLUMN_AUTHORID 9
|
||||
|
||||
#define ROLE_SORT Qt::UserRole + 1
|
||||
|
||||
#define GXSCOMMENTS_LOADTHREAD 1
|
||||
|
||||
@ -139,6 +141,9 @@ GxsCommentTreeWidget::GxsCommentTreeWidget(QWidget *parent)
|
||||
setWordWrap(true);
|
||||
|
||||
setItemDelegateForColumn(PCITEM_COLUMN_COMMENT,new MultiLinesCommentDelegate(QFontMetricsF(font()))) ;
|
||||
|
||||
commentsRole = new RSTreeWidgetItemCompareRole;
|
||||
commentsRole->setRole(PCITEM_COLUMN_DATE, ROLE_SORT);
|
||||
|
||||
// QFont font = QFont("ARIAL", 10);
|
||||
// font.setBold(true);
|
||||
@ -537,6 +542,8 @@ void GxsCommentTreeWidget::service_loadThread(const uint32_t &token)
|
||||
text = qtime.toString("yyyy-MM-dd hh:mm:ss") ;
|
||||
item->setText(PCITEM_COLUMN_DATE, text) ;
|
||||
item->setToolTip(PCITEM_COLUMN_DATE, text) ;
|
||||
item->setData(PCITEM_COLUMN_DATE, ROLE_SORT, QVariant(qlonglong(comment.mMeta.mPublishTs)));
|
||||
|
||||
}
|
||||
|
||||
text = QString::fromUtf8(comment.mComment.c_str());
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include <retroshare/rsgxscommon.h>
|
||||
#include <retroshare/rsidentity.h>
|
||||
|
||||
class RSTreeWidgetItemCompareRole;
|
||||
|
||||
class GxsCommentTreeWidget : public QTreeWidget, public TokenResponse
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -96,6 +98,8 @@ protected:
|
||||
|
||||
std::map<RsGxsMessageId, QTreeWidgetItem *> mLoadingMap;
|
||||
std::multimap<RsGxsMessageId, QTreeWidgetItem *> mPendingInsertMap;
|
||||
|
||||
RSTreeWidgetItemCompareRole *commentsRole;
|
||||
|
||||
TokenQueue *mTokenQueue;
|
||||
RsTokenService *mRsTokenService;
|
||||
|
@ -755,12 +755,12 @@ void GxsGroupDialog::setGroupSignFlags(uint32_t signFlags)
|
||||
// (cyril) very weird piece of code. Need to clear this up.
|
||||
|
||||
ui.comments_allowed->setChecked(true);
|
||||
ui.commentsValueLabel->setText("Allowed") ;
|
||||
ui.commentsValueLabel->setText("Allowed") ;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui.comments_no->setChecked(true);
|
||||
ui.commentsValueLabel->setText("Allowed") ;
|
||||
ui.commentsValueLabel->setText("Forbidden") ;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>736</height>
|
||||
<height>633</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -61,11 +61,15 @@ const uint32_t ChannelEditDefaultsFlags = ChannelCreateDefaultsFlags;
|
||||
GxsChannelGroupDialog::GxsChannelGroupDialog(TokenQueue *tokenQueue, QWidget *parent)
|
||||
: GxsGroupDialog(tokenQueue, ChannelCreateEnabledFlags, ChannelCreateDefaultsFlags, parent)
|
||||
{
|
||||
ui.commentGroupBox->setEnabled(false); // These are here because comments_allowed are actually not used yet, so the group will not be changed by the setting and when
|
||||
ui.comments_allowed->setChecked(true); // the group info is displayed it will therefore be set to "disabled" in all cases although it is enabled.
|
||||
}
|
||||
|
||||
GxsChannelGroupDialog::GxsChannelGroupDialog(TokenQueue *tokenExternalQueue, RsTokenService *tokenService, Mode mode, RsGxsGroupId groupId, QWidget *parent)
|
||||
: GxsGroupDialog(tokenExternalQueue, tokenService, mode, groupId, ChannelEditEnabledFlags, ChannelEditDefaultsFlags, parent)
|
||||
{
|
||||
ui.commentGroupBox->setEnabled(false); // These are here because comments_allowed are actually not used yet, so the group will not be changed by the setting and when
|
||||
ui.comments_allowed->setChecked(true); // the group info is displayed it will therefore be set to "disabled" in all cases although it is enabled.
|
||||
}
|
||||
|
||||
void GxsChannelGroupDialog::initUi()
|
||||
|
@ -294,7 +294,7 @@
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
@ -304,211 +304,176 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="infoFrame">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>178</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>255</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>178</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>178</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>178</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Administrator:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="infoPostsLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Posts (at neighbor nodes):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="infoLastPostLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Last Post:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QTextBrowser" name="infoDescription">
|
||||
<property name="html">
|
||||
<string notr="true"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Channel details</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Administrator:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="infoPostsLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Posts:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="infoLastPostLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Last Post:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QTextBrowser" name="infoDescription">
|
||||
<property name="html">
|
||||
<string notr="true"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Description</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="infoDescriptionLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="GxsIdLabel" name="infoAdministrator">
|
||||
<property name="text">
|
||||
<string>unknown</string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="infoPosts">
|
||||
<property name="text">
|
||||
<string notr="true">0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="infoLastPost">
|
||||
<property name="text">
|
||||
<string notr="true">unknown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Distribution:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="infoDistribution">
|
||||
<property name="text">
|
||||
<string>unknown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="openLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="infoDescriptionLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="GxsIdLabel" name="infoAdministrator">
|
||||
<property name="text">
|
||||
<string>unknown</string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="infoPosts">
|
||||
<property name="text">
|
||||
<string notr="true">0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="infoLastPost">
|
||||
<property name="text">
|
||||
<string notr="true">unknown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Distribution:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="infoDistribution">
|
||||
<property name="text">
|
||||
<string>unknown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -336,11 +336,11 @@ bool RsMessageModel::passesFilter(const Rs::Msgs::MsgInfoSummary& fmpe,int colum
|
||||
|| (std::find(fmpe.msgtags.begin(),fmpe.msgtags.end(),mQuickViewFilter) != fmpe.msgtags.end())
|
||||
|| (mQuickViewFilter==QUICK_VIEW_STARRED && (fmpe.msgflags & RS_MSG_STAR))
|
||||
|| (mQuickViewFilter==QUICK_VIEW_SYSTEM && (fmpe.msgflags & RS_MSG_SYSTEM));
|
||||
|
||||
std::cerr << "Passes filter: type=" << mFilterType << " s=\"" << s.toStdString()
|
||||
<< "MsgFlags=" << fmpe.msgflags << " msgtags=" ;
|
||||
#ifdef DEBUG_MESSAGE_MODEL
|
||||
std::cerr << "Passes filter: type=" << mFilterType << " s=\"" << s.toStdString() << "MsgFlags=" << fmpe.msgflags << " msgtags=" ;
|
||||
foreach(uint32_t i,fmpe.msgtags) std::cerr << i << " " ;
|
||||
std::cerr << "\" strings:" << passes_strings << " quick_view:" << passes_quick_view << std::endl;
|
||||
#endif
|
||||
|
||||
return passes_quick_view && passes_strings;
|
||||
}
|
||||
@ -621,10 +621,10 @@ void RsMessageModel::getMessageSummaries(BoxName box,std::list<Rs::Msgs::MsgInfo
|
||||
|
||||
switch(box)
|
||||
{
|
||||
case BOX_INBOX : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_INBOX ; break ;
|
||||
case BOX_SENT : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_SENTBOX; break ;
|
||||
case BOX_OUTBOX : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_OUTBOX ; break ;
|
||||
case BOX_DRAFTS : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_DRAFTBOX ; break ;
|
||||
case BOX_INBOX : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_INBOX && !(it->msgflags & RS_MSG_TRASH); break ;
|
||||
case BOX_SENT : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_SENTBOX && !(it->msgflags & RS_MSG_TRASH); break ;
|
||||
case BOX_OUTBOX : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_OUTBOX && !(it->msgflags & RS_MSG_TRASH); break ;
|
||||
case BOX_DRAFTS : ok = (it->msgflags & RS_MSG_BOXMASK) == RS_MSG_DRAFTBOX && !(it->msgflags & RS_MSG_TRASH); break ;
|
||||
case BOX_TRASH : ok = (it->msgflags & RS_MSG_TRASH) ; break ;
|
||||
default:
|
||||
++it;
|
||||
|
@ -27,21 +27,21 @@
|
||||
|
||||
#include "MessagesDialog.h"
|
||||
|
||||
#include "notifyqt.h"
|
||||
#include "common/TagDefs.h"
|
||||
#include "common/PeerDefs.h"
|
||||
#include "common/RSElidedItemDelegate.h"
|
||||
#include "gxs/GxsIdTreeWidgetItem.h"
|
||||
#include "gxs/GxsIdDetails.h"
|
||||
#include "gui/notifyqt.h"
|
||||
#include "gui/common/TagDefs.h"
|
||||
#include "gui/common/PeerDefs.h"
|
||||
#include "gui/common/RSElidedItemDelegate.h"
|
||||
#include "gui/gxs/GxsIdTreeWidgetItem.h"
|
||||
#include "gui/gxs/GxsIdDetails.h"
|
||||
#include "gui/Identity/IdDialog.h"
|
||||
#include "gui/MainWindow.h"
|
||||
#include "msgs/MessageComposer.h"
|
||||
#include "msgs/MessageInterface.h"
|
||||
#include "msgs/MessageUserNotify.h"
|
||||
#include "msgs/MessageWidget.h"
|
||||
#include "msgs/TagsMenu.h"
|
||||
#include "msgs/MessageModel.h"
|
||||
#include "settings/rsharesettings.h"
|
||||
#include "gui/msgs/MessageComposer.h"
|
||||
#include "gui/msgs/MessageInterface.h"
|
||||
#include "gui/msgs/MessageUserNotify.h"
|
||||
#include "gui/msgs/MessageWidget.h"
|
||||
#include "gui/msgs/TagsMenu.h"
|
||||
#include "gui/msgs/MessageModel.h"
|
||||
#include "gui/settings/rsharesettings.h"
|
||||
|
||||
#include "util/DateTime.h"
|
||||
#include "util/RsProtectedTimer.h"
|
@ -786,13 +786,11 @@ GenCertDialog QFrame#profileframe{
|
||||
|
||||
PostedListWidget QComboBox#comboBox {
|
||||
font: bold;
|
||||
font-size: 15px;
|
||||
color: #0099cc;
|
||||
}
|
||||
|
||||
PostedListWidget QToolButton#submitPostButton {
|
||||
font: bold;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
PostedListWidget QToolButton#subscribeToolButton {
|
||||
@ -830,10 +828,7 @@ GxsForumThreadWidget QToolButton#subscribeToolButton:hover {
|
||||
|
||||
GxsChannelPostsWidget QFrame#infoFrame
|
||||
{
|
||||
border: 1px solid #DCDC41;
|
||||
border-radius: 6px;
|
||||
background: #FFFFD7;
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFFFD7, stop:1 #FFFFB2);
|
||||
|
||||
}
|
||||
|
||||
GxsChannelPostsWidget QToolButton#subscribeToolButton {
|
||||
@ -889,10 +884,14 @@ PostedItem QFrame#voteFrame {
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
PostedItem QFrame#mainFrame{
|
||||
PostedItem QFrame#mainFrame [new=false]{
|
||||
background: white;
|
||||
}
|
||||
|
||||
PostedItem > QFrame#mainFrame[new=true] {
|
||||
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #F0F8FD, stop:0.8 #E6F2FD, stop: 0.81 #E6F2FD, stop: 1 #D2E7FD);
|
||||
}
|
||||
|
||||
PostedItem QFrame#frame_picture{
|
||||
background: white;
|
||||
}
|
||||
@ -906,8 +905,7 @@ PostedItem QLabel#fromBoldLabel, QLabel#fromLabel, QLabel#dateLabel, QLabel#site
|
||||
color: #787c7e;
|
||||
}
|
||||
|
||||
PostedItem QToolButton#commentButton, QPushButton#shareButton, QToolButton#notesButton{
|
||||
font-size: 12px;
|
||||
color: #878a8c;
|
||||
font-weight: bold;
|
||||
}
|
||||
GxsCommentDialog QComboBox#sortBox {
|
||||
font: bold;
|
||||
color: #0099cc;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "ratesstatus.h"
|
||||
#include <retroshare/rsiface.h>
|
||||
#include "util/misc.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
@ -47,13 +48,13 @@ RatesStatus::RatesStatus(QWidget *parent)
|
||||
setLayout(hbox);
|
||||
}
|
||||
|
||||
void RatesStatus::getRatesStatus(float downKb, float upKb)
|
||||
void RatesStatus::getRatesStatus(float downKb, uint64_t down, float upKb, uint64_t upl)
|
||||
{
|
||||
/* set users/friends/network */
|
||||
|
||||
QString normalText = QString("<strong>%1:</strong> %2 (kB/s) | <strong>%3:</strong> %4 (kB/s) ")
|
||||
.arg(tr("Down")).arg(downKb, 0, 'f', 2)
|
||||
.arg(tr("Up")).arg(upKb, 0, 'f', 2);
|
||||
QString normalText = QString("<strong>%1:</strong> %2 kB/s (%3) | <strong>%4:</strong> %5 kB/s (%6)")
|
||||
.arg(tr("Down")).arg(downKb, 0, 'f', 2).arg(misc::friendlyUnit(down))
|
||||
.arg(tr("Up")).arg(upKb, 0, 'f', 2).arg(misc::friendlyUnit(upl));
|
||||
QString compactText = QString("%1|%2").arg(downKb, 0, 'f', 2).arg(upKb, 0, 'f', 2);
|
||||
|
||||
if (statusRates) {
|
||||
|
@ -32,7 +32,7 @@ class RatesStatus : public QWidget
|
||||
public:
|
||||
RatesStatus(QWidget *parent = 0);
|
||||
|
||||
void getRatesStatus(float downKb, float upKb);
|
||||
void getRatesStatus(float downKb, uint64_t down, float upKb, uint64_t upl);
|
||||
void setCompactMode(bool compact) {_compactMode = compact; }
|
||||
|
||||
private:
|
||||
|
@ -443,6 +443,7 @@ HEADERS += rshare.h \
|
||||
gui/connect/ConfCertDialog.h \
|
||||
gui/connect/PGPKeyDialog.h \
|
||||
gui/connect/FriendRecommendDialog.h \
|
||||
gui/msgs/MessagesDialog.h \
|
||||
gui/msgs/MessageInterface.h \
|
||||
gui/msgs/MessageComposer.h \
|
||||
gui/msgs/MessageWindow.h \
|
||||
@ -541,7 +542,6 @@ HEADERS += rshare.h \
|
||||
gui/common/ToasterNotify.h \
|
||||
gui/style/RSStyle.h \
|
||||
gui/style/StyleDialog.h \
|
||||
gui/MessagesDialog.h \
|
||||
gui/help/browser/helpbrowser.h \
|
||||
gui/help/browser/helptextbrowser.h \
|
||||
gui/statusbar/peerstatus.h \
|
||||
@ -621,7 +621,6 @@ FORMS += gui/StartDialog.ui \
|
||||
gui/FriendsDialog.ui \
|
||||
gui/ShareManager.ui \
|
||||
# gui/ShareDialog.ui \
|
||||
gui/MessagesDialog.ui \
|
||||
gui/help/browser/helpbrowser.ui \
|
||||
gui/HelpDialog.ui \
|
||||
gui/ServicePermissionDialog.ui \
|
||||
@ -640,6 +639,7 @@ FORMS += gui/StartDialog.ui \
|
||||
gui/connect/ConnectFriendWizard.ui \
|
||||
gui/connect/ConnectProgressDialog.ui \
|
||||
gui/connect/FriendRecommendDialog.ui \
|
||||
gui/msgs/MessagesDialog.ui \
|
||||
gui/msgs/MessageComposer.ui \
|
||||
gui/msgs/MessageWindow.ui\
|
||||
gui/msgs/MessageWidget.ui\
|
||||
@ -745,7 +745,6 @@ SOURCES += main.cpp \
|
||||
# gui/ShareDialog.cpp \
|
||||
# gui/SFListDelegate.cpp \
|
||||
gui/SoundManager.cpp \
|
||||
gui/MessagesDialog.cpp \
|
||||
gui/im_history/ImHistoryBrowser.cpp \
|
||||
gui/im_history/IMHistoryItemDelegate.cpp \
|
||||
gui/im_history/IMHistoryItemPainter.cpp \
|
||||
@ -800,6 +799,7 @@ SOURCES += main.cpp \
|
||||
gui/chat/ChatLobbyUserNotify.cpp \
|
||||
gui/connect/ConfCertDialog.cpp \
|
||||
gui/connect/PGPKeyDialog.cpp \
|
||||
gui/msgs/MessagesDialog.cpp \
|
||||
gui/msgs/MessageComposer.cpp \
|
||||
gui/msgs/MessageWidget.cpp \
|
||||
gui/msgs/MessageWindow.cpp \
|
||||
|
@ -230,11 +230,18 @@ isEmpty(RS_UPNP_LIB):RS_UPNP_LIB = upnp ixml threadutil
|
||||
#
|
||||
# V07_NON_BACKWARD_COMPATIBLE_CHANGE_003:
|
||||
#
|
||||
# What: Do not hash PGP certificate twice when signing
|
||||
# What: Do not hash PGP certificate twice when signing
|
||||
#
|
||||
# Why: hasing twice is not per se a security issue, but it makes it harder to change the settings for hashing.
|
||||
#
|
||||
# Backward compat: patched peers cannot connect to non patched peers older than Nov 2017.
|
||||
#
|
||||
# V07_NON_BACKWARD_COMPATIBLE_CHANGE_004:
|
||||
#
|
||||
# What: Do not probe that GXS tunnels accept fast items. Just assume they do.
|
||||
# Why: Avoids sending probe packets
|
||||
# BackwardCompat: old RS before Mai 2019 will not be able to distant chat.
|
||||
#
|
||||
###########################################################################################################################################################
|
||||
|
||||
#CONFIG += rs_v07_changes
|
||||
@ -242,6 +249,7 @@ rs_v07_changes {
|
||||
DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_001
|
||||
DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_002
|
||||
DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_003
|
||||
DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_004
|
||||
DEFINES += V07_NON_BACKWARD_COMPATIBLE_CHANGE_UNNAMED
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user