On our new SV9100 system we needed a way to bulk upload user thumbnails for their extensions to appear on the new colour screen ITK phones. NEC does not appears to have any way to do this so I have written the following script.
It requires a folder containing your images with the filename ending in the extension it should be uploaded to. This works best if you pre-crop your images to square or similar as on phone the image will be cropped.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Bulk upload extension photos to SV9100 | |
.DESCRIPTION | |
Script to upload photos based on extension number to NEC SV9100 PABX, or perform other bulk individual operations | |
Photo can be checked at "http://<IP>/UserImages/000.jpg" where number is port – 1 | |
.EXAMPLE | |
Image names must have extension as last part of name e.g. "Name 122.jpg" | |
Update stored directory of photos below | |
Enter the password for a User1 level user. | |
.NOTES | |
Author: James Rudd | |
Blog : http://jrudd.org/ | |
#> | |
# Folder where images are stored. Image names must have extension as last part of name e.g. "Name 342.jpg" | |
$TARGET_FOLDER_PATH = "C:\Temp\Pics\2020" | |
$pabxHost="<PABX IP>" | |
$pabxUser="user1" | |
$pabxPass="<Password>" | |
$pabxBase = "http://$pabxHost" # Allows HTTPS if configured | |
# Configure Variables | |
$necSep = [char]18 # NEC Item seperator | |
$sessionID="" | |
$LF = "`r`n" | |
# Needed to resize images for PABX | |
Function ResizeImage() { | |
param([String]$ImagePath, [Int]$Quality = 90, [Int]$targetSize, [String]$OutputLocation) | |
Add-Type -AssemblyName "System.Drawing" | |
$img = [System.Drawing.Image]::FromFile($ImagePath) | |
$CanvasWidth = $targetSize | |
$CanvasHeight = $targetSize | |
#Encoder parameter for image quality | |
$ImageEncoder = [System.Drawing.Imaging.Encoder]::Quality | |
$encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1) | |
$encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($ImageEncoder, $Quality) | |
# get codec | |
$Codec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object {$_.MimeType -eq 'image/jpeg'} | |
#compute the final ratio to use | |
$ratioX = $CanvasWidth / $img.Width; | |
$ratioY = $CanvasHeight / $img.Height; | |
$ratio = $ratioY | |
if ($ratioX -le $ratioY) { | |
$ratio = $ratioX | |
} | |
$newWidth = [int] ($img.Width * $ratio) | |
$newHeight = [int] ($img.Height * $ratio) | |
$bmpResized = New-Object System.Drawing.Bitmap($newWidth, $newHeight) | |
$graph = [System.Drawing.Graphics]::FromImage($bmpResized) | |
$graph.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic | |
$graph.Clear([System.Drawing.Color]::White) | |
$graph.DrawImage($img, 0, 0, $newWidth, $newHeight) | |
#save to file | |
$bmpResized.Save($OutputLocation, $Codec, $($encoderParams)) | |
$bmpResized.Dispose() | |
$img.Dispose() | |
} | |
# Get Session ID | |
$R = Invoke-WebRequest "${pabxBase}/Login.htm" -SessionVariable necLogin -Method POST | |
# Login.htm?sessionId=&LOGIN() | |
$UrlLogin = "${pabxBase}/Login.htm%3FsessionId%3D%26LOGIN%28%29" | |
$Body = @{ | |
formData = "0${necSep}userName=$pabxUser${necSep}language=onChange=${necSep}password=$pabxPass" | |
} | |
$R = Invoke-WebRequest -Uri $UrlLogin -WebSession $necLogin -Method POST -Body $Body | |
$extPort = @{} | |
foreach ($script in $R.Scripts) { | |
# Get Session ID | |
if ($script.innerHTML -match 'g_sessionId="(\S+)";'){ | |
$sessionID=$Matches[1] | |
} | |
#Generate extension to port mappings | |
if ($script.src -like "*.jsx"){ | |
$URL = "${pabxBase}/" + $script.src | |
$extList = (Invoke-WebRequest $URL -WebSession $necLogin).Content.Split(";") | |
foreach ($ext in $extList) { | |
if ( $ext -match 'tel\((\d+),"(\d+)","(\w+)"\)'){ | |
$extPort.Add($Matches[2],@($Matches[1],$Matches[3])) # Ext = (Port, Type [ve|tel]) | |
} | |
} | |
} | |
} | |
if (($sessionID -eq "") -or ($extPort.Count -lt 5 )){ | |
#Failed to login and download extensions | |
Write-Host "Could not login or download extensions list" -ForegroundColor Red | |
return | |
} | |
# Go through folder and upload images to extension of filename | |
$ThumbJpgDir = "$TARGET_FOLDER_PATH\thumb" | |
New-Item -ItemType Directory -Force -Path $ThumbJpgDir | |
#for($port=0;$port -lt 2; $port++) { | |
Get-ChildItem $TARGET_FOLDER_PATH -Filter *.jpg | | |
Foreach-Object { | |
$fileName = $_.Name | |
# Check file name contains extension | |
if ($fileName -match '(\d+).[jJ][pP][gG]' ){ | |
$ext=$Matches[1] | |
} | |
else { | |
Write-Host "Could not match $fileName" -ForegroundColor Red | |
return | |
} | |
# Check NEC system has a matching Extension | |
if ($extPort.ContainsKey($ext)){ | |
$portNum=[int]$extPort[$ext][0] + 1 | |
} else { | |
Write-Host "Could not find $ext on NEC System" -ForegroundColor Red | |
return | |
} | |
$LDA_TARGET_FILE_NAME = "$TARGET_FOLDER_PATH\$fileName" | |
$filePath = "$ThumbJpgDir\$fileName" | |
# Image must have longest edge as 160 pixel | |
# Max file size is 15*1024 bytes = 15kB | |
ResizeImage $LDA_TARGET_FILE_NAME 90 160 $filePath | |
# Load Initial Page. | |
# Best not to load as can lock phone. Not needed for upload | |
<# | |
$URLassemb = "?sessionId=${sessionID}&FEAT_TEL%2823,0,${portNum}%29" | |
#$URL = "${pabxBase}/UserPro.htm" + [uri]::EscapeDataString($URLassemb) | |
$URL = "${pabxBase}/UserPro.htm" + $URLassemb | |
# Not sure if I need to load page | |
$WebResponse = Invoke-WebRequest $URL -WebSession $necLogin | |
Write-Verbose $URL | |
#> | |
# Post Image | |
$URLassemb = "?sessionId=${sessionID}&UPLOAD_USER_IMG()" | |
$URLPost = "${pabxBase}/UserPro.htm" + $URLassemb | |
# From https://stackoverflow.com/questions/61463759/powershell-upload-a-pdf-file-using-boundary-mime-to-rightfax-web-service | |
$boundary = [System.Guid]::NewGuid().ToString() | |
$boundary = "—-WebKitFormBoundary" + $boundary.Replace("-","").SubString(0,16) | |
# Headers | |
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" | |
$headers.Add("Accept", "*/*") | |
$headers.Add("Referer", $URL) | |
$headers.Add("Origin", "${pabxBase}") | |
$headers.Add("Accept-Encoding", "gzip, deflate") | |
$headers.Add("Accept-Language", "en-AU,en-GB;q=0.9,en-US;q=0.8,en;q=0.7") | |
$headers.Add("dnt", "1") | |
# Read in Image | |
$fileRead = [System.IO.File]::ReadAllBytes($FilePath) | |
$fileEnc = [System.Text.Encoding]::GetEncoding("iso-8859-1").GetString($fileRead) | |
# Generate the multipart message | |
$bodyLines = ( | |
"–$boundary", | |
"Content-Disposition: form-data; name=`"portNo`"$LF", | |
$portNum, | |
"–$boundary", | |
"Content-Disposition: form-data; name=`"fileName`"$LF", | |
$fileName, | |
"–$boundary", | |
"Content-Disposition: form-data; name=`"userImagePath`"; filename=`"newImg.jpg`"", | |
"Content-Type: image/jpeg$LF", | |
$fileEnc, | |
"–$boundary–$LF" | |
) -join $LF | |
$Attach = Invoke-RestMethod -Uri $URLPost -Headers $headers -Method Post -ContentType "multipart/form-data; boundary=$boundary" -TimeoutSec 20 -Body $bodyLines | |
Write-host "Uploaded extension $ext to port $portNum" | |
} | |
# Need to logoff to clear connections | |
$URL = "${pabxBase}/Home.htm?sessionId=$sessionID&LOGOUT%28%29" | |
Invoke-WebRequest -Uri $URL -WebSession $necLogin |Out-Null |