mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
merged to upstream/master
This commit is contained in:
commit
8e2ff56f9a
14
.travis.yml
14
.travis.yml
@ -1,16 +1,13 @@
|
||||
sudo: required
|
||||
dist: trusty
|
||||
language: cpp
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
before_install:
|
||||
- echo $LANG
|
||||
- echo $LC_ALL
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install build-essential checkinstall cmake g++ git libavutil-dev libavcodec-dev libavformat-dev libbz2-dev libcurl4-openssl-dev libdc1394-22-dev libglib2.0-dev libcv-dev libopencv-highgui-dev libhighgui-dev
|
||||
- sudo apt-get install libgnome-keyring-dev libgstreamer-plugins-base0.10-dev libgstreamer0.10-dev libjasper-dev libjpeg-dev libmicrohttpd-dev libopencv-dev libprotobuf-dev libqt4-dev
|
||||
- sudo apt-get install libspeex-dev libspeexdsp-dev libsqlite3-dev libssl-dev libswscale-dev
|
||||
- sudo apt-get install libtbb-dev libtiff4-dev libupnp-dev libv4l-dev libxine-dev libxslt1-dev libxss-dev make pkg-config protobuf-compiler python-dev python-numpy subversion git yasm qtmobility-dev
|
||||
- sudo apt-get install -y build-essential checkinstall cmake libavutil-dev libavcodec-dev libavformat-dev libbz2-dev libcurl4-openssl-dev libcv-dev libopencv-highgui-dev libhighgui-dev libgnome-keyring-dev libgstreamer-plugins-base0.10-dev libgstreamer0.10-dev libjasper-dev libjpeg-dev libmicrohttpd-dev libopencv-dev libprotobuf-dev libqt4-dev libspeex-dev libspeexdsp-dev libsqlite3-dev libssl-dev libswscale-dev libtbb-dev libtiff4-dev libupnp-dev libv4l-dev libxine-dev libxslt1-dev libxss-dev pkg-config protobuf-compiler python-dev qtmobility-dev
|
||||
# - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update && sudo apt-get install -y llvm-3.4 llvm-3.4-dev; fi
|
||||
# - rvm use $RVM --install --binary --fuzzy
|
||||
# - gem update --system
|
||||
@ -32,7 +29,7 @@ addons:
|
||||
branch_pattern: coverity_scan
|
||||
|
||||
before_script:
|
||||
- qmake CONFIG+=NO_SQLCIPHER CONFIG+=tests
|
||||
- qmake QMAKE_CC=$CC QMAKE_CXX=$CXX CONFIG+=NO_SQLCIPHER CONFIG+=tests
|
||||
|
||||
#script: make
|
||||
script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make && tests/unittests/unittests >/dev/null 2>&1 ; fi
|
||||
@ -64,6 +61,3 @@ notifications:
|
||||
|
||||
#env:
|
||||
# - RVM=2.0.0 LANG="en_US.UTF-8"
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
16
README.md
16
README.md
@ -2,6 +2,22 @@ RetroShare
|
||||
==============================
|
||||
RetroShare is a decentralized, private and secure commmunication and sharing platform. RetroShare provides filesharing, chat, messages, forums and channels.
|
||||
|
||||
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/axkopdqj9fc48kwe?svg=true)](https://ci.appveyor.com/project/PhenomRetroShare/retroshare) |
|
||||
|
||||
Compilation on Windows
|
||||
----------------------------
|
||||
Follow this file : [WindowsMSys2_InstallGuide.txt](https://github.com/RetroShare/RetroShare/blob/master/WindowsMSys2_InstallGuide.txt)
|
||||
|
||||
Compilation on MacOSX
|
||||
----------------------------
|
||||
Follow this file : [MacOS_X_InstallGuide.txt](https://github.com/RetroShare/RetroShare/blob/master/MacOS_X_InstallGuide.txt)
|
||||
|
||||
Compilation on Linux
|
||||
----------------------------
|
||||
|
||||
|
210
appveyor.yml
Normal file
210
appveyor.yml
Normal file
@ -0,0 +1,210 @@
|
||||
# Notes:
|
||||
# - Minimal appveyor.yml file is an empty file. All sections are optional.
|
||||
# - Indent each level of configuration with 2 spaces. Do not use tabs!
|
||||
# - All section names are case-sensitive.
|
||||
# - Section names should be unique on each level.
|
||||
# from example:
|
||||
# https://github.com/Phonations/Joker/blob/master/appveyor.yml
|
||||
# https://github.com/unicorn-engine/autobuild/blob/master/.appveyor.yml
|
||||
|
||||
#---------------------------------#
|
||||
# general configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# version format
|
||||
version: RetroShare 6.0.{build}-{branch}
|
||||
|
||||
# you can use {branch} name in version format too
|
||||
# version: 1.0.{build}-{branch}
|
||||
|
||||
# branches to build
|
||||
branches:
|
||||
# whitelist
|
||||
#only:
|
||||
# - master
|
||||
|
||||
# blacklist
|
||||
except:
|
||||
- /^skipthisbranch$/
|
||||
|
||||
# Do not build on tags (GitHub only)
|
||||
skip_tags: true
|
||||
|
||||
# Skipping commits with particular message or from user
|
||||
skip_commits:
|
||||
message: /Created.*\.(png|jpg|jpeg|bmp|gif)/ # Regex for matching commit message
|
||||
#author: Anonymous # Commit author's username, name, email or regexp maching one of these.
|
||||
|
||||
#---------------------------------#
|
||||
# environment configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# Operating system (build VM template)
|
||||
#os: Windows Server 2012
|
||||
|
||||
# scripts that are called at very beginning, before repo cloning
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
#To get RDP while compiling
|
||||
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
on_finish:
|
||||
#To get RDP running after compiling
|
||||
#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
|
||||
# clone directory
|
||||
clone_folder: c:\projects\RetroShare
|
||||
|
||||
# fetch repository as zip archive
|
||||
#shallow_clone: true # default is "false"
|
||||
|
||||
# set clone depth
|
||||
clone_depth: 1 # clone entire repository history if not defined
|
||||
|
||||
environment:
|
||||
global:
|
||||
#Qt: https://www.appveyor.com/docs/installed-software#qt
|
||||
QTDIR: C:\Qt\5.4\mingw491_32
|
||||
MSYS2_ARCH: i686
|
||||
TARGET: i686_32-pc-msys
|
||||
|
||||
|
||||
# build cache to preserve files/folders between builds
|
||||
cache:
|
||||
- c:\projects\libs
|
||||
# - packages -> **\packages.config # preserve "packages" directory in the root of build folder but will reset it if packages.config is modified
|
||||
# - projectA\libs
|
||||
# - node_modules # local npm modules
|
||||
# - %APPDATA%\npm-cache # npm cache
|
||||
|
||||
# scripts that run after cloning repository
|
||||
#install:
|
||||
# # by default, all script lines are interpreted as batch
|
||||
# - echo This is batch
|
||||
# # to run script as a PowerShell command prepend it with ps:
|
||||
# - ps: Write-Host 'This is PowerShell'
|
||||
# # batch commands start from cmd:
|
||||
# - cmd: echo This is batch again
|
||||
# - cmd: set MY_VAR=12345
|
||||
install:
|
||||
# Configuring MSys2
|
||||
- set PATH=C:\msys64\usr\bin;%PATH%
|
||||
- set PATH=C:\msys64\mingw32\bin;%PATH%
|
||||
# Configuring Qt
|
||||
- set PATH=%QTDIR%\bin;C:\Qt\Tools\mingw491_32\bin;%PATH%
|
||||
# Install all default programms
|
||||
#- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy base-devel git mercurial cvs wget p7zip gcc perl ruby python2" #Already installed
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sy openssl-devel"
|
||||
# Install toolchain
|
||||
#- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-toolchain mingw-w64-x86_64-toolchain" #Already installed
|
||||
# Install other binutils
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-miniupnpc mingw-w64-x86_64-miniupnpc"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-sqlite3 mingw-w64-x86_64-sqlite3"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-speex mingw-w64-x86_64-speex"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-opencv mingw-w64-x86_64-opencv"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-ffmpeg mingw-w64-x86_64-ffmpeg"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-libmicrohttpd mingw-w64-x86_64-libmicrohttpd"
|
||||
- C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw-w64-i686-libxslt mingw-w64-x86_64-libxslt"
|
||||
|
||||
# Hack for new MSys2
|
||||
- copy C:\msys64\mingw32\i686-w64-mingw32\bin\ar.exe C:\msys64\mingw32\bin\i686-w64-mingw32-ar.exe
|
||||
- copy C:\msys64\mingw32\i686-w64-mingw32\bin\ranlib.exe C:\msys64\mingw32\bin\i686-w64-mingw32-ranlib.exe
|
||||
- copy C:\msys64\mingw32\bin\windres.exe C:\msys64\mingw32\bin\i686-w64-mingw32-windres.exe
|
||||
- copy C:\msys64\mingw64\x86_64-w64-mingw32\bin\ar.exe C:\msys64\mingw64\bin\x86_64-w64-mingw32-ar.exe
|
||||
- copy C:\msys64\mingw64\x86_64-w64-mingw32\bin\ranlib.exe C:\msys64\mingw64\bin\x86_64-w64-mingw32-ranlib.exe
|
||||
- copy C:\msys64\mingw64\bin\windres.exe C:\msys64\mingw64\bin\x86_64-w64-mingw32-windres.exe
|
||||
# Build missing Libs
|
||||
- C:\msys64\mingw32_shell.bat -lc "cd /c/projects/RetroShare/msys2_build_libs/ && make"
|
||||
# Clone RetroShare
|
||||
#- git clone -q --branch={branch} https://github.com/RetroShare/RetroShare.git C:\projects\RetroShare
|
||||
|
||||
|
||||
#---------------------------------#
|
||||
# build configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# build platform, i.e. x86, x64, Any CPU. This setting is optional.
|
||||
platform: x86
|
||||
|
||||
# to add several platforms to build matrix:
|
||||
#platform:
|
||||
# - x86
|
||||
# - Any CPU
|
||||
|
||||
# build Configuration, i.e. Debug, Release, etc.
|
||||
configuration: Release
|
||||
|
||||
# to add several configurations to build matrix:
|
||||
#configuration:
|
||||
# - Debug
|
||||
# - Release
|
||||
|
||||
# scripts to run before build
|
||||
before_build:
|
||||
|
||||
# scripts to run *after* solution is built and *before* automatic packaging occurs (web apps, NuGet packages, Azure Cloud Services)
|
||||
before_package:
|
||||
|
||||
# scripts to run after build
|
||||
after_build:
|
||||
|
||||
# to run your custom scripts instead of automatic MSBuild
|
||||
build_script:
|
||||
- cd C:\projects\RetroShare
|
||||
- qmake
|
||||
- make
|
||||
|
||||
# to disable automatic builds
|
||||
#build: off
|
||||
|
||||
#---------------------------------#
|
||||
# artifacts configuration #
|
||||
#---------------------------------#
|
||||
|
||||
#artifacts:
|
||||
#
|
||||
# # pushing a single file
|
||||
# - path: test.zip
|
||||
#
|
||||
# # pushing a single file with environment variable in path and "Deployment name" specified
|
||||
# - path: MyProject\bin\$(configuration)
|
||||
# name: myapp
|
||||
#
|
||||
# # pushing entire folder as a zip archive
|
||||
# - path: logs
|
||||
|
||||
|
||||
#---------------------------------#
|
||||
# deployment configuration #
|
||||
#---------------------------------#
|
||||
#No deployment under unknown computer!!!
|
||||
|
||||
#---------------------------------#
|
||||
# global handlers #
|
||||
#---------------------------------#
|
||||
|
||||
# on successful build
|
||||
#on_success:
|
||||
# - do something
|
||||
|
||||
# on build failure
|
||||
#on_failure:
|
||||
# - do something
|
||||
|
||||
# after build failure or success
|
||||
#on_finish:
|
||||
# - do something
|
||||
|
||||
|
||||
#---------------------------------#
|
||||
# notifications #
|
||||
#---------------------------------#
|
||||
|
||||
notifications:
|
||||
|
||||
# Email
|
||||
- provider: Email
|
||||
to:
|
||||
- retrosharephenom@gmail.com
|
||||
subject: 'Build {{status}}' # optional
|
||||
message: "{{message}}, {{commitId}}, ..." # optional
|
||||
on_build_status_changed: true
|
@ -1,5 +1,364 @@
|
||||
retroshare06 (0.6.0-1.XXXXXX~YYYYYY) YYYYYY; urgency=low
|
||||
|
||||
cbef014 csoler Sun, 29 May 2016 16:09:56 -0400 added regular test of circle auto-subscribe from cache, and auto-subscribe w
|
||||
2bde81f csoler Sat, 28 May 2016 21:09:44 -0400 removed more debug info, improved tooltips
|
||||
ccd72cb csoler Sat, 28 May 2016 20:58:28 -0400 removed some debug info. Added information tooltips on circles and ids in ci
|
||||
9a328f6 csoler Sat, 28 May 2016 20:25:15 -0400 extended auto-subscribe to circles with admin flag
|
||||
d114b83 csoler Sat, 28 May 2016 20:17:19 -0400 extended auto-subscribe to circles with requested membership
|
||||
8b5e43f csoler Sat, 28 May 2016 17:18:25 -0400 remove subitems in circles member list when they are gone from cache
|
||||
dafb2e6 csoler Fri, 27 May 2016 17:35:23 -0400 Merge pull request #396 from csoler/v0.6-Circles
|
||||
cfdaa2c csoler Fri, 27 May 2016 17:09:13 -0400 removed debug info in p3gxscircles
|
||||
d03d733 csoler Fri, 27 May 2016 12:44:14 -0400 Merge pull request #395 from hasufell/master
|
||||
ed867c5 Julian Ospald Fri, 27 May 2016 18:07:28 +0200 Don't hardcode g++ in the toolchain settings
|
||||
74b4d66 csoler Thu, 26 May 2016 21:16:21 -0400 added ifdef to allow to remove the sorting of circles into member/not member. To be tested for final decision
|
||||
59aef8a csoler Thu, 26 May 2016 20:33:24 -0400 added packet slicing for large broadcast chat items, and output warning when chat of serialised item is too big. Als
|
||||
ae5929e csoler Thu, 26 May 2016 18:58:48 -0400 fixed possible crash due to using a deleted item
|
||||
a32bcba csoler Wed, 25 May 2016 21:17:09 -0400 changed Members to Invited members in circle creation dialog
|
||||
d1f4e13 csoler Wed, 25 May 2016 19:04:45 -0400 removed display of circle members in left ID list
|
||||
cfeed5c csoler Wed, 25 May 2016 18:47:06 -0400 fixed column width and titles in circles
|
||||
605763d csoler Wed, 25 May 2016 18:34:12 -0400 added all IDs in circle to display tree
|
||||
219dd01 csoler Wed, 25 May 2016 17:51:23 -0400 improved GUI display in circle list
|
||||
5b69fa0 csoler Tue, 24 May 2016 21:23:35 -0400 fixed re-draw of subitem in circle tree when flags changed
|
||||
2e91ab6 csoler Tue, 24 May 2016 21:07:50 -0400 added proper notify for subscription message reception in circles
|
||||
5bc83d9 csoler Mon, 23 May 2016 21:09:06 -0400 fixed unsubscription of external circles
|
||||
1b5d31f csoler Sun, 22 May 2016 21:15:18 -0400 attempt to fix the wrong display of uploaded size for files > 4Gb (to be confirmed)
|
||||
55cb15c csoler Sun, 22 May 2016 20:35:51 -0400 fixed updating of membership when loading circle cache entry
|
||||
fac1fb8 csoler Sun, 22 May 2016 18:50:18 -0400 enabled message publish for circle subscription requests
|
||||
69573d1 csoler Sun, 22 May 2016 18:49:54 -0400 fixed serialisation of circle subscription requests
|
||||
68e618b csoler Sun, 22 May 2016 18:21:48 -0400 fixed GUI for circle invites
|
||||
6554832 csoler Sun, 22 May 2016 18:21:26 -0400 added isOwnId handle in rsidentity
|
||||
be3be9f csoler Sun, 22 May 2016 18:21:00 -0400 put loading circles in cache as soon as we get the data for them. The cache entry might be incomplete.
|
||||
d60e99e csoler Sat, 21 May 2016 16:50:50 -0400 added subwidgets for invited GXS ids in circles
|
||||
82ad7d6 csoler Sat, 21 May 2016 15:51:49 -0400 improved debugoutput in p3gxscircles
|
||||
4c5c09c csoler Thu, 19 May 2016 10:11:15 -0400 Merge pull request #390 from PhenomRetroShare/Fix_MutexInPqiPersonGrp
|
||||
3a2b9e8 csoler Wed, 18 May 2016 21:47:34 -0400 added some debug info in new circle code
|
||||
abe0e02 anon tahoe Wed, 18 May 2016 14:46:42 +0200 replaced mktemp by mkstemp (cherry-picked from anontahoe repository)
|
||||
722609a csoler Wed, 18 May 2016 21:13:54 -0400 finished implementing the backend part for the subscription system
|
||||
af5129c Phenom Wed, 18 May 2016 19:15:37 +0200 Fix Mutex in pqipersongrp for pqilistener by adding local Mutex.
|
||||
9f56069 csoler Tue, 17 May 2016 11:21:03 -0400 Merge pull request #389 from PhenomRetroShare/Fix_ClearWebAPIWhenClearChatHistory
|
||||
07191a7 Phenom Tue, 17 May 2016 16:50:59 +0200 Fix Clear WebAPI when clear chat history in GUI and server is not running.
|
||||
f3aed81 csoler Tue, 17 May 2016 10:39:56 -0400 added test over signature size to avoid possible memory corruption (Anonymous source)
|
||||
89472d6 csoler Tue, 17 May 2016 00:00:15 -0400 put some notes and comments in the code for what is to be done
|
||||
116e742 csoler Mon, 16 May 2016 12:25:51 -0400 Merge pull request #388 from PhenomRetroShare/Fix_OpenExistingFileAsWarning
|
||||
a2a0582 Phenom Mon, 16 May 2016 17:20:53 +0200 Change Open existing file link from Question to Warning.
|
||||
2064870 csoler Mon, 16 May 2016 10:29:58 -0400 Merge pull request #385 from PhenomRetroShare/Fix_RsCollectionFileLoadCall
|
||||
1f8f413 Phenom Mon, 16 May 2016 11:32:17 +0200 Fix RsCollectionFile::load(QString, bool) calls.
|
||||
5d69072 csoler Sat, 14 May 2016 18:53:57 -0400 Merge pull request #383 from PhenomRetroShare/Fix_FreeTcpPacketIfPeersUnknown
|
||||
|
||||
-- Cyril Soler <csoler@users.sourceforge.net> Sat, 28 May 2016 10:00:00 -0500
|
||||
|
||||
retroshare06 (0.6.0-1.20160514.4dc62d0e~trusty) trusty; urgency=low
|
||||
|
||||
5bb570e csoler Sat, 14 May 2016 10:57:52 -0400 Merge pull request #384 from PhenomRetroShare/Fix_RsAccountsDetailPrivateInit
|
||||
7fd84f2 Phenom Sat, 14 May 2016 16:50:17 +0200 Fix Initialisation of Private in RsAccountDetails
|
||||
52f488c csoler Fri, 13 May 2016 11:13:07 -0400 Merge pull request #382 from PhenomRetroShare/Fix_CorrectPR378
|
||||
d7efeb9 Phenom Fri, 13 May 2016 17:06:00 +0200 Move nDir->Files into condition nDir exists.
|
||||
4b8a1d2 csoler Thu, 12 May 2016 14:42:31 -0400 Merge pull request #380 from PhenomRetroShare/Fix_ContentValue
|
||||
1c5bcb8 csoler Thu, 12 May 2016 14:41:10 -0400 Merge pull request #379 from PhenomRetroShare/Fix_UninitializedVar
|
||||
2487f3e csoler Thu, 12 May 2016 14:40:37 -0400 Merge pull request #378 from PhenomRetroShare/Fix_CasenDirResetedBefore
|
||||
61e5a62 Phenom Thu, 12 May 2016 20:29:12 +0200 Fix ContentValue::ContentValue if GetAsxxx return false.
|
||||
ed56707 Phenom Thu, 12 May 2016 20:14:59 +0200 Fix in case nDir was reset before
|
||||
a1ece16 Phenom Thu, 12 May 2016 20:00:44 +0200 Fix uninitialized variables netsize, rsnetsize in p3netmgr.cc
|
||||
1d476de csoler Thu, 12 May 2016 10:26:38 -0400 fixed initialisation of semaphores in created thread object
|
||||
96012ef csoler Wed, 11 May 2016 22:18:02 -0400 new attempt to fix thread issues
|
||||
383e403 csoler Wed, 11 May 2016 12:42:59 -0400 tried to improve the RsSemaphore class to avoid and display more info about the
|
||||
e891e2b csoler Wed, 11 May 2016 10:00:20 -0400 added missing check for ssl_connection that would cause crash when the ssl conne
|
||||
8fdf8f8 csoler Tue, 10 May 2016 09:46:33 -0400 fixed possible crash in rsnet.cc
|
||||
74bb3b6 csoler Mon, 9 May 2016 20:54:58 -0400 replaced deprecated gethostbyname by getaddrinfo. Only linux was using the re-entrant
|
||||
f8e6937 csoler Sun, 8 May 2016 18:36:41 -0400 Merge pull request #373 from PhenomRetroShare/Fix_LibResAPI_MacOS
|
||||
4b81fb0 csoler Sun, 8 May 2016 10:42:20 -0400 Merge pull request #374 from PhenomRetroShare/Fix_MacOSVersion
|
||||
ceb092c Phenom Fri, 6 May 2016 22:51:25 +0200 Fix preprocessor for MacOS version.
|
||||
61d2ab5 Phenom Fri, 6 May 2016 22:12:40 +0200 Fix compilation of LibResAPI for MacOS
|
||||
6a7bd90 csoler Fri, 6 May 2016 08:59:59 -0400 Merge pull request #372 from zeners/master
|
||||
ae631a1 zeners Fri, 6 May 2016 10:34:13 +0200 Merge remote branch 'origin/master'
|
||||
08be19f zeners Fri, 6 May 2016 10:29:03 +0200 webui: rebuild files on qmake
|
||||
13dec7a zeners Fri, 6 May 2016 10:06:03 +0200 webui: reset file-date on touch to force build
|
||||
48bc31e csoler Thu, 5 May 2016 23:55:16 -0400 Merge pull request #371 from csoler/v0.6-Threads
|
||||
67e9760 csoler Thu, 5 May 2016 22:03:46 -0400 removed debug output from threads
|
||||
b5ace40 csoler Thu, 5 May 2016 21:21:45 -0400 attempt to fix socket problem on 32bits/64bits windows, by using the proper SOCKET typ
|
||||
9847a7a csoler Thu, 5 May 2016 20:52:10 -0400 implemented a new semaphore class that should be cross plateform
|
||||
092345c csoler Thu, 5 May 2016 09:49:56 -0400 Merge pull request #363 from Nyfor/travis
|
||||
ad2df86 csoler Thu, 5 May 2016 09:45:22 -0400 Merge pull request #370 from Nyfor/fix-segfault-on-close
|
||||
dbd0418 Nyfor Wed, 4 May 2016 18:48:13 +0200 Fix segfault on shutdown.
|
||||
0817aad csoler Wed, 4 May 2016 22:51:33 -0400 improved debugging output of rsthreads.cc (part 3)
|
||||
bb00e39 csoler Wed, 4 May 2016 22:34:03 -0400 improved debugging output of rsthreads.cc (part 2)
|
||||
2e02a89 csoler Wed, 4 May 2016 22:23:36 -0400 improved debugging output of rsthreads.cc
|
||||
e50e686 csoler Wed, 4 May 2016 18:01:18 -0400 updated the debug message for incoming data with no registered tunnel
|
||||
40f8313 csoler Wed, 4 May 2016 15:32:17 -0400 Merge pull request #307 from hunbernd/fix/sqlcipher-version
|
||||
ca003c5 csoler Tue, 3 May 2016 20:55:36 -0400 added missing initialisation of deleted memory before calling realloc
|
||||
0ff2941 csoler Tue, 3 May 2016 13:11:41 -0400 Merge pull request #365 from zeners/master
|
||||
f4a4765 zeners Tue, 3 May 2016 19:04:42 +0200 Merge remote branch 'origin/master'
|
||||
962dd91 zeners Tue, 3 May 2016 19:02:07 +0200 webui: include files on first clean build
|
||||
aec8b4d csoler Mon, 2 May 2016 18:10:39 -0400 fixed bug in counting of incoming data size for sliced packets
|
||||
f3bc978 Nyfor Wed, 27 Apr 2016 18:32:59 +0200 Updated Travis file.
|
||||
|
||||
-- Cyril Soler <csoler@users.sourceforge.net> Sat, 14 May 2016 16:00:00 -0500
|
||||
|
||||
retroshare06 (0.6.0-1.20160424.0d84a558~trusty) trusty; urgency=low
|
||||
|
||||
7914aeb csoler Sat, 30 Apr 2016 17:33:47 -0400 use RsTemporaryMemory in signature verification
|
||||
be7e87c csoler Sat, 30 Apr 2016 17:25:24 -0400 use RsTemporaryMemory in signature verification
|
||||
01605e5 csoler Sat, 30 Apr 2016 11:19:21 -0400 updated description f packet slicing in comments section of pqistreamer
|
||||
1f7a94d csoler Sat, 30 Apr 2016 11:13:51 -0400 fixed bug causing crash in pqistreamer
|
||||
0bd6670 csoler Sat, 30 Apr 2016 09:47:21 -0400 Merge pull request #362 from zeners/master
|
||||
0a6ae55 zeners Sat, 30 Apr 2016 14:21:09 +0200 webui: redefined building webui
|
||||
baf9404 csoler Fri, 29 Apr 2016 20:09:48 -0400 Merge pull request #360 from csoler/v0.6-RTT3
|
||||
4bdd464 csoler Fri, 29 Apr 2016 18:53:25 -0400 removed a few debug output and timer measurement
|
||||
6d2bfcf csoler Fri, 29 Apr 2016 18:52:58 -0400 restored average kicking rate to a more reasonnable value. To be tested (for to
|
||||
3bc3989 csoler Fri, 29 Apr 2016 18:41:10 -0400 removed debug info for pqistreamer
|
||||
5ab9aed csoler Fri, 29 Apr 2016 18:40:28 -0400 added placeholder service ID for packet slicing probe
|
||||
654e0fc csoler Fri, 29 Apr 2016 17:53:21 -0400 added missing call to SSL_pending, which caused decrypted data to wait in the S
|
||||
a443064 csoler Tue, 26 Apr 2016 23:42:44 -0400 various changes to measure RTTs more accurately
|
||||
87764ab csoler Tue, 26 Apr 2016 21:23:19 -0400 removed debug info in pqistreamer
|
||||
153db5c csoler Tue, 26 Apr 2016 09:22:24 -0400 added on/off mechanism for packet slicing to ensure packward compatibility
|
||||
3b68585 csoler Mon, 25 Apr 2016 23:37:02 -0400 improved/simplified slicing protocol
|
||||
dd81ce3 csoler Mon, 25 Apr 2016 22:50:41 -0400 using BinToHex to display mem blocks in pqistreamer debug
|
||||
18e9e1c csoler Sun, 24 Apr 2016 21:29:55 -0400 moerged with upstream/master
|
||||
f629575 csoler Sun, 24 Apr 2016 21:18:44 -0400 fixed a few bugs in packet slicing in pqiQoS
|
||||
a2c11f9 csoler Sun, 24 Apr 2016 13:43:34 -0400 added packet reconstruction and deserialising
|
||||
|
||||
-- Cyril Soler <csoler@users.sourceforge.net> Sat, 30 Apr 2016 18:00:00 -0500
|
||||
|
||||
retroshare06 (0.6.0-1.20160424.0d84a558~trusty) trusty; urgency=low
|
||||
|
||||
0dc43c3 csoler Sat, 23 Apr 2016 08:29:53 -0400 Merge pull request #338 from Nyfor/master
|
||||
5e94c77 Nyfor Mon, 4 Apr 2016 12:07:09 +0200 Fixed compilation for Clang.
|
||||
d696f72 csoler Fri, 22 Apr 2016 20:38:07 -0400 fixed compilation
|
||||
acd059b csoler Fri, 22 Apr 2016 18:49:42 -0400 removed potential memory leak in TransfersDialog
|
||||
52cf66a csoler Fri, 22 Apr 2016 17:55:15 -0400 fixed memory leak in SubscribeToolButton menu
|
||||
55e8087 csoler Fri, 22 Apr 2016 17:30:55 -0400 added missing free for public keys used in envelop encryption
|
||||
10230df csoler Fri, 22 Apr 2016 16:50:43 -0400 added missing SSL shutdown when replacing existing connection
|
||||
5261c3c csoler Thu, 21 Apr 2016 22:23:07 -0400 prevented turtle to not deleting a config item when it is not cast
|
||||
e9fa9eb csoler Thu, 21 Apr 2016 22:07:50 -0400 removed tricky memory leak in chat lobbies due to handling of partial messages
|
||||
7aea6e5 csoler Thu, 21 Apr 2016 22:07:10 -0400 removed some debug info
|
||||
eca83fd csoler Thu, 21 Apr 2016 19:54:50 -0400 removed some debug info
|
||||
fba3d37 csoler Thu, 21 Apr 2016 19:47:34 -0400 fixed memory leak after receiving RsNxsItem deserialised from decrypted memory
|
||||
0d3ff0e csoler Thu, 21 Apr 2016 19:46:47 -0400 fixed possible uninitialised memory read in memory decryption return
|
||||
0c711a4 csoler Thu, 21 Apr 2016 19:41:21 -0400 added missing calls to EVP_CIPHER_CTX_cleanup() to release memory after decryption, causing memory
|
||||
3fae108 csoler Thu, 21 Apr 2016 12:58:48 -0400 removed div by zero in transfers dialog
|
||||
0572492 csoler Wed, 20 Apr 2016 21:20:47 -0400 severely reduced packet grouping, which limited the effectiveness of QoS
|
||||
d6ae71e csoler Wed, 20 Apr 2016 20:21:29 -0400 removed pointer to QStringList in QHash, causing memory loss
|
||||
aba3d2f csoler Wed, 20 Apr 2016 18:24:02 -0400 removed memory leak due to zeroing (on purpose!) a data chunk in GRouter before deleting it
|
||||
d017771 csoler Wed, 20 Apr 2016 18:08:26 -0400 fixed missing sendTime in distant chat, causing inconsistent display in GUI
|
||||
80a9fec csoler Tue, 19 Apr 2016 22:18:25 -0400 Merge pull request #353 from crhode/master
|
||||
39553a6 csoler Tue, 19 Apr 2016 21:58:30 -0400 removed debug info
|
||||
5645e44 Manuel Davis Tue, 19 Apr 2016 11:32:56 -0500 Change regular expression(s) for identifying hotlinks in feral text.
|
||||
8be53dd Manuel Davis Tue, 19 Apr 2016 11:11:58 -0500 Improve inserting placemark in ChatLobby.
|
||||
26af7c9 csoler Sun, 17 Apr 2016 22:58:48 -0400 changed heart beat limit to a larger value. Apparently too tight a value causes disconnections due
|
||||
c14c240 csoler Sun, 17 Apr 2016 00:51:45 -0400 fixed update of circles GUI using a timer. This is not optimal, and should be replaced by a proper
|
||||
3000f94 csoler Sat, 16 Apr 2016 22:44:06 -0400 separated subscribe status from wether we are part of a circle or not. Still needs update of GUI
|
||||
b861aa9 csoler Sat, 16 Apr 2016 17:10:36 -0400 Merge pull request #352 from AsamK/trailing_semicolon
|
||||
e7ec204 AsamK Sat, 16 Apr 2016 20:40:24 +0200 Add trailing semi-colon to MimeType in .desktop files
|
||||
fa8a585 csoler Fri, 15 Apr 2016 18:25:53 -0400 removed some debug info
|
||||
d642934 csoler Fri, 15 Apr 2016 18:25:41 -0400 increased frequency of update for banned PGP nodes
|
||||
|
||||
-- Cyril Soler <csoler@users.sourceforge.net> Sun, 24 Apr 2016 12:00:00 -0500
|
||||
|
||||
retroshare06 (0.6.0-1.20160415.26574fd9~trusty) trusty; urgency=low
|
||||
|
||||
2552b55 defnax Fri, 15 Apr 2016 20:32:00 +0200 Merge branch 'master' of https://github.com/RetroShare/RetroShare
|
||||
85942f4 defnax Fri, 15 Apr 2016 20:30:32 +0200 improving the create circle layout
|
||||
cb6c2c9 csoler Thu, 14 Apr 2016 23:49:55 -0400 Merge pull request #350 from csoler/v0.6-Circles
|
||||
048192e csoler Thu, 14 Apr 2016 23:47:42 -0400 added mOriginator to CircleCache entry and auto-ask for unknown GXS ids to the friend who suppl
|
||||
ba1a1b2 csoler Thu, 14 Apr 2016 23:09:59 -0400 fixed auto-subscribed of circles when some IDs are unknown
|
||||
47dd442 csoler Thu, 14 Apr 2016 18:26:47 -0400 merge upstream/master
|
||||
971f8e0 csoler Wed, 13 Apr 2016 18:41:49 -0400 fixed potential crash due to not updating mPendingDataIterator after deleting map entry
|
||||
92eb9c5 csoler Wed, 13 Apr 2016 18:15:56 -0400 Merge pull request #346 from PhenomRetroShare/Move_ChatNotifyButtonToToolBar
|
||||
aad295d defnax Wed, 13 Apr 2016 21:00:07 +0200 Fixed layout margin
|
||||
45f77de Phenom Wed, 13 Apr 2016 20:42:12 +0200 Change Lobby Send button tooltip.
|
||||
718d6f9 Phenom Wed, 13 Apr 2016 20:26:36 +0200 Resize Chat Tool Bar Button for Hight DPI screen.
|
||||
42a2b37 Phenom Wed, 13 Apr 2016 19:21:18 +0200 Move SearchBar to Tool Bar and remove Show/Hide action.
|
||||
c5873f3 Phenom Sun, 10 Apr 2016 16:42:15 +0200 Move Chat notify button from search bar to tool bar.
|
||||
d512c4a csoler Tue, 12 Apr 2016 22:59:12 -0400 enabled new link type for posted (patch from Fanch)
|
||||
cf746f1 csoler Tue, 12 Apr 2016 10:06:01 -0400 fixed possible crash in GxsIdDetails
|
||||
d5ed84e csoler Mon, 11 Apr 2016 23:43:18 -0400 allow one to change the contact author of a circle
|
||||
8f9028d csoler Mon, 11 Apr 2016 23:30:42 -0400 fixed bug in GxsIdLabel due to not removign existing jobs for a given widget before setting it
|
||||
6b2de05 csoler Mon, 11 Apr 2016 22:42:02 -0400 added channel admin and distribution method in channel summary page
|
||||
a52bd98 csoler Mon, 11 Apr 2016 10:10:10 -0400 fixed potential div by 0 in speed estimations. To be tested.
|
||||
b148239 csoler Sun, 10 Apr 2016 21:09:47 -0400 always pass data accept test in distant chat when we are on the client side of the tunnel
|
||||
c97f197 csoler Sun, 10 Apr 2016 20:39:08 -0400 removed depth obfucation of search results and replaced by 0 always, effectively removing any i
|
||||
123041a csoler Sun, 10 Apr 2016 18:55:05 -0400 skip circle vetting when sending message posts with no author
|
||||
0d5b9ae csoler Sun, 10 Apr 2016 18:55:05 -0400 fixed last commit
|
||||
b8075d6 csoler Sun, 10 Apr 2016 18:53:49 -0400 skip circle vetting when sending message posts with no author
|
||||
4fe66d6 csoler Sun, 10 Apr 2016 10:53:21 -0400 removed Edit/New circles buttons, put them in context menu. Added header frame (needs a proper
|
||||
c9c15e5 csoler Sun, 10 Apr 2016 09:49:31 -0400 Merge pull request #345 from PhenomRetroShare/Update_CircleGraphical
|
||||
d727311 Phenom Sun, 10 Apr 2016 12:00:23 +0200 Fix Graphic Circles update.
|
||||
3eb9a5e electron128 Sun, 10 Apr 2016 11:14:32 +0200 Merge pull request #344 from Phenom: Fix Escaped charaters in WebUI
|
||||
|
||||
-- Cyril Soler <csoler@users.sourceforge.net> Sat, 09 Apr 2016 23:00:00 -0500
|
||||
|
||||
retroshare06 (0.6.0-1.20160409.33d32589~trusty) trusty; urgency=low
|
||||
|
||||
3b45fd8 csoler Sat, 9 Apr 2016 17:50:46 -0400 create new item "My own identities" to store own ids in IdDialog
|
||||
a5044bd csoler Sat, 9 Apr 2016 14:48:05 -0400 improved calculation of speed in pqistreamer (was called before only when sending bytes), and prevented situation wher
|
||||
993d7d4 csoler Sat, 9 Apr 2016 14:46:12 -0400 removed debug info in rsgxsnetservice
|
||||
0853773 csoler Sat, 9 Apr 2016 12:51:15 -0400 merged and removed debug output in rsgxsnetservice.cc
|
||||
10a32d3 csoler Sat, 9 Apr 2016 11:38:07 -0400 Merge pull request #343 from csoler/v0.6-Circles
|
||||
ca0f769 csoler Fri, 8 Apr 2016 21:08:22 -0400 removed warning that would show up too often when a GxsTunnel is down and message cannot be sent
|
||||
85c8274 csoler Fri, 8 Apr 2016 20:41:12 -0400 Merge pull request #342 from PhenomRetroShare/Fix_AllowOnlyOneInst
|
||||
08e5679 Phenom Fri, 8 Apr 2016 02:14:27 +0200 Fix Allow Only One Instance
|
||||
554251d csoler Thu, 7 Apr 2016 19:50:02 -0400 Merge pull request #341 from PhenomRetroShare/Add_WebUIClearButton
|
||||
24b3f0d Phenom Fri, 8 Apr 2016 01:31:36 +0200 Add a Clear button on WebUI
|
||||
b90808d csoler Thu, 7 Apr 2016 18:26:18 -0400 changed update of server update TS in subscribeStatusChange from 0 to time(NULL)
|
||||
c8cae4c csoler Thu, 7 Apr 2016 00:09:00 -0400 Merge pull request #297 from PhenomRetroShare/Add_AllowOnlyOneIntanceAndPassArg
|
||||
4ad3b11 csoler Wed, 6 Apr 2016 22:27:02 -0400 fixed compiler warning
|
||||
4bf9262 csoler Wed, 6 Apr 2016 22:26:34 -0400 merged with upstream/master
|
||||
60ffcd2 csoler Wed, 6 Apr 2016 22:23:10 -0400 fixed double item deletion in RsGxsNetService::handleRecvItem()
|
||||
c79c9ba csoler Wed, 6 Apr 2016 21:12:54 -0400 added encryption of message sync requests for external circles-restricted groups, and verification that properly encry
|
||||
10bb542 Phenom Tue, 1 Mar 2016 13:08:33 +0100 Allow only one instance for useLocalServer option activated. If exists, pass to it arguments.
|
||||
f26348b csoler Tue, 5 Apr 2016 18:09:02 -0400 fixed bug in grouter which caused sending of messages to some offline peers, hence wasting some routes, and causing "
|
||||
7817a54 csoler Tue, 5 Apr 2016 17:55:03 -0400 merged with trunk
|
||||
9871b37 csoler Mon, 4 Apr 2016 23:02:09 -0400 Merge pull request #305 from realityfabric/openssl_crypto_infinite_loop
|
||||
9217ec3 csoler Mon, 4 Apr 2016 21:36:37 -0400 added circle distribution info in forum summary page
|
||||
ff4c360 csoler Mon, 4 Apr 2016 21:15:49 -0400 fixed display bug in bw statistics graph
|
||||
b206317 csoler Mon, 4 Apr 2016 12:17:34 -0400 Merge pull request #339 from PhenomRetroShare/Fix_UnitTests_Compilation
|
||||
f2b9957 Phenom Mon, 4 Apr 2016 17:18:42 +0200 Fix UnitTests Compilation
|
||||
d34b2e8 csoler Sun, 3 Apr 2016 17:11:13 -0400 allow to change the author ID of a group during update. Set proper value in group author widget
|
||||
18dd7ee csoler Sun, 3 Apr 2016 11:42:45 -0400 moved "too many routing clues" message to debug output, since it can be caused by normal lobby operation
|
||||
3554e48 csoler Sun, 3 Apr 2016 11:38:53 -0400 output packet error with some details (inspired by Phenom-PR289)
|
||||
a3890ad csoler Sun, 3 Apr 2016 11:00:03 -0400 added gathering of routing clues from lobbies
|
||||
9ced517 csoler Sat, 2 Apr 2016 16:54:30 -0400 improved tooltips in people list
|
||||
53dbc52 csoler Sat, 2 Apr 2016 16:50:22 -0400 removed mention of null PGP ids in People
|
||||
f8639e5 csoler Sat, 2 Apr 2016 16:44:41 -0400 fixed bug considering null PGP ids in ban list
|
||||
5bbaa1e csoler Sat, 2 Apr 2016 16:14:08 -0400 added people settings page, removed debug output
|
||||
9d9b790 csoler Sat, 2 Apr 2016 14:04:08 -0400 exposed un-verified PGP signatures on GXS ids in GUI. Added auto-ban of GXS ids signed by a PGP ids that has already s
|
||||
9a6bcf8 csoler Sat, 2 Apr 2016 14:02:04 -0400 removed blue color for admin flag in forums, since admin flag is already indicated by position in "My Forums" list, an
|
||||
7c4d85d csoler Sat, 2 Apr 2016 14:00:04 -0400 fixed compilation for ubuntu xenial
|
||||
0350c1d csoler Fri, 1 Apr 2016 17:47:03 -0400 Merge pull request #335 from PhenomRetroShare/Add_ClearWebAPIWhenClearChatHistory2
|
||||
c6f1cc4 Phenom Thu, 31 Mar 2016 22:52:53 +0200 Clear WebAPI when clear chat history in GUI.
|
||||
ab78825 thunder2 Thu, 31 Mar 2016 10:23:23 +0200 Enabled webui build script for Windows compile
|
||||
21421ab csoler Wed, 30 Mar 2016 14:03:50 -0400 Merge pull request #334 from zeners/master
|
||||
8def617 zeners Wed, 30 Mar 2016 19:50:11 +0200 webui: windows build-script
|
||||
741db13 csoler Wed, 30 Mar 2016 12:34:32 -0400 Merge pull request #333 from zeners/webui
|
||||
f570477 zeners Wed, 30 Mar 2016 18:20:59 +0200 webui: patch init.sh like build.sh
|
||||
cee3477 defnax Wed, 30 Mar 2016 17:06:34 +0200 Fixed the default splitter expanding of People Dialog
|
||||
351af47 csoler Tue, 29 Mar 2016 15:42:23 -0400 Merge pull request #332 from zeners/master
|
||||
aca8830 zeners Tue, 29 Mar 2016 21:22:14 +0200 compatible to g++11 / QT5
|
||||
5783c59 electron128 Tue, 29 Mar 2016 20:16:44 +0200 Merge pull request #318 from realityfabric/remove_empty_file
|
||||
475cb40 electron128 Tue, 29 Mar 2016 20:13:24 +0200 Merge pull request #328 from PhenomRetroShare/Fix_WebUI_MakeSrcBuild
|
||||
5b5504c electron128 Tue, 29 Mar 2016 19:42:07 +0200 Merge pull request #330 from zeners/webui
|
||||
be328e2 zeners Tue, 29 Mar 2016 18:57:18 +0200 webui: include files in install
|
||||
f5f27ed zeners Tue, 29 Mar 2016 18:56:00 +0200 Merge branch 'master'
|
||||
a53fbad thunder2 Tue, 29 Mar 2016 08:13:28 +0200 Fixed Windows compile.
|
||||
7c288fc csoler Mon, 28 Mar 2016 23:24:50 -0400 added xenial as build target
|
||||
|
||||
-- Cyril Soler <csoler@users.sourceforge.net> Sat, 09 Apr 2016 23:00:00 -0500
|
||||
|
||||
retroshare06 (0.6.0-1.20160330.21421ab8~trusty) trusty; urgency=low
|
||||
|
||||
3701366 electron128 Mon, 28 Mar 2016 14:07:19 +0200 Merge pull request #327 from zeners/webui
|
||||
dfa2cba zeners Mon, 28 Mar 2016 13:03:49 +0200 webui: menu in gui mode fixed
|
||||
a11cd25 zeners Mon, 28 Mar 2016 11:35:44 +0200 Merge branch 'master'
|
||||
bf374b3 zeners Mon, 28 Mar 2016 11:34:33 +0200 webui 4 windows build prepare
|
||||
68b4cd8 electron128 Mon, 28 Mar 2016 10:19:10 +0200 Merge pull request #323 from zeners/webui
|
||||
0482655 zeners Sun, 27 Mar 2016 20:29:48 +0200 webui: removed searchresult debug output
|
||||
bbdb04f zeners Sun, 27 Mar 2016 20:13:47 +0200 webui: searchresult cross-checking with downloads
|
||||
3bbd370 zeners Sun, 27 Mar 2016 18:28:32 +0200 webui: windows creating batch-files
|
||||
d96a8ef zeners Sat, 26 Mar 2016 23:38:18 +0100 Merge branch 'master'
|
||||
0c138d7 csoler Sat, 26 Mar 2016 18:36:52 -0400 moved discarding of banned identities from lobbies before signature checking, so as to avoid to time stamp their GXSI
|
||||
215402b zeners Sat, 26 Mar 2016 23:36:02 +0100 webui: add downloads: focus fixed
|
||||
922644f zeners Sat, 26 Mar 2016 23:24:29 +0100 Merge branch 'master'
|
||||
502b137 csoler Sat, 26 Mar 2016 17:51:51 -0400 Merge pull request #325 from csoler/v0.6-Circles
|
||||
ebf54d1 csoler Sat, 26 Mar 2016 17:25:15 -0400 fixed unit tests
|
||||
a67c1d7 zeners Sat, 26 Mar 2016 18:19:33 +0100 webui: paste RS-links for download
|
||||
1b8b9d4 csoler Fri, 25 Mar 2016 21:10:01 -0400 turned PeopleDialog to unix ff
|
||||
6c8737c csoler Fri, 25 Mar 2016 21:09:37 -0400 merged with upstream/master
|
||||
4831465 csoler Fri, 25 Mar 2016 21:03:09 -0400 fixed tiny bits in circles/people GUI
|
||||
9efc29f csoler Fri, 25 Mar 2016 20:58:10 -0400 improved display of circle creator ID
|
||||
d1b09b9 csoler Fri, 25 Mar 2016 18:54:13 -0400 removed some debug info
|
||||
083dc62 csoler Fri, 25 Mar 2016 18:27:20 -0400 small code cleaning bits
|
||||
3d45947 csoler Fri, 25 Mar 2016 18:21:37 -0400 fixed small bug in debug output; cleanup debug output
|
||||
44cadc2 csoler Thu, 24 Mar 2016 19:46:08 -0400 cleaned debug info and disabled local circles before merge
|
||||
7d8001b csoler Thu, 24 Mar 2016 19:23:34 -0400 fixed display of warning in posting into forums without proper credentials
|
||||
9dc7328 csoler Thu, 24 Mar 2016 18:41:15 -0400 fixed async-ed circle loading in IdDialog
|
||||
30193fe zeners Thu, 24 Mar 2016 18:07:21 +0100 webui: switch from react to mithril
|
||||
d33a1e8 csoler Thu, 24 Mar 2016 00:05:54 -0400 added disabling of combo elements in GxsIdChooser for creating forums posts with unautorised GXS ids. Still needs a b
|
||||
40d2350 csoler Wed, 23 Mar 2016 21:50:41 -0400 removed deadlock
|
||||
981f81d csoler Wed, 23 Mar 2016 20:54:45 -0400 added anon ids to offline vetting
|
||||
cef07ff zeners Thu, 24 Mar 2016 00:33:22 +0100 webui: integrate new webui in unix build process
|
||||
57f4463 csoler Wed, 23 Mar 2016 18:23:10 -0400 fixed potential crash due to using deleted data (found by dimqua)
|
||||
a19a068 zeners Wed, 23 Mar 2016 13:11:14 +0100 webui: options>settings, playing with colors
|
||||
585c43b zeners Tue, 22 Mar 2016 23:19:36 +0100 webui: RS-reboot / RS-reboot-detection improved
|
||||
60e9f0f zeners Tue, 22 Mar 2016 21:09:33 +0100 undo gitignore
|
||||
a069db5 zeners Tue, 22 Mar 2016 16:37:48 +0100 webui: chat: display peer location
|
||||
4733523 zeners Tue, 22 Mar 2016 16:33:05 +0100 webui: view / change rights per user
|
||||
|
||||
83ff00e zeners Tue, 22 Mar 2016 12:08:23 +0100 webui: updated mithril to v0.2.3
|
||||
1fb1f3e csoler Mon, 21 Mar 2016 23:21:26 -0400 update of groups up to the latest attached circle server update TS. Should re-send groups that depend on a circle whe
|
||||
51e0d83 zeners Mon, 21 Mar 2016 17:04:21 +0100 webui: options / rights (only defaults)
|
||||
1c94ff7 zeners Mon, 21 Mar 2016 16:41:21 +0100 Merge branch 'master'
|
||||
b153c2e csoler Sun, 20 Mar 2016 22:23:32 -0400 updated TODO
|
||||
c304a3a csoler Sun, 20 Mar 2016 22:21:09 -0400 fixed display of properties in restricted groups
|
||||
90347bd csoler Sun, 20 Mar 2016 12:51:30 -0400 Merge pull request #315 from dartraiden/master
|
||||
c627e1b dartraiden Sun, 20 Mar 2016 19:27:28 +0300 Fix typo
|
||||
c123761 csoler Sun, 20 Mar 2016 09:11:55 -0400 Merge pull request #314 from PhenomRetroShare/Fix_CppCheckerError
|
||||
b13292b Phenom Sun, 20 Mar 2016 12:10:56 +0100 Fix error reported by CppChecker:
|
||||
2e9d22c csoler Sat, 19 Mar 2016 18:47:46 -0400 used RsTemporaryMemory to avoid memory leak in case of error in GxsTunnels
|
||||
d1bb939 csoler Sat, 19 Mar 2016 17:14:00 -0400 Merge pull request #312 from PhenomRetroShare/AddPluginsPathForApple
|
||||
5061046 Phenom Sat, 19 Mar 2016 18:58:00 +0100 Add Plugins Path for Apple
|
||||
12c0efb zeners Sat, 19 Mar 2016 17:39:46 +0100 webui: pgp-linked identity disabled
|
||||
ecf8e7f zeners Sat, 19 Mar 2016 17:39:34 +0100 Merge remote branch 'origin/master'
|
||||
24ba909 csoler Sat, 19 Mar 2016 11:39:53 -0400 fixed mixup between in/out bandwidth traffic info
|
||||
526a83a csoler Fri, 18 Mar 2016 22:11:07 -0400 fixed update of circle name in the GUI
|
||||
4e0ee29 csoler Thu, 17 Mar 2016 20:18:54 -0400 fixed creation/distribution of self-restricted circles
|
||||
b6388d7 csoler Thu, 17 Mar 2016 18:17:58 -0400 fixed update of GUI when circles change
|
||||
36edde6 csoler Wed, 16 Mar 2016 23:30:23 -0400 fixed bug causing GUI to not auto-unsubscribe in circles
|
||||
a2a9079 csoler Wed, 16 Mar 2016 23:03:46 -0400 fixed qt4 compilation
|
||||
31356ba csoler Wed, 16 Mar 2016 21:27:08 -0400 added reload of grp meta on update
|
||||
b219295 csoler Wed, 16 Mar 2016 20:59:52 -0400 added update of GUI, instead of re-creating everything when a circle change
|
||||
5b00c03 csoler Wed, 16 Mar 2016 14:17:16 -0400 Merge pull request #4 from PhenomRetroShare/Fix_PictureFlowDeletion
|
||||
76fddb29 Phenom Wed, 16 Mar 2016 19:05:22 +0100 Fix delete in PictureFlow
|
||||
b6e51b2 csoler Wed, 16 Mar 2016 09:56:36 -0400 Merge pull request #308 from dartraiden/master
|
||||
5ba4f42 dartraiden Wed, 16 Mar 2016 16:24:06 +0300 correct path to Hidden Service configuration panel
|
||||
384131a csoler Tue, 15 Mar 2016 22:41:59 -0400 added force reload of cache for circles that are modified
|
||||
6466209 csoler Tue, 15 Mar 2016 22:11:36 -0400 added test to only subscribe/unsubscribe circles when needed, hence avoiding an unnecessary TS update
|
||||
80aaf30 csoler Tue, 15 Mar 2016 00:00:39 -0400 fixed potential crash due to bad usage of updates
|
||||
bdb326a csoler Mon, 14 Mar 2016 23:19:37 -0400 attempt at fixing circle cache loop. Renamed a few variables and fixed logic. Not yet fully working
|
||||
83e39d8 csoler Sun, 13 Mar 2016 17:29:38 -0400 fixed effect of selecting known/signed IDs in circle creation dialog
|
||||
4cf57d6 csoler Sun, 13 Mar 2016 17:19:14 -0400 set default value for circle distribution type
|
||||
9c649aa csoler Sun, 13 Mar 2016 12:08:03 -0400 improved debugDump(), showing the subscription status of each grp
|
||||
5fe390d csoler Sun, 13 Mar 2016 11:41:33 -0400 changed titles of tree root nodes in circles
|
||||
0518062 csoler Sun, 13 Mar 2016 11:29:21 -0400 fixed circle auto-subscribe
|
||||
|
||||
1b72d2c zeners Sat, 12 Mar 2016 23:38:39 +0100 webui: unsubscribe chat-lobby
|
||||
41a8e53 zeners Sat, 12 Mar 2016 23:28:27 +0100 webui: chat-layout fixed
|
||||
0afa2e3 zeners Sat, 12 Mar 2016 20:20:56 +0100 webui: unread chat message counter in menu
|
||||
e9af179 zeners Sat, 12 Mar 2016 19:17:37 +0100 webui: need for master
|
||||
b1286f0 zeners Sat, 12 Mar 2016 17:44:43 +0100 webui: route peer location to chat-lobby
|
||||
a065dba csoler Sat, 12 Mar 2016 11:05:03 -0500 cleaned code a little bit
|
||||
61c7da7 csoler Sat, 12 Mar 2016 11:02:32 -0500 unselect all IDs when no circle is selected
|
||||
b1da4ed zeners Sat, 12 Mar 2016 16:46:33 +0100 Merge branch 'master'
|
||||
456a882 csoler Sat, 12 Mar 2016 10:41:35 -0500 added highlighting of currently selected circle members
|
||||
5d2833f csoler Sat, 12 Mar 2016 09:25:28 -0500 improved one line of debug output in turtle
|
||||
670fb3d csoler Sat, 12 Mar 2016 09:25:00 -0500 merged
|
||||
4e2fd4e csoler Sat, 12 Mar 2016 09:22:28 -0500 Merge pull request #303 from PhenomRetroShare/Fix_CorrectColoredNameContrast
|
||||
16c59af Phenom Sat, 12 Mar 2016 13:25:10 +0100 Correct Colored Name Contrast in chat, same way than text.
|
||||
9e8a4cd csoler Fri, 11 Mar 2016 22:36:47 -0500 fixed auto-subscribe of circles when unsigned identities are locally owned
|
||||
b97c5df csoler Fri, 11 Mar 2016 17:47:12 -0500 fixed culumn name in GR stats
|
||||
692b549 csoler Fri, 11 Mar 2016 17:27:40 -0500 fixing compilation problem
|
||||
232dba2 csoler Fri, 11 Mar 2016 17:21:27 -0500 allow non signature checking for GR message recepts at intermediate peers when key is missing. Should fix return rece
|
||||
ecebace csoler Fri, 11 Mar 2016 14:26:27 -0500 Merge pull request #301 from PhenomRetroShare/Add_NewColumnInRsCollForPath
|
||||
c0cf05c csoler Fri, 11 Mar 2016 14:25:18 -0500 Merge pull request #302 from PhenomRetroShare/Fix_RsLinkCopyForExtraFile
|
||||
d62a205 Phenom Fri, 11 Mar 2016 20:08:28 +0100 Fix Paste RetroShare Link action when copy File link.
|
||||
7e76e28 Phenom Fri, 11 Mar 2016 17:26:18 +0100 Add a new column in RsColl Editor to get only name in first one.
|
||||
4136d09 csoler Thu, 10 Mar 2016 23:55:20 -0500 updated Circles TODO
|
||||
4e4980b csoler Thu, 10 Mar 2016 22:57:04 -0500 fixed display of info for non admin circles, and added readonly system to not allow editing them
|
||||
5361c85 csoler Thu, 10 Mar 2016 22:02:21 -0500 updated circles TODO
|
||||
0282c2a csoler Wed, 9 Mar 2016 21:49:24 -0500 added ban menu entry to chat lobby participant list
|
||||
3fc6f6b csoler Wed, 9 Mar 2016 20:53:49 -0500 updated TODO(circles), removed useless context menu, added tooltips for circle distribution options
|
||||
4eebe24 csoler Wed, 9 Mar 2016 20:23:33 -0500 disabled auto-sync for messages in GXS circles, while keeping Grp auto-sync
|
||||
76e7893 csoler Wed, 9 Mar 2016 20:18:19 -0500 updated circles TODO
|
||||
2017f92 csoler Tue, 8 Mar 2016 23:12:27 -0500 updated circles todo
|
||||
cf75983 csoler Tue, 8 Mar 2016 23:01:43 -0500 added TODO file specific to circles
|
||||
7e31bda csoler Tue, 8 Mar 2016 23:00:24 -0500 fixed removal of peers from circles
|
||||
cba4795 csoler Tue, 8 Mar 2016 00:02:16 -0500 improved circles GUI logic
|
||||
9b92f66 csoler Mon, 7 Mar 2016 22:51:23 -0500 added edit of existing circles
|
||||
49605a3 csoler Mon, 7 Mar 2016 22:10:18 -0500 fixed variable scope problem in introserver.cc
|
||||
|
||||
-- Cyril Soler <csoler@users.sourceforge.net> Mon, 28 Mar 2016 20:00:00 -0500
|
||||
|
||||
retroshare06 (0.6.0-1.20160306.ecf4a991~precise) precise; urgency=low
|
||||
|
||||
bb26069 csoler Wed, 2 Mar 2016 19:00:51 -0500 attempt at fixing negative bw rates in GUI that may pop up when an erro
|
||||
20fcf63 electron128 Fri, 26 Feb 2016 18:13:20 +0100 Merge pull request #285 from PhenomRetroShare/Fix_SSGxsChannelGro
|
||||
1a110e4 Phenom Mon, 22 Feb 2016 19:07:49 +0100 Define empty service string as a valid case.
|
||||
|
@ -3,7 +3,7 @@
|
||||
configure: configure-stamp
|
||||
configure-stamp:
|
||||
dh_testdir
|
||||
cd src && qmake-qt4 "CONFIG-=debug" "CONFIG+=release" PREFIX=/usr LIB_DIR=/usr/lib RetroShare.pro
|
||||
cd src && qmake "CONFIG-=debug" "CONFIG+=release" PREFIX=/usr LIB_DIR=/usr/lib RetroShare.pro
|
||||
touch $@
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ while [ ${#} -gt 0 ]; do
|
||||
done
|
||||
|
||||
if test "${dist}" = "" ; then
|
||||
dist="precise trusty vivid wily"
|
||||
dist="precise trusty vivid wily xenial"
|
||||
fi
|
||||
|
||||
echo Attempting to get revision number...
|
||||
@ -133,6 +133,8 @@ for i in ${dist}; do
|
||||
cp ../control.squeeze_bubba3 debian/control
|
||||
elif test "${i}" = "precise" ; then
|
||||
cp ../control.precise debian/control
|
||||
elif test "${i}" = "xenial" ; then
|
||||
cp ../control.xenial debian/control
|
||||
elif test "${i}" = "stretch" ; then
|
||||
cp ../control.${i} debian/control
|
||||
cp ../rules.${i} debian/rules
|
||||
|
@ -2,8 +2,9 @@
|
||||
Version=1.0
|
||||
Name=RetroShare06
|
||||
Comment=Securely share files with your friends
|
||||
Exec=/usr/bin/RetroShare06
|
||||
Exec=/usr/bin/RetroShare06 %U
|
||||
Icon=/usr/share/pixmaps/retroshare06.xpm
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Network;P2P;
|
||||
MimeType=x-scheme-handler/retroshare;
|
||||
|
@ -7,8 +7,8 @@ Group: Productivity/Networking/Other
|
||||
URL: http://retroshare.sourceforge.net/
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||
Requires: qt-x11
|
||||
BuildRequires: gcc-c++ qt-devel desktop-file-utils libgnome-keyring-devel glib2-devel libssh-devel protobuf-devel libcurl-devel libxml2-devel libxslt-devel openssl-devel libXScrnSaver-devel libupnp-devel bzip2-devel libmicrohttpd-devel
|
||||
Requires: qt5-qtbase-gui qt5-qtmultimedia qt5-qtx11extras qt5-qtbase
|
||||
BuildRequires: gcc-c++ desktop-file-utils libgnome-keyring-devel glib2-devel libssh-devel protobuf-devel libcurl-devel libxml2-devel libxslt-devel openssl-devel libXScrnSaver-devel libupnp-devel bzip2-devel libmicrohttpd-devel qt5-qtx11extras-devel qt5-qttools-devel qt5-qtmultimedia-devel qt5-qttools-static
|
||||
# This is because of sqlcipher:
|
||||
BuildRequires: tcl
|
||||
|
||||
@ -56,7 +56,7 @@ cd lib/sqlcipher
|
||||
make
|
||||
cd -
|
||||
cd src
|
||||
qmake-qt4 "CONFIG-=debug" "CONFIG+=release" PREFIX=%{_prefix} LIB_DIR=%{_libdir} RetroShare.pro
|
||||
qmake-qt5 "CONFIG-=debug" "CONFIG+=release" PREFIX=%{_prefix} LIB_DIR=%{_libdir} RetroShare.pro
|
||||
make
|
||||
cd -
|
||||
|
||||
|
@ -221,7 +221,7 @@ Section $(Section_Main) Section_Main
|
||||
|
||||
; WebUI
|
||||
SetOutPath "$INSTDIR\webui"
|
||||
File /r "${SOURCEDIR}\libresapi\src\webfiles\*.*"
|
||||
File /r "${SOURCEDIR}\libresapi\src\webui\*.*"
|
||||
|
||||
; License
|
||||
SetOutPath "$INSTDIR\license"
|
||||
|
@ -241,7 +241,7 @@ Section $(Section_Main) Section_Main
|
||||
|
||||
; WebUI
|
||||
SetOutPath "$INSTDIR\webui"
|
||||
File /r "${SOURCEDIR}\libresapi\src\webfiles\*.*"
|
||||
File /r "${SOURCEDIR}\libresapi\src\webui\*.*"
|
||||
|
||||
; License
|
||||
SetOutPath "$INSTDIR\license"
|
||||
|
@ -3,9 +3,9 @@ Encoding=UTF-8
|
||||
Version=1.0
|
||||
Name=RetroShare06
|
||||
Comment=Securely share files with your friends
|
||||
Exec=/usr/bin/RetroShare06
|
||||
Exec=/usr/bin/RetroShare06 %U
|
||||
Icon=/usr/share/pixmaps/retroshare06.xpm
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Application;Network;
|
||||
|
||||
MimeType=x-scheme-handler/retroshare;
|
||||
|
@ -46,8 +46,6 @@ bdFilter::bdFilter(const std::string &fname, const bdNodeId *ownid, uint32_t fi
|
||||
mFns = fns;
|
||||
mFilename = fname ;
|
||||
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
loadBannedIpFile() ;
|
||||
|
||||
mFilterFlags = filterFlags;
|
||||
@ -92,8 +90,6 @@ void bdFilter::loadBannedIpFile()
|
||||
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||
addr.sin_family = PF_INET;
|
||||
|
||||
unsigned short port;
|
||||
|
||||
FILE *fd = fopen(mFilename.c_str(),"r") ;
|
||||
|
||||
if(fd == NULL)
|
||||
|
@ -496,10 +496,12 @@ void bdNode::checkPotentialPeer(bdId *id, bdId *src)
|
||||
/* first check the filters */
|
||||
if (!mFilterPeers.addrOkay(&(id->addr)))
|
||||
{
|
||||
#ifdef DEBUG_NODE_MSGS
|
||||
std::cerr << "bdNode::checkPotentialPeer(";
|
||||
mFns->bdPrintId(std::cerr, id);
|
||||
std::cerr << ") BAD ADDRESS!!!! SHOULD DISCARD POTENTIAL PEER";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -344,6 +344,8 @@ int bdSpace::find_node(const bdNodeId *id, int number, std::list<bdId> &matchIds
|
||||
std::cerr << " Number: " << number;
|
||||
std::cerr << " Bucket #: " << buckno;
|
||||
std::cerr << std::endl;
|
||||
#else
|
||||
(void)number;
|
||||
#endif
|
||||
|
||||
bdBucket &buck = buckets[buckno];
|
||||
|
@ -29,7 +29,7 @@ debug {
|
||||
|
||||
################################# Linux ##########################################
|
||||
linux-* {
|
||||
QMAKE_CC = g++
|
||||
QMAKE_CC = $${QMAKE_CXX}
|
||||
}
|
||||
|
||||
linux-g++ {
|
||||
@ -64,7 +64,7 @@ win32-x-g++ {
|
||||
################################# Windows ##########################################
|
||||
|
||||
win32 {
|
||||
QMAKE_CC = g++
|
||||
QMAKE_CC = $${QMAKE_CXX}
|
||||
OBJECTS_DIR = temp/obj
|
||||
MOC_DIR = temp/moc
|
||||
DEFINES *= STATICLIB WIN32_LEAN_AND_MEAN _USE_32BIT_TIME_T
|
||||
@ -89,7 +89,7 @@ win32 {
|
||||
################################# MacOSX ##########################################
|
||||
|
||||
mac {
|
||||
QMAKE_CC = g++
|
||||
QMAKE_CC = $${QMAKE_CXX}
|
||||
OBJECTS_DIR = temp/obj
|
||||
MOC_DIR = temp/moc
|
||||
}
|
||||
|
1
libresapi/src/.gitignore
vendored
Normal file
1
libresapi/src/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
webui/*
|
@ -2,13 +2,13 @@ libresapi: resource_api and new webinterface
|
||||
============================================
|
||||
|
||||
* ./api contains a C++ backend to control retroshare from webinterfaces or scripting
|
||||
* ./webfiles contains compiled files for the webinterface
|
||||
* ./webui contains HTML/CSS/JavaScript source files for the webinterface
|
||||
* ./webui contains compiled files for the webinterface (after build)
|
||||
* ./webui-src contains HTML/CSS/JavaScript source files for the webinterface (NEW, webinterface made with mithril.js)
|
||||
|
||||
Quickinfo for builders and packagers
|
||||
====================================
|
||||
|
||||
* copy the files in ./webfiles to
|
||||
* copy the files in ./webui to
|
||||
* ./webui (Windows)
|
||||
* /usr/share/RetroShare06/webui (Linux)
|
||||
* other OS: see RsAccountsDetail::PathDataDirectory()
|
||||
* other OS: see RsAccountsDetail::PathDataDirectory()
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "StateTokenServer.h" // for the state token serialisers
|
||||
|
||||
#include "ApiPluginHandler.h"
|
||||
#include "ChannelsHandler.h"
|
||||
|
||||
/*
|
||||
data types in json http://json.org/
|
||||
@ -226,13 +227,14 @@ class ApiServerMainModules
|
||||
public:
|
||||
ApiServerMainModules(ResourceRouter& router, StateTokenServer* sts, const RsPlugInInterfaces &ifaces):
|
||||
mPeersHandler(sts, ifaces.mNotify, ifaces.mPeers, ifaces.mMsgs),
|
||||
mIdentityHandler(ifaces.mIdentity),
|
||||
mIdentityHandler(sts, ifaces.mNotify, ifaces.mIdentity),
|
||||
mForumHandler(ifaces.mGxsForums),
|
||||
mServiceControlHandler(ifaces.mServiceControl),
|
||||
mFileSearchHandler(sts, ifaces.mNotify, ifaces.mTurtle, ifaces.mFiles),
|
||||
mTransfersHandler(sts, ifaces.mFiles),
|
||||
mChatHandler(sts, ifaces.mNotify, ifaces.mMsgs, ifaces.mPeers, ifaces.mIdentity, &mPeersHandler),
|
||||
mApiPluginHandler(sts, ifaces)
|
||||
mApiPluginHandler(sts, ifaces),
|
||||
mChannelsHandler(ifaces.mGxsChannels)
|
||||
{
|
||||
// the dynamic cast is to not confuse the addResourceHandler template like this:
|
||||
// addResourceHandler(derived class, parent class)
|
||||
@ -254,6 +256,8 @@ public:
|
||||
&ChatHandler::handleRequest);
|
||||
router.addResourceHandler("apiplugin", dynamic_cast<ResourceRouter*>(&mApiPluginHandler),
|
||||
&ChatHandler::handleRequest);
|
||||
router.addResourceHandler("channels", dynamic_cast<ResourceRouter*>(&mChannelsHandler),
|
||||
&ChannelsHandler::handleRequest);
|
||||
}
|
||||
|
||||
PeersHandler mPeersHandler;
|
||||
@ -264,6 +268,7 @@ public:
|
||||
TransfersHandler mTransfersHandler;
|
||||
ChatHandler mChatHandler;
|
||||
ApiPluginHandler mApiPluginHandler;
|
||||
ChannelsHandler mChannelsHandler;
|
||||
};
|
||||
|
||||
ApiServer::ApiServer():
|
||||
@ -311,7 +316,7 @@ std::string ApiServer::handleRequest(Request &request)
|
||||
task = mRouter.handleRequest(request, resp);
|
||||
}
|
||||
|
||||
time_t start = time(NULL);
|
||||
//time_t start = time(NULL);
|
||||
bool morework = true;
|
||||
while(task && morework)
|
||||
{
|
||||
|
@ -305,7 +305,7 @@ public:
|
||||
|
||||
// get content-type from extension
|
||||
std::string ext = "";
|
||||
unsigned int i = info.fname.rfind('.');
|
||||
std::string::size_type i = info.fname.rfind('.');
|
||||
if(i != std::string::npos)
|
||||
ext = info.fname.substr(i+1);
|
||||
MHD_add_response_header(resp, "Content-Type", ContentTypes::cTypeFromExt(ext).c_str());
|
||||
@ -424,7 +424,7 @@ static void sendMessage(MHD_Connection *connection, unsigned int status, std::st
|
||||
static std::string escape_html(std::string in)
|
||||
{
|
||||
std::string out;
|
||||
for(int i = 0; i < in.size(); i++)
|
||||
for(uint32_t i = 0; i < in.size(); i++)
|
||||
{
|
||||
char a = (in[i]&0xF0)>>4;
|
||||
a = a < 10? a+'0': a-10+'A';
|
||||
|
112
libresapi/src/api/ChannelsHandler.cpp
Normal file
112
libresapi/src/api/ChannelsHandler.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include "ChannelsHandler.h"
|
||||
|
||||
#include <retroshare/rsgxschannels.h>
|
||||
#include <util/radix64.h>
|
||||
#include <algorithm>
|
||||
#include "Operators.h"
|
||||
|
||||
namespace resource_api
|
||||
{
|
||||
|
||||
StreamBase& operator << (StreamBase& left, RsGxsFile& file)
|
||||
{
|
||||
left << makeKeyValueReference("name", file.mName)
|
||||
<< makeKeyValueReference("hash", file.mHash);
|
||||
if(left.serialise())
|
||||
{
|
||||
double size = file.mSize;
|
||||
left << makeKeyValueReference("size", size);
|
||||
}
|
||||
else
|
||||
{
|
||||
double size = 0;
|
||||
left << makeKeyValueReference("size", size);
|
||||
file.mSize = size;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
ChannelsHandler::ChannelsHandler(RsGxsChannels *channels):
|
||||
mChannels(channels)
|
||||
{
|
||||
addResourceHandler("create_post", this, &ChannelsHandler::handleCreatePost);
|
||||
}
|
||||
|
||||
ResponseTask* ChannelsHandler::handleCreatePost(Request &req, Response &resp)
|
||||
{
|
||||
RsGxsChannelPost post;
|
||||
|
||||
req.mStream << makeKeyValueReference("group_id", post.mMeta.mGroupId);
|
||||
req.mStream << makeKeyValueReference("subject", post.mMeta.mMsgName);
|
||||
req.mStream << makeKeyValueReference("message", post.mMsg);
|
||||
|
||||
StreamBase& file_array = req.mStream.getStreamToMember("files");
|
||||
while(file_array.hasMore())
|
||||
{
|
||||
RsGxsFile file;
|
||||
file_array.getStreamToMember() << file;
|
||||
post.mFiles.push_back(file);
|
||||
}
|
||||
|
||||
std::string thumbnail_base64;
|
||||
req.mStream << makeKeyValueReference("thumbnail_base64_png", thumbnail_base64);
|
||||
|
||||
if(post.mMeta.mGroupId.isNull())
|
||||
{
|
||||
resp.setFail("groupd_id is null");
|
||||
return 0;
|
||||
}
|
||||
if(post.mMeta.mMsgName.empty())
|
||||
{
|
||||
resp.setFail("subject is empty");
|
||||
return 0;
|
||||
}
|
||||
if(post.mMsg.empty())
|
||||
{
|
||||
resp.setFail("msg text is empty");
|
||||
return 0;
|
||||
}
|
||||
// empty file list is ok, but files have to be valid
|
||||
for(std::list<RsGxsFile>::iterator lit = post.mFiles.begin(); lit != post.mFiles.end(); ++lit)
|
||||
{
|
||||
if(lit->mHash.isNull())
|
||||
{
|
||||
resp.setFail("at least one file hash is empty");
|
||||
return 0;
|
||||
}
|
||||
if(lit->mName.empty())
|
||||
{
|
||||
resp.setFail("at leats one file name is empty");
|
||||
return 0;
|
||||
}
|
||||
if(lit->mSize == 0)
|
||||
{
|
||||
resp.setFail("at least one file size is empty");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> png_data = Radix64::decode(thumbnail_base64);
|
||||
if(!png_data.empty())
|
||||
{
|
||||
if(png_data.size() < 8)
|
||||
{
|
||||
resp.setFail("Decoded thumbnail_base64_png is smaller than 8 byte. This can't be a valid png file!");
|
||||
return 0;
|
||||
}
|
||||
uint8_t png_magic_number[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
|
||||
if(!std::equal(&png_magic_number[0],&png_magic_number[8],png_data.begin()))
|
||||
{
|
||||
resp.setFail("Decoded thumbnail_base64_png does not seem to be a png file. (Header is missing magic number)");
|
||||
return 0;
|
||||
}
|
||||
post.mThumbnail.copy(png_data.data(), png_data.size());
|
||||
}
|
||||
|
||||
uint32_t token;
|
||||
mChannels->createPost(token, post);
|
||||
// TODO: grp creation acknowledge
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace resource_api
|
21
libresapi/src/api/ChannelsHandler.h
Normal file
21
libresapi/src/api/ChannelsHandler.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "ResourceRouter.h"
|
||||
|
||||
class RsGxsChannels;
|
||||
|
||||
namespace resource_api
|
||||
{
|
||||
|
||||
class ChannelsHandler : public ResourceRouter
|
||||
{
|
||||
public:
|
||||
ChannelsHandler(RsGxsChannels* channels);
|
||||
|
||||
private:
|
||||
ResponseTask* handleCreatePost(Request& req, Response& resp);
|
||||
|
||||
RsGxsChannels* mChannels;
|
||||
};
|
||||
|
||||
} // namespace resource_api
|
@ -6,8 +6,10 @@
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <retroshare/rsidentity.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <time.h>
|
||||
|
||||
namespace resource_api
|
||||
{
|
||||
@ -97,6 +99,39 @@ StreamBase& operator << (StreamBase& left, ChatHandler::ChatInfo& info)
|
||||
return left;
|
||||
}
|
||||
|
||||
class SendLobbyParticipantsTask: public GxsResponseTask
|
||||
{
|
||||
public:
|
||||
SendLobbyParticipantsTask(RsIdentity* idservice, ChatHandler::LobbyParticipantsInfo pi):
|
||||
GxsResponseTask(idservice, 0), mParticipantsInfo(pi)
|
||||
{
|
||||
const std::map<RsGxsId, time_t>& map = mParticipantsInfo.participants;
|
||||
for(std::map<RsGxsId, time_t>::const_iterator mit = map.begin(); mit != map.end(); ++mit)
|
||||
{
|
||||
requestGxsId(mit->first);
|
||||
}
|
||||
}
|
||||
private:
|
||||
ChatHandler::LobbyParticipantsInfo mParticipantsInfo;
|
||||
protected:
|
||||
virtual void gxsDoWork(Request &/*req*/, Response &resp)
|
||||
{
|
||||
resp.mDataStream.getStreamToMember();
|
||||
const std::map<RsGxsId, time_t>& map = mParticipantsInfo.participants;
|
||||
for(std::map<RsGxsId, time_t>::const_iterator mit = map.begin(); mit != map.end(); ++mit)
|
||||
{
|
||||
StreamBase& stream = resp.mDataStream.getStreamToMember();
|
||||
double last_active = mit->second;
|
||||
stream << makeKeyValueReference("last_active", last_active);
|
||||
streamGxsId(mit->first, stream.getStreamToMember("identity"));
|
||||
}
|
||||
resp.mStateToken = mParticipantsInfo.state_token;
|
||||
resp.setOk();
|
||||
done();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs, RsPeers* peers, RsIdentity* identity, UnreadMsgNotify* unread):
|
||||
mStateTokenServer(sts), mNotify(notify), mRsMsgs(msgs), mRsPeers(peers), mRsIdentity(identity), mUnreadMsgNotify(unread), mMtx("ChatHandler::mMtx")
|
||||
{
|
||||
@ -111,11 +146,13 @@ ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs,
|
||||
addResourceHandler("lobbies", this, &ChatHandler::handleLobbies);
|
||||
addResourceHandler("subscribe_lobby", this, &ChatHandler::handleSubscribeLobby);
|
||||
addResourceHandler("unsubscribe_lobby", this, &ChatHandler::handleUnsubscribeLobby);
|
||||
addResourceHandler("clear_lobby", this, &ChatHandler::handleClearLobby);
|
||||
addResourceHandler("lobby_participants", this, &ChatHandler::handleLobbyParticipants);
|
||||
addResourceHandler("messages", this, &ChatHandler::handleMessages);
|
||||
addResourceHandler("send_message", this, &ChatHandler::handleSendMessage);
|
||||
addResourceHandler("mark_chat_as_read", this, &ChatHandler::handleMarkChatAsRead);
|
||||
addResourceHandler("info", this, &ChatHandler::handleInfo);
|
||||
addResourceHandler("typing_label", this, &ChatHandler::handleTypingLabel);
|
||||
addResourceHandler("receive_status", this, &ChatHandler::handleReceiveStatus);
|
||||
addResourceHandler("send_status", this, &ChatHandler::handleSendStatus);
|
||||
addResourceHandler("unread_msgs", this, &ChatHandler::handleUnreadMsgs);
|
||||
}
|
||||
@ -132,20 +169,40 @@ void ChatHandler::notifyChatMessage(const ChatMessage &msg)
|
||||
mRawMsgs.push_back(msg);
|
||||
}
|
||||
|
||||
// to be removed
|
||||
/*
|
||||
ChatHandler::Lobby ChatHandler::getLobbyInfo(ChatLobbyId id)
|
||||
void ChatHandler::notifyChatCleared(const ChatId &chat_id)
|
||||
{
|
||||
tick();
|
||||
|
||||
RS_STACK_MUTEX(mMtx); // ********* LOCKED **********
|
||||
for(std::vector<Lobby>::iterator vit = mLobbies.begin(); vit != mLobbies.end(); ++vit)
|
||||
if(vit->id == id)
|
||||
return *vit;
|
||||
std::cerr << "ChatHandler::getLobbyInfo Error: Lobby not found" << std::endl;
|
||||
return Lobby();
|
||||
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
|
||||
//Remove processed messages
|
||||
std::list<Msg>& msgs = mMsgs[chat_id];
|
||||
msgs.clear();
|
||||
//Remove unprocessed messages
|
||||
for(std::list<ChatMessage>::iterator lit = mRawMsgs.begin(); lit != mRawMsgs.end();)
|
||||
{
|
||||
ChatMessage& msg = *lit;
|
||||
if (msg.chat_id == chat_id)
|
||||
{
|
||||
lit = mRawMsgs.erase(lit);
|
||||
} else {
|
||||
++lit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatHandler::notifyChatStatus(const ChatId &chat_id, const std::string &status)
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
|
||||
locked_storeTypingInfo(chat_id, status);
|
||||
}
|
||||
|
||||
void ChatHandler::notifyChatLobbyEvent(uint64_t lobby_id, uint32_t event_type,
|
||||
const RsGxsId &nickname, const std::string& any_string)
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
|
||||
if(event_type == RS_CHAT_LOBBY_EVENT_PEER_STATUS)
|
||||
{
|
||||
locked_storeTypingInfo(ChatId(lobby_id), any_string, nickname);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void ChatHandler::tick()
|
||||
{
|
||||
@ -170,9 +227,46 @@ void ChatHandler::tick()
|
||||
l.is_broadcast = false;
|
||||
l.gxs_id = info.gxs_id;
|
||||
lobbies.push_back(l);
|
||||
|
||||
// update the lobby participants list
|
||||
// maybe it causes to much traffic to do this in every tick,
|
||||
// because the client would get the whole list every time a message was received
|
||||
// we could reduce the checking frequency
|
||||
std::map<ChatLobbyId, LobbyParticipantsInfo>::iterator mit = mLobbyParticipantsInfos.find(*lit);
|
||||
if(mit == mLobbyParticipantsInfos.end())
|
||||
{
|
||||
mLobbyParticipantsInfos[*lit].participants = info.gxs_ids;
|
||||
mLobbyParticipantsInfos[*lit].state_token = mStateTokenServer->getNewToken();
|
||||
}
|
||||
else
|
||||
{
|
||||
LobbyParticipantsInfo& pi = mit->second;
|
||||
if(!std::equal(pi.participants.begin(), pi.participants.end(), info.gxs_ids.begin()))
|
||||
{
|
||||
pi.participants = info.gxs_ids;
|
||||
mStateTokenServer->replaceToken(pi.state_token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove participants info of old lobbies
|
||||
std::vector<ChatLobbyId> participants_info_to_delete;
|
||||
for(std::map<ChatLobbyId, LobbyParticipantsInfo>::iterator mit = mLobbyParticipantsInfos.begin();
|
||||
mit != mLobbyParticipantsInfos.end(); ++mit)
|
||||
{
|
||||
if(std::find(subscribed_ids.begin(), subscribed_ids.end(), mit->first) == subscribed_ids.end())
|
||||
{
|
||||
participants_info_to_delete.push_back(mit->first);
|
||||
}
|
||||
}
|
||||
for(std::vector<ChatLobbyId>::iterator vit = participants_info_to_delete.begin(); vit != participants_info_to_delete.end(); ++vit)
|
||||
{
|
||||
LobbyParticipantsInfo& pi = mLobbyParticipantsInfos[*vit];
|
||||
mStateTokenServer->discardToken(pi.state_token);
|
||||
mLobbyParticipantsInfos.erase(*vit);
|
||||
}
|
||||
|
||||
{
|
||||
Lobby l;
|
||||
l.name = "BroadCast";
|
||||
@ -369,6 +463,46 @@ void ChatHandler::tick()
|
||||
}
|
||||
}
|
||||
|
||||
static void writeUTF8 ( std::ostream & Out, unsigned int Ch )
|
||||
/* writes Ch in UTF-8 encoding to Out. Note this version only deals
|
||||
with characters up to 16 bits.
|
||||
From: http://www.codecodex.com/wiki/Unescape_HTML_special_characters_from_a_String*/
|
||||
{
|
||||
if (Ch >= 0x800)
|
||||
{
|
||||
Out.put(0xE0 | ((Ch >> 12) & 0x0F));
|
||||
Out.put(0x80 | ((Ch >> 6) & 0x3F));
|
||||
Out.put(0x80 | ((Ch ) & 0x3F));
|
||||
}
|
||||
else if (Ch >= 0x80)
|
||||
{
|
||||
Out.put(0xC0 | ((Ch >> 6) & 0x1F));
|
||||
Out.put(0x80 | ((Ch ) & 0x3F));
|
||||
}
|
||||
else
|
||||
{
|
||||
Out.put(Ch);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int stringToDecUInt ( std::string str)
|
||||
{
|
||||
unsigned int out = 0;
|
||||
unsigned int max = std::numeric_limits<int>::max() / 10;
|
||||
int lenght = str.length();
|
||||
for (int curs = 0; curs < lenght; ++curs) {
|
||||
char c = str[curs];
|
||||
if ( (c >= '0')
|
||||
&& (c <= '9')
|
||||
&& (out < max)
|
||||
) {
|
||||
out *= 10;
|
||||
out += (int)( c - '0');
|
||||
} else return 0;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void ChatHandler::getPlainText(const std::string& in, std::string &out, std::vector<Triple> &links)
|
||||
{
|
||||
if (in.size() == 0)
|
||||
@ -386,6 +520,9 @@ void ChatHandler::getPlainText(const std::string& in, std::string &out, std::vec
|
||||
std::string last_six_chars;
|
||||
unsigned int tag_start_index = 0;
|
||||
Triple current_link;
|
||||
bool onEscapeChar = false;
|
||||
unsigned int escapeCharIndexStart = -1;
|
||||
|
||||
for(unsigned int i = 0; i < in.size(); ++i)
|
||||
{
|
||||
if(keep_link && in[i] == '"')
|
||||
@ -408,10 +545,12 @@ void ChatHandler::getPlainText(const std::string& in, std::string &out, std::vec
|
||||
if(!ignore || keep_link)
|
||||
out += in[i];
|
||||
// "falling edge" resets mode to keep
|
||||
if(in[i] == '>') {
|
||||
if(in[i] == '>' && ignore) {
|
||||
// leave ignore mode on, if it's a style tag
|
||||
if (tag_start_index == 0 || tag_start_index + 6 > i || in.substr(tag_start_index, 6) != "<style")
|
||||
if (tag_start_index == 0 || tag_start_index + 6 > i || in.substr(tag_start_index, 6) != "<style") {
|
||||
ignore = false;
|
||||
tag_start_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
last_six_chars += in[i];
|
||||
@ -436,9 +575,250 @@ void ChatHandler::getPlainText(const std::string& in, std::string &out, std::vec
|
||||
}
|
||||
current_link = Triple();
|
||||
}
|
||||
std::string br = "<br/>";
|
||||
if(last_six_chars.size() >= br.size()
|
||||
&& last_six_chars.substr(last_six_chars.size()-br.size()) == br)
|
||||
{
|
||||
out += "\n";
|
||||
}
|
||||
if (in[i] == '&') {
|
||||
onEscapeChar = true;
|
||||
escapeCharIndexStart = out.length();
|
||||
}
|
||||
if (ignore || keep_link) {
|
||||
onEscapeChar = false;
|
||||
escapeCharIndexStart = -1;
|
||||
}
|
||||
if ((in[i] == ';') && onEscapeChar) {
|
||||
onEscapeChar = false;
|
||||
bool escapeFound = true;
|
||||
std::string escapeReplace = "";
|
||||
//Keep only escape value to replace it
|
||||
std::string escapeCharValue = out.substr(escapeCharIndexStart,
|
||||
out.length() - escapeCharIndexStart - 1);
|
||||
if (escapeCharValue[0] == '#') {
|
||||
int escapedCharUTF8 = stringToDecUInt(escapeCharValue.substr(1));
|
||||
std::ostringstream escapedSStream;
|
||||
writeUTF8( escapedSStream, escapedCharUTF8);
|
||||
escapeReplace = escapedSStream.str();
|
||||
} else if (escapeCharValue == "euro") {
|
||||
escapeReplace = "€";
|
||||
} else if (escapeCharValue == "nbsp") {
|
||||
escapeReplace = " ";
|
||||
} else if (escapeCharValue == "quot") {
|
||||
escapeReplace = "\"";
|
||||
} else if (escapeCharValue == "amp") {
|
||||
escapeReplace = "&";
|
||||
} else if (escapeCharValue == "lt") {
|
||||
escapeReplace = "<";
|
||||
} else if (escapeCharValue == "gt") {
|
||||
escapeReplace = ">";
|
||||
} else if (escapeCharValue == "iexcl") {
|
||||
escapeReplace = "¡";
|
||||
} else if (escapeCharValue == "cent") {
|
||||
escapeReplace = "¢";
|
||||
} else if (escapeCharValue == "pound") {
|
||||
escapeReplace = "£";
|
||||
} else if (escapeCharValue == "curren") {
|
||||
escapeReplace = "¤";
|
||||
} else if (escapeCharValue == "yen") {
|
||||
escapeReplace = "¥";
|
||||
} else if (escapeCharValue == "brvbar") {
|
||||
escapeReplace = "¦";
|
||||
} else if (escapeCharValue == "sect") {
|
||||
escapeReplace = "§";
|
||||
} else if (escapeCharValue == "uml") {
|
||||
escapeReplace = "¨";
|
||||
} else if (escapeCharValue == "copy") {
|
||||
escapeReplace = "©";
|
||||
} else if (escapeCharValue == "ordf") {
|
||||
escapeReplace = "ª";
|
||||
} else if (escapeCharValue == "not") {
|
||||
escapeReplace = "¬";
|
||||
} else if (escapeCharValue == "shy") {
|
||||
escapeReplace = " ";//?
|
||||
} else if (escapeCharValue == "reg") {
|
||||
escapeReplace = "®";
|
||||
} else if (escapeCharValue == "macr") {
|
||||
escapeReplace = "¯";
|
||||
} else if (escapeCharValue == "deg") {
|
||||
escapeReplace = "°";
|
||||
} else if (escapeCharValue == "plusmn") {
|
||||
escapeReplace = "±";
|
||||
} else if (escapeCharValue == "sup2") {
|
||||
escapeReplace = "²";
|
||||
} else if (escapeCharValue == "sup3") {
|
||||
escapeReplace = "³";
|
||||
} else if (escapeCharValue == "acute") {
|
||||
escapeReplace = "´";
|
||||
} else if (escapeCharValue == "micro") {
|
||||
escapeReplace = "µ";
|
||||
} else if (escapeCharValue == "para") {
|
||||
escapeReplace = "¶";
|
||||
} else if (escapeCharValue == "middot") {
|
||||
escapeReplace = "·";
|
||||
} else if (escapeCharValue == "cedil") {
|
||||
escapeReplace = "¸";
|
||||
} else if (escapeCharValue == "sup1") {
|
||||
escapeReplace = "¹";
|
||||
} else if (escapeCharValue == "ordm") {
|
||||
escapeReplace = "º";
|
||||
} else if (escapeCharValue == "raquo") {
|
||||
escapeReplace = "»";
|
||||
} else if (escapeCharValue == "frac14") {
|
||||
escapeReplace = "¼";
|
||||
} else if (escapeCharValue == "frac12") {
|
||||
escapeReplace = "½";
|
||||
} else if (escapeCharValue == "frac34") {
|
||||
escapeReplace = "¾";
|
||||
} else if (escapeCharValue == "iquest") {
|
||||
escapeReplace = "¿";
|
||||
} else if (escapeCharValue == "Agrave") {
|
||||
escapeReplace = "À";
|
||||
} else if (escapeCharValue == "Aacute") {
|
||||
escapeReplace = "Á";
|
||||
} else if (escapeCharValue == "Acirc") {
|
||||
escapeReplace = "Â";
|
||||
} else if (escapeCharValue == "Atilde") {
|
||||
escapeReplace = "Ã";
|
||||
} else if (escapeCharValue == "Auml") {
|
||||
escapeReplace = "Ä";
|
||||
} else if (escapeCharValue == "Aring") {
|
||||
escapeReplace = "Å";
|
||||
} else if (escapeCharValue == "AElig") {
|
||||
escapeReplace = "Æ";
|
||||
} else if (escapeCharValue == "Ccedil") {
|
||||
escapeReplace = "Ç";
|
||||
} else if (escapeCharValue == "Egrave") {
|
||||
escapeReplace = "È";
|
||||
} else if (escapeCharValue == "Eacute") {
|
||||
escapeReplace = "É";
|
||||
} else if (escapeCharValue == "Ecirc") {
|
||||
escapeReplace = "Ê";
|
||||
} else if (escapeCharValue == "Euml") {
|
||||
escapeReplace = "Ë";
|
||||
} else if (escapeCharValue == "Igrave") {
|
||||
escapeReplace = "Ì";
|
||||
} else if (escapeCharValue == "Iacute") {
|
||||
escapeReplace = "Í";
|
||||
} else if (escapeCharValue == "Icirc") {
|
||||
escapeReplace = "Î";
|
||||
} else if (escapeCharValue == "Iuml") {
|
||||
escapeReplace = "Ï";
|
||||
} else if (escapeCharValue == "ETH") {
|
||||
escapeReplace = "Ð";
|
||||
} else if (escapeCharValue == "Ntilde") {
|
||||
escapeReplace = "Ñ";
|
||||
} else if (escapeCharValue == "Ograve") {
|
||||
escapeReplace = "Ò";
|
||||
} else if (escapeCharValue == "Oacute") {
|
||||
escapeReplace = "Ó";
|
||||
} else if (escapeCharValue == "Ocirc") {
|
||||
escapeReplace = "Ô";
|
||||
} else if (escapeCharValue == "Otilde") {
|
||||
escapeReplace = "Õ";
|
||||
} else if (escapeCharValue == "Ouml") {
|
||||
escapeReplace = "Ö";
|
||||
} else if (escapeCharValue == "times") {
|
||||
escapeReplace = "×";
|
||||
} else if (escapeCharValue == "Oslash") {
|
||||
escapeReplace = "Ø";
|
||||
} else if (escapeCharValue == "Ugrave") {
|
||||
escapeReplace = "Ù";
|
||||
} else if (escapeCharValue == "Uacute") {
|
||||
escapeReplace = "Ú";
|
||||
} else if (escapeCharValue == "Ucirc") {
|
||||
escapeReplace = "Û";
|
||||
} else if (escapeCharValue == "Uuml") {
|
||||
escapeReplace = "Ü";
|
||||
} else if (escapeCharValue == "Yacute") {
|
||||
escapeReplace = "Ý";
|
||||
} else if (escapeCharValue == "THORN") {
|
||||
escapeReplace = "Þ";
|
||||
} else if (escapeCharValue == "szlig") {
|
||||
escapeReplace = "ß";
|
||||
} else if (escapeCharValue == "agrave") {
|
||||
escapeReplace = "à";
|
||||
} else if (escapeCharValue == "aacute") {
|
||||
escapeReplace = "á";
|
||||
} else if (escapeCharValue == "acirc") {
|
||||
escapeReplace = "â";
|
||||
} else if (escapeCharValue == "atilde") {
|
||||
escapeReplace = "ã";
|
||||
} else if (escapeCharValue == "auml") {
|
||||
escapeReplace = "ä";
|
||||
} else if (escapeCharValue == "aring") {
|
||||
escapeReplace = "å";
|
||||
} else if (escapeCharValue == "aelig") {
|
||||
escapeReplace = "æ";
|
||||
} else if (escapeCharValue == "ccedil") {
|
||||
escapeReplace = "ç";
|
||||
} else if (escapeCharValue == "egrave") {
|
||||
escapeReplace = "è";
|
||||
} else if (escapeCharValue == "eacute") {
|
||||
escapeReplace = "é";
|
||||
} else if (escapeCharValue == "ecirc") {
|
||||
escapeReplace = "ê";
|
||||
} else if (escapeCharValue == "euml") {
|
||||
escapeReplace = "ë";
|
||||
} else if (escapeCharValue == "igrave") {
|
||||
escapeReplace = "ì";
|
||||
} else if (escapeCharValue == "iacute") {
|
||||
escapeReplace = "í";
|
||||
} else if (escapeCharValue == "icirc") {
|
||||
escapeReplace = "î";
|
||||
} else if (escapeCharValue == "iuml") {
|
||||
escapeReplace = "ï";
|
||||
} else if (escapeCharValue == "eth") {
|
||||
escapeReplace = "ð";
|
||||
} else if (escapeCharValue == "ntilde") {
|
||||
escapeReplace = "ñ";
|
||||
} else if (escapeCharValue == "ograve") {
|
||||
escapeReplace = "ò";
|
||||
} else if (escapeCharValue == "oacute") {
|
||||
escapeReplace = "ó";
|
||||
} else if (escapeCharValue == "ocirc") {
|
||||
escapeReplace = "ô";
|
||||
} else if (escapeCharValue == "otilde") {
|
||||
escapeReplace = "õ";
|
||||
} else if (escapeCharValue == "ouml") {
|
||||
escapeReplace = "ö";
|
||||
} else if (escapeCharValue == "divide") {
|
||||
escapeReplace = "÷";
|
||||
} else if (escapeCharValue == "oslash") {
|
||||
escapeReplace = "ø";
|
||||
} else if (escapeCharValue == "ugrave") {
|
||||
escapeReplace = "ù";
|
||||
} else if (escapeCharValue == "uacute") {
|
||||
escapeReplace = "ú";
|
||||
} else if (escapeCharValue == "ucirc") {
|
||||
escapeReplace = "û";
|
||||
} else if (escapeCharValue == "uuml") {
|
||||
escapeReplace = "ü";
|
||||
} else if (escapeCharValue == "yacute") {
|
||||
escapeReplace = "ý";
|
||||
} else if (escapeCharValue == "thorn") {
|
||||
escapeReplace = "þ";
|
||||
} else {
|
||||
escapeFound = false;
|
||||
}
|
||||
if (escapeFound) {
|
||||
out = out.substr(0, escapeCharIndexStart-1);
|
||||
out += escapeReplace;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatHandler::locked_storeTypingInfo(const ChatId &chat_id, std::string status, RsGxsId lobby_gxs_id)
|
||||
{
|
||||
TypingLabelInfo& info = mTypingLabelInfo[chat_id];
|
||||
info.timestamp = time(0);
|
||||
info.status = status;
|
||||
mStateTokenServer->replaceToken(info.state_token);
|
||||
info.author_id = lobby_gxs_id;
|
||||
}
|
||||
|
||||
void ChatHandler::handleWildcard(Request &/*req*/, Response &resp)
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
|
||||
@ -496,11 +876,44 @@ void ChatHandler::handleSubscribeLobby(Request &req, Response &resp)
|
||||
resp.setFail("lobby join failed. (See console for more info)");
|
||||
}
|
||||
|
||||
void ChatHandler::handleUnsubscribeLobby(Request &req, Response &/*resp*/)
|
||||
void ChatHandler::handleUnsubscribeLobby(Request &req, Response &resp)
|
||||
{
|
||||
ChatLobbyId id = 0;
|
||||
req.mStream << makeKeyValueReference("id", id);
|
||||
mRsMsgs->unsubscribeChatLobby(id);
|
||||
resp.setOk();
|
||||
}
|
||||
|
||||
void ChatHandler::handleClearLobby(Request &req, Response &resp)
|
||||
{
|
||||
ChatLobbyId id = 0;
|
||||
req.mStream << makeKeyValueReference("id", id);
|
||||
if (id !=0) {
|
||||
notifyChatCleared(ChatId(id));
|
||||
} else {
|
||||
//Is BroadCast
|
||||
notifyChatCleared(ChatId("B"));
|
||||
}
|
||||
resp.setOk();
|
||||
}
|
||||
|
||||
ResponseTask* ChatHandler::handleLobbyParticipants(Request &req, Response &resp)
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
|
||||
|
||||
ChatId id(req.mPath.top());
|
||||
if(!id.isLobbyId())
|
||||
{
|
||||
resp.setFail("Path element \""+req.mPath.top()+"\" is not a ChatLobbyId.");
|
||||
return 0;
|
||||
}
|
||||
std::map<ChatLobbyId, LobbyParticipantsInfo>::const_iterator mit = mLobbyParticipantsInfos.find(id.toLobbyId());
|
||||
if(mit == mLobbyParticipantsInfos.end())
|
||||
{
|
||||
resp.setFail("lobby not found");
|
||||
return 0;
|
||||
}
|
||||
return new SendLobbyParticipantsTask(mRsIdentity, mit->second);
|
||||
}
|
||||
|
||||
void ChatHandler::handleMessages(Request &req, Response &resp)
|
||||
@ -573,89 +986,6 @@ void ChatHandler::handleMarkChatAsRead(Request &req, Response &resp)
|
||||
mStateTokenServer->replaceToken(mUnreadMsgsStateToken);
|
||||
}
|
||||
|
||||
// to be removed
|
||||
// we do now cache chat info, to be able to include it in new message notify easily
|
||||
/*
|
||||
class InfoResponseTask: public GxsResponseTask
|
||||
{
|
||||
public:
|
||||
InfoResponseTask(ChatHandler* ch, RsPeers* peers, RsIdentity* identity): GxsResponseTask(identity, 0), mChatHandler(ch), mRsPeers(peers), mState(BEGIN){}
|
||||
|
||||
enum State {BEGIN, WAITING};
|
||||
ChatHandler* mChatHandler;
|
||||
RsPeers* mRsPeers;
|
||||
State mState;
|
||||
bool is_broadcast;
|
||||
bool is_gxs_id;
|
||||
bool is_lobby;
|
||||
bool is_peer;
|
||||
std::string remote_author_id;
|
||||
std::string remote_author_name;
|
||||
virtual void gxsDoWork(Request& req, Response& resp)
|
||||
{
|
||||
ChatId id(req.mPath.top());
|
||||
if(id.isNotSet())
|
||||
{
|
||||
resp.setFail("not a valid chat id");
|
||||
done();
|
||||
return;
|
||||
}
|
||||
if(mState == BEGIN)
|
||||
{
|
||||
is_broadcast = false;
|
||||
is_gxs_id = false;
|
||||
is_lobby = false;
|
||||
is_peer = false;
|
||||
if(id.isBroadcast())
|
||||
{
|
||||
is_broadcast = true;
|
||||
}
|
||||
else if(id.isGxsId())
|
||||
{
|
||||
is_gxs_id = true;
|
||||
remote_author_id = id.toGxsId().toStdString();
|
||||
requestGxsId(id.toGxsId());
|
||||
}
|
||||
else if(id.isLobbyId())
|
||||
{
|
||||
is_lobby = true;
|
||||
remote_author_id = "";
|
||||
remote_author_name = mChatHandler->getLobbyInfo(id.toLobbyId()).name;
|
||||
}
|
||||
else if(id.isPeerId())
|
||||
{
|
||||
is_peer = true;
|
||||
remote_author_id = id.toPeerId().toStdString();
|
||||
remote_author_name = mRsPeers->getPeerName(id.toPeerId());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error in InfoResponseTask::gxsDoWork(): unhandled chat_id=" << id.toStdString() << std::endl;
|
||||
}
|
||||
mState = WAITING;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_gxs_id)
|
||||
remote_author_name = getName(id.toGxsId());
|
||||
resp.mDataStream << makeKeyValueReference("remote_author_id", remote_author_id)
|
||||
<< makeKeyValueReference("remote_author_name", remote_author_name)
|
||||
<< makeKeyValueReference("is_broadcast", is_broadcast)
|
||||
<< makeKeyValueReference("is_gxs_id", is_gxs_id)
|
||||
<< makeKeyValueReference("is_lobby", is_lobby)
|
||||
<< makeKeyValueReference("is_peer", is_peer);
|
||||
resp.setOk();
|
||||
done();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ResponseTask *ChatHandler::handleInfo(Request &req, Response &resp)
|
||||
{
|
||||
return new InfoResponseTask(this, mRsPeers, mRsIdentity);
|
||||
}
|
||||
*/
|
||||
|
||||
void ChatHandler::handleInfo(Request &req, Response &resp)
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
|
||||
@ -675,14 +1005,99 @@ void ChatHandler::handleInfo(Request &req, Response &resp)
|
||||
resp.setOk();
|
||||
}
|
||||
|
||||
void ChatHandler::handleTypingLabel(Request &/*req*/, Response &/*resp*/)
|
||||
class SendTypingLabelInfo: public GxsResponseTask
|
||||
{
|
||||
public:
|
||||
SendTypingLabelInfo(RsIdentity* identity, RsPeers* peers, ChatId id, const ChatHandler::TypingLabelInfo& info):
|
||||
GxsResponseTask(identity), mState(BEGIN), mPeers(peers),mId(id), mInfo(info) {}
|
||||
private:
|
||||
enum State {BEGIN, WAITING_ID};
|
||||
State mState;
|
||||
RsPeers* mPeers;
|
||||
ChatId mId;
|
||||
ChatHandler::TypingLabelInfo mInfo;
|
||||
protected:
|
||||
void gxsDoWork(Request& /*req*/, Response& resp)
|
||||
{
|
||||
if(mState == BEGIN)
|
||||
{
|
||||
// lobby and distant require to fetch a gxs_id
|
||||
if(mId.isLobbyId())
|
||||
{
|
||||
requestGxsId(mInfo.author_id);
|
||||
}
|
||||
else if(mId.isDistantChatId())
|
||||
{
|
||||
DistantChatPeerInfo dcpinfo ;
|
||||
rsMsgs->getDistantChatStatus(mId.toDistantChatId(), dcpinfo);
|
||||
requestGxsId(dcpinfo.to_id);
|
||||
}
|
||||
mState = WAITING_ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string name = "BUG: case not handled in SendTypingLabelInfo";
|
||||
if(mId.isPeerId())
|
||||
{
|
||||
name = mPeers->getPeerName(mId.toPeerId());
|
||||
}
|
||||
else if(mId.isDistantChatId())
|
||||
{
|
||||
DistantChatPeerInfo dcpinfo ;
|
||||
rsMsgs->getDistantChatStatus(mId.toDistantChatId(), dcpinfo);
|
||||
name = getName(dcpinfo.to_id);
|
||||
}
|
||||
else if(mId.isLobbyId())
|
||||
{
|
||||
name = getName(mInfo.author_id);
|
||||
}
|
||||
else if(mId.isBroadcast())
|
||||
{
|
||||
name = mPeers->getPeerName(mId.broadcast_status_peer_id);
|
||||
}
|
||||
uint32_t ts = mInfo.timestamp;
|
||||
resp.mDataStream << makeKeyValueReference("author_name", name)
|
||||
<< makeKeyValueReference("timestamp", ts)
|
||||
<< makeKeyValueReference("status_string", mInfo.status);
|
||||
resp.mStateToken = mInfo.state_token;
|
||||
resp.setOk();
|
||||
done();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ResponseTask* ChatHandler::handleReceiveStatus(Request &req, Response &resp)
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx); /********** LOCKED **********/
|
||||
ChatId id(req.mPath.top());
|
||||
if(id.isNotSet())
|
||||
{
|
||||
resp.setFail("\""+req.mPath.top()+"\" is not a valid chat id");
|
||||
return 0;
|
||||
}
|
||||
std::map<ChatId, TypingLabelInfo>::iterator mit = mTypingLabelInfo.find(id);
|
||||
if(mit == mTypingLabelInfo.end())
|
||||
{
|
||||
locked_storeTypingInfo(id, "");
|
||||
mit = mTypingLabelInfo.find(id);
|
||||
}
|
||||
return new SendTypingLabelInfo(mRsIdentity, mRsPeers, id, mit->second);
|
||||
}
|
||||
|
||||
void ChatHandler::handleSendStatus(Request &/*req*/, Response &/*resp*/)
|
||||
void ChatHandler::handleSendStatus(Request &req, Response &resp)
|
||||
{
|
||||
|
||||
std::string chat_id;
|
||||
std::string status;
|
||||
req.mStream << makeKeyValueReference("chat_id", chat_id)
|
||||
<< makeKeyValueReference("status", status);
|
||||
ChatId id(chat_id);
|
||||
if(id.isNotSet())
|
||||
{
|
||||
resp.setFail("chat_id is invalid");
|
||||
return;
|
||||
}
|
||||
mRsMsgs->sendStatusString(id, status);
|
||||
resp.setOk();
|
||||
}
|
||||
|
||||
void ChatHandler::handleUnreadMsgs(Request &/*req*/, Response &resp)
|
||||
|
@ -25,6 +25,14 @@ public:
|
||||
// from NotifyClient
|
||||
// note: this may get called from the own and from foreign threads
|
||||
virtual void notifyChatMessage(const ChatMessage& msg);
|
||||
virtual void notifyChatCleared(const ChatId& chat_id);
|
||||
|
||||
// typing label for peer, broadcast and distant chat
|
||||
virtual void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */);
|
||||
|
||||
//typing label for lobby chat, peer join and leave messages
|
||||
virtual void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ ,
|
||||
const RsGxsId& /* nickname */,const std::string& /* any string */);
|
||||
|
||||
// from tickable
|
||||
virtual void tick();
|
||||
@ -81,6 +89,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class LobbyParticipantsInfo{
|
||||
public:
|
||||
StateToken state_token;
|
||||
std::map<RsGxsId, time_t> participants;
|
||||
};
|
||||
|
||||
class ChatInfo{
|
||||
public:
|
||||
bool is_broadcast;
|
||||
@ -91,20 +105,33 @@ public:
|
||||
std::string remote_author_name;
|
||||
};
|
||||
|
||||
class TypingLabelInfo{
|
||||
public:
|
||||
time_t timestamp;
|
||||
std::string status;
|
||||
StateToken state_token;
|
||||
// only for lobbies
|
||||
RsGxsId author_id;
|
||||
};
|
||||
|
||||
private:
|
||||
void handleWildcard(Request& req, Response& resp);
|
||||
void handleLobbies(Request& req, Response& resp);
|
||||
void handleSubscribeLobby(Request& req, Response& resp);
|
||||
void handleUnsubscribeLobby(Request& req, Response& resp);
|
||||
void handleClearLobby(Request& req, Response& resp);
|
||||
ResponseTask* handleLobbyParticipants(Request& req, Response& resp);
|
||||
void handleMessages(Request& req, Response& resp);
|
||||
void handleSendMessage(Request& req, Response& resp);
|
||||
void handleMarkChatAsRead(Request& req, Response& resp);
|
||||
void handleInfo(Request& req, Response& resp);
|
||||
void handleTypingLabel(Request& req, Response& resp);
|
||||
ResponseTask *handleReceiveStatus(Request& req, Response& resp);
|
||||
void handleSendStatus(Request& req, Response& resp);
|
||||
void handleUnreadMsgs(Request& req, Response& resp);
|
||||
|
||||
void getPlainText(const std::string& in, std::string &out, std::vector<Triple> &links);
|
||||
// last parameter is only used for lobbies!
|
||||
void locked_storeTypingInfo(const ChatId& chat_id, std::string status, RsGxsId lobby_gxs_id = RsGxsId());
|
||||
|
||||
StateTokenServer* mStateTokenServer;
|
||||
RsNotify* mNotify;
|
||||
@ -121,9 +148,13 @@ private:
|
||||
|
||||
std::map<ChatId, ChatInfo> mChatInfo;
|
||||
|
||||
std::map<ChatId, TypingLabelInfo> mTypingLabelInfo;
|
||||
|
||||
StateToken mLobbiesStateToken;
|
||||
std::vector<Lobby> mLobbies;
|
||||
|
||||
std::map<ChatLobbyId, LobbyParticipantsInfo> mLobbyParticipantsInfos;
|
||||
|
||||
StateToken mUnreadMsgsStateToken;
|
||||
|
||||
};
|
||||
|
@ -4,6 +4,7 @@ class RsPlugInInterfaces;
|
||||
|
||||
namespace resource_api{
|
||||
|
||||
// populates the given RsPlugInInterfaces object with pointers from gloabl variables like rsPeers, rsMsgs, rsFiles...
|
||||
bool getPluginInterfaces(RsPlugInInterfaces& interfaces);
|
||||
|
||||
} // namespace resource_api
|
||||
|
@ -62,6 +62,7 @@ bool GxsResponseTask::doWork(Request &req, Response &resp)
|
||||
{
|
||||
more = false; // pause when an id failed, to give the service time tim fetch the data
|
||||
ready = false;
|
||||
// TODO: remove identities which failed many times from list, to avoid blocking when ids fail
|
||||
}
|
||||
}
|
||||
if(!ready)
|
||||
|
@ -15,7 +15,7 @@ class GxsResponseTask: public ResponseTask
|
||||
{
|
||||
public:
|
||||
// token service is allowed to be null if no token functions are wanted
|
||||
GxsResponseTask(RsIdentity* id_service, RsTokenService* token_service);
|
||||
GxsResponseTask(RsIdentity* id_service, RsTokenService* token_service = 0);
|
||||
virtual bool doWork(Request &req, Response& resp);
|
||||
|
||||
protected:
|
||||
|
@ -16,17 +16,18 @@ namespace resource_api
|
||||
class SendIdentitiesListTask: public GxsResponseTask
|
||||
{
|
||||
public:
|
||||
SendIdentitiesListTask(RsIdentity* idservice, std::list<RsGxsId> ids):
|
||||
GxsResponseTask(idservice, 0)
|
||||
SendIdentitiesListTask(RsIdentity* idservice, std::list<RsGxsId> ids, StateToken state):
|
||||
GxsResponseTask(idservice, 0), mStateToken(state)
|
||||
{
|
||||
for(std::list<RsGxsId>::iterator vit = ids.begin(); vit != ids.end(); ++vit)
|
||||
{
|
||||
requestGxsId(*vit);
|
||||
mIds.push_back(*vit);// convert fro list to vector
|
||||
mIds.push_back(*vit);// convert from list to vector
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<RsGxsId> mIds;
|
||||
StateToken mStateToken;
|
||||
protected:
|
||||
virtual void gxsDoWork(Request &req, Response &resp)
|
||||
{
|
||||
@ -35,17 +36,89 @@ protected:
|
||||
{
|
||||
streamGxsId(*vit, resp.mDataStream.getStreamToMember());
|
||||
}
|
||||
resp.mStateToken = mStateToken;
|
||||
resp.setOk();
|
||||
done();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
IdentityHandler::IdentityHandler(RsIdentity *identity):
|
||||
mRsIdentity(identity)
|
||||
class CreateIdentityTask: public GxsResponseTask
|
||||
{
|
||||
public:
|
||||
CreateIdentityTask(RsIdentity* idservice):
|
||||
GxsResponseTask(idservice, idservice->getTokenService()), mState(BEGIN), mToken(0), mRsIdentity(idservice){}
|
||||
private:
|
||||
enum State {BEGIN, WAIT_ACKN, WAIT_ID};
|
||||
State mState;
|
||||
uint32_t mToken;
|
||||
RsIdentity* mRsIdentity;
|
||||
RsGxsId mId;
|
||||
protected:
|
||||
virtual void gxsDoWork(Request &req, Response &resp)
|
||||
{
|
||||
switch(mState)
|
||||
{
|
||||
case BEGIN:{
|
||||
RsIdentityParameters params;
|
||||
req.mStream << makeKeyValueReference("name", params.nickname) << makeKeyValueReference("pgp_linked", params.isPgpLinked);
|
||||
|
||||
if(params.nickname == "")
|
||||
{
|
||||
resp.setFail("name can't be empty");
|
||||
done();
|
||||
return;
|
||||
}
|
||||
mRsIdentity->createIdentity(mToken, params);
|
||||
addWaitingToken(mToken);
|
||||
mState = WAIT_ACKN;
|
||||
break;
|
||||
}
|
||||
case WAIT_ACKN:{
|
||||
RsGxsGroupId grpId;
|
||||
if(!mRsIdentity->acknowledgeGrp(mToken, grpId))
|
||||
{
|
||||
resp.setFail("acknowledge of group id failed");
|
||||
done();
|
||||
return;
|
||||
}
|
||||
mId = RsGxsId(grpId);
|
||||
requestGxsId(mId);
|
||||
mState = WAIT_ID;
|
||||
break;
|
||||
}
|
||||
case WAIT_ID:
|
||||
streamGxsId(mId, resp.mDataStream);
|
||||
resp.setOk();
|
||||
done();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IdentityHandler::IdentityHandler(StateTokenServer *sts, RsNotify *notify, RsIdentity *identity):
|
||||
mStateTokenServer(sts), mNotify(notify), mRsIdentity(identity),
|
||||
mMtx("IdentityHandler Mtx"), mStateToken(sts->getNewToken())
|
||||
{
|
||||
mNotify->registerNotifyClient(this);
|
||||
|
||||
addResourceHandler("*", this, &IdentityHandler::handleWildcard);
|
||||
addResourceHandler("own", this, &IdentityHandler::handleOwn);
|
||||
addResourceHandler("create_identity", this, &IdentityHandler::handleCreateIdentity);
|
||||
}
|
||||
|
||||
IdentityHandler::~IdentityHandler()
|
||||
{
|
||||
mNotify->unregisterNotifyClient(this);
|
||||
}
|
||||
|
||||
void IdentityHandler::notifyGxsChange(const RsGxsChanges &changes)
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx); // ********** LOCKED **********
|
||||
// if changes come from identity service, invalidate own state token
|
||||
if(changes.mService == mRsIdentity->getTokenService())
|
||||
{
|
||||
mStateTokenServer->replaceToken(mStateToken);
|
||||
}
|
||||
}
|
||||
|
||||
void IdentityHandler::handleWildcard(Request &req, Response &resp)
|
||||
@ -54,6 +127,7 @@ void IdentityHandler::handleWildcard(Request &req, Response &resp)
|
||||
|
||||
if(req.isPut())
|
||||
{
|
||||
#ifdef REMOVE
|
||||
RsIdentityParameters params;
|
||||
req.mStream << makeKeyValueReference("name", params.nickname);
|
||||
if(req.mStream.isOK())
|
||||
@ -67,9 +141,14 @@ void IdentityHandler::handleWildcard(Request &req, Response &resp)
|
||||
{
|
||||
ok = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx); // ********** LOCKED **********
|
||||
resp.mStateToken = mStateToken;
|
||||
}
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
uint32_t token;
|
||||
@ -124,14 +203,24 @@ void IdentityHandler::handleWildcard(Request &req, Response &resp)
|
||||
}
|
||||
}
|
||||
|
||||
ResponseTask* IdentityHandler::handleOwn(Request &req, Response &resp)
|
||||
ResponseTask* IdentityHandler::handleOwn(Request & /* req */, Response &resp)
|
||||
{
|
||||
StateToken state;
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx); // ********** LOCKED **********
|
||||
state = mStateToken;
|
||||
}
|
||||
std::list<RsGxsId> ids;
|
||||
if(mRsIdentity->getOwnIds(ids))
|
||||
return new SendIdentitiesListTask(mRsIdentity, ids);
|
||||
return new SendIdentitiesListTask(mRsIdentity, ids, state);
|
||||
resp.mDataStream.getStreamToMember();
|
||||
resp.setWarning("identities not loaded yet");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ResponseTask* IdentityHandler::handleCreateIdentity(Request & /* req */, Response & /* resp */)
|
||||
{
|
||||
return new CreateIdentityTask(mRsIdentity);
|
||||
}
|
||||
|
||||
} // namespace resource_api
|
||||
|
@ -1,19 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <retroshare/rsnotify.h>
|
||||
#include <util/rsthreads.h>
|
||||
|
||||
#include "ResourceRouter.h"
|
||||
#include "StateTokenServer.h"
|
||||
|
||||
class RsIdentity;
|
||||
|
||||
namespace resource_api
|
||||
{
|
||||
|
||||
class IdentityHandler: public ResourceRouter
|
||||
class IdentityHandler: public ResourceRouter, NotifyClient
|
||||
{
|
||||
public:
|
||||
IdentityHandler(RsIdentity* identity);
|
||||
IdentityHandler(StateTokenServer* sts, RsNotify* notify, RsIdentity* identity);
|
||||
virtual ~IdentityHandler();
|
||||
|
||||
// from NotifyClient
|
||||
// note: this may get called from foreign threads
|
||||
virtual void notifyGxsChange(const RsGxsChanges &changes);
|
||||
|
||||
private:
|
||||
RsIdentity* mRsIdentity;
|
||||
void handleWildcard(Request& req, Response& resp);
|
||||
ResponseTask *handleOwn(Request& req, Response& resp);
|
||||
ResponseTask *handleCreateIdentity(Request& req, Response& resp);
|
||||
|
||||
StateTokenServer* mStateTokenServer;
|
||||
RsNotify* mNotify;
|
||||
RsIdentity* mRsIdentity;
|
||||
|
||||
RsMutex mMtx;
|
||||
StateToken mStateToken; // mutex protected
|
||||
};
|
||||
} // namespace resource_api
|
||||
|
@ -24,6 +24,7 @@ void handlePaginationRequest(Request& req, Response& resp, C& data)
|
||||
// set result type to list
|
||||
resp.mDataStream.getStreamToMember();
|
||||
resp.mDebug << "note: list is empty" << std::endl;
|
||||
resp.setOk();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ PeersHandler::~PeersHandler()
|
||||
mStateTokenServer->unregisterTickClient(this);
|
||||
}
|
||||
|
||||
void PeersHandler::notifyListChange(int list, int type)
|
||||
void PeersHandler::notifyListChange(int list, int /* type */)
|
||||
{
|
||||
RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/
|
||||
if(list == NOTIFY_LIST_FRIENDS)
|
||||
@ -193,6 +193,8 @@ void PeersHandler::handleWildcard(Request &req, Response &resp)
|
||||
ok &= mRsPeers->getPeerDetails(*lit, details);
|
||||
detailsVec.push_back(details);
|
||||
}
|
||||
// mark response as list, in case it is empty
|
||||
resp.mDataStream.getStreamToMember();
|
||||
for(std::list<RsPgpId>::iterator lit = identities.begin(); lit != identities.end(); ++lit)
|
||||
{
|
||||
// if no own ssl id is known, then hide the own id from the friendslist
|
||||
|
@ -12,7 +12,7 @@ public:
|
||||
{
|
||||
addResourceHandler("eins", this, &TestResource::eins);
|
||||
}
|
||||
ResponseTask* eins(Request& req, Response& resp)
|
||||
ResponseTask* eins(Request& /* req */, Response& /* resp */)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ RsControlModule::RsControlModule(int argc, char **argv, StateTokenServer* sts, A
|
||||
this->argv = argv;
|
||||
// start worker thread
|
||||
if(full_control)
|
||||
start();
|
||||
start("resapi ctrl mod");
|
||||
else
|
||||
mRunState = RUNNING_OK_NO_FULL_CONTROL;
|
||||
|
||||
@ -55,7 +55,7 @@ bool RsControlModule::processShouldExit()
|
||||
return mProcessShouldExit;
|
||||
}
|
||||
|
||||
bool RsControlModule::askForPassword(const std::string &key_details, bool prev_is_bad, std::string &password, bool& cancelled)
|
||||
bool RsControlModule::askForPassword(const std::string &key_details, bool /* prev_is_bad */, std::string &password, bool& cancelled)
|
||||
{
|
||||
cancelled = false ;
|
||||
{
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "Operators.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace resource_api
|
||||
{
|
||||
// maybe move to another place later
|
||||
@ -44,6 +46,7 @@ ServiceControlHandler::ServiceControlHandler(RsServiceControl* control):
|
||||
mRsServiceControl(control)
|
||||
{
|
||||
addResourceHandler("*", this, &ServiceControlHandler::handleWildcard);
|
||||
addResourceHandler("user", this, &ServiceControlHandler::handleUser);
|
||||
}
|
||||
|
||||
void ServiceControlHandler::handleWildcard(Request &req, Response &resp)
|
||||
@ -73,7 +76,42 @@ void ServiceControlHandler::handleWildcard(Request &req, Response &resp)
|
||||
}
|
||||
else if(req.isPut())
|
||||
{
|
||||
// change service default
|
||||
|
||||
std::string serviceidtext;
|
||||
bool enabled;
|
||||
|
||||
req.mStream << makeKeyValueReference("service_id", serviceidtext)
|
||||
<< makeKeyValueReference("default_allowed", enabled);
|
||||
|
||||
RsServicePermissions serv_perms ;
|
||||
//uint32_t serviceid = fromString<uint32_t>(serviceidtext);
|
||||
uint32_t serviceid = atoi(serviceidtext.c_str());
|
||||
if (serviceid == 0) {
|
||||
resp.setFail("service_id missed");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!rsServiceControl->getServicePermissions(serviceid, serv_perms)){
|
||||
resp.setFail("service_id " + serviceidtext + " is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
serv_perms.mDefaultAllowed = enabled;
|
||||
if(serv_perms.mDefaultAllowed)
|
||||
{
|
||||
serv_perms.mPeersDenied.clear() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
serv_perms.mPeersAllowed.clear() ;
|
||||
}
|
||||
|
||||
ok = rsServiceControl->updateServicePermissions(serviceid,serv_perms);
|
||||
if (!ok) {
|
||||
resp.setFail("updateServicePermissions failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ok)
|
||||
@ -86,4 +124,62 @@ void ServiceControlHandler::handleWildcard(Request &req, Response &resp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ServiceControlHandler::handleUser(Request& req, Response& resp){
|
||||
// no get, only put (post) to allow user or delete to remove user
|
||||
|
||||
std::string serviceidtext;
|
||||
std::string peeridtext;
|
||||
bool enabled;
|
||||
bool ok;
|
||||
|
||||
req.mStream << makeKeyValueReference("service_id", serviceidtext)
|
||||
<< makeKeyValueReference("peer_id", peeridtext)
|
||||
<< makeKeyValueReference("enabled", enabled);
|
||||
|
||||
RsPeerId peer_id(peeridtext);
|
||||
|
||||
if (peer_id.isNull()) {
|
||||
resp.setFail("peer_id missing or not found");
|
||||
return;
|
||||
}
|
||||
|
||||
RsServicePermissions serv_perms ;
|
||||
uint32_t serviceid = atoi(serviceidtext.c_str());
|
||||
if (serviceid == 0) {
|
||||
resp.setFail("service_id missed");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!rsServiceControl->getServicePermissions(serviceid, serv_perms)){
|
||||
resp.setFail("service_id " + serviceidtext + " is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
if(req.isPut())
|
||||
{
|
||||
if (enabled && !serv_perms.peerHasPermission(peer_id))
|
||||
{
|
||||
serv_perms.setPermission(peer_id);
|
||||
} else if (!enabled && serv_perms.peerHasPermission(peer_id)){
|
||||
serv_perms.resetPermission(peer_id);
|
||||
} else {
|
||||
//nothing todo
|
||||
resp.setOk();
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
resp.setFail("only POST supported.");
|
||||
return;
|
||||
}
|
||||
ok = rsServiceControl->updateServicePermissions(serviceid,serv_perms);
|
||||
if (!ok) {
|
||||
resp.setFail("updateServicePermissions failed");
|
||||
return;
|
||||
}
|
||||
|
||||
resp.setOk();
|
||||
}
|
||||
|
||||
} // namespace resource_api
|
||||
|
@ -16,5 +16,6 @@ public:
|
||||
private:
|
||||
RsServiceControl* mRsServiceControl;
|
||||
void handleWildcard(Request& req, Response& resp);
|
||||
void handleUser(Request& req, Response& resp);
|
||||
};
|
||||
} // namespace resource_api
|
||||
|
@ -114,6 +114,7 @@ void StateTokenServer::handleWildcard(Request &req, Response &resp)
|
||||
RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/
|
||||
// want to lookpup many tokens at once, return a list of invalid tokens
|
||||
// TODO: make generic list serialiser/deserialiser
|
||||
resp.mDataStream.getStreamToMember();
|
||||
while(req.mStream.hasMore())
|
||||
{
|
||||
StateToken token;
|
||||
|
@ -42,7 +42,7 @@ void TransfersHandler::tick()
|
||||
}
|
||||
}
|
||||
|
||||
void TransfersHandler::handleWildcard(Request &req, Response &resp)
|
||||
void TransfersHandler::handleWildcard(Request & /*req*/, Response & /*resp*/)
|
||||
{
|
||||
|
||||
}
|
||||
@ -108,7 +108,7 @@ void TransfersHandler::handleControlDownload(Request &req, Response &resp)
|
||||
resp.setFail("error: action not handled");
|
||||
}
|
||||
|
||||
void TransfersHandler::handleDownloads(Request &req, Response &resp)
|
||||
void TransfersHandler::handleDownloads(Request & /* req */, Response &resp)
|
||||
{
|
||||
tick();
|
||||
resp.mStateToken = mStateToken;
|
||||
|
@ -525,7 +525,7 @@ std::string SerializeValue(const Value& v)
|
||||
// json expets decimal points, so replace all commas with decimal points
|
||||
if(v.GetType() == FloatVal || v.GetType() == DoubleVal)
|
||||
{
|
||||
for(int i = 0; i < str.size(); i++)
|
||||
for(unsigned int i = 0; i < str.size(); i++)
|
||||
if(str[i] == ',')
|
||||
str[i] = '.';
|
||||
}
|
||||
|
@ -13,18 +13,97 @@ CONFIG += libmicrohttpd
|
||||
INCLUDEPATH += ../../libretroshare/src
|
||||
|
||||
unix {
|
||||
webui_files.path = "$${DATA_DIR}/webui"
|
||||
webui_files.files = webfiles/*
|
||||
INSTALLS += webui_files
|
||||
|
||||
webui_img_files.path = "$${DATA_DIR}/webui/img"
|
||||
webui_img_files.files = ../../retroshare-gui/src/gui/images/logo/logo_splash.png
|
||||
INSTALLS += webui_img_files
|
||||
webui_files.path = "$${DATA_DIR}/webui"
|
||||
webui_files.files = webui/app.js webui/app.css webui/index.html
|
||||
INSTALLS += webui_files
|
||||
|
||||
webui_img_files.path = "$${DATA_DIR}/webui/img"
|
||||
webui_img_files.files = ../../retroshare-gui/src/gui/images/logo/logo_splash.png
|
||||
INSTALLS += webui_img_files
|
||||
|
||||
# create dummy files, we need it to include files on first try
|
||||
system(webui-src/make-src/build.sh .)
|
||||
|
||||
WEBUI_SRC_SCRIPT = webui-src/make-src/build.sh
|
||||
|
||||
WEBUI_SRC_HTML = $$WEBUI_SRC_SCRIPT
|
||||
WEBUI_SRC_HTML += webui-src/app/assets/index.html
|
||||
|
||||
WEBUI_SRC_JS = $$WEBUI_SRC_SCRIPT
|
||||
WEBUI_SRC_JS += webui-src/app/accountselect.js
|
||||
WEBUI_SRC_JS += webui-src/app/adddownloads.js
|
||||
WEBUI_SRC_JS += webui-src/app/addidentity.js
|
||||
WEBUI_SRC_JS += webui-src/app/addpeer.js
|
||||
WEBUI_SRC_JS += webui-src/app/chat.js
|
||||
WEBUI_SRC_JS += webui-src/app/createlogin.js
|
||||
WEBUI_SRC_JS += webui-src/app/downloads.js
|
||||
WEBUI_SRC_JS += webui-src/app/forums.js
|
||||
WEBUI_SRC_JS += webui-src/app/home.js
|
||||
WEBUI_SRC_JS += webui-src/app/identities.js
|
||||
WEBUI_SRC_JS += webui-src/app/main.js
|
||||
WEBUI_SRC_JS += webui-src/app/menudef.js
|
||||
WEBUI_SRC_JS += webui-src/app/menu.js
|
||||
WEBUI_SRC_JS += webui-src/app/mithril.js
|
||||
WEBUI_SRC_JS += webui-src/app/mithril.min.js
|
||||
WEBUI_SRC_JS += webui-src/app/peers.js
|
||||
WEBUI_SRC_JS += webui-src/app/retroshare.js
|
||||
WEBUI_SRC_JS += webui-src/app/search.js
|
||||
WEBUI_SRC_JS += webui-src/app/searchresult.js
|
||||
WEBUI_SRC_JS += webui-src/app/servicecontrol.js
|
||||
WEBUI_SRC_JS += webui-src/app/settings.js
|
||||
WEBUI_SRC_JS += webui-src/app/waiting.js
|
||||
|
||||
WEBUI_SRC_CSS = $$WEBUI_SRC_SCRIPT
|
||||
WEBUI_SRC_CSS += webui-src/app/green-black.scss
|
||||
WEBUI_SRC_CSS += webui-src/app/_reset.scss
|
||||
WEBUI_SRC_CSS += webui-src/app/_chat.sass
|
||||
WEBUI_SRC_CSS += webui-src/app/main.sass
|
||||
|
||||
|
||||
create_webfiles_html.output = webui/index.html
|
||||
create_webfiles_html.input = WEBUI_SRC_HTML
|
||||
create_webfiles_html.commands = sh $$_PRO_FILE_PWD_/webui-src/make-src/build.sh $$_PRO_FILE_PWD_ index.html .
|
||||
create_webfiles_html.variable_out = JUNK
|
||||
create_webfiles_html.CONFIG = combine no_link
|
||||
|
||||
create_webfiles_js.output = webui/app.js
|
||||
create_webfiles_js.input = WEBUI_SRC_JS
|
||||
create_webfiles_js.commands = sh $$_PRO_FILE_PWD_/webui-src/make-src/build.sh $$_PRO_FILE_PWD_ app.js .
|
||||
create_webfiles_js.variable_out = JUNK
|
||||
create_webfiles_js.CONFIG = combine no_link
|
||||
|
||||
create_webfiles_css.output = webui/app.css
|
||||
create_webfiles_css.input = WEBUI_SRC_CSS
|
||||
create_webfiles_css.commands = sh $$_PRO_FILE_PWD_/webui-src/make-src/build.sh $$_PRO_FILE_PWD_ app.css .
|
||||
create_webfiles_css.variable_out = JUNK
|
||||
create_webfiles_css.CONFIG = combine no_link
|
||||
|
||||
|
||||
QMAKE_EXTRA_COMPILERS += create_webfiles_html create_webfiles_js create_webfiles_css
|
||||
}
|
||||
|
||||
win32{
|
||||
DEFINES *= WINDOWS_SYS
|
||||
INCLUDEPATH += . $$INC_DIR
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
# Qt 5
|
||||
PRO_PATH=$$shell_path($$_PRO_FILE_PWD_)
|
||||
MAKE_SRC=$$shell_path($$PRO_PATH/webui-src/make-src)
|
||||
} else {
|
||||
# Qt 4
|
||||
PRO_PATH=$$replace(_PRO_FILE_PWD_, /, \\)
|
||||
MAKE_SRC=$$PRO_PATH\\webui-src\\make-src
|
||||
}
|
||||
|
||||
#create_webfiles.commands = $$MAKE_SRC\\build.bat $$PRO_PATH
|
||||
#QMAKE_EXTRA_TARGETS += create_webfiles
|
||||
#PRE_TARGETDEPS += create_webfiles
|
||||
QMAKE_POST_LINK=$$MAKE_SRC\\build.bat $$PRO_PATH
|
||||
|
||||
# create dummy files
|
||||
system($$MAKE_SRC\\init.bat .)
|
||||
}
|
||||
|
||||
libmicrohttpd{
|
||||
@ -66,7 +145,8 @@ SOURCES += \
|
||||
api/LivereloadHandler.cpp \
|
||||
api/TmpBlobStore.cpp \
|
||||
util/ContentTypes.cpp \
|
||||
api/ApiPluginHandler.cpp
|
||||
api/ApiPluginHandler.cpp \
|
||||
api/ChannelsHandler.cpp
|
||||
|
||||
HEADERS += \
|
||||
api/ApiServer.h \
|
||||
@ -91,4 +171,5 @@ HEADERS += \
|
||||
api/LivereloadHandler.h \
|
||||
api/TmpBlobStore.h \
|
||||
util/ContentTypes.h \
|
||||
api/ApiPluginHandler.h
|
||||
api/ApiPluginHandler.h \
|
||||
api/ChannelsHandler.h
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,109 +0,0 @@
|
||||
/**
|
||||
* JS Api for Retroshare
|
||||
* @constructor
|
||||
* @param {object} connection - an object which implements a request() function.
|
||||
* The request function should take two parameters: an object to be send as request and a callback.
|
||||
* The callback should get called with an response object on success.
|
||||
*/
|
||||
function RsApi(connection)
|
||||
{
|
||||
var runnign = true;
|
||||
/**
|
||||
* Send a request to the server
|
||||
* @param req - the request so send
|
||||
* @param {Function} cb - callback function which takes the response as parameter
|
||||
*/
|
||||
this.request = function(req, cb)
|
||||
{
|
||||
connection.request(req, cb);
|
||||
};
|
||||
var tokenlisteners = [];
|
||||
/**
|
||||
* Register a callback to be called when the state token expired.
|
||||
* @param {Function} listener - the callback function, which does not take arguments
|
||||
* @param token - the state token to listen for
|
||||
*/
|
||||
this.register_token_listener = function(listener, token)
|
||||
{
|
||||
tokenlisteners.push({listener:listener, token:token});
|
||||
};
|
||||
/**
|
||||
* Unregister a previously registered callback.
|
||||
*/
|
||||
this.unregister_token_listener = function(listener) // no token as parameter, assuming unregister from all listening tokens
|
||||
{
|
||||
var to_delete = [];
|
||||
for(var i=0; i<tokenlisteners.length; i++){
|
||||
if(tokenlisteners[i].listener === listener){
|
||||
to_delete.push(i);
|
||||
}
|
||||
}
|
||||
for(var i=0; i<to_delete.length; i++){
|
||||
// copy the last element to the current index
|
||||
var index = to_delete[i];
|
||||
tokenlisteners[index] = tokenlisteners[tokenlisteners.length-1];
|
||||
// remove last element
|
||||
tokenlisteners.pop();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* start polling for state changes
|
||||
*/
|
||||
this.start = function(){
|
||||
running = true;
|
||||
setTimeout(tick, TICK_INTERVAL);
|
||||
}
|
||||
/**
|
||||
* stop polling for state changes
|
||||
*/
|
||||
this.stop = function(){
|
||||
running = false;
|
||||
}
|
||||
|
||||
// ************** interal stuff **************
|
||||
var TICK_INTERVAL = 3000;
|
||||
function received_tokenstates(resp)
|
||||
{
|
||||
if(resp.data){
|
||||
for(var i=0; i<resp.data.length; i++){
|
||||
var token = resp.data[i];
|
||||
// search the listener for this token
|
||||
for(var j=0; j<tokenlisteners.length; j++){
|
||||
if(tokenlisteners[j].token === token){
|
||||
// call the listener
|
||||
tokenlisteners[j].listener();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// schedule new update
|
||||
if(running)
|
||||
setTimeout(tick, TICK_INTERVAL);
|
||||
};
|
||||
function received_error()
|
||||
{
|
||||
// try again, maybe want a better logic later
|
||||
if(running)
|
||||
setTimeout(tick, TICK_INTERVAL);
|
||||
};
|
||||
function tick()
|
||||
{
|
||||
var data = [];
|
||||
// maybe cache the token list?
|
||||
// profiler will tell us if we should
|
||||
for(var i=0; i<tokenlisteners.length; i++){
|
||||
data.push(tokenlisteners[i].token);
|
||||
}
|
||||
connection.request({
|
||||
path: "statetokenservice",
|
||||
data: data,
|
||||
}, received_tokenstates, received_error);
|
||||
};
|
||||
};
|
||||
|
||||
// with this trick, we should be able to run in browser or nodejs
|
||||
if(typeof window === 'undefined')
|
||||
{
|
||||
// we are running in nodejs, so have to add to export
|
||||
module.exports = RsApi;
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
/**
|
||||
* Connection to the RS backend using XHR
|
||||
* (could add other connections later, for example WebSockets)
|
||||
* @constructor
|
||||
*/
|
||||
function RsXHRConnection(server_hostname, server_port)
|
||||
{
|
||||
var debug;
|
||||
//debug = function(str){console.log(str);};
|
||||
debug = function(str){};
|
||||
|
||||
//server_hostname = "localhost";
|
||||
//server_port = "9090";
|
||||
var api_root_path = "/api/v2/";
|
||||
|
||||
var status_listeners = [];
|
||||
|
||||
function notify_status(status)
|
||||
{
|
||||
for(var i = 0; i < status_listeners.length; i++)
|
||||
{
|
||||
status_listeners[i](status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be called when the state of the connection changes.
|
||||
* @param {function} cb - callback which receives a single argument. The arguments value is "connected" or "not_connected".
|
||||
*/
|
||||
this.register_status_listener = function(cb)
|
||||
{
|
||||
status_listeners.push(cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* Unregister a status callback function.
|
||||
* @param {function} cb - a privously registered callback function
|
||||
*/
|
||||
this.unregister_status_listener = function(cb)
|
||||
{
|
||||
var to_delete = [];
|
||||
for(var i = 0; i < status_listeners.length; i++)
|
||||
{
|
||||
if(status_listeners[i] === cb){
|
||||
to_delete.push(i);
|
||||
}
|
||||
}
|
||||
for(var i = 0; i < to_delete.length; i++)
|
||||
{
|
||||
// copy the last element to the current index
|
||||
var index = to_delete[i];
|
||||
status_listeners[i] = status_listeners[status_listeners.length-1];
|
||||
// remove the last element
|
||||
status_listeners.pop();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a request to the backend
|
||||
* automatically encodes the request as JSON before sending it to the server
|
||||
* @param {object} req - the request to send to the server
|
||||
* @param {function} cb - callback function to be called to handle the response. The callback takes one object as parameter. Can be left undefined.
|
||||
* @param {function} err_cb - callback function to signal a failed request. Can be undefined.
|
||||
*/
|
||||
this.request = function(req, cb, err_cb)
|
||||
{
|
||||
//var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
|
||||
// TODO: window is not available in QML
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function(){
|
||||
//console.log("onreadystatechanged state"+xhr.readyState);
|
||||
// TODO: figure out how to catch errors like connection refused
|
||||
// maybe want to have to set a state variable like ok=false
|
||||
// the gui could then display: "no connection to server"
|
||||
if (xhr.readyState === 4) {
|
||||
if(xhr.status !== 200)
|
||||
{
|
||||
console.log("RsXHRConnection: request failed with status: "+xhr.status);
|
||||
console.log("request was:");
|
||||
console.log(req);
|
||||
notify_status("not_connected");
|
||||
if(err_cb !== undefined)
|
||||
err_cb();
|
||||
return;
|
||||
}
|
||||
// received response
|
||||
notify_status("connected");
|
||||
debug("RsXHRConnection received response:");
|
||||
debug(xhr.responseText);
|
||||
if(false)//if(xhr.responseText === "")
|
||||
{
|
||||
debug("Warning: response is empty");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var respObj = JSON.parse(xhr.responseText);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
debug("Exception during response handling: "+e);
|
||||
}
|
||||
if(cb === undefined)
|
||||
debug("No callback function specified");
|
||||
else
|
||||
cb(respObj);
|
||||
}
|
||||
}
|
||||
// post is required for sending data
|
||||
var method;
|
||||
if(req.data){
|
||||
method = "POST";
|
||||
} else {
|
||||
method = "GET";
|
||||
}
|
||||
xhr.open(method, "http://"+server_hostname+":"+server_port+api_root_path+req.path);
|
||||
var data = JSON.stringify(req.data);
|
||||
debug("RsXHRConnection sending data:");
|
||||
debug(data);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(data);
|
||||
};
|
||||
};
|
@ -1,134 +0,0 @@
|
||||
body {
|
||||
background-color: black;
|
||||
color: lime;
|
||||
font-family: monospace;
|
||||
margin: 0em;
|
||||
/*padding: 1.5em;*/
|
||||
padding: 2mm;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
#overlay{
|
||||
z-index: 10;
|
||||
position: fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
}
|
||||
|
||||
.paddingbox{
|
||||
padding:2mm;
|
||||
}
|
||||
|
||||
.nav{
|
||||
list-style-type: none;
|
||||
padding: 0em;
|
||||
margin: 0em;
|
||||
}
|
||||
|
||||
.nav li{
|
||||
display: inline;
|
||||
padding: 0.1em;
|
||||
margin-right: 1em;
|
||||
border-width: 0.1em;
|
||||
border-color: blue;
|
||||
border-bottom-style: solid;
|
||||
cursor: pointer;
|
||||
}
|
||||
td{
|
||||
padding: 0.3em;
|
||||
border-style: solid;
|
||||
border-width: 0.1em;
|
||||
border-color: lime;
|
||||
}
|
||||
.btn{
|
||||
border-style: solid;
|
||||
border-color: lime;
|
||||
border-width: 0.1em;
|
||||
cursor: pointer;
|
||||
padding: 0.1em;
|
||||
}
|
||||
|
||||
.btn2, .box{
|
||||
border-style: solid;
|
||||
/*border-color: lime;*/
|
||||
border-color: limeGreen;
|
||||
/*border-width: 1px;*/
|
||||
border-radius: 3mm;
|
||||
padding: 2mm;
|
||||
font-size: 10mm;
|
||||
cursor: pointer;
|
||||
margin-bottom: 2mm;
|
||||
}
|
||||
.btn2:hover{
|
||||
background-color: midnightblue;
|
||||
}
|
||||
|
||||
.filelink{
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
input, textarea{
|
||||
color: lime;
|
||||
font-family: monospace;
|
||||
background-color: black;
|
||||
border-color: lime;
|
||||
font-size: 10mm;
|
||||
border-radius: 3mm;
|
||||
border-width: 1mm;
|
||||
padding: 2mm;
|
||||
margin-bottom: 2mm;
|
||||
margin-right: 2mm;
|
||||
|
||||
/* make the button the whole screen width */
|
||||
width: 100%;
|
||||
/* make the text input fit small screens*/
|
||||
box-sizing: border-box;
|
||||
}
|
||||
input:hover{
|
||||
background-color: midnightblue;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.flexbox{
|
||||
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
||||
display: -ms-flexbox; /* TWEENER - IE 10 */
|
||||
display: -webkit-flex; /* NEW - Chrome */
|
||||
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||
}
|
||||
|
||||
.flexwidemember{
|
||||
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
-moz-box-flex: 1; /* OLD - Firefox 19- */
|
||||
width: 20%; /* For old syntax, otherwise collapses. */
|
||||
-webkit-flex: 1; /* Chrome */
|
||||
-ms-flex: 1; /* IE 10 */
|
||||
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||
}
|
||||
|
||||
#logo_splash{
|
||||
-webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
|
||||
animation-fill-mode: forwards;
|
||||
-webkit-animation-name: logo_splash; /* Chrome, Safari, Opera */
|
||||
-webkit-animation-duration: 3s; /* Chrome, Safari, Opera */
|
||||
animation-name: logo_splash;
|
||||
animation-duration: 3s;
|
||||
text-align: center;
|
||||
}
|
||||
/* Chrome, Safari, Opera */
|
||||
@-webkit-keyframes logo_splash {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
||||
|
||||
/* Standard syntax */
|
||||
@keyframes logo_splash {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,29 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>New webinterface for Retroshare</title>
|
||||
|
||||
<script src="RsXHRConnection.js"></script>
|
||||
<script src="RsApi.js"></script>
|
||||
|
||||
<!-- it seems to work more reliable, if the jsx file is loaded before react -->
|
||||
<script type="text/jsx" src="gui.jsx"></script>
|
||||
|
||||
<script src="react.js"></script>
|
||||
<script src="JSXTransformer.js"></script>
|
||||
|
||||
<link href="green-black.css" rel="stylesheet">
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
document.write("<p>loading lots of stuff...</p>");
|
||||
</script>
|
||||
<p><noscript>The Retroshare web interface requires JavaScript. Please enable JavaScript in your browser.</noscript></p>
|
||||
<!--<div id="logo_splash">
|
||||
<img src="img/logo_splash.png"></img>
|
||||
</div>-->
|
||||
</body>
|
||||
</html>
|
19541
libresapi/src/webfiles/react.js
vendored
19541
libresapi/src/webfiles/react.js
vendored
File diff suppressed because it is too large
Load Diff
2
libresapi/src/webui-src/.gitignore
vendored
Normal file
2
libresapi/src/webui-src/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
node_modules/*
|
||||
public/*
|
78
libresapi/src/webui-src/README.md
Normal file
78
libresapi/src/webui-src/README.md
Normal file
@ -0,0 +1,78 @@
|
||||
A new approach to build a webinterface for RS
|
||||
=============================================
|
||||
|
||||
1. get JSON encoded data from the backend, data contains a state token
|
||||
2. render data with mithril.js
|
||||
3. ask the backend if the state token from step 1 expired. If yes, then start again with step 1.
|
||||
|
||||
Steps 1. and 3. are common for most things, only Step 2. differs. This allows to re-use code for steps 1. and 3.
|
||||
|
||||
BUILD / DEVELOPMENT
|
||||
------------
|
||||
|
||||
- install tools
|
||||
sudo apt-get install TODO (insert package names for nodejs, ruby, sass here)
|
||||
- run this once in webui-src directory, to install more tools
|
||||
npm install
|
||||
- start build
|
||||
npm run watch
|
||||
- the build process watches files for changes, and rebuilds and reloads the page. Build output is in ./public
|
||||
- use the --webinterface 9090 command line parameter to enable webui in retroshare-nogui
|
||||
- set the --docroot parameter of retroshare-nogui to point to the "libresapi/src/webui-src/public" directory
|
||||
(or symlink from /usr/share/RetroShare06/webui on Linux, ./webui on Windows)
|
||||
- retroshare-gui does not have a --docroot parameter. Use symlinks then.
|
||||
|
||||
CONTRIBUTE
|
||||
----------
|
||||
|
||||
- if you are a web developer or want to become one
|
||||
get in contact!
|
||||
- lots of work to do, i need you!
|
||||
|
||||
TODO
|
||||
----
|
||||
[ ] make stylesheets or find reusable sass/css components
|
||||
google material design has nice rules for color, spacing and everything: https://www.google.de/design/spec/material-design/introduction.html
|
||||
[ ] find icons, maybe use google material design iconfont
|
||||
[X] use urls/mithril routing for the menu. urls could replace state stored in rs.content
|
||||
[X] drag and drop private key upload and import
|
||||
[X] link from peer location to chat (use urls and mithril routing)
|
||||
[X] add/remove friend, own cert
|
||||
[X] downloads, search
|
||||
[ ] make reusable infinite list controller, the js part to load data from Pagination.h (tweak Pagination.h to make everything work)
|
||||
should provide forward, backward and follow-list-end
|
||||
[ ] backend: view/create identities
|
||||
[ ] backend: chat lobby participants list
|
||||
[X] chat: send_message
|
||||
[ ] backend: chat typing notifications
|
||||
[ ] make routines to handle retroshare links
|
||||
[ ] backend: edit shared folders
|
||||
[ ] backend: view shared files
|
||||
[ ] redirect if a url is not usable in the current runstate (e.g. redirect from login page to home page, after login)
|
||||
[X] sort friendslist
|
||||
|
||||
need 4 master
|
||||
-------------
|
||||
[X] unsubscribe lobby
|
||||
[X] unread chat message counter in menu
|
||||
[X] list chat-lobby participants
|
||||
[X] creating app.js on build (no need for npm on regulary build)
|
||||
|
||||
url-handling (brainstorming)
|
||||
----------------------------
|
||||
* normal weblinks (bbcode? => only with gui support)
|
||||
* rslinks
|
||||
- files
|
||||
- (chatrooms)
|
||||
- forum retroshare://forum?name=Developers%27%20Discussions&id=8fd22bd8f99754461e7ba1ca8a727995
|
||||
- own cert link (paste)
|
||||
- cert-links
|
||||
- searches
|
||||
- [X] downloads pasten
|
||||
- uploads?
|
||||
* enter / display urls
|
||||
- use urls in href like used for input (so it can be copy-link)
|
||||
- handle RS-urls with javascript, other with target _blank
|
||||
* smilies
|
||||
* Bilder
|
||||
* KEEP IT SIMPLE
|
81
libresapi/src/webui-src/app/_chat.sass
Normal file
81
libresapi/src/webui-src/app/_chat.sass
Normal file
@ -0,0 +1,81 @@
|
||||
.chat
|
||||
$color: black
|
||||
$header_height: 50px
|
||||
$left_width: 200px
|
||||
$right_width: 200px
|
||||
$input_height: 100px
|
||||
padding: 15px
|
||||
&.container
|
||||
height: 100%
|
||||
padding: 0px
|
||||
position: relative
|
||||
box-sizing: border-box
|
||||
&.header
|
||||
position: absolute
|
||||
top: 0px
|
||||
left: 0px
|
||||
right: 0px
|
||||
height: $header_height
|
||||
background-color: $color
|
||||
border-bottom: solid 1px gray
|
||||
box-sizing: border-box
|
||||
&.left
|
||||
position: absolute
|
||||
top: $header_height
|
||||
bottom: 0px
|
||||
left: 0px
|
||||
width: $left_width
|
||||
//border-right: solid 1px gray
|
||||
box-sizing: border-box
|
||||
background-color: black
|
||||
&.right
|
||||
position: absolute
|
||||
top: $header_height
|
||||
right: 0px
|
||||
bottom: 0px
|
||||
width: $right_width
|
||||
box-sizing: border-box
|
||||
//border-left: solid 1px gray
|
||||
&.middle
|
||||
//background-color: blue
|
||||
position: absolute
|
||||
top: 0px
|
||||
margin-top: $header_height
|
||||
left: $left_width
|
||||
right: $right_width
|
||||
box-sizing: border-box
|
||||
padding: 0px
|
||||
height: 100%
|
||||
overflow-y: scroll
|
||||
&.bottom
|
||||
position: absolute
|
||||
bottom: 0px
|
||||
right: $right_width
|
||||
left: $left_width
|
||||
padding: 5px
|
||||
&.msg
|
||||
padding: 0px
|
||||
$author_width: 100px
|
||||
&.container
|
||||
position: relative
|
||||
border-bottom: solid 1px lightgray
|
||||
padding: 10px
|
||||
height: unset
|
||||
//background-color: lime
|
||||
&.from
|
||||
position: absolute
|
||||
width: $author_width
|
||||
top: 10px
|
||||
left: 0px
|
||||
color: white
|
||||
text-align: right
|
||||
&.when
|
||||
float: right
|
||||
color: lightgray
|
||||
margin-bottom: 10px
|
||||
&.text
|
||||
padding-left: $author_width
|
||||
top: 0px
|
||||
left: $author_width
|
||||
white-space: pre-wrap
|
||||
height: initial
|
48
libresapi/src/webui-src/app/_reset.scss
Normal file
48
libresapi/src/webui-src/app/_reset.scss
Normal file
@ -0,0 +1,48 @@
|
||||
/* http://meyerweb.com/eric/tools/css/reset/
|
||||
v2.0 | 20110126
|
||||
License: none (public domain)
|
||||
*/
|
||||
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
68
libresapi/src/webui-src/app/accountselect.js
Normal file
68
libresapi/src/webui-src/app/accountselect.js
Normal file
@ -0,0 +1,68 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
function cancel(){
|
||||
rs.memory("control/locations").curraccount=null;
|
||||
m.redraw();
|
||||
}
|
||||
|
||||
function selAccount(account){
|
||||
rs.memory("control/locations").curraccount=account;
|
||||
m.redraw();
|
||||
rs.request("control/login", {id: account.id}, function(){
|
||||
console.log("login sent");
|
||||
});
|
||||
}
|
||||
|
||||
function curraccount() {
|
||||
var mem;
|
||||
mem = rs.memory("control/locations");
|
||||
if (mem.curraccount === undefined) {
|
||||
return null;
|
||||
}
|
||||
return mem.curraccount;
|
||||
}
|
||||
|
||||
module.exports = {view: function(){
|
||||
var accounts = rs("control/locations");
|
||||
if(accounts === undefined || accounts == null){
|
||||
return m("div", "accounts: waiting_server");
|
||||
}
|
||||
if (curraccount() == null) {
|
||||
return m("div", [
|
||||
m("h2","login:"),
|
||||
m("hr"),
|
||||
accounts.map(function(account){
|
||||
return [
|
||||
m("div.btn2", {
|
||||
onclick: function(){
|
||||
selAccount(account)
|
||||
}
|
||||
},
|
||||
account.location + " (" + account.name + ")"),
|
||||
m("br")
|
||||
]
|
||||
})
|
||||
]);
|
||||
} else {
|
||||
// rs.untoken("control/password");
|
||||
return m("div", [
|
||||
m("div", [
|
||||
"logging in ...",
|
||||
m("br"),
|
||||
"(waiting for password-request)",
|
||||
]),
|
||||
/*
|
||||
m("hr"),
|
||||
m(".btn2", {
|
||||
onclick: function() {
|
||||
cancel();
|
||||
}
|
||||
},"Cancel " + curraccount().name + " login "),
|
||||
*/
|
||||
]);
|
||||
}
|
||||
}
|
||||
};
|
299
libresapi/src/webui-src/app/adddownloads.js
Normal file
299
libresapi/src/webui-src/app/adddownloads.js
Normal file
@ -0,0 +1,299 @@
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
var me = {
|
||||
toParse: [], // links to parse ( = pasted content)
|
||||
toConfirm: [], // links to confirm
|
||||
toAdd: [], // links to add
|
||||
toResult: [], // Result to show
|
||||
index: 0,
|
||||
view: function(){
|
||||
return m("div", {
|
||||
style: {
|
||||
height:"100%",
|
||||
boxSizing: "border-box",
|
||||
paddingBottom: "130px",
|
||||
}
|
||||
},[
|
||||
m("h2","add downloads"),
|
||||
m("hr"),
|
||||
this.toParse.length
|
||||
? step2()
|
||||
: this.toConfirm.length
|
||||
? step3()
|
||||
: this.toAdd.length
|
||||
? step4()
|
||||
: this.toResult.length
|
||||
? step5()
|
||||
: step1()
|
||||
,
|
||||
]);
|
||||
},
|
||||
parseOne: function(){
|
||||
if (me.index == null) {
|
||||
return null;
|
||||
}
|
||||
var startindex = me.index;
|
||||
while (me.toParse.length > me.index && me.index - startindex < 10) {
|
||||
var src = me.toParse[me.index].split("?",2);
|
||||
console.log(src);
|
||||
if (src[0] == "retroshare://file" && src.length == 2) {
|
||||
var target = {action: "begin"};
|
||||
var errText = "Error: link missing name and/or hash"
|
||||
src[1].split("&").map(function(parm){
|
||||
var pos = parm.indexOf("=");
|
||||
if (pos >0){
|
||||
if (parm.substr(0,pos) == "name") {
|
||||
var sname=decodeURIComponent(parm.substr(pos+1))
|
||||
if (sname.match("[\\\\/]")) {
|
||||
errText="name contains illegal char "
|
||||
+ sname.match("[\\\\/]");
|
||||
} else {
|
||||
target.name=sname;
|
||||
}
|
||||
} else if (parm.substr(0,pos) == "size") {
|
||||
target.size=parseFloat(parm.substr(pos+1));
|
||||
} else if (parm.substr(0,pos) == "hash") {
|
||||
target.hash=parm.substr(pos+1);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (target['name'] && target['hash']){
|
||||
me.toConfirm.push({
|
||||
text: target.name,
|
||||
target: target,
|
||||
confirmed: true,
|
||||
});
|
||||
} else {
|
||||
me.toConfirm.push({
|
||||
text:errText,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
me.toConfirm.push({ text: "Error: no Retroshare-file link"})
|
||||
}
|
||||
me.index++;
|
||||
}
|
||||
if (me.toParse.length > me.index) {
|
||||
window.setTimeout("require(\"adddownloads\").parseOne()",1);
|
||||
} else {
|
||||
me.toParse = [];
|
||||
console.log(me.toConfirm.length);
|
||||
}
|
||||
refresh();
|
||||
},
|
||||
addOne: function(){
|
||||
if (me.index == null) {
|
||||
cancel();
|
||||
} else if (me.index >= me.toAdd.length) {
|
||||
me.toResult=me.toAdd;
|
||||
me.toAdd=[];
|
||||
refresh();
|
||||
} else {
|
||||
console.log([
|
||||
me.toAdd[me.index].action,
|
||||
me.toAdd[me.index].name,
|
||||
me.toAdd[me.index].size,
|
||||
me.toAdd[me.index].hash,
|
||||
]);
|
||||
refresh();
|
||||
rs.request("transfers/control_download", me.toAdd[me.index],
|
||||
function(data,statetoken){
|
||||
if (me.index != null) {
|
||||
me.toAdd[me.index].ok=true;
|
||||
me.index++;
|
||||
me.addOne();
|
||||
}
|
||||
}, {
|
||||
onfail: function(value){
|
||||
me.toAdd[me.index].ok=false;
|
||||
me.toAdd[me.index].debug_msg=value;
|
||||
me.index++;
|
||||
me.addOne();
|
||||
},
|
||||
onmismatch: function(response){
|
||||
me.toAdd[me.index].ok=false;
|
||||
me.toAdd[me.index].debug_msg=response.debug_msg;
|
||||
me.index++;
|
||||
me.addOne();
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function cancel() {
|
||||
me.toAdd=[];
|
||||
me.toConfirm=[];
|
||||
me.toParse=[];
|
||||
me.toResult=[];
|
||||
me.index=null;
|
||||
refresh();
|
||||
}
|
||||
|
||||
function parseDownloads(){
|
||||
me.toParse = document.getElementById("txtInput").value.replace("\r\n","\n").split("\n");
|
||||
var pos;
|
||||
while ((pos=me.toParse.indexOf(""))>=0) {
|
||||
me.toParse.splice(pos,1);
|
||||
}
|
||||
var parser = document.createElement('a');
|
||||
me.toConfirm = [];
|
||||
me.index = 0;
|
||||
if (me.toParse.length > me.index){
|
||||
window.setTimeout("require(\"adddownloads\").parseOne()",1);
|
||||
}
|
||||
}
|
||||
|
||||
function addDownloads(){
|
||||
me.toConfirm.map(function(item){
|
||||
if (item.confirmed) {
|
||||
item.debug_msg="";
|
||||
me.toAdd.push(item.target);
|
||||
}
|
||||
});
|
||||
me.toConfirm=[];
|
||||
if (me.toAdd.length > 0){
|
||||
me.index=0;
|
||||
window.setTimeout("require(\"adddownloads\").addOne()",1);
|
||||
} else {
|
||||
cancel();
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
function refresh(){
|
||||
m.startComputation();
|
||||
m.endComputation();
|
||||
}
|
||||
|
||||
function cancelBtn(){
|
||||
return m("div.btn2", {
|
||||
style:{
|
||||
textAlign: "center",
|
||||
color: "red",
|
||||
borderColor: "red",
|
||||
},
|
||||
onclick:cancel,
|
||||
},"cancel");
|
||||
}
|
||||
|
||||
// paste links
|
||||
function step1(){
|
||||
m.initControl = "txtInput";
|
||||
return [
|
||||
m("h3","step 1 / 5: paste retroshare-links:"),
|
||||
m("textarea[id=txtInput]", {
|
||||
style: {
|
||||
height:"100%",
|
||||
},
|
||||
onkeydown: function(event){
|
||||
if (event.keyCode == 13){
|
||||
parseDownloads();
|
||||
}
|
||||
}
|
||||
}),
|
||||
m("div.btn2", {
|
||||
style:{
|
||||
textAlign:"center",
|
||||
},
|
||||
onclick:parseDownloads,
|
||||
},"add downloads")
|
||||
]
|
||||
}
|
||||
|
||||
// parsing links
|
||||
function step2(){
|
||||
return [
|
||||
m("h3","step 2 / 5: parsing input ..."),
|
||||
m("p",
|
||||
"parsing " + (me.index) + " / " + me.toParse.length),
|
||||
cancelBtn(),
|
||||
]
|
||||
}
|
||||
|
||||
// parsing confirm
|
||||
function step3(){
|
||||
return [
|
||||
m("h3","step 3 / 5: confirm-links:"),
|
||||
m("ul",
|
||||
me.toConfirm.map(function(item){
|
||||
return m("li", {
|
||||
style:{
|
||||
color: item.confirmed
|
||||
? "lime"
|
||||
: "red"
|
||||
},
|
||||
}, item.text);
|
||||
})
|
||||
),
|
||||
m("div.btn2", {
|
||||
style:{
|
||||
textAlign:"center",
|
||||
},
|
||||
onclick:addDownloads,
|
||||
},"add green listed downloads"),
|
||||
cancelBtn(),
|
||||
]
|
||||
}
|
||||
|
||||
// adding links
|
||||
function step4(){
|
||||
return [
|
||||
m("h3","step 4 / 5: adding downloads:"),
|
||||
m("p",
|
||||
"adding " + (me.index) + " / " + me.toParse.length),
|
||||
m("ul",
|
||||
me.toAdd.map(function(item){
|
||||
return m("li", {
|
||||
style:{
|
||||
color: item.ok === undefined
|
||||
? "white"
|
||||
: item.ok == null
|
||||
? "grey"
|
||||
: item.ok
|
||||
? "lime"
|
||||
: "red"
|
||||
},
|
||||
}, (item.debug_msg ? item.debug_msg + ": " : "") + item.name
|
||||
+ " " + item.size + " " + item.hash);
|
||||
})
|
||||
),
|
||||
cancelBtn(),
|
||||
]
|
||||
}
|
||||
|
||||
// show result
|
||||
function step5(){
|
||||
return [
|
||||
m("h3","step 5 / 5: Result:"),
|
||||
m("p",
|
||||
"verarbeitet: " + me.toResult.length),
|
||||
m("ul",
|
||||
me.toResult.map(function(item){
|
||||
return m("li", {
|
||||
style:{
|
||||
color: item.ok === undefined
|
||||
? "white"
|
||||
: item.ok == null
|
||||
? "grey"
|
||||
: item.ok
|
||||
? "lime"
|
||||
: "red"
|
||||
},
|
||||
}, (item.debug_msg ? item.debug_msg + ": " : "") + item.name);
|
||||
})
|
||||
),
|
||||
m("div.btn2", {
|
||||
style:{
|
||||
textAlign: "center",
|
||||
},
|
||||
onclick: cancel,
|
||||
},"ok"),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = me;
|
54
libresapi/src/webui-src/app/addidentity.js
Normal file
54
libresapi/src/webui-src/app/addidentity.js
Normal file
@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
function createidentity(){
|
||||
var data = {
|
||||
name: document.getElementById("txtname").value,
|
||||
pgp_linked: false,
|
||||
//document.getElementById("chklinked").checked,
|
||||
};
|
||||
m.route("/waiting");
|
||||
rs.request("identity/create_identity",data, function(){
|
||||
m.route("/identities");
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {view: function(){
|
||||
m.initControl = "txtname";
|
||||
return m("div",
|
||||
m("h2","create identity"),
|
||||
m("hr"),
|
||||
m("h3","name"),
|
||||
m("input", {
|
||||
type: "text",
|
||||
id: "txtname",
|
||||
/*
|
||||
onkeydown: function(event){
|
||||
if (event.keyCode == 13){
|
||||
setPasswd(this.value);
|
||||
sendPassword(needpasswd);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}),
|
||||
/*
|
||||
m("b","linked with pgp-id: "),
|
||||
m("input", {
|
||||
type: "checkbox",
|
||||
id: "chklinked",
|
||||
style: {
|
||||
fontweight:"bold",
|
||||
width: "0%",
|
||||
}
|
||||
}),
|
||||
*/
|
||||
m("p"," "),
|
||||
m("input.btn2", {
|
||||
onclick: createidentity,
|
||||
type: "button",
|
||||
value: "create new identity",
|
||||
})
|
||||
)
|
||||
}}
|
151
libresapi/src/webui-src/app/addpeer.js
Normal file
151
libresapi/src/webui-src/app/addpeer.js
Normal file
@ -0,0 +1,151 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
var newkey = "";
|
||||
var remote = "";
|
||||
|
||||
module.exports = {
|
||||
view: function(){
|
||||
var key = m.route.param("radix");
|
||||
var pgp = m.route.param("pgp_id");
|
||||
var peer_id =m.route.param("peer_id");
|
||||
|
||||
if (key===undefined && pgp === undefined) {
|
||||
|
||||
var owncert = rs("peers/self/certificate");
|
||||
if (owncert === undefined ) {
|
||||
owncert = {cert_string:"< waiting for server ... >"}
|
||||
}
|
||||
return m("div", [
|
||||
m("h2","add new friend (Step 1/3)"),
|
||||
m("p","Your own key, give it to your friends"),
|
||||
m("pre", owncert.cert_string),
|
||||
m("p","paste your friends key below"),
|
||||
m("textarea", {
|
||||
ref:"cert",
|
||||
cols:"70",
|
||||
rows:"16",
|
||||
onchange: m.withAttr("value", function(value){newkey=value;})
|
||||
}),
|
||||
m("br"),
|
||||
m("input.btn2",{
|
||||
type:"button",
|
||||
value:"read",
|
||||
onclick: function (){
|
||||
m.route("/addpeer",{radix:newkey})
|
||||
},
|
||||
})
|
||||
]);
|
||||
} else if (pgp === undefined) {
|
||||
rs.request("peers/examine_cert",{cert_string:key},
|
||||
function(data,responsetoken){
|
||||
data.radix=key;
|
||||
m.route("/addpeer", data);
|
||||
}
|
||||
);
|
||||
return m("div", [
|
||||
m("h2","add new friend (Step 2/3)"),
|
||||
m("div", "analyse cert, please wait for server ...")
|
||||
// { data: null, debug_msg: "failed to load certificate ", returncode: "fail" }
|
||||
]);
|
||||
} else {
|
||||
var result = {
|
||||
cert_string:key ,
|
||||
flags:{
|
||||
allow_direct_download:false,
|
||||
allow_push:false,
|
||||
// set to false, until the webinterface supports managment of the blacklist/whitelist
|
||||
require_whitelist: false,
|
||||
}
|
||||
};
|
||||
return m("div",[
|
||||
m("h2","add new friend (Step 3/3)"),
|
||||
m("p","Do you want to add "
|
||||
+ m.route.param("name")
|
||||
+ " (" + m.route.param("location") + ")"
|
||||
+ " to your friendslist?"),
|
||||
m("input.checkbox[type=checkbox]", {
|
||||
onchange: m.withAttr("checked", function(checked){
|
||||
result.flags.allow_direct_download=checked;
|
||||
})
|
||||
}), "Allow direct downloads from this node",
|
||||
m("br"),
|
||||
m("input.checkbox[type=checkbox]", {
|
||||
onchange: m.withAttr("checked", function(checked){
|
||||
result.flags.allow_push=checked;
|
||||
})
|
||||
}), "Auto download recommended files from this node",
|
||||
m("div.btn2",{
|
||||
onclick: function(){
|
||||
m.route("/waiting");
|
||||
rs.request("peers",result,function(data, responsetoken){
|
||||
m.route("/peers");
|
||||
})
|
||||
}
|
||||
},"add to friendslist")
|
||||
|
||||
])
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
return "peers/self/certificate"
|
||||
|
||||
|
||||
|
||||
RS.request({path: "peers/examine_cert", data: {cert_string: cert_string}}, this.examine_cert_callback);
|
||||
this.setState({page:"waiting", cert_string: cert_string});
|
||||
|
||||
|
||||
RS.request(
|
||||
{
|
||||
path: "peers",
|
||||
data: {
|
||||
cert_string: this.state.cert_string,
|
||||
flags:{
|
||||
allow_direct_download: this.refs.cb_direct_dl.getDOMNode().checked,
|
||||
allow_push: this.refs.cb_push.getDOMNode().checked,
|
||||
// set to false, until the webinterface supports managment of the blacklist/whitelist
|
||||
require_whitelist: false,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
render: function(){
|
||||
if(this.state.page === "start")
|
||||
return(
|
||||
<div>
|
||||
<p>Your own key, give it to your friends</p>
|
||||
<OwnCert/>
|
||||
<p>paste your friends key below</p>
|
||||
<textarea ref="cert" cols="70" rows="16"></textarea><br/>
|
||||
<input
|
||||
type="button"
|
||||
value="read key"
|
||||
onClick={this.add_friend_handler}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
if(this.state.page === "waiting")
|
||||
return(
|
||||
<div>
|
||||
waiting for response from server...
|
||||
</div>
|
||||
);
|
||||
if(this.state.page === "peer")
|
||||
return(
|
||||
<div>
|
||||
<p>Do you want to add {this.state.data.name} to your friendslist?</p>
|
||||
<input className="checkbox" type="checkbox" ref="cb_direct_dl"/> Allow direct downloads from this node<br/>
|
||||
<input className="checkbox" type="checkbox" ref="cb_push"/> Auto download recommended files from this node<br/>
|
||||
<div onClick={this.final_add_handler} className="btn2">add to friendslist</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
*/
|
23
libresapi/src/webui-src/app/assets/index.html
Normal file
23
libresapi/src/webui-src/app/assets/index.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>rswebui6</title>
|
||||
<link rel="stylesheet" href="app.css">
|
||||
<script src="app.js"></script>
|
||||
</head>
|
||||
<body onload="load_ui();">
|
||||
<div id="main">if app does not load, enable JavaScript!</div>
|
||||
<script type="text/javascript">
|
||||
function load_ui(){
|
||||
var m = require("mithril");
|
||||
var ui = require("main");
|
||||
var main = document.getElementById("main");
|
||||
ui.init(main);
|
||||
if (m.initControl != undefined) {
|
||||
m.initControl.focus();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
298
libresapi/src/webui-src/app/chat.js
Normal file
298
libresapi/src/webui-src/app/chat.js
Normal file
@ -0,0 +1,298 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
var msg = null;
|
||||
var particips = [];
|
||||
|
||||
function dspmsg(from, when, text){
|
||||
return m(".chat.msg.container",[
|
||||
m(".chat.msg.from", from),
|
||||
m(".chat.msg.when", when),
|
||||
m(".chat.msg.text", text),
|
||||
]);
|
||||
}
|
||||
|
||||
function lobbies(){
|
||||
return [
|
||||
rs.list("chat/lobbies",function(lobby){
|
||||
return m("div.btn",{
|
||||
title: "topic: " + lobby.topic + "\n"
|
||||
+ "subscribed: " + lobby.subscribed,
|
||||
style: {
|
||||
backgroundColor: lobby.subscribed ? 'blue' : 'darkred',
|
||||
},
|
||||
onclick: function(){
|
||||
m.route("/chat?lobby=" + lobby.chat_id);
|
||||
}
|
||||
},
|
||||
lobby.name + (
|
||||
lobby.unread_msg_count > 0
|
||||
? ("(" + lobby.unread_msg_count + ")")
|
||||
: "")
|
||||
);
|
||||
},
|
||||
rs.sort.bool("is_broadcast",
|
||||
rs.sort.bool("subscribed",
|
||||
rs.sort("name")))
|
||||
),
|
||||
m("br"),
|
||||
m("h3","peers:"),
|
||||
rs.list("peers",function(peer){
|
||||
return peer.locations.map(function(loc){
|
||||
if (loc.location == "") {
|
||||
return [];
|
||||
};
|
||||
return m("div.btn",{
|
||||
style: {
|
||||
backgroundColor: loc.is_online ? 'blue' : 'darkred',
|
||||
},
|
||||
onclick: function(){
|
||||
m.route("/chat?lobby=" + loc.chat_id);
|
||||
}
|
||||
},
|
||||
peer.name + " / " + loc.location + (
|
||||
loc.unread_msgs > 0
|
||||
? ("(" + loc.unread_msgs + ")")
|
||||
: "")
|
||||
);
|
||||
})
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
function getLobbyDetails(lobbyid){
|
||||
var lobs = rs("chat/lobbies");
|
||||
if (lobs === undefined) {
|
||||
return null;
|
||||
};
|
||||
for(var i = 0, l = lobs.length; i < l; ++i) {
|
||||
if (lobs[i].chat_id == lobbyid) {
|
||||
return lobs[i];
|
||||
}
|
||||
}
|
||||
var peers = rs("peers");
|
||||
if (peers === undefined) {
|
||||
return null;
|
||||
};
|
||||
for(var i = 0, l = peers.length; i < l; ++i) {
|
||||
var peer = peers[i];
|
||||
for(var i1 = 0, l1 = peer.locations.length; i1 < l1; ++i1) {
|
||||
if (peer.locations[i1].chat_id == lobbyid) {
|
||||
return peer.locations[i1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function sendmsg(msgid){
|
||||
var txtmsg = document.getElementById("txtNewMsg");
|
||||
rs.request("chat/send_message", {
|
||||
chat_id: msgid,
|
||||
msg: txtmsg.value
|
||||
});
|
||||
txtmsg.value="";
|
||||
}
|
||||
|
||||
function lobby(lobbyid){
|
||||
var msgs;
|
||||
var lobdt = getLobbyDetails(lobbyid);
|
||||
var info = rs("chat/info/" + lobbyid);
|
||||
if (lobdt == null || info === undefined) {
|
||||
return m("div","waiting ...");
|
||||
}
|
||||
|
||||
var mem = rs.memory("chat/info/" + lobbyid);
|
||||
if (mem.msg === undefined) {
|
||||
mem.msg = [];
|
||||
};
|
||||
|
||||
var reqData = {};
|
||||
if (mem.lastKnownMsg != undefined) {
|
||||
reqData.begin_after = mem.lastKnownMsg;
|
||||
}
|
||||
|
||||
rs.request("chat/messages/" + lobbyid, reqData, function (data) {
|
||||
if (data.length > 0 ) {
|
||||
mem.msg = mem.msg.concat(data);
|
||||
if (mem.msg.length > 0) {
|
||||
mem.lastKnownMsg = mem.msg[mem.msg.length -1].id;
|
||||
}
|
||||
rs.request("chat/mark_chat_as_read/" + lobbyid,{}, null,
|
||||
{allow: "ok|not_set"});
|
||||
} else {
|
||||
mem.msg = [];
|
||||
}
|
||||
}, {
|
||||
onmismatch: function (){},
|
||||
log:function(){} //no logging (pulling)
|
||||
});
|
||||
|
||||
var intro = [
|
||||
m("h2",lobdt.name),
|
||||
m("p",lobdt.topic ? lobdt.topic: lobdt.location),
|
||||
m("hr")
|
||||
]
|
||||
if (lobdt.subscribed != undefined && !lobdt.subscribed) {
|
||||
return [
|
||||
intro,
|
||||
m("b","select subscribe identity:"),
|
||||
m("p"),
|
||||
rs.list("identity/own", function(item){
|
||||
return m("div.btn2",{
|
||||
onclick:function(){
|
||||
console.log("subscribe - id:" + lobdt.id +", "
|
||||
+ "gxs_id:" + item.gxs_id)
|
||||
rs.request("chat/subscribe_lobby",{
|
||||
id:lobdt.id,
|
||||
gxs_id:item.gxs_id
|
||||
})
|
||||
}
|
||||
},"subscribe as " + item.name);
|
||||
}),
|
||||
];
|
||||
} else {
|
||||
msg = m(".chat.bottom",[
|
||||
m("div","enter new message:"),
|
||||
m("input",{
|
||||
id:"txtNewMsg",
|
||||
onkeydown: function(event){
|
||||
if (event.keyCode == 13){
|
||||
sendmsg(lobbyid);
|
||||
}
|
||||
}
|
||||
}),
|
||||
m("div.btn2", {
|
||||
style: {textAlign:"center"},
|
||||
onclick: function(){
|
||||
sendmsg(lobbyid);
|
||||
}
|
||||
},"submit")
|
||||
]);
|
||||
}
|
||||
if (lobdt.subscribed != undefined
|
||||
&& lobdt.subscribed
|
||||
&& !lobdt.is_broadcast
|
||||
) {
|
||||
//set participants
|
||||
particips = [
|
||||
m("div.btn", {
|
||||
style: {
|
||||
"text-align":"center"
|
||||
},
|
||||
onclick: function (){
|
||||
rs.request("chat/unsubscribe_lobby",{
|
||||
id:lobdt.id,
|
||||
});
|
||||
m.route("/chat");
|
||||
}
|
||||
},"unsubscribe"),
|
||||
m("div.btn", {
|
||||
style: {
|
||||
"text-align":"center"
|
||||
},
|
||||
onclick: function (){
|
||||
rs.request("chat/clear_lobby",{
|
||||
id:lobdt.id,
|
||||
});
|
||||
m.route("/chat?lobby=" + lobbyid);
|
||||
}
|
||||
},"clear"),
|
||||
m("h3","participants:"),
|
||||
rs.list(
|
||||
"chat/lobby_participants/" + lobbyid,
|
||||
function(item) {
|
||||
return m("div",item.identity.name);
|
||||
},
|
||||
function (a,b){
|
||||
return rs.stringSort(a.identity.name,b.identity.name);
|
||||
}
|
||||
)
|
||||
]
|
||||
} else {
|
||||
if (lobdt.subscribed != undefined
|
||||
&& lobdt.subscribed
|
||||
&& lobdt.is_broadcast
|
||||
) {
|
||||
//set participants
|
||||
particips = [
|
||||
m("div.btn", {
|
||||
style: {
|
||||
"text-align":"center"
|
||||
},
|
||||
onclick: function (){
|
||||
rs.request("chat/clear_lobby",{
|
||||
lobbyid,
|
||||
});
|
||||
m.route("/chat?lobby=" + lobbyid);
|
||||
}
|
||||
},"clear"),
|
||||
]
|
||||
}
|
||||
}
|
||||
return [
|
||||
intro,
|
||||
mem.msg.map(function(item){
|
||||
var d = new Date(new Number(item.send_time)*1000);
|
||||
return dspmsg(
|
||||
item.author_name,
|
||||
d.toLocaleDateString() + " " + d.toLocaleTimeString(),
|
||||
item.msg
|
||||
);
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
frame: function(content, right){
|
||||
return m("div", {
|
||||
style: {
|
||||
"height": "100%",
|
||||
"box-sizing": "border-box",
|
||||
"padding-bottom": "170px",
|
||||
}
|
||||
},[
|
||||
m(".chat.container", [
|
||||
m(".chat.header", [
|
||||
m(
|
||||
"h2",
|
||||
{style:{margin:"0px"}},
|
||||
"chat"
|
||||
)
|
||||
]),
|
||||
m(".chat.left", [
|
||||
m("div.chat.header[style=position:relative]","lobbies:"),
|
||||
m("br"),
|
||||
lobbies(),
|
||||
]),
|
||||
m(".chat.right", right),
|
||||
m(".chat.middle", content),
|
||||
m(".chat.clear", ""),
|
||||
]),
|
||||
msg != null
|
||||
? msg
|
||||
: [],
|
||||
]);
|
||||
},
|
||||
view: function(){
|
||||
var lobbyid = m.route.param("lobby");
|
||||
msg = null;
|
||||
if (lobbyid != undefined ) {
|
||||
particips = [];
|
||||
return this.frame(
|
||||
lobby(lobbyid),
|
||||
particips
|
||||
);
|
||||
};
|
||||
return this.frame(
|
||||
m(
|
||||
"div",
|
||||
{style: {margin:"10px"}},
|
||||
"please select lobby"
|
||||
),
|
||||
m("div","")
|
||||
);
|
||||
}
|
||||
}
|
254
libresapi/src/webui-src/app/createlogin.js
Normal file
254
libresapi/src/webui-src/app/createlogin.js
Normal file
@ -0,0 +1,254 @@
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
var locationName = "";
|
||||
var password ="";
|
||||
var ssl_name = "";
|
||||
var newName = "";
|
||||
|
||||
function listprofiles(){
|
||||
var locations = rs("control/locations");
|
||||
var knownProfileIds = [];
|
||||
var result = [];
|
||||
if(locations === undefined || locations == null){
|
||||
return m("div", "profiles: waiting_server");
|
||||
}
|
||||
locations.map(function(location) {
|
||||
if (knownProfileIds.indexOf(location.pgp_id)<0){
|
||||
knownProfileIds.push(location.pgp_id);
|
||||
result.push(m(
|
||||
"div.btn2",{
|
||||
onclick: function(){
|
||||
m.route("/createlogin",{
|
||||
id: location.pgp_id,
|
||||
name: location.name,
|
||||
})
|
||||
}
|
||||
},
|
||||
location.name
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function setLocationName(location) {
|
||||
locationName = location;
|
||||
}
|
||||
|
||||
function setPasswd(passwd) {
|
||||
password = passwd;
|
||||
}
|
||||
|
||||
function setSslName(ssl) {
|
||||
ssl_name = ssl;
|
||||
}
|
||||
|
||||
function setNewName(name) {
|
||||
newName = name;
|
||||
}
|
||||
|
||||
function checkpasswd(){
|
||||
var status = "";
|
||||
var color = "red";
|
||||
var lbl = document.getElementById("lblpwdinfo");
|
||||
var passwd2 = document.getElementById("txtpasswd2").value;
|
||||
if (passwd2 == password && passwd2 != "") {
|
||||
color = "lime";
|
||||
status = "password ok";
|
||||
} else if (passwd2 == "") {
|
||||
color = "yellow";
|
||||
status = "password required";
|
||||
} else {
|
||||
color = "red";
|
||||
status = "passwords don't match";
|
||||
}
|
||||
lbl.textContent = status;
|
||||
lbl.style.color=color;
|
||||
}
|
||||
|
||||
|
||||
function createLocation() {
|
||||
var profile = m.route.param("id");
|
||||
var profname = m.route.param("name");
|
||||
|
||||
var loc ={
|
||||
ssl_name: document.getElementById("txtlocation").value,
|
||||
pgp_password: password,
|
||||
};
|
||||
if (profile != undefined) {
|
||||
loc.pgp_id= profile;
|
||||
} else {
|
||||
loc.pgp_name = newName;
|
||||
};
|
||||
rs.request("control/create_location",loc,function(data){
|
||||
m.route("/accountselect", {});
|
||||
});
|
||||
m.route("/createlogin",{state:wait});
|
||||
}
|
||||
|
||||
function certDrop(event)
|
||||
{
|
||||
console.log("onDrop()");
|
||||
console.log(event.dataTransfer.files);
|
||||
event.preventDefault();
|
||||
|
||||
var reader = new FileReader();
|
||||
|
||||
var widget = this;
|
||||
|
||||
reader.onload = function(evt) {
|
||||
console.log("onDrop(): file loaded");
|
||||
rs.request(
|
||||
"control/import_pgp",{
|
||||
key_string:evt.target.result,
|
||||
}, importCallback);
|
||||
};
|
||||
reader.readAsText(event.dataTransfer.files[0]);
|
||||
m.route("/createlogin",{state:"waiting"});
|
||||
}
|
||||
|
||||
function importCallback(resp)
|
||||
{
|
||||
console.log("importCallback()" + resp);
|
||||
m.route("/createlogin",{
|
||||
id:resp.pgp_id,
|
||||
name:"",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
view: function(){
|
||||
var profile = m.route.param("id");
|
||||
var state = m.route.param("state");
|
||||
var profname = m.route.param("name");
|
||||
var hidden = m.route.param("hidden");
|
||||
if (state == "wait"){
|
||||
return m("div","waiting ...");
|
||||
} if (state == "newid"){
|
||||
m.initControl = "txtnewname";
|
||||
return m("div",[
|
||||
m("h2","create login - Step 2 / 2: create location"),
|
||||
m("h3","- for new profile "),
|
||||
m("hr"),
|
||||
m("h2","PGP-profile name:"),
|
||||
m("input",{
|
||||
id: "txtnewname",
|
||||
type:"text",
|
||||
onchange:m.withAttr("value", setNewName),
|
||||
onkeydown: function(event){
|
||||
if (event.keyCode == 13){
|
||||
document.getElementById("txtpasswd").focus();
|
||||
}
|
||||
},
|
||||
}),
|
||||
m("h2","enter password:"),
|
||||
m("input", {
|
||||
id: "txtpasswd",
|
||||
type:"password",
|
||||
onchange: m.withAttr("value",setPasswd),
|
||||
onkeydown: function(event){
|
||||
if (event.keyCode == 13){
|
||||
setPasswd(this.value);
|
||||
document.getElementById("txtpasswd2").focus();
|
||||
};
|
||||
checkpasswd;
|
||||
}
|
||||
}),
|
||||
m("h2", "re-enter password:"),
|
||||
m("input", {
|
||||
id: "txtpasswd2",
|
||||
type:"password",
|
||||
onfocus: checkpasswd,
|
||||
onchange: checkpasswd,
|
||||
onkeyup: function(event){
|
||||
if (event.keyCode == 13){
|
||||
document.getElementById("txtlocation").focus();
|
||||
}
|
||||
checkpasswd();
|
||||
}
|
||||
}),
|
||||
m("h3",{
|
||||
id: "lblpwdinfo",
|
||||
style:"color:yellow",
|
||||
}, "password required"),
|
||||
m("h2","location name:"),
|
||||
m("input",{
|
||||
id: "txtlocation",
|
||||
type:"text",
|
||||
onchange:m.withAttr("value", setLocationName),
|
||||
onkeydown: function(event){
|
||||
if (event.keyCode == 13){
|
||||
setSslName(this.value);
|
||||
createLocation();
|
||||
}
|
||||
},
|
||||
}),
|
||||
m("br"),
|
||||
m("input",{
|
||||
type: "button",
|
||||
onclick: createLocation,
|
||||
value: "create location",
|
||||
}),
|
||||
]);
|
||||
} else if (profile != undefined) {
|
||||
m.initControl = "txtpasswd";
|
||||
return m("div",[
|
||||
m("h2","create login - Step 2 / 2: create location"),
|
||||
m("h3","- for " + profname + " (" +profile + ")"),
|
||||
m("hr"),
|
||||
m("h2","enter password:"),
|
||||
m("input", {
|
||||
id: "txtpasswd",
|
||||
type:"password",
|
||||
onchange: m.withAttr("value",setPasswd),
|
||||
onkeydown: function(event){
|
||||
if (event.keyCode == 13){
|
||||
setPasswd(this.value);
|
||||
document.getElementById("txtlocation").focus();
|
||||
}
|
||||
}
|
||||
}),
|
||||
m("h2","location name:"),
|
||||
m("input",{
|
||||
id: "txtlocation",
|
||||
type:"text",
|
||||
onchange:m.withAttr("value", setLocationName),
|
||||
onkeydown: function(event){
|
||||
if (event.keyCode == 13){
|
||||
setSslName(this.value);
|
||||
createLocation();
|
||||
}
|
||||
},
|
||||
}),
|
||||
m("br"),
|
||||
m("input",{
|
||||
type: "button",
|
||||
onclick: createLocation,
|
||||
value: "create location",
|
||||
}),
|
||||
]);
|
||||
} else {
|
||||
return m("div",[
|
||||
m("h2","create login - Step 1 / 2: select profile(PGP-ID)"),
|
||||
m("hr"),
|
||||
m("div.btn2",{
|
||||
onclick: function(){
|
||||
m.route("/createlogin", {state: "newid"});
|
||||
},
|
||||
} ,"<create new profile>"),
|
||||
m("div.btn2",{
|
||||
ondragover:function(event){
|
||||
/*important: block default event*/
|
||||
event.preventDefault();
|
||||
},
|
||||
ondrop: certDrop,
|
||||
} ,"<import profile (drag and drop a profile here)>"),
|
||||
listprofiles()
|
||||
]);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
96
libresapi/src/webui-src/app/downloads.js
Normal file
96
libresapi/src/webui-src/app/downloads.js
Normal file
@ -0,0 +1,96 @@
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
function makeFriendlyUnit(bytes)
|
||||
{
|
||||
if(bytes < 1e3)
|
||||
return bytes.toFixed(1) + "B";
|
||||
if(bytes < 1e6)
|
||||
return (bytes/1e3).toFixed(1) + "kB";
|
||||
if(bytes < 1e9)
|
||||
return (bytes/1e6).toFixed(1) + "MB";
|
||||
if(bytes < 1e12)
|
||||
return (bytes/1e9).toFixed(1) + "GB";
|
||||
return (bytes/1e12).toFixed(1) + "TB";
|
||||
}
|
||||
|
||||
function progressBar(file){
|
||||
return m("div[style=border:5px solid lime;"
|
||||
+ 'border-radius:3mm;'
|
||||
+ 'padding:2mm;'
|
||||
+ 'height:5mm'
|
||||
+ "]", [
|
||||
m("div[style="
|
||||
+ 'background-color:lime;'
|
||||
+ 'height:100%;'
|
||||
+ 'width:' + (file.transfered / file.size * 100)+'%'
|
||||
+ ']'
|
||||
,"")
|
||||
]);
|
||||
};
|
||||
|
||||
function cntrlBtn(file, act) {
|
||||
return(
|
||||
m("div.btn",{
|
||||
onclick: function(){
|
||||
rs.request("transfers/control_download",{action: act, id: file.id});
|
||||
}
|
||||
},
|
||||
act)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
view: function(){
|
||||
var paths = rs("transfers/downloads");
|
||||
var filestreamer_url = "/fstream/";
|
||||
if (paths === undefined) {
|
||||
return m("div", "Downloads ... please wait ...");
|
||||
}
|
||||
return m("div", [
|
||||
m("h2","Downloads (" + paths.length +")"),
|
||||
m("div.btn2", {
|
||||
onclick: function(){
|
||||
m.route("/downloads/add");
|
||||
}
|
||||
}, "add retrohare downloads"),
|
||||
m("hr"),
|
||||
m('table', [
|
||||
m("tr",[
|
||||
m("th","name"),
|
||||
m("th","size"),
|
||||
m("th","progress"),
|
||||
m("th","transfer rate"),
|
||||
m("th","status"),
|
||||
m("th","progress"),
|
||||
m("th","action")
|
||||
]),
|
||||
paths.map(function (file){
|
||||
var ctrlBtn = m("div","");
|
||||
var progress = file.transfered / file.size * 100;
|
||||
return m("tr",[
|
||||
m("td",[
|
||||
m("a.filelink",
|
||||
{
|
||||
target: "blank",
|
||||
href: filestreamer_url + file.hash + "/" + encodeURIComponent(file.name)
|
||||
},
|
||||
file.name
|
||||
)
|
||||
]),
|
||||
m("td", makeFriendlyUnit(file.size)),
|
||||
m("td", progress.toPrecision(3) + "%"),
|
||||
m("td", makeFriendlyUnit(file.transfer_rate*1e3)+"/s"),
|
||||
m("td", file.download_status),
|
||||
m("td", progressBar(file)),
|
||||
m("td", [
|
||||
cntrlBtn(file, file.download_status==="paused"?"start":"pause"),
|
||||
cntrlBtn(file, "cancel")]
|
||||
)
|
||||
])
|
||||
})
|
||||
])
|
||||
]);
|
||||
}
|
||||
};
|
65
libresapi/src/webui-src/app/forums.js
Normal file
65
libresapi/src/webui-src/app/forums.js
Normal file
@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
module.exports = {view: function(){
|
||||
return m("div",[
|
||||
m("h2","forums"),
|
||||
m("p","(work in progress, currently only listing)"),
|
||||
m("hr"),
|
||||
/*
|
||||
m("div.btn2", {
|
||||
onclick: function (){
|
||||
m.route("/addforum");
|
||||
}
|
||||
},"< create new forum >"),
|
||||
*/
|
||||
m("ul",
|
||||
rs.list("forums",
|
||||
function(item){
|
||||
return m("li",[
|
||||
m("h2",item.name),
|
||||
m("div",{style:{margin:"10px"}},
|
||||
[
|
||||
item.description != ""
|
||||
? [
|
||||
m("span", "Description: "
|
||||
+ item.description),
|
||||
m("br")]
|
||||
: [],
|
||||
m("span","messages visible: "
|
||||
+ item.visible_msg_count),
|
||||
]
|
||||
),
|
||||
/*
|
||||
item.subscribed
|
||||
? [
|
||||
m(
|
||||
"span.btn2",
|
||||
{style:{padding:"0px"}},
|
||||
"unsubscribe"
|
||||
),
|
||||
" ",
|
||||
m(
|
||||
"span.btn2",
|
||||
{style:{padding:"0px", margin:"10px"}},
|
||||
"enter"
|
||||
),
|
||||
m("hr", {style: {color:"silver"}}),
|
||||
]
|
||||
: [
|
||||
m(
|
||||
"span.btn2",
|
||||
{style:{padding:"0px", margin:"10px"}},
|
||||
"subscribe"
|
||||
),
|
||||
]
|
||||
*/
|
||||
]);
|
||||
},
|
||||
rs.sort("name")
|
||||
)
|
||||
)
|
||||
]);
|
||||
}}
|
145
libresapi/src/webui-src/app/green-black.scss
Normal file
145
libresapi/src/webui-src/app/green-black.scss
Normal file
@ -0,0 +1,145 @@
|
||||
body {
|
||||
background-color: black;
|
||||
color: lime;
|
||||
font-family: monospace;
|
||||
margin: 0em;
|
||||
/*padding: 1.5em;*/
|
||||
padding: 2mm;
|
||||
font-size: 1.1em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#overlay{
|
||||
z-index: 10;
|
||||
position: fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
}
|
||||
|
||||
.paddingbox{
|
||||
padding:2mm;
|
||||
}
|
||||
|
||||
.nav{
|
||||
list-style-type: none;
|
||||
padding: 0em;
|
||||
margin: 0em;
|
||||
}
|
||||
|
||||
.nav li{
|
||||
display: inline;
|
||||
padding: 0.1em;
|
||||
margin-right: 1em;
|
||||
border-width: 0.1em;
|
||||
border-color: blue;
|
||||
border-bottom-style: solid;
|
||||
cursor: pointer;
|
||||
}
|
||||
td{
|
||||
padding: 0.3em;
|
||||
border-style: solid;
|
||||
border-width: 0.1em;
|
||||
border-color: lime;
|
||||
}
|
||||
hr {
|
||||
color: lime;
|
||||
}
|
||||
.menu{
|
||||
border-style: solid;
|
||||
border-color: lime;
|
||||
border-width: 0.1em;
|
||||
cursor: pointer;
|
||||
padding: 0.0em;
|
||||
}
|
||||
.btn{
|
||||
border-style: solid;
|
||||
border-color: lime;
|
||||
border-width: 0.1em;
|
||||
cursor: pointer;
|
||||
padding: 0.1em;
|
||||
}
|
||||
|
||||
.btn2, .box{
|
||||
border-style: solid;
|
||||
/*border-color: lime;*/
|
||||
border-color: limeGreen;
|
||||
/*border-width: 1px;*/
|
||||
border-radius: 3mm;
|
||||
padding: 2mm;
|
||||
font-size: 10mm;
|
||||
cursor: pointer;
|
||||
margin-bottom: 2mm;
|
||||
}
|
||||
.btn2:hover{
|
||||
background-color: midnightblue;
|
||||
}
|
||||
|
||||
.filelink{
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
input, textarea{
|
||||
color: lime;
|
||||
font-family: monospace;
|
||||
background-color: black;
|
||||
border-color: lime;
|
||||
font-size: 10mm;
|
||||
border-radius: 3mm;
|
||||
border-width: 1mm;
|
||||
padding: 2mm;
|
||||
margin-bottom: 2mm;
|
||||
margin-right: 2mm;
|
||||
|
||||
/* make the button the whole screen width */
|
||||
width: 100%;
|
||||
/* make the text input fit small screens*/
|
||||
box-sizing: border-box;
|
||||
}
|
||||
input:hover{
|
||||
background-color: midnightblue;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.flexbox{
|
||||
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
||||
display: -ms-flexbox; /* TWEENER - IE 10 */
|
||||
display: -webkit-flex; /* NEW - Chrome */
|
||||
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||
}
|
||||
|
||||
.flexwidemember{
|
||||
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
-moz-box-flex: 1; /* OLD - Firefox 19- */
|
||||
width: 20%; /* For old syntax, otherwise collapses. */
|
||||
-webkit-flex: 1; /* Chrome */
|
||||
-ms-flex: 1; /* IE 10 */
|
||||
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||
}
|
||||
|
||||
#logo_splash{
|
||||
-webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
|
||||
animation-fill-mode: forwards;
|
||||
-webkit-animation-name: logo_splash; /* Chrome, Safari, Opera */
|
||||
-webkit-animation-duration: 3s; /* Chrome, Safari, Opera */
|
||||
animation-name: logo_splash;
|
||||
animation-duration: 3s;
|
||||
text-align: center;
|
||||
}
|
||||
/* Chrome, Safari, Opera */
|
||||
@-webkit-keyframes logo_splash {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
||||
|
||||
/* Standard syntax */
|
||||
@keyframes logo_splash {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
6
libresapi/src/webui-src/app/home.js
Normal file
6
libresapi/src/webui-src/app/home.js
Normal file
@ -0,0 +1,6 @@
|
||||
var m = require("mithril");
|
||||
|
||||
module.exports = {view: function(){
|
||||
return m("div","RetroShare - WebClient - Welcome");
|
||||
}
|
||||
};
|
22
libresapi/src/webui-src/app/identities.js
Normal file
22
libresapi/src/webui-src/app/identities.js
Normal file
@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
module.exports = {view: function(){
|
||||
return m("div",[
|
||||
m("h2","identities"),
|
||||
m("hr"),
|
||||
m("div.btn2", {
|
||||
onclick: function (){
|
||||
m.route("/addidentity");
|
||||
}
|
||||
},"< create new identity >"),
|
||||
m("ul",
|
||||
rs.list("identity/own", function(item){
|
||||
return m("li",[m("h2",item.name)]);
|
||||
},
|
||||
rs.sort("name"))
|
||||
)
|
||||
]);
|
||||
}}
|
122
libresapi/src/webui-src/app/main.js
Normal file
122
libresapi/src/webui-src/app/main.js
Normal file
@ -0,0 +1,122 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
var menu =require("menu");
|
||||
var currentpasswd = null;
|
||||
|
||||
|
||||
function setPasswd(password) {
|
||||
currentpasswd = password
|
||||
}
|
||||
|
||||
function sendPassword(data) {
|
||||
console.log("sending pwd for " + data.key_name + "...");
|
||||
rs.request("control/password", {password: currentpasswd}, function(){
|
||||
m.redraw();
|
||||
});
|
||||
}
|
||||
|
||||
function Page(menu){
|
||||
this.menu = menu;
|
||||
this.module = (menu.module != undefined) ? menu.module : menu.name;
|
||||
this.path = menu.path != undefined ? menu.path : ("/" + menu.name);
|
||||
|
||||
var runst = menu.runstate;
|
||||
var content = require(this.module);
|
||||
var mm = require("menu");
|
||||
|
||||
this.view = function(){
|
||||
var runstate = rs("control/runstate");
|
||||
var needpasswd = rs("control/password");
|
||||
//console.log("runstate: " + (runstate === undefined ? runstate : runstate.runstate));
|
||||
if(runstate === undefined){
|
||||
return m("h2", "waiting_server ... ");
|
||||
} else if (runstate.runstate == null){
|
||||
// try clean reboot ...
|
||||
rs.clearCache();
|
||||
rs("control/runstate"); //reboot detector
|
||||
console.log("i'm down");
|
||||
return m("h2", "server down");
|
||||
} else if (needpasswd != undefined && needpasswd.want_password === true){
|
||||
m.initControl = "txtpasswd";
|
||||
return m("div",[
|
||||
m("h2","password required"),
|
||||
m("h3",needpasswd.key_name),
|
||||
m("input",{
|
||||
id: "txtpasswd",
|
||||
type:"password",
|
||||
onchange:m.withAttr("value", setPasswd),
|
||||
onkeydown: function(event){
|
||||
if (event.keyCode == 13){
|
||||
setPasswd(this.value);
|
||||
sendPassword(needpasswd);
|
||||
}
|
||||
}
|
||||
}),
|
||||
m("br"),
|
||||
m("input[type=button][value=send password]",{
|
||||
onclick: function(){
|
||||
sendPassword(needpasswd);
|
||||
}
|
||||
}),
|
||||
]);
|
||||
} else {
|
||||
if (runstate.runstate.match("waiting_init|waiting_startup")) {
|
||||
return m("h2","server starting ...")
|
||||
} else if(runstate.runstate.match("waiting_account_select|running_ok.*")) {
|
||||
if (runst === undefined || runstate.runstate.match(runst)) {
|
||||
return m("div", {
|
||||
style: {
|
||||
height: "100%",
|
||||
"box-sizing": "border-box",
|
||||
"padding-bottom": "40px"
|
||||
}
|
||||
}, [
|
||||
m("div", mm.view()),
|
||||
m("hr"),
|
||||
m("div", {
|
||||
style: {
|
||||
height: "100%",
|
||||
"box-sizing": "border-box",
|
||||
"padding-bottom":"40px"
|
||||
}
|
||||
}, content)
|
||||
]);
|
||||
} else {
|
||||
// funktion currently not available
|
||||
m.route("/");
|
||||
return m("div", [
|
||||
m("div", mm.view()),
|
||||
m("hr"),
|
||||
m("div", require("home").view())
|
||||
]);
|
||||
};
|
||||
} else {
|
||||
return m("div", "unknown runstate: " + runstate.runstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
init:function(main){
|
||||
console.log("start init ...");
|
||||
var menudef = require("menudef");
|
||||
var maps = {};
|
||||
var m = require("mithril");
|
||||
|
||||
menudef.nodes.map(function(menu){
|
||||
if (menu.action === undefined) {
|
||||
var p = new Page(menu)
|
||||
console.log("adding route " + menu.name + " for " + p.path + " with module " + p.module);
|
||||
maps[p.path] = p;
|
||||
}
|
||||
});
|
||||
m.route.mode = "hash";
|
||||
m.route(main,"/",maps);
|
||||
console.log("init done.");
|
||||
}
|
||||
};
|
||||
|
12
libresapi/src/webui-src/app/main.sass
Normal file
12
libresapi/src/webui-src/app/main.sass
Normal file
@ -0,0 +1,12 @@
|
||||
/*@import "reset" */
|
||||
|
||||
html, body, #main
|
||||
height: 100%
|
||||
|
||||
|
||||
/*body */
|
||||
/* font-family: "Sans-serif" */
|
||||
|
||||
|
||||
@import "chat"
|
||||
@import "green-black"
|
65
libresapi/src/webui-src/app/menu.js
Normal file
65
libresapi/src/webui-src/app/menu.js
Normal file
@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
var mnodes = require("menudef");
|
||||
|
||||
function goback(){
|
||||
rs.content=null;
|
||||
m.redraw();
|
||||
}
|
||||
|
||||
function buildmenu(menu, tagname, runstate, ignore){
|
||||
if (
|
||||
(menu.runstate === undefined
|
||||
|| runstate.match("^(" + menu.runstate + ")$")!=null)
|
||||
&& (!menu.name.match(ignore))
|
||||
&& (menu.path === undefined || menu.path.match(":")==null)
|
||||
&& (menu.show === undefined || menu.show)
|
||||
) {
|
||||
var name = menu.name;
|
||||
if (menu.counter != undefined) {
|
||||
name += menu.counter();
|
||||
}
|
||||
if (menu.action === undefined) {
|
||||
return m(tagname , {
|
||||
onclick: function(){
|
||||
m.route(
|
||||
menu.path != undefined ? menu.path : "/" + menu.name
|
||||
)
|
||||
}
|
||||
}, name);
|
||||
} else {
|
||||
return m(tagname, {onclick: function(){menu.action(m)}}, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {view: function(){
|
||||
var runstate = rs("control/runstate");
|
||||
if (runstate === undefined
|
||||
|| runstate.runstate === undefined
|
||||
|| runstate.runstate == null)
|
||||
return m("div.nav","menu: waiting for server ...");
|
||||
if (m.route() != "/")
|
||||
return m("span",[
|
||||
m("span"," | "),
|
||||
mnodes.nodes.map(function(menu){
|
||||
var item = buildmenu(menu,"span.menu", runstate.runstate, "-");
|
||||
if (item != null){
|
||||
return [
|
||||
item,
|
||||
m("span"," | ")
|
||||
]
|
||||
}
|
||||
})
|
||||
]);
|
||||
return m("div", [
|
||||
m("h2","home"),
|
||||
m("hr"),
|
||||
mnodes.nodes.map(function(menu){
|
||||
return buildmenu(menu,"div.btn2", runstate.runstate, "home");
|
||||
})
|
||||
]);
|
||||
}
|
||||
};
|
119
libresapi/src/webui-src/app/menudef.js
Normal file
119
libresapi/src/webui-src/app/menudef.js
Normal file
@ -0,0 +1,119 @@
|
||||
var rs=require("retroshare");
|
||||
module.exports = { nodes: [
|
||||
{
|
||||
name: "home",
|
||||
path: "/"
|
||||
},
|
||||
{
|
||||
name: "login",
|
||||
module: "accountselect",
|
||||
runstate: "waiting_account_select",
|
||||
counter: rs.counting("control/locations"),
|
||||
},
|
||||
{
|
||||
name: "create login",
|
||||
path: "/createlogin",
|
||||
module: "createlogin",
|
||||
runstate: "waiting_account_select",
|
||||
},
|
||||
{
|
||||
name: "peers",
|
||||
runstate: "running_ok.*",
|
||||
counter: rs.counting("peers", function(data){
|
||||
var onlinecount = 0;
|
||||
data.map(function(peer) {
|
||||
var is_online = false;
|
||||
peer.locations.map(function (location){
|
||||
if (location.is_online) {
|
||||
is_online=true;
|
||||
}
|
||||
});
|
||||
if (is_online) {
|
||||
onlinecount +=1;
|
||||
}
|
||||
});
|
||||
return onlinecount + "/" + data.length;
|
||||
})
|
||||
},
|
||||
{
|
||||
name: "addpeer",
|
||||
runstate: "running_ok.*",
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: "identities",
|
||||
runstate: "running_ok.*",
|
||||
counter: rs.counting("identity/own"),
|
||||
},
|
||||
{
|
||||
name: "addidentity",
|
||||
runstate: "running_ok.*",
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name:"searchresult",
|
||||
path: "/search/:id",
|
||||
runstate: "running_ok.*",
|
||||
},
|
||||
{
|
||||
name: "search",
|
||||
runstate: "running_ok.*",
|
||||
},
|
||||
{
|
||||
name: "downloads",
|
||||
runstate: "running_ok.*",
|
||||
counter: rs.counting("transfers/downloads")
|
||||
},
|
||||
{
|
||||
name: "adddownloads",
|
||||
runstate: "running_ok.*",
|
||||
path: "/downloads/add",
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: "forums",
|
||||
runstate: "running_ok.*",
|
||||
},
|
||||
{
|
||||
name: "chat",
|
||||
runstate: "running_ok.*",
|
||||
counter: rs.counting2({
|
||||
"peers": function(peer) {
|
||||
var sum = 0;
|
||||
peer.locations.map(function (loc) {
|
||||
sum += parseInt(loc.unread_msgs);
|
||||
});
|
||||
return sum;
|
||||
},
|
||||
"chat/lobbies": function(lobby) {
|
||||
return lobby.unread_msg_count;
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
name:"settings",
|
||||
runstate: "running_ok.*",
|
||||
},
|
||||
{
|
||||
name:"servicecontrol",
|
||||
runstate: "running_ok.*",
|
||||
path:"/settings/servicecontrol",
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: "shutdown",
|
||||
runstate: "running_ok|waiting_account_select",
|
||||
action: function(m){
|
||||
rs.request("control/shutdown",null,function(){
|
||||
rs("control/runstate").runstate=null;
|
||||
rs.forceUpdate("control/runstate");
|
||||
m.redraw();
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "waiting",
|
||||
show: false,
|
||||
},
|
||||
]
|
||||
}
|
2141
libresapi/src/webui-src/app/mithril.js
Normal file
2141
libresapi/src/webui-src/app/mithril.js
Normal file
File diff suppressed because it is too large
Load Diff
8
libresapi/src/webui-src/app/mithril.min.js
vendored
Normal file
8
libresapi/src/webui-src/app/mithril.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
libresapi/src/webui-src/app/mithril.min.js.map
Normal file
1
libresapi/src/webui-src/app/mithril.min.js.map
Normal file
File diff suppressed because one or more lines are too long
89
libresapi/src/webui-src/app/peers.js
Normal file
89
libresapi/src/webui-src/app/peers.js
Normal file
@ -0,0 +1,89 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
module.exports = {view: function(){
|
||||
var peers = rs("peers");
|
||||
//console.log("peers:" + peers);
|
||||
|
||||
//waiting for peerlist ...
|
||||
if(peers === undefined || peers == null){
|
||||
return m("div",[
|
||||
m("h2","peers"),
|
||||
m("h3","waiting_server"),
|
||||
]);
|
||||
};
|
||||
peers = peers.sort(rs.sort("name"));
|
||||
|
||||
//building peerlist (prebuild for counting)
|
||||
var online = 0;
|
||||
var peerlist = peers.map(function(peer){
|
||||
var isonline = false;
|
||||
var avatar_address ="";
|
||||
|
||||
//building location list (prebuild for state + icon)
|
||||
var loclist = peer.locations.map(function(location){
|
||||
if (location.is_online && ! isonline){
|
||||
online +=1;
|
||||
isonline = true;
|
||||
}
|
||||
if (location.avatar_address != "" && avatar_address =="") {
|
||||
avatar_address=location.avatar_address;
|
||||
}
|
||||
return m("li",{
|
||||
style:"color:" + (location.is_online ? "lime": "grey")
|
||||
+ ";cursor:pointer",
|
||||
onclick: function(){
|
||||
m.route("/chat?lobby=" + location.chat_id)
|
||||
}
|
||||
|
||||
}, location.location);
|
||||
});
|
||||
|
||||
//return friend (peer + locations)
|
||||
return m("div.flexbox[style=color:lime]",[
|
||||
// avatar-icon
|
||||
m("div", [
|
||||
avatar_address == "" ? "" : (
|
||||
m("img",{
|
||||
src: rs.apiurl("peers" + avatar_address),
|
||||
style:"border-radius:3mm;margin:2mm;",
|
||||
})
|
||||
)
|
||||
]),
|
||||
//peername + locations
|
||||
m("div.flexwidemember",[
|
||||
m("h1[style=margin-bottom:1mm;]",
|
||||
{style:"color:" + (isonline ? "lime": "grey")} ,
|
||||
peer.name
|
||||
),
|
||||
m("ul", loclist ),
|
||||
]),
|
||||
//remove-button
|
||||
m("div", {
|
||||
style: "color:red;" +
|
||||
"font-size:1.5em;" +
|
||||
"padding:0.2em;" +
|
||||
"cursor:pointer",
|
||||
onclick: function (){
|
||||
var yes = window.confirm(
|
||||
"Remove " + peer.name + " from friendslist?");
|
||||
if(yes){
|
||||
rs.request("peers/" + peer.pgp_id +"/delete");
|
||||
}
|
||||
}
|
||||
}, "X")
|
||||
]);
|
||||
});
|
||||
|
||||
// return add-peer-button + peerlist
|
||||
return m("div",[
|
||||
m("div.btn2",{onclick: function(){m.route("/addpeer")}},"add new friend"),
|
||||
m("h2","peers (online: " + online +" / " + peers.length + "):"),
|
||||
m("div", [
|
||||
peerlist,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
};
|
410
libresapi/src/webui-src/app/retroshare.js
Normal file
410
libresapi/src/webui-src/app/retroshare.js
Normal file
@ -0,0 +1,410 @@
|
||||
/*
|
||||
var rs = requires("rs");
|
||||
var m = require("mithril");
|
||||
|
||||
function main(){
|
||||
var state = rs("runstate");
|
||||
if(state=== undefined){
|
||||
return m("div", "waiting for server");
|
||||
}
|
||||
if(state === "waiting_login"){
|
||||
return require("login")();
|
||||
}
|
||||
if(state === "running_ok"){
|
||||
return require("mainwindow")();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
idea: statetokenservice could just send the date instead of the token
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
|
||||
var api_url = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port + "/api/v2/";
|
||||
var filestreamer_url = window.location.protocol + "//" +window.location.hostname + ":" + window.location.port + "/fstream/";
|
||||
var upload_url = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port + "/upload/";
|
||||
|
||||
function for_key_in_obj(obj, callback){
|
||||
var key;
|
||||
for(key in obj){
|
||||
callback(key, obj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
var cache = {};
|
||||
var last_update_ts = 0;
|
||||
|
||||
function check_for_changes(){
|
||||
var tokens = [];
|
||||
var paths_to_fetch = [];
|
||||
// console.log("start-check " + Object.keys(cache));
|
||||
for_key_in_obj(cache, function(path, item){
|
||||
var token = item.statetoken;
|
||||
if(token === undefined || token== null) {
|
||||
paths_to_fetch.push(path)
|
||||
} else if (tokens.indexOf(token)<0) {
|
||||
tokens.push(token);
|
||||
}
|
||||
});
|
||||
// console.log("tokens found: " + tokens);
|
||||
var req = m.request({
|
||||
method: "POST",
|
||||
url: api_url + "statetokenservice",
|
||||
background: true,
|
||||
data: tokens,
|
||||
});
|
||||
|
||||
req.then(function handle_statetoken_response(response){
|
||||
// console.log("checking result " + response.data ? Object.keys(response.data) : "<null>") ;
|
||||
for_key_in_obj(cache, function(path, item){
|
||||
var found = false;
|
||||
for(var i = 0; i < response.data.length; i++){
|
||||
if(response.data[i] === item.statetoken){
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if(found){
|
||||
paths_to_fetch.push(path);
|
||||
}
|
||||
});
|
||||
// console.log("generating Results for paths " + paths_to_fetch);
|
||||
var requests = [];
|
||||
paths_to_fetch.map(function request_it(path){
|
||||
var req2 = m.request({
|
||||
method: "GET",
|
||||
url: api_url + path,
|
||||
background: true,
|
||||
});
|
||||
req2 = req2.then(function fill_in_result(response){
|
||||
cache[path].data = response.data;
|
||||
cache[path].statetoken = response.statetoken;
|
||||
});
|
||||
requests.push(req2);
|
||||
});
|
||||
if(requests.length > 0){
|
||||
// console.log("requesting " + requests.length + " requests");
|
||||
m.sync(requests).then(function trigger_render(){
|
||||
m.startComputation();
|
||||
m.endComputation();
|
||||
checkFocus();
|
||||
setTimeout(check_for_changes, 500);
|
||||
});
|
||||
}
|
||||
else{
|
||||
// console.log("no requests");
|
||||
setTimeout(check_for_changes, 500);
|
||||
}
|
||||
}, function errhandling(value){
|
||||
// console.log("server disconnected " + value);
|
||||
setTimeout(check_for_changes, 500);
|
||||
});
|
||||
}
|
||||
|
||||
check_for_changes();
|
||||
|
||||
var update_scheduled = false;
|
||||
function schedule_request_missing(){
|
||||
if(update_scheduled)
|
||||
return;
|
||||
update_scheduled = true;
|
||||
// place update logic outside of render loop, this way we can fetch multiple things at once
|
||||
// (because after the render loop everything we should fetch is in the list)
|
||||
// if we fetch multiple things at once, we can delay a re-rende runtil everything is done
|
||||
// so we need only one re-render for multiple updates
|
||||
setTimeout(function request_missing(){
|
||||
update_scheduled = false;
|
||||
var requests = [];
|
||||
for_key_in_obj(cache, function(path, item){
|
||||
if(!item.requested){
|
||||
var req = m.request({
|
||||
method: "GET",
|
||||
url: api_url + path,
|
||||
background: true,
|
||||
});
|
||||
|
||||
req.then(function fill_data(response){
|
||||
// TODO: add errorhandling
|
||||
item.data = response.data;
|
||||
item.statetoken = response.statetoken;
|
||||
if (item.then != undefined && item.then != null) {
|
||||
try {
|
||||
item.then(response);
|
||||
} catch (ex) {
|
||||
if (item.errorCallback != undefined && item.errorCallback != null) {
|
||||
item.errorCallback(ex);
|
||||
};
|
||||
}
|
||||
};
|
||||
}, function errhandling(value){
|
||||
if (item.errorCallback != undefined && item.errorCallback != null) {
|
||||
item.errorCallback(value);
|
||||
}
|
||||
});
|
||||
requests.push(req);
|
||||
}
|
||||
item.requested = true;
|
||||
});
|
||||
m.sync(requests).then(function trigger_render(){
|
||||
m.startComputation();
|
||||
m.endComputation();
|
||||
checkFocus();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkFocus(){
|
||||
if (m.initControl != undefined) {
|
||||
var ctrl = document.getElementById(m.initControl);
|
||||
if (ctrl!= null) {
|
||||
ctrl.focus();
|
||||
m.initControl = undefined;
|
||||
} else {
|
||||
console.log("focus-control '" + m.initControl + "' not found!");
|
||||
m.initControl = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// called every time, rs or rs.request failed, only response or value is set
|
||||
function requestFail(path, response, value) {
|
||||
rs.error = "error on " + path;
|
||||
console.log("Error on " + path +
|
||||
(response == null ? ", value: " + value : (", response: " +
|
||||
(response.debug_msg === undefined ? response : response.debug_msg)
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
function rs(path, args, callback, options){
|
||||
if(cache[path] === undefined){
|
||||
options=optionsPrep(options,path);
|
||||
var req = {
|
||||
data: args,
|
||||
statetoken: undefined,
|
||||
requested: false,
|
||||
allow: options.allow,
|
||||
then: function(response){
|
||||
options.log(path + ": response: " + response.returncode);
|
||||
if (!this.allow.match(response.returncode)) {
|
||||
options.onmismatch(response);
|
||||
} else if (callback != undefined && callback != null) {
|
||||
callback(response.data, response.statetoken);
|
||||
}
|
||||
},
|
||||
errorCallback: options.onfail
|
||||
};
|
||||
cache[path] = req;
|
||||
schedule_request_missing();
|
||||
}
|
||||
return cache[path].data;
|
||||
}
|
||||
|
||||
module.exports = rs;
|
||||
|
||||
rs.for_key_in_obj = for_key_in_obj;
|
||||
|
||||
// single request for action
|
||||
rs.request=function(path, args, callback, options){
|
||||
options = optionsPrep(options, path);
|
||||
var req = m.request({
|
||||
method: options.method === undefined ? "POST" : options.method,
|
||||
url: api_url + path,
|
||||
data: args,
|
||||
background: true
|
||||
});
|
||||
req.then(function checkResponseAndCallback(response){
|
||||
options.log(path + ": response: " + response.returncode);
|
||||
if (!options.allow.match(response.returncode)) {
|
||||
options.onmismatch(response);
|
||||
} else if (callback != undefined && callback != null) {
|
||||
callback(response.data, response.statetoken);
|
||||
}
|
||||
}, options.onfail);
|
||||
return req;
|
||||
};
|
||||
|
||||
//set default-values for shared options in rs() and rs.request()
|
||||
function optionsPrep(options, path) {
|
||||
if (options === undefined) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (options.onfail === undefined) {
|
||||
options.onfail = function errhandling(value){
|
||||
requestFail(path, null, value);
|
||||
}
|
||||
};
|
||||
if (options.onmismatch === undefined) {
|
||||
options.onmismatch = function errhandling(response){
|
||||
requestFail(path, response,null);
|
||||
}
|
||||
};
|
||||
|
||||
if (options.log === undefined) {
|
||||
options.log = function(message) {
|
||||
console.log(message);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.allow === undefined) {
|
||||
options.allow = "ok";
|
||||
};
|
||||
return options;
|
||||
}
|
||||
|
||||
// force reload for path
|
||||
rs.forceUpdate = function(path, removeCache){
|
||||
if (removeCache === undefined || !removeCache) {
|
||||
cache[path].requested=false;
|
||||
} else {
|
||||
delete cache[path];
|
||||
}
|
||||
}
|
||||
|
||||
// force reload for all
|
||||
rs.clearCache = function(path, removeCache){
|
||||
console.log("clearing Cache ...")
|
||||
cache = {};
|
||||
console.log("update_scheduled: " + update_scheduled);
|
||||
update_scheduled = false;
|
||||
check_for_changes();
|
||||
console.log("Cache cleared.")
|
||||
}
|
||||
|
||||
// dismiss statetoken (= force reload)
|
||||
rs.untoken = function(path) {
|
||||
cache[path].statetoken = null;
|
||||
}
|
||||
|
||||
|
||||
//return api-path
|
||||
rs.apiurl = function(path) {
|
||||
if (path === undefined) {
|
||||
path="";
|
||||
}
|
||||
if (path.length > 0 && "^\\\\|\\/".match(path)) {
|
||||
path=path.substr(1);
|
||||
}
|
||||
return api_url + path;
|
||||
}
|
||||
|
||||
// counting in menu
|
||||
rs.counting = function(path, counterfnkt) {
|
||||
return function () {
|
||||
var data=rs(path);
|
||||
if (data != undefined) {
|
||||
if (counterfnkt === undefined) {
|
||||
return " (" + data.length + ")";
|
||||
}
|
||||
return " (" + counterfnkt(data) + ")";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
// counting in menu
|
||||
rs.counting2 = function(targets) {
|
||||
return function () {
|
||||
var sum = 0;
|
||||
for (var path in targets) {
|
||||
var data=rs(path);
|
||||
if (data != undefined) {
|
||||
data.map(function(item){
|
||||
sum += parseInt(targets[path](item));
|
||||
});
|
||||
};
|
||||
};
|
||||
if (sum > 0) {
|
||||
return " (" + sum + ")";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
// listing data-elements
|
||||
rs.list = function(path, buildfktn, sortfktn){
|
||||
var list = rs(path);
|
||||
if (list === undefined|| list == null) {
|
||||
return "< waiting for server ... >"
|
||||
};
|
||||
if (sortfktn != undefined && sortfktn != null) {
|
||||
list=list.sort(sortfktn);
|
||||
}
|
||||
return list.map(buildfktn);
|
||||
};
|
||||
|
||||
//remember additional data (feature of last resort)
|
||||
rs.memory = function(path, args){
|
||||
var item = cache[path];
|
||||
if (item === undefined) {
|
||||
rs(path, args);
|
||||
item = cache[path];
|
||||
}
|
||||
if (item.memory === undefined) {
|
||||
item.memory = {};
|
||||
}
|
||||
return item.memory;
|
||||
};
|
||||
|
||||
// Sortierfunktion für Texte von Objekten,
|
||||
// falls einfache Namen nicht funktionieren
|
||||
rs.stringSort = function(textA,textB, innersort, objectA, objectB){
|
||||
if (textA.toLowerCase() == textB.toLowerCase()) {
|
||||
if (innersort === undefined) {
|
||||
return 0
|
||||
}
|
||||
return innersort(objectA,objectB);
|
||||
} else if (textA.toLowerCase() < textB.toLowerCase()) {
|
||||
return -1
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//return sorting-function for string, based on property name
|
||||
//using: list.sort(rs.sort("name"));
|
||||
// -----
|
||||
//innersort: cascading sorting - using:
|
||||
//list.sort(rs.sort("type",rs.sort("name")))
|
||||
rs.sort = function(name, innersort){
|
||||
return function(a,b) {
|
||||
return rs.stringSort(a[name],b[name],innersort,a,b);
|
||||
}
|
||||
}
|
||||
|
||||
//return sorting-function for boolean, based on property name
|
||||
rs.sort.bool = function(name, innersort){
|
||||
return function(a,b){
|
||||
if (a[name] == b[name]) {
|
||||
if (innersort === undefined) {
|
||||
return 0
|
||||
}
|
||||
return innersort(a,b);
|
||||
} else if (a[name]) {
|
||||
return -1
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// searching a element in a list
|
||||
// items: list to search in
|
||||
// name: name of attribute to lookup
|
||||
// value: attribute's value to compare
|
||||
rs.find = function(items, name, value) {
|
||||
if (items === undefined||items == null) {
|
||||
return null;
|
||||
};
|
||||
for(var i = 0, l = items.length; i < l; ++i) {
|
||||
if (items[i][name] == value) {
|
||||
return items[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
54
libresapi/src/webui-src/app/search.js
Normal file
54
libresapi/src/webui-src/app/search.js
Normal file
@ -0,0 +1,54 @@
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
var state = {};
|
||||
var searchText = "";
|
||||
|
||||
function updateText(newText) {
|
||||
searchText = newText;
|
||||
}
|
||||
|
||||
function dosearch(){
|
||||
console.log("searching for: "+searchText);
|
||||
rs.request(
|
||||
"filesearch/create_search", {
|
||||
distant: true,
|
||||
search_string: searchText
|
||||
},
|
||||
function(resp){
|
||||
m.route("/search/" + resp.search_id);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
view: function(){
|
||||
var results = rs("filesearch");
|
||||
if (results === undefined||results == null) {
|
||||
results = [];
|
||||
};
|
||||
return m("div",[
|
||||
m("h2","turtle file search"),
|
||||
m("div", [
|
||||
m("input[type=text]", {onchange:m.withAttr("value", updateText)}),
|
||||
m("input[type=button][value=search]",{onclick:dosearch})
|
||||
]),
|
||||
m("hr"),
|
||||
m("h2","previous searches:"),
|
||||
m("div", [
|
||||
results.map(function(item){
|
||||
var res = rs("filesearch/" + item.id,{},null,{allow:"not_set|ok"});
|
||||
if (res === undefined) {
|
||||
res =[];
|
||||
};
|
||||
return m("div.btn2",{
|
||||
onclick:function(){
|
||||
m.route("/search/" + item.id);
|
||||
}
|
||||
}, item.search_string + " (" + res.length + ")");
|
||||
})
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
|
71
libresapi/src/webui-src/app/searchresult.js
Normal file
71
libresapi/src/webui-src/app/searchresult.js
Normal file
@ -0,0 +1,71 @@
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
module.exports = {
|
||||
view: function(){
|
||||
var id=m.route.param("id");
|
||||
var results = rs("filesearch/" + id ,{},null,{allow:"not_set|ok"});
|
||||
if (results === undefined || results.length == undefined) {
|
||||
results = [];
|
||||
}
|
||||
var searches = rs("filesearch");
|
||||
var searchdetail = "<unknown>";
|
||||
if (!(searches === undefined) && !(searches.length === undefined)) {
|
||||
searches.forEach(function(s){
|
||||
if (s.id == id) {
|
||||
searchdetail = s.search_string;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var dl_ids = [];
|
||||
|
||||
var downloads =rs("transfers/downloads");
|
||||
if (downloads !== undefined) {
|
||||
downloads.map(function(item){
|
||||
dl_ids.push(item.hash);
|
||||
})
|
||||
}
|
||||
|
||||
return m("div",[
|
||||
m("h2","turtle file search results"),
|
||||
m("h3", "searchtext: " + searchdetail + " (" + results.length + ")"),
|
||||
m("hr"),
|
||||
m("table", [
|
||||
m("tr" ,[
|
||||
m("th","name"),
|
||||
m("th","size"),
|
||||
m("th",""),
|
||||
]),
|
||||
results.map(function(file){
|
||||
if (dl_ids.indexOf(file.hash)>=0) {
|
||||
file.state="in download queue"
|
||||
}
|
||||
return m("tr",[
|
||||
m("th",file.name),
|
||||
m("th",file.size),
|
||||
m("th",[
|
||||
file.state === undefined
|
||||
? m("span.btn", {
|
||||
onclick:function(){
|
||||
rs.request("transfers/control_download", {
|
||||
action: "begin",
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
hash: file.hash,
|
||||
}, function(){
|
||||
result="added";
|
||||
});
|
||||
m.startComputation();
|
||||
m.endComputation();
|
||||
}
|
||||
}, "download")
|
||||
: file.state
|
||||
]),
|
||||
])
|
||||
})
|
||||
])
|
||||
])
|
||||
}
|
||||
}
|
||||
|
264
libresapi/src/webui-src/app/servicecontrol.js
Normal file
264
libresapi/src/webui-src/app/servicecontrol.js
Normal file
@ -0,0 +1,264 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
function setOption(id,value) {
|
||||
return function(){
|
||||
rs.request("servicecontrol", {
|
||||
service_id: id,
|
||||
default_allowed: value,
|
||||
});
|
||||
rs.forceUpdate("servicecontrol", true);
|
||||
}
|
||||
}
|
||||
|
||||
function setUserOption(serviceid, userid, value) {
|
||||
return function(){
|
||||
rs.request("servicecontrol/user", {
|
||||
service_id: serviceid,
|
||||
peer_id: userid,
|
||||
enabled: value
|
||||
}, function(){
|
||||
rs.forceUpdate("servicecontrol", true)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createSwitch(isOn, width) {
|
||||
if (width === undefined) {
|
||||
width = "2.1em";
|
||||
}
|
||||
return [
|
||||
m("div.menu", {
|
||||
style: {
|
||||
float:"left",
|
||||
width: width,
|
||||
textAlign: "center",
|
||||
color: "#303030",
|
||||
borderColor: isOn
|
||||
? "lime"
|
||||
: "red",
|
||||
backgroundColor: !isOn
|
||||
? "black"
|
||||
: "lime",
|
||||
}
|
||||
}, "ON"),
|
||||
m("div.menu",{
|
||||
style: {
|
||||
float:"left",
|
||||
width: width,
|
||||
textAlign: "center",
|
||||
marginRight:"5px",
|
||||
color: "#303030",
|
||||
borderColor: isOn
|
||||
? "lime"
|
||||
: "red",
|
||||
backgroundColor: isOn
|
||||
? "black"
|
||||
: "red",
|
||||
}
|
||||
}, "OFF"),
|
||||
];
|
||||
}
|
||||
|
||||
function breadcrums(name, parts){
|
||||
var result = [];
|
||||
rs.for_key_in_obj(parts, function(partname,item){
|
||||
result.push(
|
||||
m("span.btn",{
|
||||
onclick: function(){
|
||||
m.route(item)
|
||||
}
|
||||
},partname)
|
||||
);
|
||||
result.push(" / ");
|
||||
});
|
||||
result.push(name);
|
||||
return result;
|
||||
}
|
||||
|
||||
function serviceView(serviceid) {
|
||||
var service, liste;
|
||||
service = rs.find(rs("servicecontrol"),"service_id",serviceid);
|
||||
if (service == null) {
|
||||
return m("h3","<please wait ... >");
|
||||
}
|
||||
liste = service.default_allowed
|
||||
? service.peers_denied
|
||||
: service.peers_allowed;
|
||||
return m("div", [
|
||||
m("h2", breadcrums(service.service_name, {
|
||||
settings:"/settings",
|
||||
rights: "/settings/servicecontrol",
|
||||
})),
|
||||
m("hr"),
|
||||
m("h2",{
|
||||
style:{
|
||||
float:"left",
|
||||
}
|
||||
},[
|
||||
m("div",{
|
||||
style:{
|
||||
float:"left",
|
||||
}
|
||||
},"user rights for: " + service.service_name + ", default: "),
|
||||
m("div", {
|
||||
onclick: setOption(
|
||||
serviceid,
|
||||
!service.default_allowed
|
||||
),
|
||||
style: {
|
||||
float:"left",
|
||||
marginLeft: "0.4em",
|
||||
marginRight: "0.4em",
|
||||
}
|
||||
},createSwitch(service.default_allowed)),
|
||||
]),
|
||||
m("div", {
|
||||
style: {
|
||||
clear:"left",
|
||||
}
|
||||
}),
|
||||
m("ul", rs.list("peers",function(peer){
|
||||
var locs;
|
||||
locs = peer.locations;
|
||||
locs.sort(rs.sort("location"));
|
||||
return peer.locations.map(function(location){
|
||||
var isExcept, isOn;
|
||||
isExcept = liste != null
|
||||
&& liste.indexOf(location.peer_id)>=0;
|
||||
isOn = service.default_allowed ? !isExcept: isExcept;
|
||||
return m("li", {
|
||||
style: {
|
||||
margin: "5px",
|
||||
color: isOn ? "lime" :"red",
|
||||
}
|
||||
}, [
|
||||
m("div"),
|
||||
m("div", {
|
||||
onclick: setUserOption(
|
||||
serviceid,
|
||||
location.peer_id,
|
||||
!isOn
|
||||
),
|
||||
style: {
|
||||
float:"left",
|
||||
},
|
||||
},createSwitch(isOn)),
|
||||
m("div",
|
||||
{
|
||||
style: {
|
||||
//color: "lime",
|
||||
float:"left",
|
||||
marginLeft: "5px",
|
||||
marginRight: "5px",
|
||||
fontWeight: "bold",
|
||||
}
|
||||
},
|
||||
peer.name + (location.location
|
||||
? " (" + location.location + ")"
|
||||
: "")
|
||||
),
|
||||
m("div", {
|
||||
style: {
|
||||
clear: "left"
|
||||
}
|
||||
}),
|
||||
]);
|
||||
})
|
||||
}, rs.sort("name")))
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
view: function(){
|
||||
if (m.route.param("service_id")) {
|
||||
return serviceView(m.route.param("service_id"));
|
||||
}
|
||||
return m("div", [
|
||||
m("h2", breadcrums("rights", {
|
||||
settings:"/settings",
|
||||
})),
|
||||
m("hr"),
|
||||
m("ul", rs.list("servicecontrol", function(item){
|
||||
return m("li", {
|
||||
style: {
|
||||
margin: "5px",
|
||||
color: item.default_allowed ? "lime" :"red",
|
||||
}
|
||||
}, [
|
||||
m("div"),
|
||||
m("div", {
|
||||
onclick: setOption(
|
||||
item.service_id,
|
||||
!item.default_allowed
|
||||
),
|
||||
style: {
|
||||
float:"left",
|
||||
}
|
||||
},createSwitch(item.default_allowed)),
|
||||
m("div.menu",
|
||||
{
|
||||
style: {
|
||||
// color: "lime",
|
||||
borderColor: item.default_allowed
|
||||
? "lime"
|
||||
: "red",
|
||||
float: "left",
|
||||
marginLeft: "5px",
|
||||
marginRight: "5px",
|
||||
paddingLeft: "2px",
|
||||
paddingRight: "2px",
|
||||
},
|
||||
onclick: function(){
|
||||
m.route("/settings/servicecontrol/", {
|
||||
service_id: item.service_id,
|
||||
})
|
||||
}
|
||||
}, "more"
|
||||
),
|
||||
m("div",
|
||||
{
|
||||
style: {
|
||||
// color: "lime",
|
||||
float:"left",
|
||||
marginLeft: "5px",
|
||||
marginRight: "5px",
|
||||
fontWeight: "bold",
|
||||
}
|
||||
},
|
||||
item.service_name
|
||||
),
|
||||
m("div",
|
||||
{
|
||||
style: {
|
||||
color: "lime",
|
||||
float:"left",
|
||||
marginLeft: "5px",
|
||||
marginRight: "5px",
|
||||
}
|
||||
},
|
||||
(
|
||||
item.default_allowed
|
||||
? ( item.peers_denied != null
|
||||
? "(" + item.peers_denied.length + " denied)"
|
||||
: "")
|
||||
: ( item.peers_allowed != null
|
||||
? "(" + item.peers_allowed.length + " allowed)"
|
||||
: "")
|
||||
)
|
||||
),
|
||||
m("div", {
|
||||
style: {
|
||||
clear: "left"
|
||||
}
|
||||
}),
|
||||
]);
|
||||
})
|
||||
)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
19
libresapi/src/webui-src/app/settings.js
Normal file
19
libresapi/src/webui-src/app/settings.js
Normal file
@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
module.exports = {
|
||||
view: function(){
|
||||
return m("div", [
|
||||
m("h2","settings"),
|
||||
m("hr"),
|
||||
m("div.btn2",{
|
||||
onclick: function(){
|
||||
m.route("/settings/servicecontrol");
|
||||
},
|
||||
}, "rights")
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
8
libresapi/src/webui-src/app/waiting.js
Normal file
8
libresapi/src/webui-src/app/waiting.js
Normal file
@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
var m = require("mithril");
|
||||
var rs = require("retroshare");
|
||||
|
||||
module.exports = {view: function(){
|
||||
return m("h2","please wait ...");
|
||||
}}
|
12
libresapi/src/webui-src/brunch-config.js
Normal file
12
libresapi/src/webui-src/brunch-config.js
Normal file
@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
config:{
|
||||
files:{
|
||||
javascripts:{
|
||||
joinTo: 'app.js'
|
||||
},
|
||||
stylesheets:{
|
||||
joinTo: 'app.css'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
41
libresapi/src/webui-src/make-src/build.bat
Normal file
41
libresapi/src/webui-src/make-src/build.bat
Normal file
@ -0,0 +1,41 @@
|
||||
@echo off
|
||||
REM create webfiles from sources at compile time (works without npm/node.js)
|
||||
|
||||
set publicdest=%1\webui
|
||||
set src=%1\webui-src
|
||||
|
||||
if "%1" == "" set publicdest=..\..\webui&&set src=..
|
||||
|
||||
if exist "%publicdest%" echo remove existing %publicdest%&&rd %publicdest% /S /Q
|
||||
|
||||
echo mkdir %publicdest%
|
||||
md %publicdest%
|
||||
|
||||
echo building app.js
|
||||
echo - copy template.js ...
|
||||
copy %src%\make-src\template.js %publicdest%\app.js
|
||||
|
||||
for %%F in (%src%\app\*.js) DO (set "fname=%%~nF" && CALL :addfile)
|
||||
|
||||
echo building app.css
|
||||
type %src%\app\green-black.scss >> %publicdest%\app.css
|
||||
type %src%\make-src\main.css >> %publicdest%\app.css
|
||||
type %src%\make-src\chat.css >> %publicdest%\app.css
|
||||
|
||||
echo copy index.html
|
||||
copy %src%\app\assets\index.html %publicdest%\index.html
|
||||
|
||||
echo build.bat complete
|
||||
|
||||
goto :EOF
|
||||
|
||||
:addfile
|
||||
echo - adding %fname% ...
|
||||
echo require.register("%fname%", function(exports, require, module) { >> %publicdest%\app.js
|
||||
echo %src%\app\%fname%.js
|
||||
type %src%\app\%fname%.js >> %publicdest%\app.js
|
||||
echo. >> %publicdest%\app.js
|
||||
echo }); >> %publicdest%\app.js
|
||||
|
||||
|
||||
:EOF
|
62
libresapi/src/webui-src/make-src/build.sh
Executable file
62
libresapi/src/webui-src/make-src/build.sh
Executable file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# create webfiles from sources at compile time (works without npm/node.js)
|
||||
|
||||
if [ "$1" = "" ]; then
|
||||
publicdest=../../webui
|
||||
src=..
|
||||
else
|
||||
publicdest=$1/webui
|
||||
src=$1/webui-src
|
||||
fi
|
||||
|
||||
if [ "$2" = "" ]; then
|
||||
|
||||
if [ -d "$publicdest" ]; then
|
||||
echo remove existing $publicdest
|
||||
rm $publicdest -R
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "$publicdest" ]; then
|
||||
echo mkdir $publicdest
|
||||
mkdir $publicdest
|
||||
fi
|
||||
|
||||
if [ "$2" = "" ]||[ "$2" = "app.js" ]; then
|
||||
echo building app.js
|
||||
echo - copy template.js ...
|
||||
cp $src/make-src/template.js $publicdest/app.js
|
||||
|
||||
for filename in $src/app/*.js; do
|
||||
fname=$(basename "$filename")
|
||||
fname="${fname%.*}"
|
||||
echo - adding $fname ...
|
||||
echo require.register\(\"$fname\", function\(exports, require, module\) { >> $publicdest/app.js
|
||||
cat $filename >> $publicdest/app.js
|
||||
echo >> $publicdest/app.js
|
||||
echo }\)\; >> $publicdest/app.js
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$2" = "" ]||[ "$2" = "app.css" ]; then
|
||||
echo building app.css
|
||||
cat $src/app/green-black.scss >> $publicdest/app.css
|
||||
cat $src/make-src/main.css >> $publicdest/app.css
|
||||
cat $src/make-src/chat.css >> $publicdest/app.css
|
||||
fi
|
||||
|
||||
if [ "$2" = "" ]||[ "$2" = "index.html" ]; then
|
||||
echo copy index.html
|
||||
cp $src/app/assets/index.html $publicdest/index.html
|
||||
fi
|
||||
|
||||
if [ "$2" != "" ]&&[ "$3" != "" ]; then
|
||||
if [ ! -d "$3/webui" ]; then
|
||||
echo mkdir $3/webui
|
||||
mkdir $3/webui
|
||||
fi
|
||||
echo copy $2 nach $3/webui/$2
|
||||
cp $publicdest/$2 $3/webui/$2
|
||||
fi
|
||||
echo build.sh complete
|
72
libresapi/src/webui-src/make-src/chat.css
Normal file
72
libresapi/src/webui-src/make-src/chat.css
Normal file
@ -0,0 +1,72 @@
|
||||
.chat {
|
||||
padding: 15px; }
|
||||
.chat.container {
|
||||
height: 100%;
|
||||
padding: 0px;
|
||||
position: relative;
|
||||
box-sizing: border-box; }
|
||||
.chat.header {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 50px;
|
||||
background-color: black;
|
||||
border-bottom: solid 1px gray;
|
||||
box-sizing: border-box; }
|
||||
.chat.left {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: 200px;
|
||||
box-sizing: border-box;
|
||||
background-color: black; }
|
||||
.chat.right {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
width: 200px;
|
||||
box-sizing: border-box; }
|
||||
.chat.middle {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
margin-top: 50px;
|
||||
left: 200px;
|
||||
right: 200px;
|
||||
box-sizing: border-box;
|
||||
padding: 0px;
|
||||
height: 100%;
|
||||
overflow-y: scroll; }
|
||||
.chat.bottom {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 200px;
|
||||
left: 200px;
|
||||
padding: 5px; }
|
||||
.chat.msg {
|
||||
padding: 0px; }
|
||||
.chat.msg.container {
|
||||
position: relative;
|
||||
border-bottom: solid 1px lightgray;
|
||||
padding: 10px;
|
||||
height: unset; }
|
||||
.chat.msg.from {
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
top: 10px;
|
||||
left: 0px;
|
||||
color: white;
|
||||
text-align: right; }
|
||||
.chat.msg.when {
|
||||
float: right;
|
||||
color: lightgray;
|
||||
margin-bottom: 10px; }
|
||||
.chat.msg.text {
|
||||
padding-left: 100px;
|
||||
top: 0px;
|
||||
left: 100px;
|
||||
white-space: pre-wrap;
|
||||
height: initial; }
|
||||
|
15
libresapi/src/webui-src/make-src/init.bat
Normal file
15
libresapi/src/webui-src/make-src/init.bat
Normal file
@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
REM create dummy webfiles at qmake run
|
||||
|
||||
set publicdest=%1\webui
|
||||
if "%1" == "" set publicdest=..\..\webui
|
||||
|
||||
if exist %publicdest% echo remove %publicdest%&&rd %publicdest% /S /Q
|
||||
|
||||
echo create %publicdest%
|
||||
md %publicdest%
|
||||
|
||||
echo create %publicdest%\app.js, %publicdest%\app.css, %publicdest%\index.html
|
||||
echo. > %publicdest%\app.js
|
||||
echo. > %publicdest%\app.css
|
||||
echo. > %publicdest%\index.html
|
22
libresapi/src/webui-src/make-src/init.sh
Executable file
22
libresapi/src/webui-src/make-src/init.sh
Executable file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# create dummy webfiles at qmake run
|
||||
|
||||
if [ "$1" = "" ];then
|
||||
publicdest=../../webui
|
||||
else
|
||||
publicdest=$1/webui
|
||||
fi
|
||||
|
||||
if [ -d "$publicdest" ]; then
|
||||
echo remove $publicdest
|
||||
rm $publicdest -R
|
||||
fi
|
||||
|
||||
echo create $publicdest
|
||||
mkdir $publicdest
|
||||
|
||||
echo touch $publicdest/app.js, $publicdest/app.css, $publicdest/index.html
|
||||
touch $publicdest/app.js -d 1970-01-01
|
||||
touch $publicdest/app.css -d 1970-01-01
|
||||
touch $publicdest/index.html -d 1970-01-01
|
2
libresapi/src/webui-src/make-src/main.css
Normal file
2
libresapi/src/webui-src/make-src/main.css
Normal file
@ -0,0 +1,2 @@
|
||||
html, body, #main {
|
||||
height: 100%; }
|
7
libresapi/src/webui-src/make-src/readme.md
Normal file
7
libresapi/src/webui-src/make-src/readme.md
Normal file
@ -0,0 +1,7 @@
|
||||
this folder contains files needed to create webfiles at compile-time and qmake
|
||||
|
||||
* init.sh creates dummy files at qmake
|
||||
* build.sh creates files at compile time
|
||||
* chat.css compiled version of _chat.sass (.sass should replaced by .scss)
|
||||
* main.css simple template extracted from main.sass
|
||||
* template.js start of compiled app.js, containing additional created content
|
112
libresapi/src/webui-src/make-src/template.js
Normal file
112
libresapi/src/webui-src/make-src/template.js
Normal file
@ -0,0 +1,112 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var globals = typeof window === 'undefined' ? global : window;
|
||||
if (typeof globals.require === 'function') return;
|
||||
|
||||
var modules = {};
|
||||
var cache = {};
|
||||
var aliases = {};
|
||||
var has = ({}).hasOwnProperty;
|
||||
|
||||
var endsWith = function(str, suffix) {
|
||||
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||
};
|
||||
|
||||
var _cmp = 'components/';
|
||||
var unalias = function(alias, loaderPath) {
|
||||
var start = 0;
|
||||
if (loaderPath) {
|
||||
if (loaderPath.indexOf(_cmp) === 0) {
|
||||
start = _cmp.length;
|
||||
}
|
||||
if (loaderPath.indexOf('/', start) > 0) {
|
||||
loaderPath = loaderPath.substring(start, loaderPath.indexOf('/', start));
|
||||
}
|
||||
}
|
||||
var result = aliases[alias + '/index.js'] || aliases[loaderPath + '/deps/' + alias + '/index.js'];
|
||||
if (result) {
|
||||
return _cmp + result.substring(0, result.length - '.js'.length);
|
||||
}
|
||||
return alias;
|
||||
};
|
||||
|
||||
var _reg = /^\.\.?(\/|$)/;
|
||||
var expand = function(root, name) {
|
||||
var results = [], part;
|
||||
var parts = (_reg.test(name) ? root + '/' + name : name).split('/');
|
||||
for (var i = 0, length = parts.length; i < length; i++) {
|
||||
part = parts[i];
|
||||
if (part === '..') {
|
||||
results.pop();
|
||||
} else if (part !== '.' && part !== '') {
|
||||
results.push(part);
|
||||
}
|
||||
}
|
||||
return results.join('/');
|
||||
};
|
||||
|
||||
var dirname = function(path) {
|
||||
return path.split('/').slice(0, -1).join('/');
|
||||
};
|
||||
|
||||
var localRequire = function(path) {
|
||||
return function expanded(name) {
|
||||
var absolute = expand(dirname(path), name);
|
||||
return globals.require(absolute, path);
|
||||
};
|
||||
};
|
||||
|
||||
var initModule = function(name, definition) {
|
||||
var module = {id: name, exports: {}};
|
||||
cache[name] = module;
|
||||
definition(module.exports, localRequire(name), module);
|
||||
return module.exports;
|
||||
};
|
||||
|
||||
var require = function(name, loaderPath) {
|
||||
var path = expand(name, '.');
|
||||
if (loaderPath == null) loaderPath = '/';
|
||||
path = unalias(name, loaderPath);
|
||||
|
||||
if (has.call(cache, path)) return cache[path].exports;
|
||||
if (has.call(modules, path)) return initModule(path, modules[path]);
|
||||
|
||||
var dirIndex = expand(path, './index');
|
||||
if (has.call(cache, dirIndex)) return cache[dirIndex].exports;
|
||||
if (has.call(modules, dirIndex)) return initModule(dirIndex, modules[dirIndex]);
|
||||
|
||||
throw new Error('Cannot find module "' + name + '" from '+ '"' + loaderPath + '"');
|
||||
};
|
||||
|
||||
require.alias = function(from, to) {
|
||||
aliases[to] = from;
|
||||
};
|
||||
|
||||
require.register = require.define = function(bundle, fn) {
|
||||
if (typeof bundle === 'object') {
|
||||
for (var key in bundle) {
|
||||
if (has.call(bundle, key)) {
|
||||
modules[key] = bundle[key];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
modules[bundle] = fn;
|
||||
}
|
||||
};
|
||||
|
||||
require.list = function() {
|
||||
var result = [];
|
||||
for (var item in modules) {
|
||||
if (has.call(modules, item)) {
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
require.brunch = true;
|
||||
require._cache = cache;
|
||||
globals.require = require;
|
||||
})();
|
||||
|
11
libresapi/src/webui-src/package.json
Normal file
11
libresapi/src/webui-src/package.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "webui_neu",
|
||||
"scripts": {
|
||||
"watch": "brunch watch --server"
|
||||
},
|
||||
"devDependencies": {
|
||||
"auto-reload-brunch": "^1.8.0",
|
||||
"brunch": "^1.8.5",
|
||||
"sass-brunch": "^1.9.1"
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
REACT_VERSION = 0.13.1
|
||||
|
||||
DISTDIR = ../webfiles
|
||||
JSEXTLIBS = $(DISTDIR)/react.js $(DISTDIR)/JSXTransformer.js
|
||||
JSLIBS = RsXHRConnection.js RsApi.js
|
||||
HTML = index.html
|
||||
JSGUI = gui.jsx
|
||||
CSS = green-black.css
|
||||
|
||||
all: $(DISTDIR) $(JSEXTLIBS) $(addprefix $(DISTDIR)/, $(JSLIBS)) $(addprefix $(DISTDIR)/, $(HTML)) $(addprefix $(DISTDIR)/, $(JSGUI)) $(addprefix $(DISTDIR)/, $(CSS))
|
||||
.PHONY: all
|
||||
|
||||
$(DISTDIR)/livereload: $(DISTDIR) $(JSEXTLIBS) $(addprefix $(DISTDIR)/, $(JSLIBS)) $(addprefix $(DISTDIR)/, $(HTML)) $(addprefix $(DISTDIR)/, $(JSGUI)) $(addprefix $(DISTDIR)/, $(CSS))
|
||||
wget -qO- http://localhost:9090/api/v2/livereload/trigger
|
||||
touch $(DISTDIR)/livereload
|
||||
|
||||
$(DISTDIR)/react.js:
|
||||
cd $(DISTDIR) && wget --no-check-certificate --output-document react.js http://fb.me/react-$(REACT_VERSION).js
|
||||
|
||||
$(DISTDIR)/JSXTransformer.js:
|
||||
cd $(DISTDIR) && wget --no-check-certificate --output-document JSXTransformer.js http://fb.me/JSXTransformer-$(REACT_VERSION).js
|
||||
|
||||
$(addprefix $(DISTDIR)/, $(JSLIBS)): $(DISTDIR)/%: %
|
||||
cp $< $@
|
||||
|
||||
$(addprefix $(DISTDIR)/, $(HTML)): $(DISTDIR)/%: %
|
||||
cp $< $@
|
||||
|
||||
$(addprefix $(DISTDIR)/, $(JSGUI)): $(DISTDIR)/%: %
|
||||
cp $< $@
|
||||
|
||||
$(addprefix $(DISTDIR)/, $(CSS)): $(DISTDIR)/%: %
|
||||
cp $< $@
|
||||
|
||||
$(DISTDIR):
|
||||
mkdir $(DISTDIR)
|
@ -1,142 +0,0 @@
|
||||
var TypesMod = require("./Types.js");
|
||||
var Type = TypesMod.Type;
|
||||
var string = TypesMod.string;
|
||||
var bool = TypesMod.bool;
|
||||
var any = TypesMod.any;
|
||||
|
||||
if(require.main === module)
|
||||
{
|
||||
var RsNodeHttpConnection = require("./RsNodeHttpConnection.js");
|
||||
debugger;
|
||||
var connection = new RsNodeHttpConnection();
|
||||
var RsApi = require("./RsApi.js");
|
||||
var RS = new RsApi(connection);
|
||||
|
||||
var tests = [];
|
||||
var doc = {
|
||||
counter: 0,
|
||||
toc: [],
|
||||
content: [],
|
||||
header: function(h){
|
||||
this.toc.push(h);
|
||||
this.content.push("<a name=\""+this.counter+"\"><h1>"+h+"</h1></a>");
|
||||
this.counter += 1;
|
||||
},
|
||||
paragraph: function(p){
|
||||
this.content.push("<p>"+p+"</p>");
|
||||
},
|
||||
|
||||
};
|
||||
PeersTest(tests, doc);
|
||||
|
||||
var docstr = "<!DOCTYPE html><html><body>";
|
||||
docstr += "<h1>Table of Contents</h1>";
|
||||
docstr += "<ul>";
|
||||
for(var i in doc.toc)
|
||||
{
|
||||
docstr += "<li><a href=\"#"+i+"\">"+doc.toc[i]+"</a></li>";
|
||||
}
|
||||
docstr += "</ul>";
|
||||
for(var i in doc.content)
|
||||
{
|
||||
docstr += doc.content[i];
|
||||
}
|
||||
docstr += "</body></html>";
|
||||
|
||||
var fs = require('fs');
|
||||
fs.writeFile("dist/api_documentation.html", docstr);
|
||||
|
||||
tests.map(function(test){
|
||||
test(RS);
|
||||
});
|
||||
}
|
||||
|
||||
function PeersTest(tests, doc)
|
||||
{
|
||||
// compound types
|
||||
var location = new Type("location",
|
||||
{
|
||||
avatar_address: string,
|
||||
groups: any,
|
||||
is_online: bool,
|
||||
location: string,
|
||||
peer_id: any,
|
||||
});
|
||||
var peer_info = new Type("peer_info",
|
||||
{
|
||||
name: string,
|
||||
pgp_id: any,
|
||||
locations: [location],
|
||||
});
|
||||
var peers_list = new Type("peers_list",[peer_info]);
|
||||
|
||||
doc.header("peers");
|
||||
doc.paragraph("<pre>"+graphToText(peers_list)+"</pre>");
|
||||
|
||||
tests.push(function(RS){
|
||||
console.log("testing peers module...");
|
||||
console.log("expected schema is:")
|
||||
console.log(graphToText(peers_list));
|
||||
RS.request({path: "peers"}, function(resp){
|
||||
//console.log("got response:"+JSON.stringify(resp));
|
||||
var ok = peers_list.check(function(str){console.log(str);}, resp.data, [])
|
||||
if(ok)
|
||||
console.log("success");
|
||||
else
|
||||
console.log("fail");
|
||||
});
|
||||
});
|
||||
|
||||
function graphToText(top_node)
|
||||
{
|
||||
//var dbg = function(str){console.log(str);};
|
||||
var dbg = function(str){};
|
||||
|
||||
dbg("called graphToText with " + top_node);
|
||||
|
||||
var res = "";
|
||||
|
||||
_visit(top_node.getObj(), 0);
|
||||
|
||||
return res;
|
||||
|
||||
function _indent(count)
|
||||
{
|
||||
var str = "";
|
||||
for(var i = 0; i < count; i++)
|
||||
{
|
||||
str = str + " ";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
function _visit(node, indent)
|
||||
{
|
||||
dbg("_visit");
|
||||
if(node instanceof Array)
|
||||
{
|
||||
dbg("is instanceof Array");
|
||||
//res = res + "[";
|
||||
res = res + "array\n";
|
||||
_visit(node[0], indent);
|
||||
//res = res + _indent(indent) + "]\n";
|
||||
}
|
||||
else if(node instanceof Type && node.isLeaf())
|
||||
{
|
||||
dbg("is instanceof Type");
|
||||
res = res + node.getName() + "\n";
|
||||
}
|
||||
else // Object, have to check all children
|
||||
{
|
||||
dbg("is Object");
|
||||
//res = res + "{\n";
|
||||
for(m in node.getObj())
|
||||
{
|
||||
res = res + _indent(indent+1) + m + ": ";
|
||||
_visit(node.getObj()[m], indent+1);
|
||||
}
|
||||
//res = res + _indent(indent) + "}\n";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
A new approach to build a webinterface for RS
|
||||
=============================================
|
||||
|
||||
1. get JSON encoded data from the backend, data contains a state token
|
||||
2. render data with react.js
|
||||
3. ask the backend if the state token from step 1 expired. If yes, then start again with step 1.
|
||||
|
||||
Steps 1. and 3. are common for most things, only Step 2. differs. This allows to re-use code for steps 1. and 3.
|
||||
|
||||
BUILD / INSTALLATION
|
||||
------------
|
||||
|
||||
- run (requires wget, use MinGW shell on Windows)
|
||||
make
|
||||
- all output files are now in libresapi/src/webfiles
|
||||
- use the --webinterface 9090 command line parameter to enable webui in retroshare-nogui
|
||||
- set the --docroot parameter of retroshare-nogui to point to the "libresapi/src/webfiles" directory
|
||||
(or symlink from /usr/share/RetroShare06/webui on Linux, ./webui on Windows)
|
||||
- retroshare-gui does not have a --docroot parameter. Use symlinks then.
|
||||
|
||||
DEVELOPMENT
|
||||
-----------
|
||||
|
||||
- Ubuntu: install nodejs package
|
||||
sudo apt-get install nodejs
|
||||
- Windows: download and install nodejs from http://nodejs.org
|
||||
- Download development tools with the nodejs package manager (short npm)
|
||||
npm install
|
||||
- run Retroshare with webinterface on port 9090
|
||||
- during development, run this command (use MinGW shell on Windows)
|
||||
while true; do make ../webfiles/livereload --silent; sleep 1; done
|
||||
- the command will copy the source files to libresapi/src/webfiles if they change
|
||||
- it will trigger livereload at http://localhost:9090/api/v2/livereload/trigger
|
||||
|
||||
API DOCUMENTATION
|
||||
-----------------
|
||||
|
||||
- run
|
||||
node PeersTest.js
|
||||
- this will print the expected schema of the api output, and it will try to test it with real data
|
||||
- run retroshare-nogui with webinterface enabled on port 9090, to test if the real output of the api matches the expected schema
|
||||
|
||||
CONTRIBUTE
|
||||
----------
|
||||
|
||||
- if you are a web developer or want to become one
|
||||
get in contact!
|
||||
- lots of work to do, i need you!
|
@ -1,109 +0,0 @@
|
||||
/**
|
||||
* JS Api for Retroshare
|
||||
* @constructor
|
||||
* @param {object} connection - an object which implements a request() function.
|
||||
* The request function should take two parameters: an object to be send as request and a callback.
|
||||
* The callback should get called with an response object on success.
|
||||
*/
|
||||
function RsApi(connection)
|
||||
{
|
||||
var runnign = true;
|
||||
/**
|
||||
* Send a request to the server
|
||||
* @param req - the request so send
|
||||
* @param {Function} cb - callback function which takes the response as parameter
|
||||
*/
|
||||
this.request = function(req, cb)
|
||||
{
|
||||
connection.request(req, cb);
|
||||
};
|
||||
var tokenlisteners = [];
|
||||
/**
|
||||
* Register a callback to be called when the state token expired.
|
||||
* @param {Function} listener - the callback function, which does not take arguments
|
||||
* @param token - the state token to listen for
|
||||
*/
|
||||
this.register_token_listener = function(listener, token)
|
||||
{
|
||||
tokenlisteners.push({listener:listener, token:token});
|
||||
};
|
||||
/**
|
||||
* Unregister a previously registered callback.
|
||||
*/
|
||||
this.unregister_token_listener = function(listener) // no token as parameter, assuming unregister from all listening tokens
|
||||
{
|
||||
var to_delete = [];
|
||||
for(var i=0; i<tokenlisteners.length; i++){
|
||||
if(tokenlisteners[i].listener === listener){
|
||||
to_delete.push(i);
|
||||
}
|
||||
}
|
||||
for(var i=0; i<to_delete.length; i++){
|
||||
// copy the last element to the current index
|
||||
var index = to_delete[i];
|
||||
tokenlisteners[index] = tokenlisteners[tokenlisteners.length-1];
|
||||
// remove last element
|
||||
tokenlisteners.pop();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* start polling for state changes
|
||||
*/
|
||||
this.start = function(){
|
||||
running = true;
|
||||
setTimeout(tick, TICK_INTERVAL);
|
||||
}
|
||||
/**
|
||||
* stop polling for state changes
|
||||
*/
|
||||
this.stop = function(){
|
||||
running = false;
|
||||
}
|
||||
|
||||
// ************** interal stuff **************
|
||||
var TICK_INTERVAL = 3000;
|
||||
function received_tokenstates(resp)
|
||||
{
|
||||
if(resp.data){
|
||||
for(var i=0; i<resp.data.length; i++){
|
||||
var token = resp.data[i];
|
||||
// search the listener for this token
|
||||
for(var j=0; j<tokenlisteners.length; j++){
|
||||
if(tokenlisteners[j].token === token){
|
||||
// call the listener
|
||||
tokenlisteners[j].listener();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// schedule new update
|
||||
if(running)
|
||||
setTimeout(tick, TICK_INTERVAL);
|
||||
};
|
||||
function received_error()
|
||||
{
|
||||
// try again, maybe want a better logic later
|
||||
if(running)
|
||||
setTimeout(tick, TICK_INTERVAL);
|
||||
};
|
||||
function tick()
|
||||
{
|
||||
var data = [];
|
||||
// maybe cache the token list?
|
||||
// profiler will tell us if we should
|
||||
for(var i=0; i<tokenlisteners.length; i++){
|
||||
data.push(tokenlisteners[i].token);
|
||||
}
|
||||
connection.request({
|
||||
path: "statetokenservice",
|
||||
data: data,
|
||||
}, received_tokenstates, received_error);
|
||||
};
|
||||
};
|
||||
|
||||
// with this trick, we should be able to run in browser or nodejs
|
||||
if(typeof window === 'undefined')
|
||||
{
|
||||
// we are running in nodejs, so have to add to export
|
||||
module.exports = RsApi;
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
var http = require('http');
|
||||
|
||||
/**
|
||||
* Connection to the RS backend using http for running under node.js
|
||||
* Mainly for testing, but could also use it for general purpose scripting.
|
||||
* @constructor
|
||||
*/
|
||||
module.exports = function()
|
||||
{
|
||||
var server_hostname = "localhost";
|
||||
var server_port = "9090";
|
||||
var api_root_path = "/api/v2/";
|
||||
|
||||
this.request = function(request, callback)
|
||||
{
|
||||
var data;
|
||||
if(request.data)
|
||||
data = JSON.stringify(request.data);
|
||||
else
|
||||
data = "";
|
||||
|
||||
// NODEJS specific
|
||||
var req = http.request({
|
||||
host: server_hostname,
|
||||
port: server_port,
|
||||
path: api_root_path + request.path,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Length": data.length, // content length is required, else Wt will not provide the data (maybe WT does not like chunked encoding?)
|
||||
}
|
||||
//method: "POST",
|
||||
}, function(response){
|
||||
var databuffer = [];
|
||||
response.on("data", function(chunk){
|
||||
//console.log("got some data");
|
||||
databuffer = databuffer + chunk;
|
||||
})
|
||||
response.on("end", function(){
|
||||
//console.log("finished receiving data");
|
||||
//console.log("data:"+databuffer);
|
||||
callback(JSON.parse(databuffer));
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
//console.log("uploading data:");
|
||||
//console.log(data);
|
||||
req.write(data);
|
||||
req.end();
|
||||
}
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
/**
|
||||
* Connection to the RS backend using XHR
|
||||
* (could add other connections later, for example WebSockets)
|
||||
* @constructor
|
||||
*/
|
||||
function RsXHRConnection(server_hostname, server_port)
|
||||
{
|
||||
var debug;
|
||||
//debug = function(str){console.log(str);};
|
||||
debug = function(str){};
|
||||
|
||||
//server_hostname = "localhost";
|
||||
//server_port = "9090";
|
||||
var api_root_path = "/api/v2/";
|
||||
|
||||
var status_listeners = [];
|
||||
|
||||
function notify_status(status)
|
||||
{
|
||||
for(var i = 0; i < status_listeners.length; i++)
|
||||
{
|
||||
status_listeners[i](status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be called when the state of the connection changes.
|
||||
* @param {function} cb - callback which receives a single argument. The arguments value is "connected" or "not_connected".
|
||||
*/
|
||||
this.register_status_listener = function(cb)
|
||||
{
|
||||
status_listeners.push(cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* Unregister a status callback function.
|
||||
* @param {function} cb - a privously registered callback function
|
||||
*/
|
||||
this.unregister_status_listener = function(cb)
|
||||
{
|
||||
var to_delete = [];
|
||||
for(var i = 0; i < status_listeners.length; i++)
|
||||
{
|
||||
if(status_listeners[i] === cb){
|
||||
to_delete.push(i);
|
||||
}
|
||||
}
|
||||
for(var i = 0; i < to_delete.length; i++)
|
||||
{
|
||||
// copy the last element to the current index
|
||||
var index = to_delete[i];
|
||||
status_listeners[i] = status_listeners[status_listeners.length-1];
|
||||
// remove the last element
|
||||
status_listeners.pop();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a request to the backend
|
||||
* automatically encodes the request as JSON before sending it to the server
|
||||
* @param {object} req - the request to send to the server
|
||||
* @param {function} cb - callback function to be called to handle the response. The callback takes one object as parameter. Can be left undefined.
|
||||
* @param {function} err_cb - callback function to signal a failed request. Can be undefined.
|
||||
*/
|
||||
this.request = function(req, cb, err_cb)
|
||||
{
|
||||
//var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
|
||||
// TODO: window is not available in QML
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function(){
|
||||
//console.log("onreadystatechanged state"+xhr.readyState);
|
||||
// TODO: figure out how to catch errors like connection refused
|
||||
// maybe want to have to set a state variable like ok=false
|
||||
// the gui could then display: "no connection to server"
|
||||
if (xhr.readyState === 4) {
|
||||
if(xhr.status !== 200)
|
||||
{
|
||||
console.log("RsXHRConnection: request failed with status: "+xhr.status);
|
||||
console.log("request was:");
|
||||
console.log(req);
|
||||
notify_status("not_connected");
|
||||
if(err_cb !== undefined)
|
||||
err_cb();
|
||||
return;
|
||||
}
|
||||
// received response
|
||||
notify_status("connected");
|
||||
debug("RsXHRConnection received response:");
|
||||
debug(xhr.responseText);
|
||||
if(false)//if(xhr.responseText === "")
|
||||
{
|
||||
debug("Warning: response is empty");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var respObj = JSON.parse(xhr.responseText);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
debug("Exception during response handling: "+e);
|
||||
}
|
||||
if(cb === undefined)
|
||||
debug("No callback function specified");
|
||||
else
|
||||
cb(respObj);
|
||||
}
|
||||
}
|
||||
// post is required for sending data
|
||||
var method;
|
||||
if(req.data){
|
||||
method = "POST";
|
||||
} else {
|
||||
method = "GET";
|
||||
}
|
||||
xhr.open(method, "http://"+server_hostname+":"+server_port+api_root_path+req.path);
|
||||
var data = JSON.stringify(req.data);
|
||||
debug("RsXHRConnection sending data:");
|
||||
debug(data);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(data);
|
||||
};
|
||||
};
|
@ -1,146 +0,0 @@
|
||||
/**
|
||||
* Construct a new type from an array, object or function.
|
||||
* Use instances of this class to build a schema graph.
|
||||
* The schema graph must not contain data other than arrays and instances of this class.
|
||||
* Use the check function to check if arbitrary JS objects matches the schema.
|
||||
* @constructor
|
||||
* @param {String} name - name for the new type
|
||||
* @param obj - array, object or function
|
||||
* array: array should contain one instance of class "Type"
|
||||
* object: object members can be arrays or instances of class "Type".
|
||||
* Can also have child objects, but the leaf members have to be instances of class "Type"
|
||||
* function: a function which takes three parameters: log, other, stack
|
||||
* must return true if other matches the type, can report errors using the function passed in log.
|
||||
*/
|
||||
function Type(name, obj)
|
||||
{
|
||||
//var dbg = function(str){console.log(str);};
|
||||
var dbg = function(str){};
|
||||
|
||||
this.getName = function(){
|
||||
return name;
|
||||
}
|
||||
this.isLeaf = function(){
|
||||
return typeof(obj) === "function";
|
||||
}
|
||||
this.getObj = function(){
|
||||
return obj;
|
||||
}
|
||||
this.check = function(log, other, stack)
|
||||
{
|
||||
if(typeof(obj) === "object")
|
||||
{
|
||||
stack.push("<"+name+">");
|
||||
var ok = _check(log, obj, other, stack);
|
||||
stack.pop;
|
||||
return ok;
|
||||
}
|
||||
if(typeof(obj) === "function")
|
||||
return obj(log, other, stack);
|
||||
log("FATAL Error: wrong usage of new Type(), second parameter should be an object or checker function");
|
||||
return false;
|
||||
}
|
||||
function _check(log, ref, other, stack)
|
||||
{
|
||||
dbg("_check");
|
||||
dbg("ref=" + ref);
|
||||
dbg("other=" + other);
|
||||
dbg("stack=[" + stack + "]");
|
||||
if(ref instanceof Array)
|
||||
{
|
||||
dbg("is instanceof Array");
|
||||
if(other instanceof Array)
|
||||
{
|
||||
if(other.length > 0)
|
||||
{
|
||||
return _check(log, ref[0], other[0], stack);
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Warning: can't check array of length 0 in ["+stack+"]");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Error: not an Array ["+stack+"]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(ref instanceof Type)
|
||||
{
|
||||
dbg("is instanceof Type");
|
||||
return ref.check(log, other, stack);
|
||||
}
|
||||
else // Object, have to check all children
|
||||
{
|
||||
dbg("is Object");
|
||||
var ok = true;
|
||||
for(m in ref)
|
||||
{
|
||||
if(m in other)
|
||||
{
|
||||
stack.push(m);
|
||||
ok = ok && _check(log, ref[m], other[m], stack);
|
||||
stack.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Error: missing member \""+m+"\" in ["+stack+"]");
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
// check for additionally undocumented members
|
||||
for(m in other)
|
||||
{
|
||||
if(!(m in ref))
|
||||
{
|
||||
log("Warning: found additional member \""+m+"\" in ["+stack+"]");
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// basic data types
|
||||
// - string
|
||||
// - bool
|
||||
// - any (placeholder for unknown type)
|
||||
|
||||
var string = new Type("string",
|
||||
function(log, other, stack)
|
||||
{
|
||||
if(typeof(other) !== "string")
|
||||
{
|
||||
log("Error: not a string ["+stack+"]");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
);
|
||||
var bool = new Type("bool",
|
||||
function(log, other, stack)
|
||||
{
|
||||
if(typeof(other) !== "boolean")
|
||||
{
|
||||
log("Error: not a bool ["+stack+"]");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
);
|
||||
var any = new Type("any",
|
||||
function(log, other, stack)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
exports.Type = Type;
|
||||
exports.string = string;
|
||||
exports.bool = bool;
|
||||
exports.any = any;
|
@ -1,134 +0,0 @@
|
||||
body {
|
||||
background-color: black;
|
||||
color: lime;
|
||||
font-family: monospace;
|
||||
margin: 0em;
|
||||
/*padding: 1.5em;*/
|
||||
padding: 2mm;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
#overlay{
|
||||
z-index: 10;
|
||||
position: fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
}
|
||||
|
||||
.paddingbox{
|
||||
padding:2mm;
|
||||
}
|
||||
|
||||
.nav{
|
||||
list-style-type: none;
|
||||
padding: 0em;
|
||||
margin: 0em;
|
||||
}
|
||||
|
||||
.nav li{
|
||||
display: inline;
|
||||
padding: 0.1em;
|
||||
margin-right: 1em;
|
||||
border-width: 0.1em;
|
||||
border-color: blue;
|
||||
border-bottom-style: solid;
|
||||
cursor: pointer;
|
||||
}
|
||||
td{
|
||||
padding: 0.3em;
|
||||
border-style: solid;
|
||||
border-width: 0.1em;
|
||||
border-color: lime;
|
||||
}
|
||||
.btn{
|
||||
border-style: solid;
|
||||
border-color: lime;
|
||||
border-width: 0.1em;
|
||||
cursor: pointer;
|
||||
padding: 0.1em;
|
||||
}
|
||||
|
||||
.btn2, .box{
|
||||
border-style: solid;
|
||||
/*border-color: lime;*/
|
||||
border-color: limeGreen;
|
||||
/*border-width: 1px;*/
|
||||
border-radius: 3mm;
|
||||
padding: 2mm;
|
||||
font-size: 10mm;
|
||||
cursor: pointer;
|
||||
margin-bottom: 2mm;
|
||||
}
|
||||
.btn2:hover{
|
||||
background-color: midnightblue;
|
||||
}
|
||||
|
||||
.filelink{
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
input, textarea{
|
||||
color: lime;
|
||||
font-family: monospace;
|
||||
background-color: black;
|
||||
border-color: lime;
|
||||
font-size: 10mm;
|
||||
border-radius: 3mm;
|
||||
border-width: 1mm;
|
||||
padding: 2mm;
|
||||
margin-bottom: 2mm;
|
||||
margin-right: 2mm;
|
||||
|
||||
/* make the button the whole screen width */
|
||||
width: 100%;
|
||||
/* make the text input fit small screens*/
|
||||
box-sizing: border-box;
|
||||
}
|
||||
input:hover{
|
||||
background-color: midnightblue;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.flexbox{
|
||||
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
|
||||
display: -ms-flexbox; /* TWEENER - IE 10 */
|
||||
display: -webkit-flex; /* NEW - Chrome */
|
||||
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||
}
|
||||
|
||||
.flexwidemember{
|
||||
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
|
||||
-moz-box-flex: 1; /* OLD - Firefox 19- */
|
||||
width: 20%; /* For old syntax, otherwise collapses. */
|
||||
-webkit-flex: 1; /* Chrome */
|
||||
-ms-flex: 1; /* IE 10 */
|
||||
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
|
||||
}
|
||||
|
||||
#logo_splash{
|
||||
-webkit-animation-fill-mode: forwards; /* Chrome, Safari, Opera */
|
||||
animation-fill-mode: forwards;
|
||||
-webkit-animation-name: logo_splash; /* Chrome, Safari, Opera */
|
||||
-webkit-animation-duration: 3s; /* Chrome, Safari, Opera */
|
||||
animation-name: logo_splash;
|
||||
animation-duration: 3s;
|
||||
text-align: center;
|
||||
}
|
||||
/* Chrome, Safari, Opera */
|
||||
@-webkit-keyframes logo_splash {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
||||
|
||||
/* Standard syntax */
|
||||
@keyframes logo_splash {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,29 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>New webinterface for Retroshare</title>
|
||||
|
||||
<script src="RsXHRConnection.js"></script>
|
||||
<script src="RsApi.js"></script>
|
||||
|
||||
<!-- it seems to work more reliable, if the jsx file is loaded before react -->
|
||||
<script type="text/jsx" src="gui.jsx"></script>
|
||||
|
||||
<script src="react.js"></script>
|
||||
<script src="JSXTransformer.js"></script>
|
||||
|
||||
<link href="green-black.css" rel="stylesheet">
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
document.write("<p>loading lots of stuff...</p>");
|
||||
</script>
|
||||
<p><noscript>The Retroshare web interface requires JavaScript. Please enable JavaScript in your browser.</noscript></p>
|
||||
<!--<div id="logo_splash">
|
||||
<img src="img/logo_splash.png"></img>
|
||||
</div>-->
|
||||
</body>
|
||||
</html>
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "rswebui",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
},
|
||||
"scripts": {
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
|
||||
This is the list of known BUGS:
|
||||
-------------------------------
|
||||
* None!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -124,10 +124,13 @@ void DistantChatService::handleRecvChatStatusItem(RsChatStatusItem *cs)
|
||||
std::cerr << "DistantChatService::handleRecvChatStatusItem(): received keep alive packet for inactive chat! peerId=" << cs->PeerId() << std::endl;
|
||||
}
|
||||
|
||||
bool DistantChatService::acceptDataFromPeer(const RsGxsId& gxs_id,const RsGxsTunnelId& tunnel_id)
|
||||
bool DistantChatService::acceptDataFromPeer(const RsGxsId& gxs_id,const RsGxsTunnelId& tunnel_id,bool is_client_side)
|
||||
{
|
||||
bool res = true ;
|
||||
|
||||
if(is_client_side) // always accept distant chat when we're the client side.
|
||||
return true ;
|
||||
|
||||
if(mDistantChatPermissions & RS_DISTANT_CHAT_CONTACT_PERMISSION_FLAG_FILTER_NON_CONTACTS)
|
||||
res = (rsIdentity!=NULL) && rsIdentity->isARegularContact(gxs_id) ;
|
||||
|
||||
@ -261,9 +264,12 @@ bool DistantChatService::initiateDistantChatConnexion(const RsGxsId& to_gxs_id,
|
||||
RsChatMsgItem *item = new RsChatMsgItem;
|
||||
item->message = "[Starting distant chat. Please wait for secure tunnel to be established]" ;
|
||||
item->chatFlags = RS_CHAT_FLAG_PRIVATE ;
|
||||
item->sendTime = time(NULL) ;
|
||||
item->PeerId(RsPeerId(tunnel_id)) ;
|
||||
handleRecvChatMsgItem(item) ;
|
||||
|
||||
delete item ; // item is replaced by NULL if partial, but this is not the case here.
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
|
||||
// derived in p3ChatService, so as to pass down some info
|
||||
virtual void handleIncomingItem(RsItem *) = 0;
|
||||
virtual bool handleRecvChatMsgItem(RsChatMsgItem *ci)=0 ;
|
||||
virtual bool handleRecvChatMsgItem(RsChatMsgItem *& ci)=0 ;
|
||||
|
||||
bool handleOutgoingItem(RsChatItem *) ;
|
||||
bool handleRecvItem(RsChatItem *) ;
|
||||
@ -89,7 +89,7 @@ public:
|
||||
virtual void connectToGxsTunnelService(RsGxsTunnelService *tunnel_service) ;
|
||||
|
||||
private:
|
||||
virtual bool acceptDataFromPeer(const RsGxsId& gxs_id,const RsGxsTunnelService::RsGxsTunnelId& tunnel_id) ;
|
||||
virtual bool acceptDataFromPeer(const RsGxsId& gxs_id, const RsGxsTunnelService::RsGxsTunnelId& tunnel_id, bool is_client_side) ;
|
||||
virtual void notifyTunnelStatus(const RsGxsTunnelService::RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) ;
|
||||
virtual void receiveData(const RsGxsTunnelService::RsGxsTunnelId& id,unsigned char *data,uint32_t data_size) ;
|
||||
|
||||
|
@ -152,6 +152,10 @@ bool DistributedChatService::handleRecvChatLobbyMsgItem(RsChatMsgItem *ci)
|
||||
return false;
|
||||
}
|
||||
|
||||
// add a routing clue for this peer/GXSid combination. This is quite reliable since the lobby transport is almost instantaneous
|
||||
|
||||
rsGRouter->addRoutingClue(GRouterKeyId(cli->signature.keyId),cli->PeerId()) ;
|
||||
|
||||
ChatLobbyFlags fl ;
|
||||
|
||||
// delete items that are not for us, as early as possible.
|
||||
@ -420,11 +424,6 @@ void DistributedChatService::checkSizeAndSendLobbyMessage(RsChatItem *msg)
|
||||
sendChatItem(msg) ;
|
||||
}
|
||||
|
||||
bool DistributedChatService::locked_checkAndRebuildPartialLobbyMessage(RsChatLobbyMsgItem *ci)
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool DistributedChatService::handleRecvItem(RsChatItem *item)
|
||||
{
|
||||
switch(item->PacketSubType())
|
||||
@ -699,6 +698,9 @@ void DistributedChatService::handleRecvChatLobbyEventItem(RsChatLobbyEventItem *
|
||||
std::cerr << std::endl;
|
||||
return ;
|
||||
}
|
||||
// add a routing clue for this peer/GXSid combination. This is quite reliable since the lobby transport is almost instantaneous
|
||||
rsGRouter->addRoutingClue(GRouterKeyId(item->signature.keyId),item->PeerId()) ;
|
||||
|
||||
if(! bounceLobbyObject(item,item->PeerId()))
|
||||
return ;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user