NEC SV9100 Bulk Photo Upload

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

About James Rudd

Network Administrator at Sydney Boys High School
This entry was posted in General, PABX. Bookmark the permalink.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.