Skip to content

Instantly share code, notes, and snippets.

Last active October 26, 2020 03:32
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Bulk upload extension photos to SV9100
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
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.
Author: James Rudd
Blog :
# 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>"
$pabxBase = "http://$pabxHost" # Allows HTTPS if configured
# Configure Variables
$necSep = [char]18 # NEC Item seperator
$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.DrawImage($img, 0, 0, $newWidth, $newHeight)
#save to file
$bmpResized.Save($OutputLocation, $Codec, $($encoderParams))
# 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+)";'){
#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
# 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]' ){
else {
Write-Host "Could not match $fileName" -ForegroundColor Red
# 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
$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
$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 = (
"Content-Disposition: form-data; name=`"portNo`"$LF",
"Content-Disposition: form-data; name=`"fileName`"$LF",
"Content-Disposition: form-data; name=`"userImagePath`"; filename=`"newImg.jpg`"",
"Content-Type: image/jpeg$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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment