Exercise more caution with user filenames.

In particular, don't assume "1" is an extension in "Schematic_1.1".

Fixes https://gitlab.com/kicad/code/kicad/issues/14263
This commit is contained in:
Jeff Young 2023-03-12 14:49:57 +00:00
parent e6945a85b0
commit c4ef08bead
14 changed files with 60 additions and 91 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 jean-pierre.charras
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -27,6 +27,7 @@
#include <bitmap2cmp_settings.h>
#include <bitmap_io.h>
#include <bitmaps.h>
#include <common.h>
#include <kiface_base.h>
#include <math/util.h> // for KiROUND
#include <kiway.h>
@ -814,8 +815,7 @@ void BM2CMP_FRAME::exportEeschemaFormat()
if( fileDlg.ShowModal() != wxID_OK )
return;
fn = fileDlg.GetPath();
fn.SetExt( KiCadSymbolLibFileExtension );
fn = EnsureFileExtension( fileDlg.GetPath(), KiCadSymbolLibFileExtension );
m_ConvertedFileName = fn.GetFullPath();
FILE* outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );
@ -849,8 +849,7 @@ void BM2CMP_FRAME::exportPcbnewFormat()
if( fileDlg.ShowModal() != wxID_OK )
return;
fn = fileDlg.GetPath();
fn.SetExt( KiCadFootprintFileExtension );
fn = EnsureFileExtension( fileDlg.GetPath(), KiCadFootprintFileExtension );
m_ConvertedFileName = fn.GetFullPath();
FILE* outfile = wxFopen( m_ConvertedFileName, wxT( "w" ) );

View File

@ -377,6 +377,25 @@ bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName,
}
wxString EnsureFileExtension( const wxString& aFilename, const wxString& aExtension )
{
wxString newFilename( aFilename );
// It's annoying to throw up nag dialogs when the extension isn't right. Just fix it,
// but be careful not to destroy existing after-dot-text that isn't actually a bad
// extension, such as "Schematic_1.1".
if( newFilename.Lower().AfterLast( '.' ) != aExtension )
{
if( newFilename.Last() != '.' )
newFilename.Append( '.' );
newFilename.Append( aExtension );
}
return newFilename;
}
/**
* Performance enhancements to file and directory operations.
*

View File

@ -39,6 +39,7 @@
#include <erc.h>
#include <id.h>
#include <confirm.h>
#include <common.h>
#include <widgets/wx_html_report_box.h>
#include <wx/ffile.h>
#include <wx/filedlg.h>
@ -960,10 +961,7 @@ void DIALOG_ERC::OnSaveReport( wxCommandEvent& aEvent )
if( dlg.ShowModal() != wxID_OK )
return;
fn = dlg.GetPath();
if( fn.GetExt().IsEmpty() )
fn.SetExt( ReportFileExtension );
fn = EnsureFileExtension( dlg.GetPath(), ReportFileExtension );
if( !fn.IsAbsolute() )
{

View File

@ -30,6 +30,7 @@
#include <bitmaps.h>
#include <kiway.h>
#include <confirm.h>
#include <common.h>
#include <string_utils.h>
#include <sch_base_frame.h>
#include <sch_edit_frame.h>
@ -356,15 +357,7 @@ bool DIALOG_FIELD_PROPERTIES::TransferDataFromWindow()
}
else if( m_fieldId == SHEETFILENAME_V )
{
wxFileName fn( m_text );
// It's annoying to throw up nag dialogs when the extension isn't right. Just
// fix it.
if( fn.GetExt().CmpNoCase( KiCadSchematicFileExtension ) != 0 )
{
fn.SetExt( KiCadSchematicFileExtension );
m_text = fn.GetFullPath();
}
m_text = EnsureFileExtension( m_text, KiCadSchematicFileExtension );
}
m_position = VECTOR2I( m_posX.GetValue(), m_posY.GetValue() );

View File

@ -27,6 +27,7 @@
#include <wx/string.h>
#include <wx/log.h>
#include <wx/tooltip.h>
#include <common.h>
#include <confirm.h>
#include <validators.h>
#include <wx_filename.h>
@ -277,16 +278,11 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
return false;
}
// Ensure the filename extension is OK. In normal use will be caught by grid validators,
// but unedited data from existing files can be bad.
// Ensure the filename extension is OK. (In normal use will be caught by grid validators,
// but unedited data from existing files can be bad.)
sheetFileName = EnsureFileExtension( sheetFileName, KiCadSchematicFileExtension );
wxFileName fn( sheetFileName );
if( fn.GetExt().CmpNoCase( KiCadSchematicFileExtension ) != 0 )
{
DisplayError( this, _( "Sheet file must have a '.kicad_sch' extension." ) );
return false;
}
wxString newRelativeFilename = fn.GetFullPath();
// Inside Eeschema, filenames are stored using unix notation
@ -415,26 +411,11 @@ bool DIALOG_SHEET_PROPERTIES::TransferDataFromWindow()
bool DIALOG_SHEET_PROPERTIES::onSheetFilenameChanged( const wxString& aNewFilename )
{
wxString msg;
wxString msg;
wxFileName sheetFileName( EnsureFileExtension( aNewFilename, KiCadSchematicFileExtension ) );
// Sheet file names are relative to the path of the current sheet. This allows for
// nesting of schematic files in subfolders. Screen file names are always absolute.
wxFileName sheetFileName( aNewFilename );
if( sheetFileName.GetExt().IsEmpty() )
{
sheetFileName.SetExt( KiCadSchematicFileExtension );
}
else if( sheetFileName.GetExt().CmpNoCase( KiCadSchematicFileExtension ) != 0 )
{
msg = wxString::Format( _( "The file '%s' does not appear to be a valid schematic file." ),
sheetFileName.GetFullName() );
wxMessageDialog badSchFileDialog( this, msg, _( "Invalid Schematic File" ),
wxOK | wxCENTRE | wxICON_EXCLAMATION );
badSchFileDialog.ShowModal();
return false;
}
SCHEMATIC& schematic = m_frame->Schematic();
SCH_SHEET_LIST fullHierarchy = schematic.GetFullHierarchy();
wxFileName screenFileName( sheetFileName );

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018-2022 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -31,7 +31,6 @@
#include <sch_validators.h>
#include <validators.h>
#include <sch_edit_frame.h>
#include <netclass.h>
#include <symbol_library.h>
#include <schematic.h>
#include <template_fieldnames.h>
@ -687,15 +686,7 @@ void FIELDS_GRID_TABLE<T>::SetValue( int aRow, int aCol, const wxString &aValue
{
if( m_parentType == SCH_SHEET_T && aRow == SHEETFILENAME )
{
wxFileName fn( value );
// It's annoying to throw up nag dialogs when the extension isn't right. Just
// fix it.
if( fn.GetExt().CmpNoCase( KiCadSchematicFileExtension ) != 0 )
{
fn.SetExt( KiCadSchematicFileExtension );
value = fn.GetFullPath();
}
value = EnsureFileExtension( value, KiCadSchematicFileExtension );
}
else if( m_parentType == LIB_SYMBOL_T && aRow == VALUE_FIELD )
{

View File

@ -26,6 +26,7 @@
#include <symbol_library.h>
#include <confirm.h>
#include <common.h>
#include <connection_graph.h>
#include <dialog_migrate_buses.h>
#include <dialog_symbol_remap.h>
@ -841,8 +842,7 @@ bool SCH_EDIT_FRAME::SaveProject( bool aSaveAs )
if( dlg.ShowModal() == wxID_CANCEL )
return false;
newFileName = dlg.GetPath();
newFileName.SetExt( KiCadSchematicFileExtension );
newFileName = EnsureFileExtension( dlg.GetPath(), KiCadSchematicFileExtension );
if( ( !newFileName.DirExists() && !newFileName.Mkdir() ) ||
!newFileName.IsDirWritable() )

View File

@ -1120,8 +1120,7 @@ void SCH_EDIT_FRAME::NewProject()
if( dlg.ShowModal() != wxID_CANCEL )
{
// Enforce the extension, wxFileDialog is inept.
wxFileName create_me = dlg.GetPath();
create_me.SetExt( KiCadSchematicFileExtension );
wxFileName create_me = EnsureFileExtension( dlg.GetPath(), KiCadSchematicFileExtension );
if( create_me.FileExists() )
{

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2004-2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -24,6 +24,7 @@
*/
#include <confirm.h>
#include <common.h>
#include <symbol_lib_table.h>
#include <symbol_edit_frame.h>
#include <symbol_library.h>
@ -57,13 +58,12 @@ void SYMBOL_EDIT_FRAME::ImportSymbol()
if( dlg.ShowModal() == wxID_CANCEL )
return;
wxFileName fn = dlg.GetPath();
wxFileName fn;
if( fn.GetExt().IsEmpty() )
{
fn.SetExt( (dlg.GetFilterIndex() == 0) ? KiCadSymbolLibFileExtension
: LegacySymbolLibFileExtension );
}
if( dlg.GetFilterIndex() == 0 )
fn = EnsureFileExtension( dlg.GetPath(), KiCadSymbolLibFileExtension );
else
fn = EnsureFileExtension( dlg.GetPath(), LegacySymbolLibFileExtension );
m_mruPath = fn.GetPath();

View File

@ -33,7 +33,6 @@
#include <dialogs/dialog_assign_netclass.h>
#include <project_rescue.h>
#include <erc.h>
#include <fmt.h>
#include <invoke_sch_dialog.h>
#include <string_utils.h>
#include <kiway.h>
@ -59,7 +58,6 @@
#include <sim/sim_lib_mgr.h>
#include "symbol_library_manager.h"
#include <symbol_viewer_frame.h>
#include <status_popup.h>
#include <tool/picker_tool.h>
#include <tool/tool_manager.h>
#include <tools/ee_actions.h>
@ -114,10 +112,9 @@ int SCH_EDITOR_CONTROL::SaveCurrSheetCopyAs( const TOOL_EVENT& aEvent )
if( dlg.ShowModal() == wxID_CANCEL )
return false;
wxFileName newFileName = dlg.GetPath();
newFileName.SetExt( KiCadSchematicFileExtension );
wxString newFilename = EnsureFileExtension( dlg.GetPath(), KiCadSchematicFileExtension );
m_frame->saveSchematicFile( curr_sheet, newFileName.GetFullPath() );
m_frame->saveSchematicFile( curr_sheet, newFilename );
return 0;
}

View File

@ -19,6 +19,7 @@
*/
#include <confirm.h>
#include <common.h>
#include <dialogs/dialog_layers_select_to_pcb.h>
#include <export_to_pcbnew.h>
#include <gerber_file_image.h>
@ -129,7 +130,7 @@ int GERBVIEW_CONTROL::ExportToPcbnew( const TOOL_EVENT& aEvent )
if( filedlg.ShowModal() == wxID_CANCEL )
return 0;
wxFileName fileName = filedlg.GetPath();
wxFileName fileName = EnsureFileExtension( filedlg.GetPath(), KiCadPcbFileExtension );
/* Install a dialog frame to choose the mapping
* between gerber layers and Pcbnew layers
@ -141,10 +142,6 @@ int GERBVIEW_CONTROL::ExportToPcbnew( const TOOL_EVENT& aEvent )
if( ok != wxID_OK )
return 0;
// If no extension was entered, then force the extension to be a KiCad PCB file
if( !fileName.HasExt() )
fileName.SetExt( KiCadPcbFileExtension );
m_frame->SetMruPath( fileName.GetPath() );
GBR_TO_PCB_EXPORTER gbr_exporter( m_frame, fileName.GetFullPath() );

View File

@ -70,6 +70,11 @@ bool EnsureFileDirectoryExists( wxFileName* aTargetFullFileName,
const wxString& aBaseFilename,
REPORTER* aReporter = nullptr );
/**
* It's annoying to throw up nag dialogs when the extension isn't right. Just fix it.
*/
wxString EnsureFileExtension( const wxString& aFilename, const wxString& aExtension );
/**
* Replace any environment variable & text variable references with their values.
*

View File

@ -247,12 +247,8 @@ bool AskSaveBoardFileName( PCB_EDIT_FRAME* aParent, wxString* aFileName, bool* a
if( dlg.ShowModal() != wxID_OK )
return false;
fn = dlg.GetPath();
// always enforce filename extension, user may not have entered it.
fn.SetExt( KiCadPcbFileExtension );
*aFileName = fn.GetFullPath();
*aFileName = dlg.GetPath();
*aFileName = EnsureFileExtension( *aFileName, KiCadPcbFileExtension );
#if wxCHECK_VERSION( 3, 1, 7 )
if( newProjectHook.IsAttachedToDialog() )
@ -1161,10 +1157,7 @@ bool PCB_EDIT_FRAME::SavePcbFile( const wxString& aFileName, bool addToHistory,
bool PCB_EDIT_FRAME::SavePcbCopy( const wxString& aFileName, bool aCreateProject )
{
wxFileName pcbFileName = aFileName;
// Ensure the file ext is the right ext:
pcbFileName.SetExt( KiCadPcbFileExtension );
wxFileName pcbFileName( EnsureFileExtension( aFileName, KiCadPcbFileExtension ) );
if( !IsWritable( pcbFileName ) )
{

View File

@ -341,7 +341,7 @@ void FOOTPRINT_EDIT_FRAME::ExportFootprint( FOOTPRINT* aFootprint )
if( dlg.ShowModal() == wxID_CANCEL )
return;
fn = dlg.GetPath();
fn = EnsureFileExtension( dlg.GetPath(), KiCadFootprintFileExtension );
cfg->m_LastImportExportPath = fn.GetPath();
try
@ -430,16 +430,13 @@ wxString PCB_BASE_EDIT_FRAME::createNewLibrary( const wxString& aLibName,
}
else
{
fn = aLibName;
fn = EnsureFileExtension( aLibName, KiCadFootprintLibPathExtension );
if( !fn.IsAbsolute() )
{
fn.SetName( aLibName );
fn.MakeAbsolute( initialPath );
}
// Enforce the .pretty extension:
fn.SetExt( KiCadFootprintLibPathExtension );
}
// We can save fp libs only using IO_MGR::KICAD_SEXP format (.pretty libraries)