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.
<# | |
.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 |