Open Source notices.
This commit is contained in:
+4
-1
@@ -18,16 +18,19 @@ add_subdirectory("src")
|
|||||||
|
|
||||||
set (REACT_BUILD_DIRECTORY ${PROJECT_SOURCE_DIR}/build/react/build/)
|
set (REACT_BUILD_DIRECTORY ${PROJECT_SOURCE_DIR}/build/react/build/)
|
||||||
|
|
||||||
|
# install
|
||||||
|
|
||||||
install(
|
install(
|
||||||
DIRECTORY config/ DESTINATION /etc/pipedal/config
|
DIRECTORY config/ DESTINATION /etc/pipedal/config
|
||||||
)
|
)
|
||||||
install(
|
install(
|
||||||
FILES ${PROJECT_SRC_DIR}/debian/copyright DESTINATION /usr/share/doc/pipedal/copyright
|
FILES ${PROJECT_SOURCE_DIR}/debian/copyright DESTINATION /usr/share/doc/pipedal/copyright
|
||||||
)
|
)
|
||||||
install (
|
install (
|
||||||
DIRECTORY ${REACT_BUILD_DIRECTORY} DESTINATION /etc/pipedal/react
|
DIRECTORY ${REACT_BUILD_DIRECTORY} DESTINATION /etc/pipedal/react
|
||||||
)
|
)
|
||||||
|
install (FILES ${PROJECT_SOURCE_DIR}/build/src/notices.txt
|
||||||
|
DESTINATION /etc/pipedal/react/var/)
|
||||||
|
|
||||||
install (FILES ${PROJECT_SOURCE_DIR}/src/template.service
|
install (FILES ${PROJECT_SOURCE_DIR}/src/template.service
|
||||||
${PROJECT_SOURCE_DIR}/src/templateShutdown.service
|
${PROJECT_SOURCE_DIR}/src/templateShutdown.service
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
"socketServerAddress": "0.0.0.0:80",
|
"socketServerAddress": "0.0.0.0:80",
|
||||||
|
|
||||||
/* Number of threads to use for servicing websockets */
|
/* Number of threads to use for servicing websockets */
|
||||||
"threads" : 5,
|
"threads" : 10,
|
||||||
|
|
||||||
"logHttpRequests": false,
|
"logHttpRequests": false,
|
||||||
/* { None=0,Error =1,Warning =2,Info = 3, Debug=4} */
|
/* { None=0,Error =1,Warning =2,Info = 3, Debug=4} */
|
||||||
|
|||||||
Vendored
+4787
File diff suppressed because it is too large
Load Diff
Vendored
+21
@@ -1,16 +1,33 @@
|
|||||||
---
|
---
|
||||||
|
check:
|
||||||
|
pattern:
|
||||||
|
- license.*
|
||||||
|
- LICENSE.*
|
||||||
|
- license
|
||||||
|
- LICENSE
|
||||||
|
|
||||||
ignore:
|
ignore:
|
||||||
pattern:
|
pattern:
|
||||||
- /.cache/
|
- /.cache/
|
||||||
- /react/public/
|
- /react/public/
|
||||||
- /debian/
|
- /debian/
|
||||||
|
- /source-map/
|
||||||
- /build/
|
- /build/
|
||||||
- /CMakeFiles/
|
- /CMakeFiles/
|
||||||
|
- /
|
||||||
- /test/
|
- /test/
|
||||||
|
- /atob/
|
||||||
- react/src/react-app-env.d.ts
|
- react/src/react-app-env.d.ts
|
||||||
- react/src/reportWebVitals.ts
|
- react/src/reportWebVitals.ts
|
||||||
- react/src/setupTests.ts
|
- react/src/setupTests.ts
|
||||||
- /usr/share/perl5/Dpkg/Copyright/Scanner.pm
|
- /usr/share/perl5/Dpkg/Copyright/Scanner.pm
|
||||||
|
- react/node_modules/glob/
|
||||||
|
- react/node_modules/fs.realpath/
|
||||||
|
- react/node_modules/sax/
|
||||||
|
- react/node_modules/sha.js/
|
||||||
|
- AUTHORS
|
||||||
|
- /debian/copyright/
|
||||||
|
|
||||||
|
|
||||||
suffixes:
|
suffixes:
|
||||||
- generic
|
- generic
|
||||||
@@ -39,3 +56,7 @@ ignore:
|
|||||||
- nycrc
|
- nycrc
|
||||||
- flow
|
- flow
|
||||||
- bundle.js
|
- bundle.js
|
||||||
|
- js
|
||||||
|
- tsx
|
||||||
|
- md
|
||||||
|
- yml
|
||||||
Vendored
+50
@@ -1,4 +1,8 @@
|
|||||||
---
|
---
|
||||||
|
/:
|
||||||
|
license: Expat
|
||||||
|
copyright: 2021, Robin Davies.
|
||||||
|
|
||||||
src/react/:
|
src/react/:
|
||||||
license: Expat
|
license: Expat
|
||||||
copyright: 2021, Robin Davies.
|
copyright: 2021, Robin Davies.
|
||||||
@@ -174,8 +178,54 @@ react/node_modules/atob/:
|
|||||||
copyright: 2012-2018, AJ ONeal
|
copyright: 2012-2018, AJ ONeal
|
||||||
license: Apache-2.0 or Expat
|
license: Apache-2.0 or Expat
|
||||||
|
|
||||||
|
react/node_modules/fs.realpath/old.js:
|
||||||
|
copyright: Copyright Joyent, Inc. and other Node contributors.
|
||||||
|
license: Expat
|
||||||
|
|
||||||
|
|
||||||
|
react/node_modules/fs.realpath/:
|
||||||
|
copyright: Copyright (c) Isaac Z. Schlueter and Contributors
|
||||||
|
license: ISC
|
||||||
|
|
||||||
|
react/node_modules/glob/:
|
||||||
|
license: CC-BY-SA-4.0 or ISC
|
||||||
|
|
||||||
|
debian/:
|
||||||
|
skip: 1
|
||||||
|
|
||||||
|
~/src/pipedal/react/node_modules/indefinite-observable/AUTHORS:
|
||||||
|
skip: 1
|
||||||
|
|
||||||
|
react/node_modules/node-notifier/vendor/snoreToast/:
|
||||||
|
license: LGPL-3
|
||||||
|
|
||||||
|
react/node_modules/sockjs-client/AUTHORS:
|
||||||
|
skip: 1
|
||||||
|
|
||||||
|
react/node_modules/terser/bin/:
|
||||||
|
skip: 1
|
||||||
|
|
||||||
|
react/node_modules/unquote/:
|
||||||
|
license: Expat
|
||||||
|
|
||||||
|
react/node_modules/css-select/:
|
||||||
|
license: BSD-2-clause
|
||||||
|
|
||||||
|
react/node_modules/css-what/:
|
||||||
|
license: BSD-2-clause
|
||||||
|
|
||||||
|
react/node_modules/dom-serializer/:
|
||||||
|
license: BSD-2-clause
|
||||||
|
|
||||||
|
react/node_modules/domelementtype/:
|
||||||
|
license: BSD-2-clause
|
||||||
|
|
||||||
|
react/node_modules/domelementtype/:
|
||||||
|
license: BSD-2-clause
|
||||||
|
|
||||||
|
react/node_modules/domelementtype/:
|
||||||
|
license: BSD-2-clause
|
||||||
|
|
||||||
|
react/node_modules/domutils/:
|
||||||
|
license: BSD-2-clause
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ endif()
|
|||||||
|
|
||||||
set (BUILD_DIRECTORY ${PROJECT_SOURCE_DIR}/build/react/build)
|
set (BUILD_DIRECTORY ${PROJECT_SOURCE_DIR}/build/react/build)
|
||||||
|
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${BUILD_DIRECTORY}/index.html
|
OUTPUT ${BUILD_DIRECTORY}/index.html
|
||||||
COMMAND ${BUILD_REACT}
|
COMMAND ${BUILD_REACT}
|
||||||
|
|||||||
+38
-11
@@ -12,6 +12,7 @@ import { Theme, withStyles, WithStyles, createStyles } from '@material-ui/core/s
|
|||||||
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
|
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
|
||||||
import Divider from '@material-ui/core/Divider';
|
import Divider from '@material-ui/core/Divider';
|
||||||
import JackHostStatus from './JackHostStatus';
|
import JackHostStatus from './JackHostStatus';
|
||||||
|
import {PiPedalError} from './PiPedalError';
|
||||||
|
|
||||||
|
|
||||||
interface AboutDialogProps extends WithStyles<typeof styles> {
|
interface AboutDialogProps extends WithStyles<typeof styles> {
|
||||||
@@ -23,6 +24,8 @@ interface AboutDialogProps extends WithStyles<typeof styles> {
|
|||||||
|
|
||||||
interface AboutDialogState {
|
interface AboutDialogState {
|
||||||
jackStatus?: JackHostStatus;
|
jackStatus?: JackHostStatus;
|
||||||
|
|
||||||
|
openSourceNotices: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -90,16 +93,17 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
|
|||||||
class extends Component<AboutDialogProps, AboutDialogState> {
|
class extends Component<AboutDialogProps, AboutDialogState> {
|
||||||
|
|
||||||
model: PiPedalModel;
|
model: PiPedalModel;
|
||||||
|
refNotices: React.RefObject<HTMLDivElement>;
|
||||||
|
|
||||||
|
|
||||||
constructor(props: AboutDialogProps) {
|
constructor(props: AboutDialogProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.model = PiPedalModelFactory.getInstance();
|
this.model = PiPedalModelFactory.getInstance();
|
||||||
|
this.refNotices = React.createRef();
|
||||||
this.handleDialogClose = this.handleDialogClose.bind(this);
|
this.handleDialogClose = this.handleDialogClose.bind(this);
|
||||||
this.state = {
|
this.state = {
|
||||||
jackStatus: undefined
|
jackStatus: undefined,
|
||||||
|
openSourceNotices: ""
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -134,10 +138,37 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startFossRequest()
|
||||||
|
{
|
||||||
|
if (this.state.openSourceNotices === "")
|
||||||
|
{
|
||||||
|
fetch("var/notices.txt")
|
||||||
|
.then((request)=>
|
||||||
|
{
|
||||||
|
if (!request.ok)
|
||||||
|
{
|
||||||
|
throw new PiPedalError("notices request failed.");
|
||||||
|
}
|
||||||
|
return request.text();
|
||||||
|
})
|
||||||
|
.then((text) => {
|
||||||
|
if (this.mounted)
|
||||||
|
{
|
||||||
|
this.setState({ openSourceNotices: text});
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
// ok in debug builds. File doesn't get placed until install time.
|
||||||
|
console.log("Failed to fetch open-source notices. " + err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.mounted = true;
|
this.mounted = true;
|
||||||
this.updateNotifications();
|
this.updateNotifications();
|
||||||
|
this.startFossRequest();
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.mounted = false;
|
this.mounted = false;
|
||||||
@@ -175,10 +206,10 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
|
|||||||
</div>
|
</div>
|
||||||
<div style={{
|
<div style={{
|
||||||
flex: "1 1 auto", position: "relative", overflow: "hidden",
|
flex: "1 1 auto", position: "relative", overflow: "hidden",
|
||||||
overflowX: "hidden", overflowY: "auto", margin: 22
|
overflowX: "hidden", overflowY: "auto"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>
|
<div style={{margin: 24}}>
|
||||||
<Typography display="block" variant="h6" color="textPrimary">
|
<Typography display="block" variant="h6" color="textPrimary">
|
||||||
PiPedal <span style={{fontSize: "0.7em"}}>
|
PiPedal <span style={{fontSize: "0.7em"}}>
|
||||||
{(this.model.serverVersion? this.model.serverVersion.serverVersion : "")
|
{(this.model.serverVersion? this.model.serverVersion.serverVersion : "")
|
||||||
@@ -201,12 +232,8 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
|
|||||||
<Typography display="block" variant="caption" >
|
<Typography display="block" variant="caption" >
|
||||||
LEGAL NOTICES
|
LEGAL NOTICES
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography display="block" variant="caption" style={{paddingTop: 12, paddingBottom: 12}} >
|
<div dangerouslySetInnerHTML={{__html: this.state.openSourceNotices}}>
|
||||||
Pi Pedal uses the following open-source components.
|
</div>
|
||||||
</Typography>
|
|
||||||
<Typography display="block" variant="caption" style={{paddingTop: 12, paddingBottom: 12}} >
|
|
||||||
TBD
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+14
-1
@@ -1 +1,14 @@
|
|||||||
|
.fossCopyrights P {
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
.fossCopyrights {
|
||||||
|
padding-top: 16px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
.fossLicense {
|
||||||
|
padding-left: 36px;
|
||||||
|
border-bottom: 1px #CCC solid
|
||||||
|
}
|
||||||
|
|||||||
+35
-5
@@ -30,7 +30,7 @@ endif()
|
|||||||
|
|
||||||
pkg_check_modules(LILV_0 "lilv-0")
|
pkg_check_modules(LILV_0 "lilv-0")
|
||||||
if(!LILV_0_FOUND)
|
if(!LILV_0_FOUND)
|
||||||
message(ERROR "lilv-0 package not installed.")
|
message(ERROR "liblilv-dev package not installed.")
|
||||||
else()
|
else()
|
||||||
message(STATUS "LILV_0_LIBRARIES: ${LILV_0_LIBRARIES}")
|
message(STATUS "LILV_0_LIBRARIES: ${LILV_0_LIBRARIES}")
|
||||||
message(STATUS "LILV_0_INCLUDE_DIRS: ${LILV_0_INCLUDE_DIRS}")
|
message(STATUS "LILV_0_INCLUDE_DIRS: ${LILV_0_INCLUDE_DIRS}")
|
||||||
@@ -121,7 +121,7 @@ configure_file(config.hpp.in config.hpp)
|
|||||||
add_executable(pipedald ${PIPEDAL_SOURCES} main.cpp
|
add_executable(pipedald ${PIPEDAL_SOURCES} main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories( ${PiPedal_SOURCE_DIR}/. ../build/src)
|
include_directories( ${pipedald_SOURCE_DIR}/. ../build/src)
|
||||||
|
|
||||||
target_precompile_headers(pipedald PRIVATE pch.h)
|
target_precompile_headers(pipedald PRIVATE pch.h)
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ add_executable(pipedaltest ${PIPEDAL_SOURCES} testMain.cpp
|
|||||||
)
|
)
|
||||||
|
|
||||||
configure_file(config.hpp.in config.hpp)
|
configure_file(config.hpp.in config.hpp)
|
||||||
include_directories( ${PiPedal_SOURCE_DIR}/. ../build/src)
|
include_directories( ${pipedald_SOURCE_DIR}/. ../build/src)
|
||||||
|
|
||||||
target_precompile_headers(pipedaltest PRIVATE pch.h)
|
target_precompile_headers(pipedaltest PRIVATE pch.h)
|
||||||
|
|
||||||
@@ -170,7 +170,8 @@ add_executable(pipedalconfig json.cpp json.hpp
|
|||||||
SetWifiConfig.hpp SetWifiConfig.cpp
|
SetWifiConfig.hpp SetWifiConfig.cpp
|
||||||
SystemConfigFile.hpp SystemConfigFile.cpp
|
SystemConfigFile.hpp SystemConfigFile.cpp
|
||||||
SysExec.hpp SysExec.cpp
|
SysExec.hpp SysExec.cpp
|
||||||
)
|
asan_options.cpp
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(pipedalconfig PRIVATE pthread atomic stdc++fs
|
target_link_libraries(pipedalconfig PRIVATE pthread atomic stdc++fs
|
||||||
)
|
)
|
||||||
@@ -183,11 +184,40 @@ add_executable(pipedalshutdownd ShutdownMain.cpp CommandLineParser.hpp
|
|||||||
SetWifiConfig.hpp SetWifiConfig.cpp
|
SetWifiConfig.hpp SetWifiConfig.cpp
|
||||||
SystemConfigFile.hpp SystemConfigFile.cpp
|
SystemConfigFile.hpp SystemConfigFile.cpp
|
||||||
SysExec.hpp SysExec.cpp
|
SysExec.hpp SysExec.cpp
|
||||||
|
asan_options.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(pipedalshutdownd PRIVATE pthread atomic stdc++fs systemd)
|
target_link_libraries(pipedalshutdownd PRIVATE pthread atomic stdc++fs systemd)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(processcopyrights copyrightMain.cpp
|
||||||
|
CommandLineParser.hpp
|
||||||
|
PiPedalException.hpp
|
||||||
|
HtmlHelper.hpp HtmlHelper.cpp
|
||||||
|
asan_options.cpp )
|
||||||
|
target_link_libraries(processcopyrights PRIVATE stdc++fs)
|
||||||
|
|
||||||
|
set (REACT_BUILD_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../build/react/build/)
|
||||||
|
set (REACT_NOTICES_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../build/src/notices.txt)
|
||||||
|
set (DEBIAN_COPYRIGHT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../debian/copyright)
|
||||||
|
|
||||||
|
# generate Copyright section of settings page.
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${REACT_NOTICES_FILE}
|
||||||
|
COMMAND "$<TARGET_FILE:processcopyrights>"
|
||||||
|
--output ${REACT_NOTICES_FILE}
|
||||||
|
--projectCopyright ${DEBIAN_COPYRIGHT_FILE}
|
||||||
|
liblilv-0-0 libboost-system1.67-dev libnl-3-dev libnl-3-dev lv2-dev
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
DEPENDS ${DEBIAN_COPYRIGHT_FILE} "$<TARGET_FILE:processcopyrights>"
|
||||||
|
COMMENT "Updating copyright notices."
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target (
|
||||||
|
CopyrightBuild ALL
|
||||||
|
DEPENDS ${REACT_NOTICES_FILE}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
install (TARGETS pipedalconfig pipedald pipedalshutdownd DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
install (TARGETS pipedalconfig pipedald pipedalshutdownd DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||||
EXPORT pipedalTargets)
|
EXPORT pipedalTargets)
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -221,7 +221,7 @@ std::string HtmlHelper::Rfc5987EncodeFileName(const std::string&name)
|
|||||||
|
|
||||||
const std::string SF_SPECIALS = " <>@;:\"\'/[]?=";
|
const std::string SF_SPECIALS = " <>@;:\"\'/[]?=";
|
||||||
|
|
||||||
std::string HtmlHelper::SafeFileName(const std::string name)
|
std::string HtmlHelper::SafeFileName(const std::string &name)
|
||||||
{
|
{
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
for (char c : name)
|
for (char c : name)
|
||||||
@@ -239,6 +239,22 @@ std::string HtmlHelper::SafeFileName(const std::string name)
|
|||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string HtmlHelper::HtmlEncode(const std::string& text)
|
||||||
|
{
|
||||||
|
std::stringstream os;
|
||||||
|
for (char c: text)
|
||||||
|
{
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '<': os << "<"; break;
|
||||||
|
case '>': os << ">"; break;
|
||||||
|
case '&': os << "&"; break;
|
||||||
|
default: os << c; break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -47,7 +47,8 @@ public:
|
|||||||
|
|
||||||
static std::string Rfc5987EncodeFileName(const std::string&name);
|
static std::string Rfc5987EncodeFileName(const std::string&name);
|
||||||
|
|
||||||
static std::string SafeFileName(const std::string name);
|
static std::string SafeFileName(const std::string &name);
|
||||||
|
static std::string HtmlEncode(const std::string& text);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,374 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "CommandLineParser.hpp"
|
||||||
|
#include "PiPedalException.hpp"
|
||||||
|
#include <filesystem>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string.h>
|
||||||
|
#include <set>
|
||||||
|
#include "HtmlHelper.hpp"
|
||||||
|
|
||||||
|
using namespace pipedal;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#define UNKNOWN_LICENSE "~unknown" // primary purpose: show this group last, not first.
|
||||||
|
|
||||||
|
std::vector<std::string> unknownLicense ={
|
||||||
|
"Unknown License",
|
||||||
|
"."
|
||||||
|
"These copyright notices were found, but we were unable to automatically identify an associated license."
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Copyrights {
|
||||||
|
struct License {
|
||||||
|
std::string tag;
|
||||||
|
std::vector<std::string> licenseText;
|
||||||
|
std::set<std::string> copyrights;
|
||||||
|
};
|
||||||
|
std::map<std::string,std::shared_ptr<License> > licenseMap;
|
||||||
|
static std::string trim(const std::string&value)
|
||||||
|
{
|
||||||
|
size_t start = 0;
|
||||||
|
while (start < value.length() && value[start] == ' ' || value[start] == '\t')
|
||||||
|
{
|
||||||
|
++start;
|
||||||
|
}
|
||||||
|
size_t end = value.length();
|
||||||
|
while (end > start && value[end-1] == ' ' || value[end-1] == '\t')
|
||||||
|
{
|
||||||
|
--end;
|
||||||
|
}
|
||||||
|
return value.substr(start,end-start);
|
||||||
|
}
|
||||||
|
void addLicense(const std::string&license,const std::vector<std::string> &licenseText)
|
||||||
|
{
|
||||||
|
auto currentLicense = licenseMap.find(license);
|
||||||
|
if (currentLicense == licenseMap.end())
|
||||||
|
{
|
||||||
|
std::shared_ptr<License> l = std::make_shared<License>();
|
||||||
|
l->tag = license;
|
||||||
|
l->licenseText = licenseText;
|
||||||
|
licenseMap[license] = std::move(l);
|
||||||
|
} else {
|
||||||
|
(*currentLicense).second->licenseText = licenseText;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCopyright(std::string license,const std::string ©right)
|
||||||
|
{
|
||||||
|
if (copyright.length() == 0) return;
|
||||||
|
if (copyright == "no-info-found") return;
|
||||||
|
if (copyright == "info-missing") return;
|
||||||
|
if (license == "")
|
||||||
|
{
|
||||||
|
license = UNKNOWN_LICENSE;
|
||||||
|
}
|
||||||
|
auto currentLicense = licenseMap.find(license);
|
||||||
|
if (currentLicense == licenseMap.end())
|
||||||
|
{
|
||||||
|
std::shared_ptr<License> l = std::make_shared<License>();
|
||||||
|
l->tag = license;
|
||||||
|
l->copyrights.insert(copyright);
|
||||||
|
licenseMap[license] = l;
|
||||||
|
} else {
|
||||||
|
auto & copyrights = (*currentLicense).second->copyrights;
|
||||||
|
copyrights.insert(copyright);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool splitLicense(const std::string & license, const std::string &match, std::string*pLeft, std::string *pRight)
|
||||||
|
{
|
||||||
|
auto pos = license.find(match);
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
*pLeft = trim(license.substr(0,pos));
|
||||||
|
*pRight = trim(license.substr(pos+match.length()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void parseLicenses(const std::string &license,std::vector<std::string>*pLicenses)
|
||||||
|
{
|
||||||
|
std::string l,r;
|
||||||
|
if (splitLicense(license," and ",&l,&r))
|
||||||
|
{
|
||||||
|
parseLicenses(l,pLicenses);
|
||||||
|
parseLicenses(r,pLicenses);
|
||||||
|
|
||||||
|
} else if (splitLicense(license," or ",&l,&r))
|
||||||
|
{
|
||||||
|
parseLicenses(l,pLicenses);
|
||||||
|
parseLicenses(r,pLicenses);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
auto pos = license.find_last_of(',');
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
pLicenses->push_back(license.substr(0,pos));
|
||||||
|
} else {
|
||||||
|
pLicenses->push_back(license);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void addCopyright(
|
||||||
|
std::string license,
|
||||||
|
const std::vector<std::string> &licenseText,
|
||||||
|
const std::vector<std::string> ©rights)
|
||||||
|
{
|
||||||
|
if (license.length() == 0 && licenseText.size() != 0)
|
||||||
|
{
|
||||||
|
std::stringstream uniqueName;
|
||||||
|
uniqueName << "unique-" << licenseMap.size();
|
||||||
|
license = uniqueName.str();
|
||||||
|
}
|
||||||
|
std::vector<std::string> licenses;
|
||||||
|
parseLicenses(license,&licenses);
|
||||||
|
for (size_t i = 0; i < licenses.size(); ++i)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < copyrights.size(); ++j)
|
||||||
|
{
|
||||||
|
addCopyright(licenses[i], copyrights[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (licenseText.size() != 0)
|
||||||
|
{
|
||||||
|
addLicense(license,licenseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void writeLicenseText(std::ostream &os, const std::vector<std::string>&licenseText)
|
||||||
|
{
|
||||||
|
bool open = false;
|
||||||
|
for (const std::string&line: licenseText)
|
||||||
|
{
|
||||||
|
if (line == ".")
|
||||||
|
{
|
||||||
|
if (open) {
|
||||||
|
os << "</p>" << endl;
|
||||||
|
} else {
|
||||||
|
os << "<p> </p>" << endl;
|
||||||
|
}
|
||||||
|
open = false;
|
||||||
|
} else {
|
||||||
|
if (!open)
|
||||||
|
{
|
||||||
|
open = true;
|
||||||
|
os << "<p>";
|
||||||
|
}
|
||||||
|
os << HtmlHelper::HtmlEncode(line) << ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (open)
|
||||||
|
{
|
||||||
|
os << "</p>" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static std::vector<std::string> copyrightPrefixes;
|
||||||
|
|
||||||
|
std::string stripCopyrightPrefix(std::string text)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (auto & prefix: copyrightPrefixes)
|
||||||
|
{
|
||||||
|
if (text.rfind(prefix,0) != std::string::npos)
|
||||||
|
{
|
||||||
|
text = trim(text.substr(prefix.length()));
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
void write(const std::filesystem::path&path)
|
||||||
|
{
|
||||||
|
ofstream f(path);
|
||||||
|
if (!f.is_open())
|
||||||
|
{
|
||||||
|
throw PiPedalException(SS("Can't write to " << path));
|
||||||
|
}
|
||||||
|
f << "<div class='fossLicenses'>" << endl;
|
||||||
|
|
||||||
|
f << "<div class='fossIntro'>" << endl;
|
||||||
|
f << "<p>PiPedal uses open-source software covered by the following copyright notices and licenses.</p>" << endl;
|
||||||
|
f << "</div>" << endl;
|
||||||
|
for (auto &iter: licenseMap)
|
||||||
|
{
|
||||||
|
auto license = (iter).second;
|
||||||
|
if (license->copyrights.size() != 0)
|
||||||
|
{
|
||||||
|
f << "<div class='fossCopyrights'>" << endl;
|
||||||
|
for (auto©right: license->copyrights) {
|
||||||
|
std::string text = stripCopyrightPrefix(copyright);
|
||||||
|
f << " <p>\u00A9 " << HtmlHelper::HtmlEncode(text) << "</p>" << endl;
|
||||||
|
}
|
||||||
|
f << "</div>" << endl;
|
||||||
|
f << "<div class='fossLicense' tag='" << license->tag << "'>" << endl;
|
||||||
|
if (license->tag == UNKNOWN_LICENSE) {
|
||||||
|
writeLicenseText(f,unknownLicense);
|
||||||
|
} else {
|
||||||
|
writeLicenseText(f,license->licenseText);
|
||||||
|
}
|
||||||
|
f << "</div>" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void loadFile(const std::filesystem::path&path)
|
||||||
|
{
|
||||||
|
std::ifstream f(path);
|
||||||
|
if (!f.is_open())
|
||||||
|
{
|
||||||
|
stringstream s;
|
||||||
|
s << "Can't open file " << path;
|
||||||
|
throw PiPedalException(s.str());
|
||||||
|
}
|
||||||
|
std::vector<std::string> copyrights;
|
||||||
|
std::vector<std::string> licenseText;
|
||||||
|
std::string license;
|
||||||
|
enum class State {
|
||||||
|
none,
|
||||||
|
copyright,
|
||||||
|
license,
|
||||||
|
other
|
||||||
|
};
|
||||||
|
State state = State::none;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (f.eof()) break;
|
||||||
|
std::string line;
|
||||||
|
std::getline(f,line);
|
||||||
|
bool isContinuation = (line[0] == ' ' || line[0] == '\t');
|
||||||
|
line = trim(line);
|
||||||
|
|
||||||
|
|
||||||
|
if (line.length() == 0)
|
||||||
|
{
|
||||||
|
if (copyrights.size() != 0 || licenseText.size() != 0)
|
||||||
|
{
|
||||||
|
addCopyright(license,licenseText,copyrights);
|
||||||
|
}
|
||||||
|
copyrights.clear();
|
||||||
|
license.clear();
|
||||||
|
licenseText.clear();
|
||||||
|
} else {
|
||||||
|
if (isContinuation)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case State::copyright:
|
||||||
|
copyrights.push_back(line);
|
||||||
|
break;
|
||||||
|
case State::none:
|
||||||
|
break; // permissively ignore it.
|
||||||
|
case State::license:
|
||||||
|
licenseText.push_back(line);
|
||||||
|
break;
|
||||||
|
case State::other:
|
||||||
|
// ignore
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int nPos = line.find(':');
|
||||||
|
if (nPos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string tag = line.substr(0,nPos);
|
||||||
|
std::string arg = trim(line.substr(nPos+1));
|
||||||
|
if (tag == "Copyright")
|
||||||
|
{
|
||||||
|
copyrights.push_back(arg);
|
||||||
|
state = State::copyright;
|
||||||
|
} else if (tag == "License")
|
||||||
|
{
|
||||||
|
license = arg;
|
||||||
|
state = State::license;
|
||||||
|
} else {
|
||||||
|
state = State::other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::string> Copyrights::copyrightPrefixes = {
|
||||||
|
"Copyright",
|
||||||
|
"copyright",
|
||||||
|
"(c)",
|
||||||
|
"(C)",
|
||||||
|
"\u00A9"
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, const char*argv[])
|
||||||
|
{
|
||||||
|
CommandLineParser parser;
|
||||||
|
bool help = false;
|
||||||
|
bool helpError = false;
|
||||||
|
std::string copyrightFile;
|
||||||
|
std::string outputFile;
|
||||||
|
parser.AddOption("-h",&help);
|
||||||
|
parser.AddOption("--help",&help);
|
||||||
|
parser.AddOption("--projectCopyright",©rightFile);
|
||||||
|
parser.AddOption("--output", &outputFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
parser.Parse(argc,argv);
|
||||||
|
if (copyrightFile == "")
|
||||||
|
{
|
||||||
|
throw PiPedalException("--projectCopyright not specified.");
|
||||||
|
}
|
||||||
|
if (outputFile == "")
|
||||||
|
{
|
||||||
|
throw PiPedalException("--output file not specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
cerr << "Error: " << e.what() << endl;
|
||||||
|
helpError = true;
|
||||||
|
}
|
||||||
|
if (help || helpError)
|
||||||
|
{
|
||||||
|
if (helpError)
|
||||||
|
{
|
||||||
|
cerr << endl;
|
||||||
|
}
|
||||||
|
cout << "Syntax: processcopyrights --projectCopyright debian/copyright -output <oututfile> [<dependents>]*" << endl;
|
||||||
|
return helpError? EXIT_FAILURE: EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Copyrights copyrights;
|
||||||
|
copyrights.loadFile(copyrightFile);
|
||||||
|
for (std::string dependent: parser.Arguments())
|
||||||
|
{
|
||||||
|
cout << "Processing copyrights for " << dependent << endl;
|
||||||
|
std::filesystem::path dependentCopyrightFile =
|
||||||
|
std::filesystem::path("/usr/share/doc")
|
||||||
|
/ dependent / "copyright";
|
||||||
|
copyrights.loadFile(dependentCopyrightFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// our file last, so that our notices take precedence.
|
||||||
|
cout << "Processing copyrights for " << copyrightFile << endl;
|
||||||
|
copyrights.loadFile(copyrightFile);
|
||||||
|
|
||||||
|
|
||||||
|
copyrights.write(outputFile);
|
||||||
|
|
||||||
|
cout << "Copyright notices written to " << outputFile << endl;
|
||||||
|
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user