mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-04 06:11:39 +00:00
Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
542f21d58d | ||
|
|
1af3f9f196 | ||
|
|
f0ca2e2601 | ||
|
|
84f0296917 | ||
|
|
96ad8c15c6 | ||
|
|
d77d45b5bc | ||
|
|
dc788a68f8 | ||
|
|
d3af49972c | ||
|
|
c7a732a61e | ||
|
|
d28a412204 | ||
|
|
2722d97a7d | ||
|
|
79c62d86cc | ||
|
|
9f1dcc4c9f | ||
|
|
4230f49bd9 | ||
|
|
9fe9171798 | ||
|
|
dac3b79f4d | ||
|
|
083c2f4e9b | ||
|
|
17f88eb4e7 | ||
|
|
2798e89925 | ||
|
|
79db8f2df3 | ||
|
|
089aadd729 | ||
|
|
201e37d185 | ||
|
|
9d6b569ddb | ||
|
|
c7b026fd1d | ||
|
|
66b95abb96 | ||
|
|
e2ef8a293d | ||
|
|
b25f6e041c | ||
|
|
4607580e6f | ||
|
|
f2d48c0e8f | ||
|
|
c9d12e21d8 | ||
|
|
2f4764a3f2 | ||
|
|
8b67039fa6 | ||
|
|
8cf8d51c79 | ||
|
|
90226c6981 | ||
|
|
91a248bdbe | ||
|
|
0d3bfacc84 | ||
|
|
ac3c156a0b | ||
|
|
f24d403705 | ||
|
|
da3b16c0d4 | ||
|
|
2b2cb03784 | ||
|
|
19d0ff3d46 | ||
|
|
04b6b0ad76 | ||
|
|
6a5fb33306 | ||
|
|
d0262ea6ae | ||
|
|
512c2ee000 | ||
|
|
e708e885f6 | ||
|
|
cc3b7b8124 | ||
|
|
39c9deb456 | ||
|
|
7991790f94 | ||
|
|
5f418d3f1a | ||
|
|
5047bf5466 | ||
|
|
dca7c26b9d | ||
|
|
c6173e2957 | ||
|
|
b646023c41 | ||
|
|
45e3b01b15 | ||
|
|
97515ab758 | ||
|
|
d85328e729 | ||
|
|
0aa7082391 | ||
|
|
946431b83f | ||
|
|
a101e3e7a6 | ||
|
|
f73120dbaa | ||
|
|
a55879c93a | ||
|
|
fe02af151d | ||
|
|
f1a963fa9c | ||
|
|
8c6dee4213 | ||
|
|
9208b4c4dd | ||
|
|
0e04b34852 | ||
|
|
796e35e8a4 | ||
|
|
72f0ae906f | ||
|
|
464482d197 | ||
|
|
48ce39a645 | ||
|
|
f993240d2b | ||
|
|
83fd9babef | ||
|
|
66fb0cf8fc | ||
|
|
459ac84d29 | ||
|
|
736b833d52 | ||
|
|
dc37020d73 | ||
|
|
93916d4ed1 | ||
|
|
1d1e48acb7 | ||
|
|
1884e1a111 | ||
|
|
2d0396da21 | ||
|
|
cce47ba723 | ||
|
|
2831680d14 | ||
|
|
5e3374acbc | ||
|
|
13d7de9501 | ||
|
|
d78abc92f2 | ||
|
|
07672eb874 | ||
|
|
e7225ce487 | ||
|
|
cb24d3bf78 | ||
|
|
8360019080 | ||
|
|
f3b34bea26 | ||
|
|
edf09a2d7b | ||
|
|
1de445c5b8 | ||
|
|
8d7f307173 | ||
|
|
0a23a6d084 | ||
|
|
87fa70be2c | ||
|
|
b57c62fe1b | ||
|
|
a8c1051e0f | ||
|
|
d7ba12e729 | ||
|
|
1d3c47f3fd | ||
|
|
4ae81bae99 | ||
|
|
2fc301d061 | ||
|
|
fc6e6d1ab6 | ||
|
|
9cb4ee9d6f | ||
|
|
0e1da6982b | ||
|
|
28573b47a8 | ||
|
|
851bd1ef14 | ||
|
|
0c7d64563d | ||
|
|
b984f62bbf | ||
|
|
a89e0936c2 | ||
|
|
677146d905 | ||
|
|
00b7ead8bb | ||
|
|
dce5016261 | ||
|
|
2bc759778c | ||
|
|
3aa6869a4b | ||
|
|
209fdfd5b9 | ||
|
|
eec0df14b5 | ||
|
|
7e2810d33d | ||
|
|
78404c8cd3 | ||
|
|
f05ceecf8e | ||
|
|
bcef526213 | ||
|
|
00d5767246 | ||
|
|
6655301bfe | ||
|
|
5beff97f95 | ||
|
|
cfa6b49bab | ||
|
|
a659d5fada | ||
|
|
c1521bfa3f | ||
|
|
096e6c911a | ||
|
|
26f7cd38e5 | ||
|
|
802541c09f |
30
.github/workflows/pythonpackage.yml
vendored
Normal file
30
.github/workflows/pythonpackage.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: GAM
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, ubuntu-16.04, windows-2019, windows-2016, macOS-10.14]
|
||||
python-version: [3.5, 3.6, 3.7]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up $(( matrix.runs-on )) Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r src/requirements.txt
|
||||
- name: Run GAM
|
||||
run: |
|
||||
python src/gam.py version extended
|
||||
- name: Get Env
|
||||
run: |
|
||||
set
|
||||
- name: Test Install
|
||||
run: |
|
||||
if [[ $(uname -s) == "Linux" || $(uname -s) == "Darwin" ]]; then bash <(curl -s -S -L https://git.io/install-gam) -l; fi
|
||||
84
.travis.yml
84
.travis.yml
@@ -2,10 +2,9 @@ if: tag IS blank
|
||||
|
||||
env:
|
||||
global:
|
||||
- BUILD_PYTHON_VERSION=3.7.4
|
||||
- BUILD_OPENSSL_VERSION=1.1.1c
|
||||
- BUILD_PYTHON_VERSION=3.8.0
|
||||
- BUILD_OPENSSL_VERSION=1.1.1d
|
||||
- PATCHELF_VERSION=0.9
|
||||
- MUSL_VERSION=1.1.23
|
||||
- PYINSTALLER_VERSION=3.5
|
||||
- secure: "FSKvLaiqhKz21SVgAQZI3bSX34Ffyev4l+R2G//QXNDu6UVQcuFsykzw+eZEG7fkhotXr8BMDL7xIkookiL8eLwUtcd/Z95HCjPBBHcmCSQleyvuuJBxdrQ9xldmiGLzMCYiumSH9OH4uJhQ39Yjnjsa8TK+PlTci6a/BTzlYyBSyDYDf7Iv/uhfQPDHL3pNwrQPHf4fL6/jcvo+uaPcv83AVZkNzZjjyoi9Aa+uh9xlbyHg11jp44463qqxoxTdYik3pYuXRBPjknjOGcnFHqn+QOVSdRQoiwbmT8xVuYuCzTv9THhuJ//i5u7s4y3Xyl7u17B3tdm86UlMpQHy/w9EsYaSBPOU4oPNomRtOnTSugh0v9ZBwptP5XfbslII/iA+LQdzTHhchn0W0CRyDqjOMSestWlrsq5NZJtBJTYHbebllOhEI7xbj9tY+re1zFWSPMOPgHJP23ovsdk3hD9OT93AzRHInCx5IxL6QvEgRhAancRuGkf2rGP0g/vX9fQ0Il3rNMSQxHB5CyHUBtUJ9nhU79YkMDZicD0jFMEwjWJO3itAp3ynoLXRgktgQCYUfgc9SpdWKD5SXLCYnSo22JD3D1P6h2EertRHaoKRLb+CRXQC/lM8uh/W+BjA2Xe6Vut2I/72ndjM+10T7E2xk1CFyCH37a5p8cH26Fs="
|
||||
- secure: "J9380tGLOZWa7dSH1y5Il8T5JQpN6ad81gI6VR1HIU0svpRdjgikyDA7ca2MKYDUYYY9yVSkTV6gCl6iIU/9+SKaYugpP+tkvdGYkC2moJdcTgYM/WOnIK9ExQ3BPhN1neGxJjPTwKo1ft27mtZ2I5vuCiBwIcnKWLnKPyW3PD+mWpfqiLuEzkHoAh6G3jC4qbcCrZDeX/knE+PzqESUEi+8k1G8gYcSDWujba9ypSsqZ8T/MXagGla6l7y2Rz+/KZTJmFHwKAA10V+xPLVqxoiqi4ar66yUqy0BamwRXPcseI+ns3Q+4lUpMqVQ5GlRy7LF1xC8myjmcAexXk0F9hg+CMzewKI8UgmQH/ZJvQZEh8s6mW26+CqA4d3zMQkWaR0WtEtpiuH7AGHCflIqvEQ6UiG7ia3B8iZfW2wl0j/kqx4OuHkS3r0pWKVVIIvCj9Ow2BHP7SpiV1AcUGsVxzwbgTh67fitna3Z3c6Uj8ccQlNr7ZIt1az6Wf3w5njijkLOiBpQSLKunTTCTSge/JzBTKUcie3RE9vzirl58gUxAt36nDtPWnory+RttMZrOkBVbTeSxp+IUe8pNwLFPHABsafXsjkfzBOtFmm+0ZXWt2Rlog5NvlemJfQUWDlsL4g+BSakzN+4sIPKzSauWDHyaEeULY7Uprkil6c5zwo="
|
||||
@@ -33,18 +32,20 @@ cache:
|
||||
- $HOME/.cache/pip
|
||||
- $HOME/python
|
||||
- $HOME/ssl
|
||||
- $HOME/pybuild
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- arch: arm64
|
||||
include:
|
||||
# - os: linux
|
||||
# name: "Linux 64-bit Bionic"
|
||||
# dist: bionic
|
||||
# language: bash
|
||||
# env:
|
||||
# - GAMOS=linux
|
||||
# - PLATFORM=x86_64
|
||||
# - VMTYPE=cache
|
||||
- os: linux
|
||||
name: "Linux 64-bit Bionic"
|
||||
dist: bionic
|
||||
language: bash
|
||||
env:
|
||||
- GAMOS=linux
|
||||
- PLATFORM=x86_64
|
||||
- VMTYPE=build
|
||||
- os: linux
|
||||
name: "Linux 64-bit Xenial"
|
||||
dist: xenial
|
||||
@@ -53,6 +54,34 @@ matrix:
|
||||
- GAMOS=linux
|
||||
- PLATFORM=x86_64
|
||||
- VMTYPE=build
|
||||
- os: linux
|
||||
dist: bionic
|
||||
arch: arm64
|
||||
name: "Linux ARM64 Bionic"
|
||||
language: bash
|
||||
filter_secrets: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- ruby
|
||||
env:
|
||||
- GAMOS=linux
|
||||
- PLATFORM=arm64
|
||||
- VMTYPE=build
|
||||
- os: linux
|
||||
dist: xenial
|
||||
arch: arm64
|
||||
name: "Linux ARM64 Xenial"
|
||||
language: bash
|
||||
filter_secrets: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- ruby
|
||||
env:
|
||||
- GAMOS=linux
|
||||
- PLATFORM=arm64
|
||||
- VMTYPE=build
|
||||
- os: linux
|
||||
name: "Linux 64-bit Trusty"
|
||||
dist: trusty
|
||||
@@ -90,11 +119,11 @@ matrix:
|
||||
- PLATFORM=x86_64
|
||||
- VMTYPE=test
|
||||
- os: linux
|
||||
name: "Linux 64-bit - Python 3.8-dev Source Testing"
|
||||
name: "Linux 64-bit - Python 3.7 Source Testing"
|
||||
dist: bionic
|
||||
language: python
|
||||
python:
|
||||
- "3.8-dev"
|
||||
- "3.7"
|
||||
env:
|
||||
- GAMOS=linux
|
||||
- PLATFORM=x86_64
|
||||
@@ -110,13 +139,29 @@ matrix:
|
||||
- PLATFORM=x86_64
|
||||
- VMTYPE=test
|
||||
- os: osx
|
||||
name: "MacOS 64-bit"
|
||||
name: "MacOS 10.12"
|
||||
language: generic
|
||||
osx_image: xcode9.2
|
||||
env:
|
||||
- GAMOS=macos
|
||||
- PLATFORM=x86_64
|
||||
- VMTYPE=build
|
||||
- os: osx
|
||||
name: "MacOS 10.13"
|
||||
language: generic
|
||||
osx_image: xcode10.1
|
||||
env:
|
||||
- GAMOS=macos
|
||||
- PLATFORM=x86_64
|
||||
- VMTYPE=build
|
||||
- os: osx
|
||||
name: "MacOS 10.14"
|
||||
language: generic
|
||||
osx_image: xcode11.1
|
||||
env:
|
||||
- GAMOS=macos
|
||||
- PLATFORM=x86_64
|
||||
- VMTYPE=build
|
||||
- os: windows
|
||||
name: "Windows 64-bit"
|
||||
language: shell
|
||||
@@ -134,6 +179,9 @@ matrix:
|
||||
- PLATFORM=x86
|
||||
- VMTYPE=build
|
||||
|
||||
before_cache:
|
||||
- echo "this is before cache"
|
||||
|
||||
before_install:
|
||||
- source src/travis/$TRAVIS_OS_NAME-$PLATFORM-before-install.sh
|
||||
|
||||
@@ -144,9 +192,9 @@ script:
|
||||
- $gam version extended
|
||||
- $gam version | grep travis # travis should be part of the path (not /tmp or such)
|
||||
# determine which Python version GAM is built with and ensure it's at least build version from above.
|
||||
- if [ "VMTYPE" == "build" ]; then vline=$(gam version | grep "Python "); python_line=($vline); this_python=${python_line[1]}; tools/a_atleast_b.py $this_python $BUILD_PYTHON_VERSION; fi
|
||||
- if [ "$VMTYPE" == "build" ]; then vline=$($gam version | grep "Python "); python_line=($vline); this_python=${python_line[1]}; $python tools/a_atleast_b.py $this_python $BUILD_PYTHON_VERSION; fi
|
||||
# determine which OpenSSL version GAM is built with and ensure it's at least build version from above.
|
||||
- if [ "VMTYPE" == "build" ]; then vline=$(gam version extended | grep "OpenSSL "); openssl_line=($vline); this_openssl=${openssl_line[1]}; tools/a_atleast_b.py $this_openssl $BUILD_OPENSSL_VERSION; fi
|
||||
- if [ "$VMTYPE" == "build" ]; then vline=$($gam version extended | grep "OpenSSL "); openssl_line=($vline); this_openssl=${openssl_line[1]}; $python tools/a_atleast_b.py $this_openssl $BUILD_OPENSSL_VERSION; fi
|
||||
- if [ "$VMTYPE" == "build" ]; then $gam version extended | grep TLSv1\.[23]; fi # Builds should default TLS 1.2 or 1.3 to Google
|
||||
- if [ "$VMTYPE" == "build" ]; then GAM_TLS_MIN_VERSION=TLSv1_2 $gam version extended location tls-v1-0.badssl.com:1010; [[ $? == 3 ]]; fi # expect fail since server doesn't support our TLS version
|
||||
- export jid="$(cut -d'.' -f2 <<<"$TRAVIS_JOB_NUMBER")"
|
||||
@@ -231,9 +279,11 @@ script:
|
||||
- if [ "$e2e" = true ]; then $gam print users query "travis.jid=$jid" | $gam csv - gam delete user ~primaryEmail; fi
|
||||
- if [ "$e2e" = true ]; then $gam print mobile; fi
|
||||
- if [ "$e2e" = true ]; then $gam print cros allfields nolists; fi
|
||||
- if [ "$TRAVIS_OS_NAME" != "windows" ]; then bash <(curl -s -S -L https://git.io/install-gam) -l; fi
|
||||
|
||||
before_deploy:
|
||||
- export TRAVIS_TAG="preview"
|
||||
- unset LD_LIBRARY_PATH
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
|
||||
@@ -140,6 +140,7 @@ If an item contains spaces, it should be surrounded by ".
|
||||
|
||||
<AccessToken> ::= <String>
|
||||
<ACLScope> ::= [user:]<EmailAddress>|group:<EmailAddress>|domain[:<DomainName>]|default
|
||||
<APIScopeURL> ::= <String>
|
||||
<ASPID> ::= <String>
|
||||
<BuildingID> ::= <String>|id:<String>
|
||||
<CalendarACLRole> ::= editor|freebusy|freebusyreader|owner|reader|writer
|
||||
@@ -303,6 +304,7 @@ If an item contains spaces, it should be surrounded by ".
|
||||
cancomment|
|
||||
canreadrevisions|
|
||||
copyable|
|
||||
copyrequireswriterpermission|
|
||||
createddate|createdtime|
|
||||
description|
|
||||
editable|
|
||||
@@ -551,6 +553,7 @@ Items, separated by spaces, with spaces, commas or single quotes in the items th
|
||||
"'it em' 'it,em' \"it'em\""
|
||||
|
||||
<ACLList> ::= "<ACLScope>(,<ACLScope>)*"
|
||||
<APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*"
|
||||
<ASPIDList> ::= "<ASPID>(,<ASPID>)*"
|
||||
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
|
||||
<ChatRoomList> ::= "<ChatRoom>(,<ChatRoom>)*"
|
||||
@@ -670,12 +673,16 @@ Specify a collection of Users by directly specifying them or by specifiying item
|
||||
|
||||
<DriveFileAddAttributes> ::=
|
||||
(localfile <FileName>)|
|
||||
(convert)|(ocr)|(ocrlanguage <Language>)|(restricted|restrict)|(starred|star)|(trashed|trash)|(viewed|view)|
|
||||
(convert)|(ocr)|(ocrlanguage <Language>)|
|
||||
(restricted|restrict)|(starred|star)|(trashed|trash)|(viewed|view)|
|
||||
copyrequireswriterpermission|
|
||||
(lastviewedbyme <Time>)|(modifieddate|modifiedtime <Time>)|(description <String>)|(mimetype <MimeType>)|
|
||||
(parentid <DriveFolderID>)|(parentname <DriveFolderName>)|(anyownerparentname <DriveFolderName>)|writerscantshare
|
||||
<DriveFileUpdateAttributes> ::=
|
||||
(localfile <FileName>)|
|
||||
(convert)|(ocr)|(ocrlanguage <Language>)|(restricted|restrict <Boolean>)|(starred|star <Boolean>)|(trashed|trash <Boolean>)|(viewed|view <Boolean>)|
|
||||
(convert)|(ocr)|(ocrlanguage <Language>)|
|
||||
(restricted|restrict <Boolean>)|(starred|star <Boolean>)|(trashed|trash <Boolean>)|(viewed|view <Boolean>)|
|
||||
(copyrequireswriterpermission <Boolean>)|
|
||||
(lastviewedbyme <Time>)|(modifieddate <Time>)|(description <String>)|(mimetype <MimeType>)|
|
||||
(parentid <DriveFolderID>)|(parentname <DriveFolderName>)|(anyownerparentname <DriveFolderName>)|writerscantshare
|
||||
<GroupSettingsAttribute> ::=
|
||||
@@ -834,7 +841,7 @@ gam oauth|oauth2 delete|revoke
|
||||
gam oauth|oauth2 info|verify [accesstoken <AccessToken>] [idtoken <IDToken>] [showsecret]
|
||||
gam oauth|oauth2 refresh
|
||||
|
||||
gam <UserTypeEntity> check serviceaccount
|
||||
gam <UserTypeEntity> check serviceaccount [scope|scopes <APIScopeURLList>]
|
||||
|
||||
gam whatis <EmailItem>
|
||||
|
||||
@@ -1083,6 +1090,7 @@ gam info member <UserItem> <GroupItem>
|
||||
gam print group-members|groups-members [todrive]
|
||||
([domain <DomainName>] ([member <UserItem>]|[query <QueryGroup>]))|[group|group_ns|group_susp <GroupItem>] [notsuspended|suspended]
|
||||
[roles <GroupRoleList>] [membernames] [fields <MembersFieldNameList>]
|
||||
[includederivedmembership]
|
||||
|
||||
gam print licenses [todrive] [(products|product <ProductIDList>)|(skus|sku <SKUIDList>)|allskus|gsuite] [countsonly]
|
||||
gam show license|licenses|licence|licences [(products|product <ProductIDList>)|(skus|sku <SKUIDList>)|allskus|gsuite]
|
||||
|
||||
@@ -10,6 +10,7 @@ OPTIONS:
|
||||
-d Directory where gam folder will be installed. Default is \$HOME/bin/
|
||||
-a Architecture to install (i386, x86_64, x86_64_legacy, arm, arm64). Default is to detect your arch with "uname -m".
|
||||
-o OS we are running (linux, macos). Default is to detect your OS with "uname -s".
|
||||
-b OS version. Default is to detect on MacOS and Linux.
|
||||
-l Just upgrade GAM to latest version. Skips project creation and auth.
|
||||
-p Profile update (true, false). Should script add gam command to environment. Default is true.
|
||||
-u Admin user email address to use with GAM. Default is to prompt.
|
||||
@@ -21,20 +22,23 @@ EOF
|
||||
target_dir="$HOME/bin"
|
||||
gamarch=$(uname -m)
|
||||
gamos=$(uname -s)
|
||||
osversion=""
|
||||
update_profile=true
|
||||
upgrade_only=false
|
||||
gamversion="latest"
|
||||
adminuser=""
|
||||
regularuser=""
|
||||
gam_glibc_vers="2.23 2.19 2.15"
|
||||
gam_glibc_vers="2.27 2.23 2.19 2.15"
|
||||
gam_macos_vers="10.14.4 10.13.6 10.12.6"
|
||||
|
||||
while getopts "hd:a:o:lp:u:r:v:" OPTION
|
||||
while getopts "hd:a:o:b:lp:u:r:v:" OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
h) usage; exit;;
|
||||
d) target_dir="$OPTARG";;
|
||||
a) gamarch="$OPTARG";;
|
||||
o) gamos="$OPTARG";;
|
||||
b) osversion="$OPTARG";;
|
||||
l) upgrade_only=true;;
|
||||
p) update_profile="$OPTARG";;
|
||||
u) adminuser="$OPTARG";;
|
||||
@@ -79,13 +83,26 @@ echo -e '\x1B[0m'
|
||||
|
||||
version_gt()
|
||||
{
|
||||
test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"
|
||||
# MacOS < 10.13 doesn't support sort -V
|
||||
echo "" | sort -V > /dev/null 2>&1
|
||||
vsort_failed=$?
|
||||
if [ "${1}" = "${2}" ]; then
|
||||
true
|
||||
elif (( $vsort_failed != 0 )); then
|
||||
false
|
||||
else
|
||||
test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
case $gamos in
|
||||
[lL]inux)
|
||||
gamos="linux"
|
||||
this_glibc_ver=$(ldd --version | awk '/ldd/{print $NF}')
|
||||
if [ "$osversion" == "" ]; then
|
||||
this_glibc_ver=$(ldd --version | awk '/ldd/{print $NF}')
|
||||
else
|
||||
this_glibc_ver=$osversion
|
||||
fi
|
||||
echo "This Linux distribution uses glibc $this_glibc_ver"
|
||||
useglibc="legacy"
|
||||
for gam_glibc_ver in $gam_glibc_vers; do
|
||||
@@ -97,24 +114,33 @@ case $gamos in
|
||||
done
|
||||
case $gamarch in
|
||||
x86_64) gamfile="linux-x86_64-$useglibc.tar.xz";;
|
||||
i?86) gamfile="linux-i686.tar.xz";;
|
||||
arm|armv7l) gamfile="linux-armv7l.tar.xz";;
|
||||
arm64|aarch64) gamfile="linux-aarch64.tar.xz";;
|
||||
arm64|aarch64) gamfile="linux-arm64-$useglibc.tar.xz";;
|
||||
*)
|
||||
echo_red "ERROR: this installer currently only supports i386, x86_64, arm and arm64 Linux. Looks like you're running on $gamarch. Exiting."
|
||||
echo_red "ERROR: this installer currently only supports x86_64 and arm64 Linux. Looks like you're running on $gamarch. Exiting."
|
||||
exit
|
||||
esac
|
||||
;;
|
||||
[Mm]ac[Oo][sS]|[Dd]arwin)
|
||||
osver=$(sw_vers -productVersion | awk -F'.' '{print $2}')
|
||||
if (( $osver < 13 )); then
|
||||
echo_red "ERROR: GAM currently requires MacOS 10.13 or newer. You are running MacOS 10.$osver. Please upgrade."
|
||||
exit
|
||||
else
|
||||
echo_green "Good, you're running MacOS 10.$osver..."
|
||||
fi
|
||||
gamos="macos"
|
||||
gamfile="macos-x86_64.tar.xz"
|
||||
if [ "$osversion" == "" ]; then
|
||||
this_macos_ver=$(sw_vers -productVersion)
|
||||
else
|
||||
this_macos_ver=$osversion
|
||||
fi
|
||||
echo "You are running MacOS $this_macos_ver"
|
||||
use_macos_ver=""
|
||||
for gam_macos_ver in $gam_macos_vers; do
|
||||
if version_gt $this_macos_ver $gam_macos_ver; then
|
||||
use_macos_ver="MacOS$gam_macos_ver"
|
||||
echo_green "Using GAM compiled on $use_macos_ver"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$use_macos_ver" == "" ]; then
|
||||
echo_red "Sorry, you need to be running at least MacOS $gam_macos_ver to run GAM"
|
||||
exit
|
||||
fi
|
||||
gamfile="macos-x86_64-$use_macos_ver.tar.xz"
|
||||
;;
|
||||
*)
|
||||
echo_red "Sorry, this installer currently only supports Linux and MacOS. Looks like you're runnning on $gamos. Exiting."
|
||||
@@ -161,11 +187,16 @@ try:
|
||||
except KeyError:
|
||||
print('ERROR: assets value not found in JSON value of:\n\n%s' % release)"
|
||||
|
||||
pycmd="python"
|
||||
pycmd="python3"
|
||||
$pycmd -V >/dev/null 2>&1
|
||||
rc=$?
|
||||
if (( $rc != 0 )); then
|
||||
pycmd="python3"
|
||||
pycmd="python"
|
||||
fi
|
||||
$pycmd -V >/dev/null 2>&1
|
||||
rc=$?
|
||||
if (( $rc != 0 )); then
|
||||
pycmd="python2"
|
||||
fi
|
||||
$pycmd -V >/dev/null 2>&1
|
||||
rc=$?
|
||||
@@ -205,7 +236,7 @@ fi
|
||||
|
||||
if [ "$upgrade_only" = true ]; then
|
||||
echo_green "Here's information about your GAM upgrade:"
|
||||
"$target_dir/gam/gam" version
|
||||
"$target_dir/gam/gam" version extended
|
||||
rc=$?
|
||||
if (( $rc != 0 )); then
|
||||
echo_red "ERROR: Failed running GAM for the first time with $rc. Please report this error to GAM mailing list. Exiting."
|
||||
@@ -328,7 +359,7 @@ while $project_created; do
|
||||
done
|
||||
|
||||
echo_green "Here's information about your new GAM installation:"
|
||||
"$target_dir/gam/gam" version
|
||||
"$target_dir/gam/gam" version extended
|
||||
rc=$?
|
||||
if (( $rc != 0 )); then
|
||||
echo_red "ERROR: Failed running GAM for the first time with $rc. Please report this error to GAM mailing list. Exiting."
|
||||
|
||||
353
src/gam.py
353
src/gam.py
@@ -28,6 +28,7 @@ import csv
|
||||
import datetime
|
||||
import difflib
|
||||
from email import message_from_string
|
||||
from filelock import FileLock
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
@@ -51,10 +52,16 @@ import uuid
|
||||
import webbrowser
|
||||
import zipfile
|
||||
import http.client as http_client
|
||||
from multiprocessing import Pool
|
||||
from multiprocessing import freeze_support
|
||||
from multiprocessing import Pool as mp_pool
|
||||
from multiprocessing import freeze_support as mp_freeze_support
|
||||
from multiprocessing import set_start_method as mp_set_start_method
|
||||
from urllib.parse import urlencode, urlparse
|
||||
# workaround https://bitbucket.org/ecollins/passlib/issues/107/timeclock-has-gone
|
||||
# can be removed with passlib > 1.7.1
|
||||
if sys.platform == 'win32' and sys.version_info[1] >= 8:
|
||||
time.clock = time.time
|
||||
from passlib.hash import sha512_crypt
|
||||
time.__dict__.pop('clock', None)
|
||||
import dateutil.parser
|
||||
|
||||
import googleapiclient
|
||||
@@ -70,6 +77,9 @@ import httplib2
|
||||
import utils
|
||||
from var import *
|
||||
|
||||
if platform.system() == 'Linux':
|
||||
import distro
|
||||
|
||||
# Finding path method varies between Python source, PyInstaller and StaticX
|
||||
if os.environ.get('STATICX_PROG_PATH', False):
|
||||
# StaticX static executable
|
||||
@@ -610,46 +620,61 @@ def SetGlobalVariables():
|
||||
rowFilters = {}
|
||||
if not value:
|
||||
return rowFilters
|
||||
try:
|
||||
for column, filterStr in iter(json.loads(value.encode('unicode-escape').decode(UTF8)).items()):
|
||||
mg = ROW_FILTER_COMP_PATTERN.match(filterStr)
|
||||
if mg:
|
||||
if mg.group(1) in ['date', 'time']:
|
||||
if mg.group(1) == 'date':
|
||||
valid, filterValue = getRowFilterDateOrDeltaFromNow(mg.group(3))
|
||||
else:
|
||||
valid, filterValue = getRowFilterTimeOrDeltaFromNow(mg.group(3))
|
||||
if valid:
|
||||
rowFilters[column] = (mg.group(1), mg.group(2), filterValue)
|
||||
continue
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": "{2}", Expected: {3}'.format(itemName, column, filterStr, filterValue))
|
||||
else: #count
|
||||
if mg.group(3).isdigit():
|
||||
rowFilters[column] = (mg.group(1), mg.group(2), int(mg.group(3)))
|
||||
continue
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": "{2}", Expected: {3}'.format(itemName, column, filterStr, '<Number>'))
|
||||
mg = ROW_FILTER_BOOL_PATTERN.match(filterStr)
|
||||
if mg:
|
||||
value = mg.group(2).lower()
|
||||
if value in true_values:
|
||||
filterValue = True
|
||||
elif value in false_values:
|
||||
filterValue = False
|
||||
else:
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": "{2}", Expected true|false'.format(itemName, column, filterStr))
|
||||
rowFilters[column] = (mg.group(1), filterValue)
|
||||
if value.startswith('{'):
|
||||
try:
|
||||
filterDict = json.loads(value.encode('unicode-escape').decode(UTF8))
|
||||
except (TypeError, ValueError) as e:
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}", Failed to parse as JSON: {2}'.format(itemName, value, str(e)))
|
||||
else:
|
||||
filterDict = {}
|
||||
status, filterList = shlexSplitListStatus(value)
|
||||
if not status:
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}", Failed to parse as list'.format(itemName, value))
|
||||
for filterVal in filterList:
|
||||
if not filterVal:
|
||||
continue
|
||||
mg = ROW_FILTER_RE_PATTERN.match(filterStr)
|
||||
if mg:
|
||||
try:
|
||||
rowFilters[column] = (mg.group(1), re.compile(mg.group(2)))
|
||||
try:
|
||||
column, filterStr = filterVal.split(':', 1)
|
||||
except ValueError:
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}", Expected column:filter'.format(itemName, filterVal))
|
||||
filterDict[column] = filterStr
|
||||
for column, filterStr in iter(filterDict.items()):
|
||||
mg = ROW_FILTER_COMP_PATTERN.match(filterStr)
|
||||
if mg:
|
||||
if mg.group(1) in ['date', 'time']:
|
||||
if mg.group(1) == 'date':
|
||||
valid, filterValue = getRowFilterDateOrDeltaFromNow(mg.group(3))
|
||||
else:
|
||||
valid, filterValue = getRowFilterTimeOrDeltaFromNow(mg.group(3))
|
||||
if valid:
|
||||
rowFilters[column] = (mg.group(1), mg.group(2), filterValue)
|
||||
continue
|
||||
except re.error as e:
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": "{2}", Invalid RE: {3}'.format(itemName, column, filterStr, e))
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": {2}, Expected: (date|time|count<Operator><Value>) or (boolean:true|false) or (regex|notregex:<RegularExpression>)'.format(itemName, column, filterStr))
|
||||
return rowFilters
|
||||
except (TypeError, ValueError) as e:
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}", Failed to parse as JSON: {2}'.format(itemName, value, str(e)))
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": "{2}", Expected: {3}'.format(itemName, column, filterStr, filterValue))
|
||||
else: #count
|
||||
if mg.group(3).isdigit():
|
||||
rowFilters[column] = (mg.group(1), mg.group(2), int(mg.group(3)))
|
||||
continue
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": "{2}", Expected: {3}'.format(itemName, column, filterStr, '<Number>'))
|
||||
mg = ROW_FILTER_BOOL_PATTERN.match(filterStr)
|
||||
if mg:
|
||||
value = mg.group(2).lower()
|
||||
if value in true_values:
|
||||
filterValue = True
|
||||
elif value in false_values:
|
||||
filterValue = False
|
||||
else:
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": "{2}", Expected true|false'.format(itemName, column, filterStr))
|
||||
rowFilters[column] = (mg.group(1), filterValue)
|
||||
continue
|
||||
mg = ROW_FILTER_RE_PATTERN.match(filterStr)
|
||||
if mg:
|
||||
try:
|
||||
rowFilters[column] = (mg.group(1), re.compile(mg.group(2)))
|
||||
continue
|
||||
except re.error as e:
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": "{2}", Invalid RE: {3}'.format(itemName, column, filterStr, e))
|
||||
systemErrorExit(3, 'Item: {0}, Value: "{1}": {2}, Expected: (date|time|count<Operator><Value>) or (boolean:true|false) or (regex|notregex:<RegularExpression>)'.format(itemName, column, filterStr))
|
||||
return rowFilters
|
||||
|
||||
GC_Defaults[GC_CONFIG_DIR] = GM_Globals[GM_GAM_PATH]
|
||||
GC_Defaults[GC_CACHE_DIR] = os.path.join(GM_Globals[GM_GAM_PATH], 'gamcache')
|
||||
@@ -720,6 +745,8 @@ def SetGlobalVariables():
|
||||
GM_Globals[GM_CACHE_DISCOVERY_ONLY] = False
|
||||
return True
|
||||
|
||||
TIME_OFFSET_UNITS = [('day', 86400), ('hour', 3600), ('minute', 60), ('second', 1)]
|
||||
|
||||
def getLocalGoogleTimeOffset(testLocation='www.googleapis.com'):
|
||||
localUTC = datetime.datetime.now(datetime.timezone.utc)
|
||||
try:
|
||||
@@ -729,23 +756,18 @@ def getLocalGoogleTimeOffset(testLocation='www.googleapis.com'):
|
||||
badhttp = _createHttpObj()
|
||||
badhttp.disable_ssl_certificate_validation = True
|
||||
googleUTC = dateutil.parser.parse(badhttp.request('https://'+testLocation, 'HEAD')[0]['date'])
|
||||
offset = abs(localUTC-googleUTC).total_seconds()
|
||||
days, remainder = divmod(offset, 86400)
|
||||
hours, remainder = divmod(remainder, 3600)
|
||||
minutes, seconds = divmod(remainder, 60)
|
||||
timeoff = []
|
||||
if days:
|
||||
timeoff.append('%d days' % days)
|
||||
if hours:
|
||||
timeoff.append('%d hours' % hours)
|
||||
if minutes:
|
||||
timeoff.append('%d minutes' % minutes)
|
||||
if seconds:
|
||||
timeoff.append('%d seconds' % seconds)
|
||||
nicetime = ', '.join(timeoff)
|
||||
return (offset, nicetime)
|
||||
except (httplib2.ServerNotFoundError, RuntimeError, ValueError) as e:
|
||||
systemErrorExit(4, str(e))
|
||||
offset = remainder = int(abs((localUTC-googleUTC).total_seconds()))
|
||||
timeoff = []
|
||||
for tou in TIME_OFFSET_UNITS:
|
||||
uval, remainder = divmod(remainder, tou[1])
|
||||
if uval:
|
||||
timeoff.append('{0} {1}{2}'.format(uval, tou[0], 's' if uval != 1 else ''))
|
||||
if not timeoff:
|
||||
timeoff.append('less than 1 second')
|
||||
nicetime = ', '.join(timeoff)
|
||||
return (offset, nicetime)
|
||||
|
||||
def doGAMCheckForUpdates(forceCheck=False):
|
||||
|
||||
@@ -800,6 +822,22 @@ def doGAMCheckForUpdates(forceCheck=False):
|
||||
except (httplib2.HttpLib2Error, httplib2.ServerNotFoundError, RuntimeError, socket.timeout):
|
||||
return
|
||||
|
||||
def getOSPlatform():
|
||||
myos = platform.system()
|
||||
if myos == 'Linux':
|
||||
pltfrm = ' '.join(distro.linux_distribution(full_distribution_name=False)).title()
|
||||
elif myos == 'Windows':
|
||||
pltfrm = ' '.join(platform.win32_ver())
|
||||
elif myos == 'Darwin':
|
||||
myos = 'MacOS'
|
||||
mac_ver = platform.mac_ver()[0]
|
||||
minor_ver = int(mac_ver.split('.')[1]) # macver 10.14.6 == minor_ver 14
|
||||
codename = MACOS_CODENAMES.get(minor_ver, '')
|
||||
pltfrm = ' '.join([codename, mac_ver])
|
||||
else:
|
||||
pltfrm = platform.platform()
|
||||
return '%s %s' % (myos, pltfrm)
|
||||
|
||||
def doGAMVersion(checkForArgs=True):
|
||||
force_check = extended = simple = timeOffset = False
|
||||
testLocation = 'www.googleapis.com'
|
||||
@@ -832,12 +870,14 @@ def doGAMVersion(checkForArgs=True):
|
||||
print(version_data.format(gam_version, GAM_URL, gam_author, sys.version_info[0],
|
||||
sys.version_info[1], sys.version_info[2], struct.calcsize('P')*8,
|
||||
sys.version_info[3], googleapiclient.__version__,
|
||||
platform.platform(), platform.machine(), GM_Globals[GM_GAM_PATH]))
|
||||
getOSPlatform(), platform.machine(), GM_Globals[GM_GAM_PATH]))
|
||||
if sys.platform.startswith('win') and str(struct.calcsize('P')*8).find('32') != -1 and platform.machine().find('64') != -1:
|
||||
print(MESSAGE_UPDATE_GAM_TO_64BIT)
|
||||
if timeOffset:
|
||||
offset, nicetime = getLocalGoogleTimeOffset(testLocation)
|
||||
print('Your computer is %s off from Google\'s time.' % (nicetime))
|
||||
print(MESSAGE_YOUR_SYSTEM_TIME_DIFFERS_FROM_GOOGLE_BY % nicetime)
|
||||
if offset > MAX_LOCAL_GOOGLE_TIME_OFFSET:
|
||||
systemErrorExit(4, 'Please fix your system clock.')
|
||||
systemErrorExit(4, 'Please fix your system time.')
|
||||
if force_check:
|
||||
doGAMCheckForUpdates(forceCheck=True)
|
||||
if extended:
|
||||
@@ -1146,7 +1186,6 @@ def callGAPIpages(service, function, items='items',
|
||||
Template strings allow for dynamic content to be inserted during paging.
|
||||
|
||||
Supported template strings:
|
||||
%%num_items%% : The number of items in the current page.
|
||||
%%total_items%% : The current number of items discovered across all
|
||||
pages.
|
||||
%%first_item%% : In conjunction with `message_attribute` arg, will
|
||||
@@ -1197,8 +1236,7 @@ def callGAPIpages(service, function, items='items',
|
||||
|
||||
# Show a paging message to the user that indicates paging progress
|
||||
if page_message:
|
||||
show_message = page_message.replace('%%num_items%%', str(num_page_items))
|
||||
show_message = show_message.replace('%%total_items%%', str(total_items))
|
||||
show_message = page_message.replace('%%total_items%%', str(total_items))
|
||||
if message_attribute:
|
||||
first_item = page_items[0] if num_page_items > 0 else {}
|
||||
last_item = page_items[-1] if num_page_items > 1 else first_item
|
||||
@@ -1286,25 +1324,35 @@ def getOauth2TxtStorageCredentials():
|
||||
return creds
|
||||
|
||||
def getValidOauth2TxtCredentials(force_refresh=False):
|
||||
"""Gets OAuth2 credentials which are guaranteed to be fresh and valid."""
|
||||
credentials = getOauth2TxtStorageCredentials()
|
||||
if (credentials and credentials.expired) or force_refresh:
|
||||
retries = 3
|
||||
for n in range(1, retries+1):
|
||||
try:
|
||||
credentials.refresh(google_auth_httplib2.Request(_createHttpObj()))
|
||||
writeCredentials(credentials)
|
||||
break
|
||||
except google.auth.exceptions.RefreshError as e:
|
||||
systemErrorExit(18, str(e))
|
||||
except (google.auth.exceptions.TransportError, httplib2.ServerNotFoundError, RuntimeError) as e:
|
||||
if n != retries:
|
||||
waitOnFailure(n, retries, str(e))
|
||||
continue
|
||||
systemErrorExit(4, str(e))
|
||||
elif credentials is None or not credentials.valid:
|
||||
doRequestOAuth()
|
||||
"""Gets OAuth2 credentials which are guaranteed to be fresh and valid.
|
||||
Locks during read and possible write so that only one process will
|
||||
attempt refresh/write when running in parallel. """
|
||||
lock_file = '%s.lock' % GC_Values[GC_OAUTH2_TXT]
|
||||
lock = FileLock(lock_file)
|
||||
with lock:
|
||||
credentials = getOauth2TxtStorageCredentials()
|
||||
if (credentials and credentials.expired) or force_refresh:
|
||||
retries = 3
|
||||
for n in range(1, retries+1):
|
||||
try:
|
||||
credentials.refresh(google_auth_httplib2.Request(_createHttpObj()))
|
||||
writeCredentials(credentials)
|
||||
break
|
||||
except google.auth.exceptions.RefreshError as e:
|
||||
systemErrorExit(18, str(e))
|
||||
except (google.auth.exceptions.TransportError, httplib2.ServerNotFoundError, RuntimeError) as e:
|
||||
if n != retries:
|
||||
waitOnFailure(n, retries, str(e))
|
||||
continue
|
||||
systemErrorExit(4, str(e))
|
||||
elif credentials is None or not credentials.valid:
|
||||
doRequestOAuth()
|
||||
credentials = getOauth2TxtStorageCredentials()
|
||||
if not GM_Globals[GM_WINDOWS]:
|
||||
try:
|
||||
os.remove(lock_file)
|
||||
except IOError:
|
||||
pass
|
||||
return credentials
|
||||
|
||||
def getService(api, http):
|
||||
@@ -1518,10 +1566,18 @@ def buildGmailGAPIObject(user):
|
||||
return (userEmail, buildGAPIServiceObject('gmail', userEmail))
|
||||
|
||||
def printPassFail(description, result):
|
||||
padding = 80 - len(description) - 2
|
||||
print(' {} {:>{padding}}'.format(description, result, padding=str(padding)))
|
||||
print(' {0:74} {1}'.format(description, result))
|
||||
|
||||
def doCheckServiceAccount(users):
|
||||
i = 5
|
||||
check_scopes = []
|
||||
while i < len(sys.argv):
|
||||
myarg = sys.argv[i].lower()
|
||||
if myarg in ['scope', 'scopes']:
|
||||
check_scopes = sys.argv[i+1].replace(',', ' ').split()
|
||||
i += 2
|
||||
else:
|
||||
systemErrorExit(3, '%s is not a valid argument for "gam user <email> check serviceaccount"' % myarg)
|
||||
something_failed = False
|
||||
print('Computer clock status:')
|
||||
timeOffset, nicetime = getLocalGoogleTimeOffset()
|
||||
@@ -1530,7 +1586,7 @@ def doCheckServiceAccount(users):
|
||||
else:
|
||||
time_status = 'FAIL'
|
||||
something_failed = True
|
||||
printPassFail('Your computer clock differs from Google by %s' % nicetime, time_status)
|
||||
printPassFail(MESSAGE_YOUR_SYSTEM_TIME_DIFFERS_FROM_GOOGLE_BY % nicetime, time_status)
|
||||
oa2 = googleapiclient.discovery.build('oauth2', 'v1', _createHttpObj())
|
||||
print('Service Account Private Key Authentication:')
|
||||
# We are explicitly not doing DwD here, just confirming service account can auth
|
||||
@@ -1550,18 +1606,18 @@ def doCheckServiceAccount(users):
|
||||
something_failed = True
|
||||
auth_error = str(e.args[0])
|
||||
printPassFail('Authenticating...%s' % auth_error, sa_token_result)
|
||||
all_scopes = []
|
||||
for _, scopes in list(API_SCOPE_MAPPING.items()):
|
||||
for scope in scopes:
|
||||
if scope not in all_scopes:
|
||||
all_scopes.append(scope)
|
||||
all_scopes.sort()
|
||||
if not check_scopes:
|
||||
for _, scopes in list(API_SCOPE_MAPPING.items()):
|
||||
for scope in scopes:
|
||||
if scope not in check_scopes:
|
||||
check_scopes.append(scope)
|
||||
check_scopes.sort()
|
||||
for user in users:
|
||||
user = user.lower()
|
||||
all_scopes_pass = True
|
||||
oa2 = googleapiclient.discovery.build('oauth2', 'v1', _createHttpObj())
|
||||
print('Domain-Wide Delegation authentication as %s:' % (user))
|
||||
for scope in all_scopes:
|
||||
for scope in check_scopes:
|
||||
# try with and without email scope
|
||||
for scopes in [[scope, USERINFO_EMAIL_SCOPE], [scope]]:
|
||||
try:
|
||||
@@ -1590,7 +1646,7 @@ def doCheckServiceAccount(users):
|
||||
return
|
||||
user_domain = user[user.find('@')+1:]
|
||||
# Tack on email scope for more accurate checking
|
||||
all_scopes.append('https://www.googleapis.com/auth/userinfo.email')
|
||||
check_scopes.append(USERINFO_EMAIL_SCOPE)
|
||||
scopes_failed = '''Some scopes failed! Please go to:
|
||||
|
||||
https://admin.google.com/%s/AdminHome?#OGX:ManageOauthClients
|
||||
@@ -1601,7 +1657,7 @@ and grant Client name:
|
||||
|
||||
Access to scopes:
|
||||
|
||||
%s\n''' % (user_domain, service_account, ',\n'.join(all_scopes))
|
||||
%s\n''' % (user_domain, service_account, ',\n'.join(check_scopes))
|
||||
systemErrorExit(1, scopes_failed)
|
||||
|
||||
# Batch processing request_id fields
|
||||
@@ -1700,7 +1756,7 @@ def showReport():
|
||||
sys.exit(1)
|
||||
if fullData == 0:
|
||||
continue
|
||||
page_message = 'Got %%num_items%% Users\n'
|
||||
page_message = 'Got %%total_items%% Users\n'
|
||||
usage = callGAPIpages(rep.userUsageReport(), 'get', 'usageReports', page_message=page_message, throw_reasons=[GAPI_INVALID],
|
||||
date=tryDate, userKey=userKey, customerId=customerId, orgUnitID=orgUnitId, filters=filters, parameters=parameters)
|
||||
break
|
||||
@@ -1805,7 +1861,7 @@ def showReport():
|
||||
report = 'token'
|
||||
elif report == 'group':
|
||||
report = 'groups'
|
||||
page_message = 'Got %%num_items%% items\n'
|
||||
page_message = 'Got %%total_items%% items\n'
|
||||
activities = callGAPIpages(rep.activities(), 'list', 'items',
|
||||
page_message=page_message,
|
||||
applicationName=report, userKey=userKey,
|
||||
@@ -2948,7 +3004,7 @@ def doPrintCourses():
|
||||
fieldsList.append('ownerId')
|
||||
fields = 'nextPageToken,courses({0})'.format(','.join(set(fieldsList))) if fieldsList else None
|
||||
printGettingAllItems('Courses', None)
|
||||
page_message = 'Got %%num_items%% Courses...\n'
|
||||
page_message = 'Got %%total_items%% Courses...\n'
|
||||
all_courses = callGAPIpages(croom.courses(), 'list', 'courses', page_message=page_message, teacherId=teacherId, studentId=studentId, courseStates=courseStates, fields=fields)
|
||||
for course in all_courses:
|
||||
if ownerEmails is not None:
|
||||
@@ -2975,20 +3031,20 @@ def doPrintCourses():
|
||||
i += 1
|
||||
courseId = course['id']
|
||||
if showAliases:
|
||||
alias_message = ' Got %%%%num_items%%%% Aliases for course %s%s' % (courseId, currentCount(i, count))
|
||||
alias_message = ' Got %%%%total_items%%%% Aliases for course %s%s' % (courseId, currentCount(i, count))
|
||||
course_aliases = callGAPIpages(croom.courses().aliases(), 'list', 'aliases',
|
||||
page_message=alias_message,
|
||||
courseId=courseId)
|
||||
course['Aliases'] = delimiter.join([alias['alias'][2:] for alias in course_aliases])
|
||||
if showMembers:
|
||||
if showMembers != 'students':
|
||||
teacher_message = ' Got %%%%num_items%%%% Teachers for course %s%s' % (courseId, currentCount(i, count))
|
||||
teacher_message = ' Got %%%%total_items%%%% Teachers for course %s%s' % (courseId, currentCount(i, count))
|
||||
results = callGAPIpages(croom.courses().teachers(), 'list', 'teachers',
|
||||
page_message=teacher_message,
|
||||
courseId=courseId, fields=teachersFields)
|
||||
_saveParticipants(course, results, 'teachers')
|
||||
if showMembers != 'teachers':
|
||||
student_message = ' Got %%%%num_items%%%% Students for course %s%s' % (courseId, currentCount(i, count))
|
||||
student_message = ' Got %%%%total_items%%%% Students for course %s%s' % (courseId, currentCount(i, count))
|
||||
results = callGAPIpages(croom.courses().students(), 'list', 'students',
|
||||
page_message=student_message,
|
||||
courseId=courseId, fields=studentsFields)
|
||||
@@ -3033,7 +3089,7 @@ def doPrintCourseParticipants():
|
||||
systemErrorExit(2, '%s is not a valid argument for "gam print course-participants"' % sys.argv[i])
|
||||
if not courses:
|
||||
printGettingAllItems('Courses', None)
|
||||
page_message = 'Got %%num_items%% Courses...\n'
|
||||
page_message = 'Got %%total_items%% Courses...\n'
|
||||
all_courses = callGAPIpages(croom.courses(), 'list', 'courses', page_message=page_message,
|
||||
teacherId=teacherId, studentId=studentId, courseStates=courseStates, fields='nextPageToken,courses(id,name)')
|
||||
else:
|
||||
@@ -3046,12 +3102,12 @@ def doPrintCourseParticipants():
|
||||
i += 1
|
||||
courseId = course['id']
|
||||
if showMembers != 'students':
|
||||
page_message = ' Got %%%%num_items%%%% Teachers for course %s (%s/%s)' % (courseId, i, count)
|
||||
page_message = ' Got %%%%total_items%%%% Teachers for course %s (%s/%s)' % (courseId, i, count)
|
||||
teachers = callGAPIpages(croom.courses().teachers(), 'list', 'teachers', page_message=page_message, courseId=courseId)
|
||||
for teacher in teachers:
|
||||
addRowTitlesToCSVfile(flatten_json(teacher, flattened={'courseId': courseId, 'courseName': course['name'], 'userRole': 'TEACHER'}), csvRows, titles)
|
||||
if showMembers != 'teachers':
|
||||
page_message = ' Got %%%%num_items%%%% Students for course %s (%s/%s)' % (courseId, i, count)
|
||||
page_message = ' Got %%%%total_items%%%% Students for course %s (%s/%s)' % (courseId, i, count)
|
||||
students = callGAPIpages(croom.courses().students(), 'list', 'students', page_message=page_message, courseId=courseId)
|
||||
for student in students:
|
||||
addRowTitlesToCSVfile(flatten_json(student, flattened={'courseId': courseId, 'courseName': course['name'], 'userRole': 'STUDENT'}), csvRows, titles)
|
||||
@@ -4928,6 +4984,13 @@ def getDriveFileAttribute(i, body, parameters, myarg, update=False):
|
||||
elif myarg == 'ocrlanguage':
|
||||
parameters[DFA_OCRLANGUAGE] = LANGUAGE_CODES_MAP.get(sys.argv[i+1].lower(), sys.argv[i+1])
|
||||
i += 2
|
||||
elif myarg in ['copyrequireswriterpermission', 'restrict', 'restricted']:
|
||||
if update:
|
||||
body['copyRequiresWriterPermission'] = getBoolean(sys.argv[i+1], myarg)
|
||||
i += 2
|
||||
else:
|
||||
body['copyRequiresWriterPermission'] = True
|
||||
i += 1
|
||||
elif myarg in DRIVEFILE_LABEL_CHOICES_MAP:
|
||||
body.setdefault('labels', {})
|
||||
if update:
|
||||
@@ -7738,7 +7801,7 @@ def _run_oauth_flow(client_id, client_secret, scopes, access_type, login_hint=No
|
||||
}
|
||||
}
|
||||
|
||||
flow = ShortURLFlow.from_client_config(client_config, scopes)
|
||||
flow = ShortURLFlow.from_client_config(client_config, scopes, autogenerate_code_verifier=True)
|
||||
kwargs = {'access_type': access_type}
|
||||
if login_hint:
|
||||
kwargs['login_hint'] = login_hint
|
||||
@@ -10648,7 +10711,7 @@ def doGetCrosInfo():
|
||||
if deviceFile:
|
||||
downloadfilename = os.path.join(targetFolder, 'cros-logs-{0}-{1}.zip'.format(deviceId, deviceFile['createTime']))
|
||||
_, content = cd._http.request(deviceFile['downloadUrl'])
|
||||
writeFile(downloadfilename, content, continueOnError=True)
|
||||
writeFile(downloadfilename, content, mode='wb', continueOnError=True)
|
||||
print('Downloaded: {0}'.format(downloadfilename))
|
||||
elif downloadfile:
|
||||
print('ERROR: no files to download.')
|
||||
@@ -11555,6 +11618,8 @@ USER_ARGUMENT_TO_PROPERTY_MAP = {
|
||||
'posix': ['posixAccounts',],
|
||||
'posixaccounts': ['posixAccounts',],
|
||||
'primaryemail': ['primaryEmail',],
|
||||
'recoveryemail': ['recoveryEmail',],
|
||||
'recoveryphone': ['recoveryPhone',],
|
||||
'relation': ['relations',],
|
||||
'relations': ['relations',],
|
||||
'ssh': ['sshPublicKeys',],
|
||||
@@ -11923,7 +11988,7 @@ def doPrintGroups():
|
||||
if not ownersCountOnly:
|
||||
addTitlesToCSVfile(['Owners',], titles)
|
||||
printGettingAllItems('Groups', None)
|
||||
page_message = 'Got %%num_items%% Groups: %%first_item%% - %%last_item%%\n'
|
||||
page_message = 'Got %%total_items%% Groups: %%first_item%% - %%last_item%%\n'
|
||||
entityList = callGAPIpages(cd.groups(), 'list', 'groups',
|
||||
page_message=page_message, message_attribute='email',
|
||||
customer=customer, domain=usedomain, userKey=usemember, query=usequery,
|
||||
@@ -11942,7 +12007,7 @@ def doPrintGroups():
|
||||
group[fieldsTitles[field]] = groupEntity[field]
|
||||
if roles:
|
||||
sys.stderr.write(' Getting %s for %s (%s/%s)\n' % (roles, groupEmail, i, count))
|
||||
page_message = ' Got %%num_items%% members: %%first_item%% - %%last_item%%\n'
|
||||
page_message = ' Got %%total_items%% members: %%first_item%% - %%last_item%%\n'
|
||||
validRoles, listRoles, listFields = _getRoleVerification(roles, 'nextPageToken,members(email,id,role)')
|
||||
groupMembers = callGAPIpages(cd.members(), 'list', 'members',
|
||||
page_message=page_message, message_attribute='email',
|
||||
@@ -12131,7 +12196,7 @@ def doPrintAliases():
|
||||
if doUsers:
|
||||
for query in queries:
|
||||
printGettingAllItems('User Aliases', query)
|
||||
page_message = 'Got %%num_items%% Users %%first_item%% - %%last_item%%\n'
|
||||
page_message = 'Got %%total_items%% Users %%first_item%% - %%last_item%%\n'
|
||||
all_users = callGAPIpages(cd.users(), 'list', 'users', page_message=page_message,
|
||||
message_attribute='primaryEmail', customer=GC_Values[GC_CUSTOMER_ID], query=query,
|
||||
fields='nextPageToken,users({0})'.format(','.join(userFields)))
|
||||
@@ -12142,7 +12207,7 @@ def doPrintAliases():
|
||||
csvRows.append({'NonEditableAlias': alias, 'Target': user['primaryEmail'], 'TargetType': 'User'})
|
||||
if doGroups:
|
||||
printGettingAllItems('Group Aliases', None)
|
||||
page_message = 'Got %%num_items%% Groups %%first_item%% - %%last_item%%\n'
|
||||
page_message = 'Got %%total_items%% Groups %%first_item%% - %%last_item%%\n'
|
||||
all_groups = callGAPIpages(cd.groups(), 'list', 'groups', page_message=page_message,
|
||||
message_attribute='email', customer=GC_Values[GC_CUSTOMER_ID],
|
||||
fields='nextPageToken,groups({0})'.format(','.join(groupFields)))
|
||||
@@ -12157,6 +12222,7 @@ def doPrintGroupMembers():
|
||||
cd = buildGAPIObject('directory')
|
||||
todrive = False
|
||||
membernames = False
|
||||
includeDerivedMembership = False
|
||||
customer = GC_Values[GC_CUSTOMER_ID]
|
||||
checkSuspended = usedomain = usemember = usequery = None
|
||||
roles = []
|
||||
@@ -12208,6 +12274,9 @@ def doPrintGroupMembers():
|
||||
elif myarg in ['suspended', 'notsuspended']:
|
||||
checkSuspended = myarg == 'suspended'
|
||||
i += 1
|
||||
elif myarg == 'includederivedmembership':
|
||||
includeDerivedMembership = True
|
||||
i += 1
|
||||
else:
|
||||
systemErrorExit(2, '%s is not a valid argument for "gam print group-members"' % sys.argv[i])
|
||||
if not groups_to_get:
|
||||
@@ -12223,6 +12292,7 @@ def doPrintGroupMembers():
|
||||
validRoles, listRoles, listFields = _getRoleVerification(','.join(roles), fields)
|
||||
group_members = callGAPIpages(cd.members(), 'list', 'members',
|
||||
soft_errors=True,
|
||||
includeDerivedMembership=includeDerivedMembership,
|
||||
groupKey=group_email, roles=listRoles, fields=listFields)
|
||||
for member in group_members:
|
||||
if not _checkMemberRoleIsSuspended(member, validRoles, checkSuspended):
|
||||
@@ -12281,7 +12351,7 @@ def doPrintVaultMatters():
|
||||
else:
|
||||
systemErrorExit(3, '%s is not a valid argument to "gam print matters"' % myarg)
|
||||
printGettingAllItems('Vault Matters', None)
|
||||
page_message = 'Got %%num_items%% Vault Matters...\n'
|
||||
page_message = 'Got %%total_items%% Vault Matters...\n'
|
||||
matters = callGAPIpages(v.matters(), 'list', 'matters', page_message=page_message, view=view)
|
||||
for matter in matters:
|
||||
addRowTitlesToCSVfile(flatten_json(matter), csvRows, titles)
|
||||
@@ -12414,7 +12484,7 @@ def doPrintMobileDevices():
|
||||
systemErrorExit(2, '%s is not a valid argument for "gam print mobile"' % sys.argv[i])
|
||||
for query in queries:
|
||||
printGettingAllItems('Mobile Devices', query)
|
||||
page_message = 'Got %%num_items%% Mobile Devices...\n'
|
||||
page_message = 'Got %%total_items%% Mobile Devices...\n'
|
||||
all_mobile = callGAPIpages(cd.mobiledevices(), 'list', 'mobiledevices', page_message=page_message,
|
||||
customerId=GC_Values[GC_CUSTOMER_ID], query=query, projection=projection, fields=fields,
|
||||
orderBy=orderBy, sortOrder=sortOrder)
|
||||
@@ -13084,6 +13154,15 @@ def shlexSplitList(entity, dataDelimiter=' ,'):
|
||||
lexer.whitespace_split = True
|
||||
return list(lexer)
|
||||
|
||||
def shlexSplitListStatus(entity, dataDelimiter=' ,'):
|
||||
lexer = shlex.shlex(entity, posix=True)
|
||||
lexer.whitespace = dataDelimiter
|
||||
lexer.whitespace_split = True
|
||||
try:
|
||||
return (True, list(lexer))
|
||||
except ValueError as e:
|
||||
return (False, str(e))
|
||||
|
||||
def getQueries(myarg, argstr):
|
||||
if myarg == 'query':
|
||||
return [argstr]
|
||||
@@ -13354,25 +13433,33 @@ def OAuthInfo():
|
||||
print('%s: %s' % (key, value))
|
||||
|
||||
def doDeleteOAuth():
|
||||
credentials = getOauth2TxtStorageCredentials()
|
||||
if credentials is None:
|
||||
return
|
||||
simplehttp = _createHttpObj()
|
||||
params = {'token': credentials.refresh_token}
|
||||
revoke_uri = 'https://accounts.google.com/o/oauth2/revoke?%s' % urlencode(params)
|
||||
sys.stderr.write('This OAuth token will self-destruct in 3...')
|
||||
sys.stderr.flush()
|
||||
time.sleep(1)
|
||||
sys.stderr.write('2...')
|
||||
sys.stderr.flush()
|
||||
time.sleep(1)
|
||||
sys.stderr.write('1...')
|
||||
sys.stderr.flush()
|
||||
time.sleep(1)
|
||||
sys.stderr.write('boom!\n')
|
||||
sys.stderr.flush()
|
||||
simplehttp.request(revoke_uri, 'GET')
|
||||
os.remove(GC_Values[GC_OAUTH2_TXT])
|
||||
lock_file = '%s.lock' % GC_Values[GC_OAUTH2_TXT]
|
||||
lock = FileLock(lock_file, timeout=10)
|
||||
with lock:
|
||||
credentials = getOauth2TxtStorageCredentials()
|
||||
if credentials is None:
|
||||
return
|
||||
simplehttp = _createHttpObj()
|
||||
params = {'token': credentials.refresh_token}
|
||||
revoke_uri = 'https://accounts.google.com/o/oauth2/revoke?%s' % urlencode(params)
|
||||
sys.stderr.write('This OAuth token will self-destruct in 3...')
|
||||
sys.stderr.flush()
|
||||
time.sleep(1)
|
||||
sys.stderr.write('2...')
|
||||
sys.stderr.flush()
|
||||
time.sleep(1)
|
||||
sys.stderr.write('1...')
|
||||
sys.stderr.flush()
|
||||
time.sleep(1)
|
||||
sys.stderr.write('boom!\n')
|
||||
sys.stderr.flush()
|
||||
simplehttp.request(revoke_uri, 'GET')
|
||||
os.remove(GC_Values[GC_OAUTH2_TXT])
|
||||
if not GM_Globals[GM_WINDOWS]:
|
||||
try:
|
||||
os.remove(lock_file)
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
def writeCredentials(creds):
|
||||
creds_data = {
|
||||
@@ -13989,7 +14076,7 @@ def run_batch(items):
|
||||
if not items:
|
||||
return
|
||||
num_worker_threads = min(len(items), GC_Values[GC_NUM_THREADS])
|
||||
pool = Pool(num_worker_threads, init_gam_worker)
|
||||
pool = mp_pool(num_worker_threads, init_gam_worker)
|
||||
sys.stderr.write('Using %s processes...\n' % num_worker_threads)
|
||||
try:
|
||||
results = []
|
||||
@@ -13998,7 +14085,7 @@ def run_batch(items):
|
||||
sys.stderr.write('commit-batch - waiting for running processes to finish before proceeding\n')
|
||||
pool.close()
|
||||
pool.join()
|
||||
pool = Pool(num_worker_threads, init_gam_worker)
|
||||
pool = mp_pool(num_worker_threads, init_gam_worker)
|
||||
sys.stderr.write('commit-batch - running processes finished, proceeding\n')
|
||||
continue
|
||||
results.append(pool.apply_async(ProcessGAMCommandMulti, [item]))
|
||||
@@ -14891,8 +14978,12 @@ def ProcessGAMCommand(args):
|
||||
|
||||
# Run from command line
|
||||
if __name__ == "__main__":
|
||||
if sys.platform.startswith('win'):
|
||||
freeze_support()
|
||||
mp_freeze_support()
|
||||
if sys.platform == 'darwin':
|
||||
# https://bugs.python.org/issue33725 in Python 3.8.0 seems
|
||||
# to break parallel operations with errors about extra -b
|
||||
# command line arguments
|
||||
mp_set_start_method('fork')
|
||||
if sys.version_info[0] < 3 or sys.version_info[1] < 5:
|
||||
systemErrorExit(5, 'GAM requires Python 3.5 or newer. You are running %s.%s.%s. Please upgrade your Python version or use one of the binary GAM downloads.' % sys.version_info[:3])
|
||||
sys.exit(ProcessGAMCommand(sys.argv))
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
python-dateutil
|
||||
distro; sys_platform == 'linux'
|
||||
filelock
|
||||
google-api-python-client>=1.7.10
|
||||
google-auth
|
||||
google-auth-httplib2
|
||||
google-auth-oauthlib==0.4.0
|
||||
google-auth-oauthlib>=0.4.1
|
||||
httplib2>=0.13.0
|
||||
passlib
|
||||
|
||||
15
src/tools/a_atleast_b.py
Executable file
15
src/tools/a_atleast_b.py
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
#from packaging import version
|
||||
from distutils.version import LooseVersion
|
||||
import sys
|
||||
|
||||
a = sys.argv[1]
|
||||
b = sys.argv[2]
|
||||
#result = version.parse(a) >= version.parse(b)
|
||||
result = LooseVersion(a) >= LooseVersion(b)
|
||||
if result:
|
||||
print('OK: %s is equal or newer than %s' % (a, b))
|
||||
else:
|
||||
print('ERROR: %s is older than %s' % (a, b))
|
||||
sys.exit(not result)
|
||||
73
src/travis/linux-arm64-before-install.sh
Executable file
73
src/travis/linux-arm64-before-install.sh
Executable file
@@ -0,0 +1,73 @@
|
||||
export whereibelong=$(pwd)
|
||||
export dist=$(lsb_release --codename --short)
|
||||
echo "We are running on Ubuntu $dist"
|
||||
export LD_LIBRARY_PATH=~/ssl/lib:~/python/lib
|
||||
cpucount=$(nproc --all)
|
||||
echo "This device has $cpucount CPUs for compiling..."
|
||||
sudo apt-get -qq --yes update > /dev/null
|
||||
sudo apt-get -qq --yes install xz-utils > /dev/null
|
||||
SSLVER=$(~/ssl/bin/openssl version)
|
||||
SSLRESULT=$?
|
||||
PYVER=$(~/python/bin/python3 -V)
|
||||
PYRESULT=$?
|
||||
if [ $SSLRESULT -ne 0 ] || [[ "$SSLVER" != "OpenSSL $BUILD_OPENSSL_VERSION "* ]] || [ $PYRESULT -ne 0 ] || [[ "$PYVER" != "Python $PYTHON_BUILD_VERSION"* ]]; then
|
||||
echo "RUNNING: apt dist-upgrade..."
|
||||
sudo apt-get -qq --yes dist-upgrade > /dev/null
|
||||
echo "Installing build tools..."
|
||||
sudo apt-get -qq --yes install build-essential
|
||||
|
||||
echo "Installing deps for python3"
|
||||
sudo cp -v /etc/apt/sources.list /tmp
|
||||
sudo chmod a+rwx /tmp/sources.list
|
||||
echo "deb-src http://archive.ubuntu.com/ubuntu/ $dist main" >> /tmp/sources.list
|
||||
sudo cp -v /tmp/sources.list /etc/apt
|
||||
sudo apt-get -qq --yes update > /dev/null
|
||||
sudo apt-get -qq --yes build-dep python3 > /dev/null
|
||||
sudo apt-get -qq --yes install zlib1g-dev > /dev/null
|
||||
sudo apt-get -qq --yes install libffi-dev > /dev/null
|
||||
|
||||
# Compile latest OpenSSL
|
||||
echo "Downloading OpenSSL..."
|
||||
wget --quiet https://www.openssl.org/source/openssl-$BUILD_OPENSSL_VERSION.tar.gz
|
||||
echo "Extracting OpenSSL..."
|
||||
tar xf openssl-$BUILD_OPENSSL_VERSION.tar.gz
|
||||
cd openssl-$BUILD_OPENSSL_VERSION
|
||||
echo "Compiling OpenSSL $BUILD_OPENSSL_VERSION..."
|
||||
./config shared --prefix=$HOME/ssl
|
||||
echo "Running make for OpenSSL..."
|
||||
make -j$cpucount -s
|
||||
echo "Running make install for OpenSSL..."
|
||||
make install > /dev/null
|
||||
cd ~
|
||||
|
||||
# Compile latest Python
|
||||
echo "Downloading Python $BUILD_PYTHON_VERSION..."
|
||||
curl -O https://www.python.org/ftp/python/$BUILD_PYTHON_VERSION/Python-$BUILD_PYTHON_VERSION.tar.xz
|
||||
echo "Extracting Python..."
|
||||
tar xf Python-$BUILD_PYTHON_VERSION.tar.xz
|
||||
cd Python-$BUILD_PYTHON_VERSION
|
||||
echo "Compiling Python $BUILD_PYTHON_VERSION..."
|
||||
safe_flags="--with-openssl=$HOME/ssl --enable-shared --prefix=$HOME/python --with-ensurepip=upgrade"
|
||||
unsafe_flags="--enable-optimizations --with-lto"
|
||||
echo "running configure with safe and unsafe"
|
||||
./configure $safe_flags $unsafe_flags > /dev/null
|
||||
make -j$cpucount PROFILE_TASK="-m test.regrtest --pgo -j$(( $cpucount * 2 ))" -s
|
||||
echo "Installing Python..."
|
||||
make install > /dev/null
|
||||
fi
|
||||
|
||||
python=~/python/bin/python3
|
||||
pip=~/python/bin/pip3
|
||||
|
||||
$python -V
|
||||
|
||||
cd $whereibelong
|
||||
|
||||
echo "Upgrading pip packages..."
|
||||
$pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 $pip install -U
|
||||
$pip install --upgrade -r src/requirements.txt
|
||||
$pip install --upgrade https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz
|
||||
|
||||
mkdir ~/.ruby
|
||||
export GEM_HOME=~/.ruby
|
||||
export PATH=$PATH:~/.ruby/bin
|
||||
33
src/travis/linux-arm64-install.sh
Executable file
33
src/travis/linux-arm64-install.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
cd src
|
||||
if [ "$VMTYPE" == "test" ]; then
|
||||
export gam="$python gam.py"
|
||||
export gampath=$(readlink -e .)
|
||||
else
|
||||
$python -OO -m PyInstaller --clean --noupx --strip -F --distpath=gam $GAMOS-gam.spec
|
||||
export gam="gam/gam"
|
||||
export gampath=$(readlink -e gam)
|
||||
export GAMVERSION=`$gam version simple`
|
||||
cp LICENSE $gampath
|
||||
cp whatsnew.txt $gampath
|
||||
cp GamCommands.txt $gampath
|
||||
this_glibc_ver=$(ldd --version | awk '/ldd/{print $NF}')
|
||||
GAM_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM-glibc$this_glibc_ver.tar.xz
|
||||
rm $gampath/lastupdatecheck.txt
|
||||
tar cfJ $GAM_ARCHIVE gam/
|
||||
echo "PyInstaller GAM info:"
|
||||
du -h gam/gam
|
||||
time $gam version extended
|
||||
|
||||
if [[ "$dist" == "precise" ]]; then
|
||||
GAM_LEGACY_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM-legacy.tar.xz
|
||||
$python -OO -m staticx gam/gam gam/gam-staticx
|
||||
strip gam/gam-staticx
|
||||
rm gam/gam
|
||||
mv gam/gam-staticx gam/gam
|
||||
tar cfJ $GAM_LEGACY_ARCHIVE gam/
|
||||
echo "Legacy StaticX GAM info:"
|
||||
du -h gam/gam
|
||||
time $gam version extended
|
||||
fi
|
||||
|
||||
fi
|
||||
@@ -7,86 +7,90 @@ else
|
||||
export whereibelong=$(pwd)
|
||||
export dist=$(lsb_release --codename --short)
|
||||
echo "We are running on Ubuntu $dist"
|
||||
echo "RUNNING: apt update..."
|
||||
sudo apt-get -qq --yes update > /dev/null
|
||||
echo "RUNNING: apt dist-upgrade..."
|
||||
# sudo apt-get -qq --yes dist-upgrade > /dev/null
|
||||
echo "Installing build tools..."
|
||||
sudo apt-get -qq --yes install build-essential
|
||||
|
||||
echo "Installing deps for python3"
|
||||
sudo cp -v /etc/apt/sources.list /tmp
|
||||
sudo chmod a+rwx /tmp/sources.list
|
||||
echo "deb-src http://archive.ubuntu.com/ubuntu/ $dist main" >> /tmp/sources.list
|
||||
sudo cp -v /tmp/sources.list /etc/apt
|
||||
sudo apt-get -qq --yes update > /dev/null
|
||||
sudo apt-get -qq --yes build-dep python3 > /dev/null
|
||||
|
||||
mypath=$HOME
|
||||
echo "My Path is $mypath"
|
||||
export LD_LIBRARY_PATH=~/ssl/lib:~/python/lib
|
||||
cpucount=$(nproc --all)
|
||||
echo "This device has $cpucount CPUs for compiling..."
|
||||
SSLVER=$(~/ssl/bin/openssl version)
|
||||
SSLRESULT=$?
|
||||
PYVER=$(~/python/bin/python3 -V)
|
||||
PYRESULT=$?
|
||||
if [ $SSLRESULT -ne 0 ] || [[ "$SSLVER" != "OpenSSL $BUILD_OPENSSL_VERSION "* ]] || [ $PYRESULT -ne 0 ] || [[ "$PYVER" != "Python $PYTHON_BUILD_VERSION"* ]]; then
|
||||
echo "SSL Result: $SSLRESULT - SSL Ver: $SSLVER - Py Result: $PYRESULT - Py Ver: $PYVER"
|
||||
if [ $SSLRESULT -ne 0 ]; then
|
||||
echo "sslresult -ne 0"
|
||||
fi
|
||||
if [[ "$SSLVER" != "OpenSSL $BUILD_OPENSSL_VERSION "* ]]; then
|
||||
echo "sslver not equal to..."
|
||||
fi
|
||||
if [ $PYRESULT -ne 0 ]; then
|
||||
echo "pyresult -ne 0"
|
||||
fi
|
||||
if [[ "$PYVER" != "Python $PYTHON_BUILD_VERSION" ]]; then
|
||||
echo "pyver not equal to..."
|
||||
fi
|
||||
cd ~
|
||||
rm -rf ssl
|
||||
rm -rf python
|
||||
mkdir ssl
|
||||
mkdir python
|
||||
echo "RUNNING: apt update..."
|
||||
sudo apt-get -qq --yes update > /dev/null
|
||||
echo "RUNNING: apt dist-upgrade..."
|
||||
sudo apt-get -qq --yes dist-upgrade > /dev/null
|
||||
echo "Installing build tools..."
|
||||
sudo apt-get -qq --yes install build-essential
|
||||
echo "Installing deps for python3"
|
||||
sudo cp -v /etc/apt/sources.list /tmp
|
||||
sudo chmod a+rwx /tmp/sources.list
|
||||
echo "deb-src http://archive.ubuntu.com/ubuntu/ $dist main" >> /tmp/sources.list
|
||||
sudo cp -v /tmp/sources.list /etc/apt
|
||||
sudo apt-get -qq --yes update > /dev/null
|
||||
sudo apt-get -qq --yes build-dep python3 > /dev/null
|
||||
|
||||
cd ~/pybuild
|
||||
# Compile latest OpenSSL
|
||||
if [ ! -d openssl-$BUILD_OPENSSL_VERSION ]; then
|
||||
# Compile latest OpenSSL
|
||||
wget --quiet https://www.openssl.org/source/openssl-$BUILD_OPENSSL_VERSION.tar.gz
|
||||
echo "Extracting OpenSSL..."
|
||||
tar xf openssl-$BUILD_OPENSSL_VERSION.tar.gz
|
||||
fi
|
||||
cd openssl-$BUILD_OPENSSL_VERSION
|
||||
echo "Compiling OpenSSL $BUILD_OPENSSL_VERSION..."
|
||||
./config shared --prefix=$mypath/ssl
|
||||
echo "Running make for OpenSSL..."
|
||||
make -j$cpucount -s
|
||||
echo "Running make install for OpenSSL..."
|
||||
make install > /dev/null
|
||||
export LD_LIBRARY_PATH=~/ssl/lib
|
||||
cd ~
|
||||
cd openssl-$BUILD_OPENSSL_VERSION
|
||||
echo "Compiling OpenSSL $BUILD_OPENSSL_VERSION..."
|
||||
./config shared --prefix=$HOME/ssl
|
||||
echo "Running make for OpenSSL..."
|
||||
make -j$cpucount -s
|
||||
echo "Running make install for OpenSSL..."
|
||||
make install > /dev/null
|
||||
cd ~
|
||||
|
||||
cd ~/pybuild
|
||||
# Compile latest Python
|
||||
if [ ! -d Python-$BUILD_PYTHON_VERSION ]; then
|
||||
# Compile latest Python
|
||||
echo "Downloading Python $BUILD_PYTHON_VERSION..."
|
||||
curl -O https://www.python.org/ftp/python/$BUILD_PYTHON_VERSION/Python-$BUILD_PYTHON_VERSION.tar.xz
|
||||
echo "Extracting Python..."
|
||||
tar xf Python-$BUILD_PYTHON_VERSION.tar.xz
|
||||
fi
|
||||
cd Python-$BUILD_PYTHON_VERSION
|
||||
#if [[ "$dist" == "bionic" ]]; then
|
||||
# echo "running bionic make clean"
|
||||
# make clean
|
||||
# rm Makefile
|
||||
#fi
|
||||
echo "Compiling Python $BUILD_PYTHON_VERSION..."
|
||||
safe_flags="--with-openssl=$mypath/ssl --enable-shared --prefix=$mypath/python --with-ensurepip=upgrade"
|
||||
unsafe_flags="--enable-optimizations --with-lto"
|
||||
|
||||
if [ ! -e Makefile ]; then
|
||||
echo "running configure with safe and unsafe"
|
||||
./configure $safe_flags $unsafe_flags > /dev/null
|
||||
fi
|
||||
timeout 1800 make -j$cpucount -s
|
||||
RESULT=$?
|
||||
echo "First make exited with $RESULT"
|
||||
if [ $RESULT != 0 ]; then
|
||||
#echo "Trying Python compile again without unsafe flags..."
|
||||
#make clean
|
||||
#./configure $safe_flags > /dev/null
|
||||
#make -j$cpucount -s
|
||||
echo "Sticking with safe Python for now..."
|
||||
else
|
||||
echo "Installing optimized Python..."
|
||||
cd Python-$BUILD_PYTHON_VERSION
|
||||
echo "Compiling Python $BUILD_PYTHON_VERSION..."
|
||||
safe_flags="--with-openssl=$HOME/ssl --enable-shared --prefix=$HOME/python --with-ensurepip=upgrade"
|
||||
unsafe_flags="--enable-optimizations --with-lto"
|
||||
if [ ! -e Makefile ]; then
|
||||
echo "running configure with safe and unsafe"
|
||||
./configure $safe_flags $unsafe_flags > /dev/null
|
||||
fi
|
||||
make -j$cpucount PROFILE_TASK="-m test.regrtest --pgo -j$(( $cpucount * 2 ))" -s
|
||||
RESULT=$?
|
||||
echo "First make exited with $RESULT"
|
||||
if [ $RESULT != 0 ]; then
|
||||
echo "Trying Python compile again without unsafe flags..."
|
||||
make clean
|
||||
./configure $safe_flags > /dev/null
|
||||
make -j$cpucount -s
|
||||
echo "Sticking with safe Python for now..."
|
||||
fi
|
||||
echo "Installing Python..."
|
||||
make install > /dev/null
|
||||
cd ~
|
||||
fi
|
||||
cd ~
|
||||
|
||||
export LD_LIBRARY_PATH=~/ssl/lib:~/python/lib
|
||||
python=~/python/bin/python3
|
||||
pip=~/python/bin/pip3
|
||||
|
||||
$python -V
|
||||
|
||||
if [[ "$dist" == "precise" ]]; then
|
||||
echo "Installing deps for StaticX..."
|
||||
sudo apt-get install --yes scons
|
||||
@@ -99,21 +103,13 @@ else
|
||||
make
|
||||
sudo make install
|
||||
fi
|
||||
if [ ! -d musl=$MUSL_VERSION ]; then
|
||||
echo "Downloading MUSL $MUSL_VERSION"
|
||||
wget https://www.musl-libc.org/releases/musl-$MUSL_VERSION.tar.gz
|
||||
tar xf musl-$MUSL_VERSION.tar.gz
|
||||
cd musl-$MUSL_VERSION
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
fi
|
||||
$pip install git+https://github.com/JonathonReinhart/staticx.git@master
|
||||
fi
|
||||
|
||||
cd $whereibelong
|
||||
fi
|
||||
|
||||
echo "Upgrading pip packages..."
|
||||
$pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 $pip install -U
|
||||
$pip install --upgrade -r src/requirements.txt
|
||||
$pip install --upgrade pyinstaller
|
||||
$pip install --upgrade https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz
|
||||
|
||||
@@ -3,15 +3,24 @@ whereibelong=$(pwd)
|
||||
#echo "Brew installing xz..."
|
||||
#brew install xz > /dev/null
|
||||
|
||||
cd ~/pybuild
|
||||
#brew upgrade
|
||||
|
||||
cd ~
|
||||
|
||||
if [ ! -f python-$BUILD_PYTHON_VERSION-macosx10.9.pkg ]; then
|
||||
wget --quiet https://www.python.org/ftp/python/$BUILD_PYTHON_VERSION/python-$BUILD_PYTHON_VERSION-macosx10.9.pkg
|
||||
fi
|
||||
sudo installer -pkg python-$BUILD_PYTHON_VERSION-macosx10.9.pkg -target /
|
||||
|
||||
#brew install openssl@1.1
|
||||
#brew upgrade python
|
||||
|
||||
export python=python3
|
||||
export pip=pip3
|
||||
|
||||
echo "Python location:"
|
||||
which $python
|
||||
|
||||
# Compile latest OpenSSL
|
||||
#if [ ! -d openssl-$BUILD_OPENSSL_VERSION ]; then
|
||||
# wget --quiet https://www.openssl.org/source/openssl-$BUILD_OPENSSL_VERSION.tar.gz
|
||||
@@ -26,7 +35,7 @@ export pip=pip3
|
||||
#echo "Running make install for OpenSSL..."
|
||||
#make install > /dev/null
|
||||
#export LD_LIBRARY_PATH=~/ssl/lib
|
||||
#cd ~/pybuild
|
||||
#cd ~
|
||||
|
||||
# Compile latest Python
|
||||
#if [ ! -d Python-$BUILD_PYTHON_VERSION ]; then
|
||||
@@ -58,7 +67,6 @@ export pip=pip3
|
||||
#python=~/python/bin/python3
|
||||
#pip=~/python/bin/pip3
|
||||
|
||||
|
||||
$python -V
|
||||
|
||||
cd $whereibelong
|
||||
@@ -67,4 +75,4 @@ export PATH=/usr/local/opt/python/libexec/bin:$PATH
|
||||
$pip install --upgrade pip
|
||||
$pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 $pip install -U
|
||||
$pip install --upgrade -r src/requirements.txt
|
||||
$pip install --upgrade pyinstaller
|
||||
$pip install --upgrade https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
cd src
|
||||
echo "MacOS Version Info According to Python:"
|
||||
python -c "import platform; print(platform.mac_ver())"
|
||||
$python -OO -m PyInstaller --clean --noupx --strip -F --distpath=gam $GAMOS-gam.spec
|
||||
export gam="gam/gam"
|
||||
export gampath=gam
|
||||
@@ -7,6 +9,7 @@ export GAMVERSION=`gam/gam version simple`
|
||||
cp LICENSE gam
|
||||
cp whatsnew.txt gam
|
||||
cp GamCommands.txt gam
|
||||
GAM_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM.tar.xz
|
||||
MACOSVERSION=$(defaults read loginwindow SystemVersionStampAsString)
|
||||
GAM_ARCHIVE=gam-$GAMVERSION-$GAMOS-$PLATFORM-MacOS$MACOSVERSION.tar.xz
|
||||
rm gam/lastupdatecheck.txt
|
||||
tar cfJ $GAM_ARCHIVE gam/
|
||||
|
||||
@@ -1,44 +1,34 @@
|
||||
echo "Installing Net-Framework-Core..."
|
||||
export mypath=$(pwd)
|
||||
cd ~
|
||||
until powershell Install-WindowsFeature Net-Framework-Core; do echo "trying again..."; done
|
||||
cd ~/pybuild
|
||||
#export exefile=Win32OpenSSL_Light-${BUILD_OPENSSL_VERSION//./_}.exe
|
||||
#if [ ! -e $exefile ]; then
|
||||
# echo "Downloading $exefile..."
|
||||
# wget --quiet https://slproweb.com/download/$exefile
|
||||
#fi
|
||||
#echo "Installing $exefile..."
|
||||
#powershell ".\\${exefile} /silent /sp- /suppressmsgboxes /DIR=C:\\ssl"
|
||||
cinst -y --forcex86 python3
|
||||
until cinst -y wixtoolset; do echo "trying again..."; done
|
||||
#echo "OpenSSL dlls..."
|
||||
#ls -alRF /c/ssl
|
||||
#echo "c drive"
|
||||
#ls -al /c/
|
||||
#echo "Python dlls..."
|
||||
#ls -al /c/Python37/DLLs
|
||||
#until cp -v /c/ssl/*.dll /c/Python37/DLLs; do echo "trying again..."; done
|
||||
export PATH=$PATH:/c/Python37/scripts
|
||||
export PATH=$PATH:/c/Python38/scripts
|
||||
cd $mypath
|
||||
pip install --upgrade pip
|
||||
pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
|
||||
pip install --upgrade -r src/requirements.txt
|
||||
export python=/c/Python38/python.exe
|
||||
export pip=/c/Python38/scripts/pip.exe
|
||||
|
||||
#pip install --upgrade pyinstaller
|
||||
$pip install --upgrade pip
|
||||
$pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 $pip install -U
|
||||
$pip install --upgrade -r src/requirements.txt
|
||||
|
||||
#$pip install --upgrade pyinstaller
|
||||
# Install PyInstaller from source and build bootloader
|
||||
# to try and avoid getting flagged as malware since
|
||||
# lots of malware uses PyInstaller default bootloader
|
||||
# https://stackoverflow.com/questions/53584395/how-to-recompile-the-bootloader-of-pyinstaller
|
||||
echo "Downloading PyInstaller..."
|
||||
wget --quiet https://github.com/pyinstaller/pyinstaller/releases/download/v$PYINSTALLER_VERSION/PyInstaller-$PYINSTALLER_VERSION.tar.gz
|
||||
tar xf PyInstaller-$PYINSTALLER_VERSION.tar.gz
|
||||
cd PyInstaller-$PYINSTALLER_VERSION/bootloader
|
||||
wget --quiet https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz
|
||||
tar xf develop.tar.gz
|
||||
cd pyinstaller-develop/bootloader
|
||||
echo "bootloader before:"
|
||||
md5sum ../PyInstaller/bootloader/Windows-32bit/*
|
||||
/c/python37/python ./waf all --target-arch=32bit
|
||||
$python ./waf all --target-arch=32bit
|
||||
echo "bootloader after:"
|
||||
md5sum ../PyInstaller/bootloader/Windows-32bit/*
|
||||
echo "PATH: $PATH"
|
||||
cd ..
|
||||
/c/python37/python setup.py install
|
||||
$python setup.py install
|
||||
echo "cd to $mypath"
|
||||
cd $mypath
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
echo "Installing Net-Framework-Core..."
|
||||
export mypath=$(pwd)
|
||||
until powershell Install-WindowsFeature Net-Framework-Core; do echo "trying again..."; done
|
||||
cd ~/pybuild
|
||||
cd ~
|
||||
#export exefile=Win64OpenSSL_Light-${BUILD_OPENSSL_VERSION//./_}.exe
|
||||
#if [ ! -e $exefile ]; then
|
||||
# echo "Downloading $exefile..."
|
||||
@@ -11,33 +11,36 @@ cd ~/pybuild
|
||||
#powershell ".\\${exefile} /silent /sp- /suppressmsgboxes /DIR=C:\\ssl"
|
||||
cinst -y python3
|
||||
until cinst -y wixtoolset; do echo "trying again..."; done
|
||||
#echo "OpenSSL dlls..."
|
||||
#ls -alRF /c/ssl
|
||||
#echo "c drive"
|
||||
#ls -al /c
|
||||
#echo "Python dlls..."
|
||||
#ls -al /c/Python37/DLLs
|
||||
#until cp -v /c/ssl/*.dll /c/Python37/DLLs; do echo "trying again..."; done
|
||||
export PATH=$PATH:/c/Python37/scripts
|
||||
#until cp -v /c/ssl/libcrypto-1_1-x64.dll /c/Python37/DLLs/libcrypto-1_1.dll; do echo "trying again..."; done
|
||||
#until cp -v /c/ssl/libssl-1_1-x64.dll /c/Python37/DLLs/libssl-1_1.dll; do echo "trying again..."; done
|
||||
export PATH=$PATH:/c/Python38/scripts
|
||||
cd $mypath
|
||||
pip install --upgrade pip
|
||||
pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U
|
||||
pip install --upgrade -r src/requirements.txt
|
||||
#pip install --upgrade pyinstaller
|
||||
export python=/c/Python38/python.exe
|
||||
export pip=/c/Python38/scripts/pip.exe
|
||||
|
||||
$pip install --upgrade pip
|
||||
$pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 $pip install -U
|
||||
$pip install --upgrade -r src/requirements.txt
|
||||
#$pip install --upgrade pyinstaller
|
||||
# Install PyInstaller from source and build bootloader
|
||||
# to try and avoid getting flagged as malware since
|
||||
# lots of malware uses PyInstaller default bootloader
|
||||
# https://stackoverflow.com/questions/53584395/how-to-recompile-the-bootloader-of-pyinstaller
|
||||
echo "Downloading PyInstaller..."
|
||||
wget --quiet https://github.com/pyinstaller/pyinstaller/releases/download/v$PYINSTALLER_VERSION/PyInstaller-$PYINSTALLER_VERSION.tar.gz
|
||||
tar xf PyInstaller-$PYINSTALLER_VERSION.tar.gz
|
||||
cd PyInstaller-$PYINSTALLER_VERSION/bootloader
|
||||
#wget --quiet https://github.com/pyinstaller/pyinstaller/releases/download/v$PYINSTALLER_VERSION/PyInstaller-$PYINSTALLER_VERSION.tar.gz
|
||||
wget --quiet https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz
|
||||
#tar xf PyInstaller-$PYINSTALLER_VERSION.tar.gz
|
||||
tar xf develop.tar.gz
|
||||
#cd PyInstaller-$PYINSTALLER_VERSION/bootloader
|
||||
cd pyinstaller-develop/bootloader
|
||||
echo "bootloader before:"
|
||||
md5sum ../PyInstaller/bootloader/Windows-64bit/*
|
||||
/c/python37/python ./waf all --target-arch=64bit
|
||||
$python ./waf all --target-arch=64bit
|
||||
echo "bootloader after:"
|
||||
md5sum ../PyInstaller/bootloader/Windows-64bit/*
|
||||
echo "PATH: $PATH"
|
||||
cd ..
|
||||
/c/python37/python setup.py install
|
||||
$python setup.py install
|
||||
echo "cd to $mypath..."
|
||||
#until cp -v /c/ssl/*.dll /c/Python37/DLLs; do echo "trying again..."; done
|
||||
cd $mypath
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
cd src
|
||||
echo "compiling GAM with pyinstaller..."
|
||||
pyinstaller --clean --noupx -F --distpath=gam $GAMOS-gam.spec
|
||||
export gam="gam/gam"
|
||||
export gampath=$(readlink -e gam)
|
||||
echo "running compiled GAM..."
|
||||
$gam version
|
||||
export GAMVERSION=`$gam version simple`
|
||||
rm gam/lastupdatecheck.txt
|
||||
|
||||
44
src/var.py
44
src/var.py
@@ -6,7 +6,7 @@ import platform
|
||||
import re
|
||||
|
||||
gam_author = 'Jay Lee <jay0lee@gmail.com>'
|
||||
gam_version = '4.94'
|
||||
gam_version = '4.96'
|
||||
gam_license = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||
|
||||
GAM_URL = 'https://git.io/gam'
|
||||
@@ -232,6 +232,7 @@ DRIVEFILE_FIELDS_CHOICES_MAP = {
|
||||
'cancomment': 'canComment',
|
||||
'canreadrevisions': 'canReadRevisions',
|
||||
'copyable': 'copyable',
|
||||
'copyrequireswriterpermission': 'copyRequiresWriterPermission',
|
||||
'createddate': 'createdDate',
|
||||
'createdtime': 'createdDate',
|
||||
'description': 'description',
|
||||
@@ -381,18 +382,33 @@ GOOGLEDOC_VALID_EXTENSIONS_MAP = {
|
||||
MIMETYPE_GA_SPREADSHEET: ['.csv', '.ods', '.pdf', '.xlsx', '.zip'],
|
||||
}
|
||||
|
||||
_MICROSOFT_FORMATS_LIST = [{'mime': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'ext': '.docx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'ext': '.dotx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'ext': '.pptx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ext': '.potx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'ext': '.xlsx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'ext': '.xltx'},
|
||||
{'mime': 'application/msword', 'ext': '.doc'},
|
||||
{'mime': 'application/msword', 'ext': '.dot'},
|
||||
{'mime': 'application/vnd.ms-powerpoint', 'ext': '.ppt'},
|
||||
{'mime': 'application/vnd.ms-powerpoint', 'ext': '.pot'},
|
||||
{'mime': 'application/vnd.ms-excel', 'ext': '.xls'},
|
||||
{'mime': 'application/vnd.ms-excel', 'ext': '.xlt'}]
|
||||
MACOS_CODENAMES = {
|
||||
6: 'Snow Leopard',
|
||||
7: 'Lion',
|
||||
8: 'Mountain Lion',
|
||||
9: 'Mavericks',
|
||||
10: 'Yosemite',
|
||||
11: 'El Capitan',
|
||||
12: 'Sierra',
|
||||
13: 'High Sierra',
|
||||
14: 'Mojave',
|
||||
15: 'Catalina'
|
||||
}
|
||||
|
||||
_MICROSOFT_FORMATS_LIST = [
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'ext': '.docx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'ext': '.dotx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'ext': '.pptx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ext': '.potx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'ext': '.xlsx'},
|
||||
{'mime': 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'ext': '.xltx'},
|
||||
{'mime': 'application/msword', 'ext': '.doc'},
|
||||
{'mime': 'application/msword', 'ext': '.dot'},
|
||||
{'mime': 'application/vnd.ms-powerpoint', 'ext': '.ppt'},
|
||||
{'mime': 'application/vnd.ms-powerpoint', 'ext': '.pot'},
|
||||
{'mime': 'application/vnd.ms-excel', 'ext': '.xls'},
|
||||
{'mime': 'application/vnd.ms-excel', 'ext': '.xlt'}
|
||||
]
|
||||
|
||||
DOCUMENT_FORMATS_MAP = {
|
||||
'csv': [{'mime': 'text/csv', 'ext': '.csv'}],
|
||||
@@ -933,6 +949,8 @@ MESSAGE_NO_TRANSFER_LACK_OF_DISK_SPACE = 'Cowardly refusing to perform migration
|
||||
MESSAGE_RESULTS_TOO_LARGE_FOR_GOOGLE_SPREADSHEET = 'Results are too large for Google Spreadsheets. Uploading as a regular CSV file.'
|
||||
MESSAGE_SERVICE_NOT_APPLICABLE = 'Service not applicable for this address: {0}. Please make sure service is enabled for user and run\n\ngam user <user> check serviceaccount\n\nfor further instructions'
|
||||
MESSAGE_INSTRUCTIONS_OAUTH2SERVICE_JSON = 'Please run\n\ngam create project\ngam user <user> check serviceaccount\n\nto create and configure a service account.'
|
||||
MESSAGE_UPDATE_GAM_TO_64BIT = "You're running a 32-bit version of GAM on a 64-bit version of Windows, upgrade to a windows-x86_64 version of GAM"
|
||||
MESSAGE_YOUR_SYSTEM_TIME_DIFFERS_FROM_GOOGLE_BY = 'Your system time differs from Google by %s'
|
||||
# oauth errors
|
||||
OAUTH2_TOKEN_ERRORS = [
|
||||
'access_denied',
|
||||
|
||||
Reference in New Issue
Block a user