OneDrive.psm1
function Get-ODAuthentication { PARAM( [Parameter(Mandatory=$True)] [string]$ClientID = "unknown", [string]$Scope = "onedrive.readwrite", [string]$RedirectURI ="https://login.live.com/oauth20_desktop.srf" ) [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | out-null [Reflection.Assembly]::LoadWithPartialName("System.Drawing") | out-null [Reflection.Assembly]::LoadWithPartialName("System.Web") | out-null # ???????????????????????????????????????????????? $URIGetAccessTokenRedirect=$RedirectURI $URIGetAccessToken="https://login.live.com/oauth20_authorize.srf?client_id="+$ClientID+"&scope="+$Scope+"&response_type=token&redirect_uri="+$URIGetAccessTokenRedirect $form = New-Object Windows.Forms.Form $form.text = "Authenticate to OneDrive" $form.size = New-Object Drawing.size @(700,600) $form.Width = 675 $form.Height = 750 $web = New-object System.Windows.Forms.WebBrowser $web.IsWebBrowserContextMenuEnabled = $true $web.Width = 600 $web.Height = 700 $web.Location = "25, 25" $web.navigate($URIGetAccessToken) $DocComplete = { $uri = $web.Url.AbsoluteUri if ($web.Url.AbsoluteUri -match "access_token=|error") {$form.Close() } } $web.Add_DocumentCompleted($DocComplete) $form.Controls.Add($web) $form.showdialog() | out-null # Build object from last URI (which should contains the token) $ReturnURI=($web.Url).ToString().Replace("#","&") $Authentication = New-Object PSObject ForEach ($element in $ReturnURI.Split("?")[1].Split("&")) { $Authentication | add-member Noteproperty $element.split("=")[0] $element.split("=")[1] } if ($Authentication.PSobject.Properties.name -match "expires_in") { $Authentication | add-member Noteproperty "expires" ([System.DateTime]::Now.AddSeconds($Authentication.expires_in)) } if (!($Authentication.PSobject.Properties.name -match "expires_in")) { write-warning("There is maybe an errror, because there is no access_token!") } return $Authentication } function Get-ODWebContent { <# .DESCRIPTION Internal function to handle request to the OneDrive API .PARAMETER AccessToken Specifies a valid access token for bearer authorization .PARAMETER rURI Relative path to the API .PARAMETER Method Webreques method like PUT, GET, ... .PARAMETER Body Payload of a webrequest .PARAMETER BinaryMode Do not convert response to JSON #> PARAM( [Parameter(Mandatory=$True)] [string]$AccessToken, [string]$rURI = "", [ValidateSet("PUT","GET","POST","PATCH","DELETE")] [String]$Method="GET", [String]$Body, [switch]$BinaryMode ) if ($Body -eq "") { $xBody=$null } else { $xBody=$Body } $ODRootURI="https://api.onedrive.com/v1.0" try { $webRequest=Invoke-WebRequest -Method $Method -Uri ($ODRootURI+$rURI) -Header @{ Authorization = "BEARER "+$AccessToken} -ContentType "application/json" -Body $xBody -ErrorAction SilentlyContinue } catch { write-error("Cannot access the api. Webrequest return code is: "+$_.Exception.Response.StatusCode+"`n"+$_.Exception.Response.StatusDescription) break } switch ($webRequest.StatusCode) { 200 { if (!$BinaryMode) {$responseObject = ConvertFrom-Json $webRequest.Content} return $responseObject } 201 { write-debug("Success: "+$webRequest.StatusCode+" - "+$webRequest.StatusDescription) if (!$BinaryMode) {$responseObject = ConvertFrom-Json $webRequest.Content} return $responseObject } 204 { write-debug("Success: "+$webRequest.StatusCode+" - "+$webRequest.StatusDescription+" (item deleted)") $responseObject = "0" return $responseObject } default {write-warning("Cannot access the api. Webrequest return code is: "+$webRequest.StatusCode+"`n"+$webRequest.StatusDescription)} } } function Get-ODDrives { <# .DESCRIPTION Get user's drives .PARAMETER AccessToken Specifies a valid access token for bearer authorization #> PARAM( [Parameter(Mandatory=$True)] [string]$AccessToken ) $ResponseObject=Get-ODWebContent -AccessToken $AccessToken -Method GET -rURI "/drives" return $ResponseObject.Value } function Format-ODPathorIDString { <# .DESCRIPTION Formats a given path like '/myFolder/mySubfolder/myFile' into an expected uri format .PARAMETER Path Specifies the path of an elements. If not given it's the root is used "/" .PARAMETER ElementID Specifies the id of an elements. If Path and ElementID are given, ElementID is used with a warning .PARAMETER DriveID Specifies the OneDrive drive id. If not set, the default drive is used #> PARAM( [string]$Path="", [string]$DriveID="", [string]$ElementID="" ) if (!$ElementID -eq "") { #Use ElementID parameters if (!$Path -eq "") {write-debug("Warning: Path and ElementID parameters are set. Only ElementID is used!")} return "/drive/items/"+$ElementID } else { #Use Path parameter #remove substring starts with "?" if ($Path.Contains("?")) {$Path=$Path.Substring(1,$Path.indexof("?")-1)} #replace "\" with "/" $Path=$Path.Replace("\","/") #filter possible string at the end "/children" (case insensitive) $Path=$Path+"/" $Path=$Path -replace "/children/","" #encoding of url parts $tmpString="" foreach ($Sub in $Path.Split("/")) {$tmpString+=[System.Web.HttpUtility]::UrlEncode($Sub)+"/"} $Path=$tmpString #remove last "/" if exist $Path=$Path.TrimEnd("/") #insert drive part of url if ($DriveID -eq "") { #Default drive $Path="/drive/root:"+$Path+":" } else { #Named drive $Path="/drives/"+$DriveID+"/root:"+$Path+":" } return $Path } } function Get-ODItemProperty { <# .DESCRIPTION Get the properties of an item (file or folder) .PARAMETER AccessToken Specifies a valid access token for bearer authorization .PARAMETER Path Specifies the path to the element/item. If not given the property of your default root are listed .PARAMETER ElementID Specifies the id of the element/item. If Path and ElementID are given, ElementID is used with a warning .PARAMETER SelectProperties Specifies comma separated the properties to return from file and folder objects (case sensitive). If not set name, size, lastModifiedDateTime and id is used. (See https://dev.onedrive.com/odata/optional-query-parameters.htm). If yout use - SelectProperties "" all properties are listed. Warning: A complex content.downloadUrl is listed/generated for download files without authentication for several hours .PARAMETER DriveID Specifies the OneDrive drive id. If not set, the default drive is used #> PARAM( [Parameter(Mandatory=$True)] [string]$AccessToken, [string]$Path="/", [string]$ElementID="", [string]$SelectProperties="name,size,lastModifiedDateTime,id", [string]$DriveID="" ) return Get-ODChildItems -AccessToken $AccessToken -Path $Path -ElementID $ElementID -SelectProperties $SelectProperties -DriveID $DriveID -ItemPropertyMode } function Get-ODChildItems { <# .DESCRIPTION Get child items of a path. Return count is not limited. .PARAMETER AccessToken Specifies a valid access token for bearer authorization .PARAMETER Path Specifies the path of elements to list. If not given it's the root ist used "/" .PARAMETER ElementID Specifies the id of an elements. If Path and ElementID are given, ElementID is used with a warning .PARAMETER SelectProperties Specifies comma separated the properties to return from file and folder objects (case sensitive). If not set name, size, lastModifiedDateTime and id is used. (See https://dev.onedrive.com/odata/optional-query-parameters.htm). If yout use - SelectProperties "" all properties are listed. Warning: A complex content.downloadUrl is listed/generated for download files without authentication for several hours .PARAMETER DriveID Specifies the OneDrive drive id. If not set, the default drive is used #> PARAM( [Parameter(Mandatory=$True)] [string]$AccessToken, [string]$Path="/", [string]$ElementID="", [string]$SelectProperties="name,size,lastModifiedDateTime,id", [string]$DriveID="", [Parameter(DontShow)] [switch]$ItemPropertyMode, [Parameter(DontShow)] [string]$SearchText ) $ODRootURI="https://api.onedrive.com/v1.0" if ($Path.Contains("$skiptoken=")) { #Recures mode of odata.nextLink detection write-debug("Recurce call") $rURI=$Path } else { $rURI=Format-ODPathorIDString -path $Path -ElementID $ElementID -DriveID $DriveID $SelectProperties=$SelectProperties.Replace(" ","") if ($SelectProperties -eq "") { $opt="" } else { $SelectProperties=$SelectProperties.Replace(" ","")+",folder" $opt="?select="+$SelectProperties } if ($ItemPropertyMode) { #item property mode $rURI=$rURI+$opt } else { if (!$SearchText -eq "") { #Search mode $opt="/view.search?q="+$SearchText+"&select="+$SelectProperties $rURI=$rURI+$opt } else { #child item mode $rURI=$rURI+"/children"+$opt } } } write-debug("Accessing API with GET to "+$rURI) $ResponseObject=Get-ODWebContent -AccessToken $AccessToken -Method GET -rURI $rURI if ($ResponseObject.PSobject.Properties.name -match "@odata.nextLink") { write-debug("Getting more elements form service (@odata.nextLink is present)") Get-ODChildItems -AccessToken $AccessToken -SelectProperties $SelectProperties -Path $ResponseObject."@odata.nextLink".Replace($ODRootURI,"") } if ($ItemPropertyMode) { #item property mode return $ResponseObject } else { #child item mode return $ResponseObject.value } } function Search-ODItems { <# .DESCRIPTION Search for items starting at Path or ElementID .PARAMETER AccessToken Specifies a valid access token for bearer authorization .PARAMETER SearchText Specifies search string .PARAMETER Path Specifies the path of the folder to start the search. If not given it's the root ist used "/" .PARAMETER ElementID Specifies the element id of the folder to start the search. If Path and ElementID are given, ElementID is used with a warning .PARAMETER SelectProperties Specifies comma separated the properties to return from file and folder objects (case sensitive). If not set name, size, lastModifiedDateTime and id is used. (See https://dev.onedrive.com/odata/optional-query-parameters.htm). If yout use - SelectProperties "" all properties are listed. Warning: A complex content.downloadUrl is listed/generated for download files without authentication for several hours .PARAMETER DriveID Specifies the OneDrive drive id. If not set, the default drive is used #> PARAM( [Parameter(Mandatory=$True)] [string]$AccessToken, [Parameter(Mandatory=$True)] [string]$SearchText, [string]$Path="/", [string]$ElementID="", [string]$SelectProperties="name,size,lastModifiedDateTime,id", [string]$DriveID="" ) return Get-ODChildItems -AccessToken $AccessToken -Path $Path -ElementID $ElementID -SelectProperties $SelectProperties -DriveID $DriveID -SearchText $SearchText } function New-ODFolder { <# .DESCRIPTION Creates a new folder .PARAMETER AccessToken Specifies a valid access token for bearer authorization .PARAMETER FolderName Name of the new folder .PARAMETER Path Specifies the path for the new folder. If not given it's the root ist used "/" .PARAMETER ElementID Specifies the element id for the new folder. If Path and ElementID are given, ElementID is used with a warning .PARAMETER DriveID Specifies the OneDrive drive id. If not set, the default drive is used #> PARAM( [Parameter(Mandatory=$True)] [string]$AccessToken, [Parameter(Mandatory=$True)] [string]$FolderName, [string]$Path="/", [string]$ElementID="", [string]$DriveID="" ) $rURI=Format-ODPathorIDString -path $Path -ElementID $ElementID -DriveID $DriveID $rURI=$rURI+"/children" return Get-ODWebContent -AccessToken $AccessToken -Method POST -rURI $rURI -Body ('{"name": "'+$FolderName+'","folder": { },"@name.conflictBehavior": "fail"}') } function Remove-ODItem { <# .DESCRIPTION Delete an item (folder or file) .PARAMETER AccessToken Specifies a valid access token for bearer authorization .PARAMETER Path Specifies the path for the item to delete .PARAMETER ElementID Specifies the element id for the item to delete .PARAMETER DriveID Specifies the OneDrive drive id. If not set, the default drive is used #> PARAM( [Parameter(Mandatory=$True)] [string]$AccessToken, [string]$Path="", [string]$ElementID="", [string]$DriveID="" ) if (($ElementID+$Path) -eq "") { debug-error("Path nor ElementID is set") } else { $rURI=Format-ODPathorIDString -path $Path -ElementID $ElementID -DriveID $DriveID return Get-ODWebContent -AccessToken $AccessToken -Method DELETE -rURI $rURI } } function Get-ODItem { <# .DESCRIPTION Download an item/file. Warning: A local file will be overwritten .PARAMETER AccessToken Specifies a valid access token for bearer authorization .PARAMETER Path Specifies the path of the file to download. If not given it's the root ist used "/" .PARAMETER ElementID Specifies the element id of the file to download. If Path and ElementID are given, ElementID is used with a warning .PARAMETER DriveID Specifies the OneDrive drive id. If not set, the default drive is used .PARAMETER LocalPath Save file to path (if not given the current path is used) .PARAMETER LocalFileName Filename. If not given the file name from OneDrive is used #> PARAM( [Parameter(Mandatory=$True)] [string]$AccessToken, [string]$Path="", [string]$ElementID="", [string]$DriveID="", [string]$LocalPath="", [string]$LocalFileName ) if (($ElementID+$Path) -eq "") { debug-error("Path nor ElementID is set") } else { $Download=Get-ODItemProperty -AccessToken $AccessToken -Path $Path -ElementID $ElementID -DriveID $DriveID -SelectProperties "name,@content.downloadUrl" if ($LocalPath -eq "") {$LocalPath=Get-Location} if ($LocalFileName -eq "") { $SaveTo=$LocalPath.TrimEnd("\")+"\"+$Download.name } else { $SaveTo=$LocalPath.TrimEnd("\")+"\"+$LocalFileName } try { [System.Net.WebClient]::WebClient $client = New-Object System.Net.WebClient $client.DownloadFile($Download."@content.downloadUrl",$SaveTo) write-verbose("Download complete") return 0 } catch { write-error("Download error: "+$_.Exception.Response.StatusCode+"`n"+$_.Exception.Response.StatusDescription) return -1 } } } function New-ODItem { <# .DESCRIPTION Upload an item/file. Warning: A local file will be overwritten .PARAMETER AccessToken Specifies a valid access token for bearer authorization .PARAMETER Path Specifies the path for the upload folder. If not given it's the root ist used "/" .PARAMETER ElementID Specifies the element id for the upload folder. If Path and ElementID are given, ElementID is used with a warning .PARAMETER DriveID Specifies the OneDrive drive id. If not set, the default drive is used .PARAMETER LocalFile Path and file of the local file to upload (C:\data\data.csv) #> PARAM( [Parameter(Mandatory=$True)] [string]$AccessToken, [string]$Path="/", [string]$ElementID="", [string]$DriveID="", [Parameter(Mandatory=$True)] [string]$LocalFile="" ) $rURI=Format-ODPathorIDString -path $Path -ElementID $ElementID -DriveID $DriveID try { $ODRootURI="https://api.onedrive.com/v1.0" $rURI=($ODRootURI+$rURI+"/"+[System.IO.Path]::GetFileName($LocalFile)+":/content").Replace("::",":") return $webRequest=Invoke-WebRequest -Method PUT -InFile $LocalFile -Uri $rURI -Header @{ Authorization = "BEARER "+$AccessToken} -ContentType "multipart/form-data" -ErrorAction SilentlyContinue } catch { write-error("Upload error: "+$_.Exception.Response.StatusCode+"`n"+$_.Exception.Response.StatusDescription) return -1 } } |