Skip to content

Commit

Permalink
Escape xml special characters (#278) Release 2.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] authored and [email protected] committed Nov 3, 2020
1 parent 9468b41 commit e17515d
Show file tree
Hide file tree
Showing 21 changed files with 64 additions and 61 deletions.
1 change: 0 additions & 1 deletion examples/directory/clear_directory.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import adal

from settings import settings

from office365.graph_client import GraphClient
Expand Down
1 change: 0 additions & 1 deletion examples/onedrive/export_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import tempfile

import adal

from settings import settings

from office365.graph_client import GraphClient
Expand Down
1 change: 0 additions & 1 deletion examples/onedrive/import_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from os.path import isfile, join

import adal

from settings import settings

from office365.graph_client import GraphClient
Expand Down
1 change: 0 additions & 1 deletion examples/onedrive/print_folders_and_files.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import adal

from settings import settings

from office365.graph_client import GraphClient
Expand Down
1 change: 0 additions & 1 deletion examples/outlook/send_message.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import adal

from settings import settings

from office365.graph_client import GraphClient
Expand Down
4 changes: 2 additions & 2 deletions examples/sharepoint/connect_with_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from office365.runtime.auth.client_credential import ClientCredential
from office365.sharepoint.client_context import ClientContext

credentials = ClientCredential(settings['client_credentials']['client_id'],
settings['client_credentials']['client_secret'])
credentials = ClientCredential(settings.get('client_credentials').get('client_id'),
settings.get('client_credentials').get('client_secret'))
ctx = ClientContext(settings['url']).with_credentials(credentials)
if not ctx.authentication_context.acquire_token_func():
print("Acquire token failed")
Expand Down
4 changes: 2 additions & 2 deletions examples/sharepoint/connect_with_user_creds.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from office365.sharepoint.client_context import ClientContext

ctx = ClientContext(settings["url"]).with_credentials(
UserCredential(settings['user_credentials']['username'],
settings['user_credentials']['password']))
UserCredential(settings.get('user_credentials').get('username'),
settings.get('user_credentials').get('password')))

web = ctx.web
ctx.load(web)
Expand Down
4 changes: 2 additions & 2 deletions examples/sharepoint/files/download_file_large.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import os
import tempfile

from office365.runtime.http.request_options import RequestOptions
from settings import settings

from office365.runtime.auth.client_credential import ClientCredential
from office365.runtime.http.request_options import RequestOptions
from office365.sharepoint.client_context import ClientContext


Expand Down Expand Up @@ -40,7 +40,7 @@ def print_download_progress(offset):
settings.get('client_credentials').get('client_secret'))
ctx = ClientContext(site_url).with_credentials(credentials)

file_url = f'/sites/team/Shared Documents/big_buck_bunny.mp4'
file_url = '/sites/team/Shared Documents/big_buck_bunny.mp4'
local_file_name = os.path.join(tempfile.mkdtemp(), os.path.basename(file_url))
with open(local_file_name, "wb") as local_file:
download_file(ctx, file_url, local_file, print_download_progress)
Expand Down
19 changes: 9 additions & 10 deletions examples/sharepoint/lists_and_items/read_attachments.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import os
import tempfile


from settings import settings

from office365.runtime.auth.client_credential import ClientCredential
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.listitems.caml.caml_query import CamlQuery

download_path = tempfile.mkdtemp()
creds = ClientCredential(settings.get('client_credentials').get('client_id'),
settings.get('client_credentials').get('client_secret'))
ctx = ClientContext(settings['url']).with_credentials(creds)

client_creds = ClientCredential(settings['client_credentials']['client_id'],
settings['client_credentials']['client_secret'])
ctx = ClientContext(settings['url']).with_credentials(client_creds)
download_path = tempfile.mkdtemp()

list_obj = ctx.web.lists.get_by_title("Tasks123")
#items = list_obj.get_items(CamlQuery.create_all_items_query())
#items = list_obj.get_items()
items = list_obj.items
list_title = "Tasks"
source_list = ctx.web.lists.get_by_title(list_title)
# items = list_obj.get_items(CamlQuery.create_all_items_query())
# items = list_obj.get_items()
items = source_list.items
ctx.load(items, ["ID", "UniqueId", "FileRef", "LinkFilename", "Title", "Attachments"])
ctx.execute_query()
for item in items:
Expand Down
2 changes: 1 addition & 1 deletion examples/teams/connect_with_msal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import msal

from settings import settings

from office365.graph_client import GraphClient


Expand Down
1 change: 0 additions & 1 deletion examples/teams/provision_team.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import uuid

import adal

from settings import settings

from office365.directory.groupProfile import GroupProfile
Expand Down
9 changes: 4 additions & 5 deletions examples/teams/send_message.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import msal

from office365.teams.itemBody import ItemBody
from settings import settings

from office365.graph_client import GraphClient


Expand Down Expand Up @@ -29,6 +28,6 @@ def acquire_token_by_username_password():
messages = target_team.primaryChannel.messages.get().execute_query()
print(messages)

#item_body = ItemBody("Hello world!")
#message = target_team.primaryChannel.messages.add(item_body).execute_query()
#print(message.web_url)
# item_body = ItemBody("Hello world!")
# message = target_team.primaryChannel.messages.add(item_body).execute_query()
# print(message.web_url)
8 changes: 4 additions & 4 deletions office365/runtime/auth/authentication_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ def acquire_token_for_user(self, username, password):
:type password: str
:type username: str
"""
self.provider = SamlTokenProvider(self.url, username, password)
if not self.provider.acquire_token():
self.provider = SamlTokenProvider(self.url)
if not self.provider.acquire_token(username=username, password=password):
raise ValueError('Acquire token failed: {0}'.format(self.provider.error))
return True

def acquire_token_for_app(self, client_id, client_secret):
"""Acquire token via client credentials (SharePoint App Principal)"""
self.provider = ACSTokenProvider(self.url, client_id, client_secret)
if not self.provider.acquire_token():
self.provider = ACSTokenProvider(self.url)
if not self.provider.acquire_token(client_id=client_id, client_secret=client_secret):
raise ValueError('Acquire token failed: {0}'.format(self.provider.error))
return True

Expand Down
23 changes: 14 additions & 9 deletions office365/runtime/auth/providers/acs_token_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,14 @@

class ACSTokenProvider(BaseTokenProvider, office365.logger.LoggerContext):

def __init__(self, url, client_id, client_secret):
def __init__(self, url):
"""
Provider to acquire the access token from a Microsoft Azure Access Control Service (ACS)
:type client_secret: str
:type client_id: str
:type url: str
"""
self.token = TokenResponse()
self.url = url
self.client_id = client_id
self.client_secret = client_secret
self.redirect_url = None
self.error = None
self.SharePointPrincipal = "00000003-0000-0ff1-ce00-000000000000"
Expand All @@ -28,23 +24,32 @@ def is_authenticated(self):

def acquire_token(self, **kwargs):
try:
client_id = kwargs.get("client_id")
client_secret = kwargs.get("client_secret")
realm = self._get_realm_from_target_url()
try:
from urlparse import urlparse # Python 2.X
except ImportError:
from urllib.parse import urlparse # Python 3+
url_info = urlparse(self.url)
self.token = self.get_app_only_access_token(url_info.hostname, realm)
self.token = self.get_app_only_access_token(client_id, client_secret, url_info.hostname, realm)
return self.token.is_valid
except requests.exceptions.RequestException as e:
self.error = "Error: {}".format(e)
return False

def get_app_only_access_token(self, target_host, target_realm):
def get_app_only_access_token(self, client_id, client_secret, target_host, target_realm):
"""
:type client_id: str
:type client_secret: str
:type target_host: str
:type target_realm: str
"""
resource = self.get_formatted_principal(self.SharePointPrincipal, target_host, target_realm)
principal_id = self.get_formatted_principal(self.client_id, None, target_realm)
principal_id = self.get_formatted_principal(client_id, None, target_realm)
sts_url = self.get_security_token_service_url(target_realm)
oauth2_request = self.create_access_token_request(principal_id, self.client_secret, resource)
oauth2_request = self.create_access_token_request(principal_id, client_secret, resource)
response = requests.post(url=sts_url, headers={'Content-Type': 'application/x-www-form-urlencoded'},
data=oauth2_request)
return TokenResponse.from_json(response.json())
Expand Down
24 changes: 15 additions & 9 deletions office365/runtime/auth/providers/saml_token_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,21 @@ def resolve_base_url(url):
return parts[0] + '://' + host_name


def xml_escape(s_val):
s_val = s_val.replace("&", "&")
s_val = s_val.replace("<", "&lt;")
s_val = s_val.replace(">", "&gt;")
s_val = s_val.replace("\"", "&quot;")
return s_val


class SamlTokenProvider(BaseTokenProvider, office365.logger.LoggerContext):

def __init__(self, url, username, password):
def __init__(self, url):
"""SAML Security Token Service provider
:type password: str
:type username: str
:type url: str
"""
self.__username = username
self.__password = password
# Security Token Service info
self.__sts_profile = STSProfile(resolve_base_url(url))
# Last occurred error
Expand Down Expand Up @@ -62,11 +66,13 @@ def acquire_token(self, **kwargs):

try:
logger.debug("Acquiring Access Token..")
user_realm = self._get_user_realm(self.__username)
username = kwargs.get("username")
password = xml_escape(kwargs.get("password"))
user_realm = self._get_user_realm(username)
if user_realm.IsFederated:
token = self.acquire_service_token_from_adfs(user_realm.STSAuthUrl, self.__username, self.__password)
token = self.acquire_service_token_from_adfs(user_realm.STSAuthUrl, username, password)
else:
token = self._acquire_service_token(self.__username, self.__password)
token = self._acquire_service_token(username, password)
return self._acquire_authentication_cookie(token, user_realm.IsFederated)
except requests.exceptions.RequestException as e:
self.error = "Error: {}".format(e)
Expand Down Expand Up @@ -118,7 +124,7 @@ def acquire_service_token_from_adfs(self, adfs_url, username, password):
'{0}Body/{1}RequestSecurityTokenResponse/{1}RequestedSecurityToken/{2}Assertion'.format(
self.__ns_prefixes['s'], self.__ns_prefixes['wst'], self.__ns_prefixes['saml']))
if assertion_node is None:
self.error = 'Cannot get security assertion for user {0} from {1}'.format(self.__username, adfs_url)
self.error = 'Cannot get security assertion for user {0} from {1}'.format(username, adfs_url)
logger.error(self.error)
return None
# 2. prepare & submit token request
Expand Down
2 changes: 1 addition & 1 deletion office365/sharepoint/userprofiles/peopleManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
from office365.runtime.queries.service_operation_query import ServiceOperationQuery
from office365.runtime.resource_path import ResourcePath
from office365.sharepoint.base_entity import BaseEntity
from office365.sharepoint.userprofiles.personalSiteCreationPriority import PersonalSiteCreationPriority
from office365.sharepoint.userprofiles.personProperties import PersonProperties
from office365.sharepoint.userprofiles.personPropertiesCollection import PersonPropertiesCollection
from office365.sharepoint.userprofiles.personalSiteCreationPriority import PersonalSiteCreationPriority


class PeopleManager(BaseEntity):
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
requests~=2.24.0
requests_ntlm [NTLMAuthentication]
setuptools~=50.3.2
msal~=1.5.1
msal~=1.6.0

7 changes: 4 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

setup(
name="Office365-REST-Python-Client",
version="2.2.1.1",
version="2.2.2",
author="Vadim Gremyachev",
author_email="[email protected]",
maintainer="Konrad Gądek",
Expand All @@ -19,7 +19,7 @@
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/vgrem/Office365-REST-Python-Client",
install_requires=['requests', 'adal'],
install_requires=['requests', 'msal'],
extras_require={
'NTLMAuthentication': ["requests_ntlm"]
},
Expand All @@ -44,6 +44,7 @@
],
packages=setuptools.find_packages(),
package_data={
'office365': ["runtime/auth/providers/templates/SAML.xml", "runtime/auth/providers/templates/RST2.xml", "runtime/auth/providers/templates/FederatedSAML.xml"]
'office365': ["runtime/auth/providers/templates/SAML.xml", "runtime/auth/providers/templates/RST2.xml",
"runtime/auth/providers/templates/FederatedSAML.xml"]
}
)
3 changes: 2 additions & 1 deletion tests/sharepoint/test_folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ def test1_enum_folders_and_files(self):
self.assertIsNotNone(file_in_folder.resource_path)

def test2_create_folder(self):
folder_new = self.__class__.target_list.rootFolder.folders.add(self.__class__.target_folder_name).execute_query()
folder_new = self.__class__.target_list.rootFolder.folders.add(self.__class__.target_folder_name)\
.execute_query()
self.assertTrue(folder_new.properties["Exists"])
self.__class__.target_folder = folder_new

Expand Down
3 changes: 1 addition & 2 deletions tests/sharepoint/test_taxonomy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import uuid
from tests.sharepoint.sharepoint_case import SPTestCase

from office365.sharepoint.fields.field import Field
from tests.sharepoint.sharepoint_case import SPTestCase


class TestSPTaxonomy(SPTestCase):
Expand Down
5 changes: 2 additions & 3 deletions tests/sharepoint/test_user_profile.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from unittest import TestCase

from settings import settings

from office365.runtime.auth.user_credential import UserCredential
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.userprofiles.peopleManager import PeopleManager
from settings import settings


from office365.sharepoint.userprofiles.profileLoader import ProfileLoader


Expand Down

0 comments on commit e17515d

Please sign in to comment.