Only You Can Help Prevent Accidental Deletion in SharePoint
Question
An anonymous user asks, "i want to prevent the user to delete a folder in document Library, if user selects the folder and clicks an delete document icon on ribbon, he is only able to delete the files in the folder not the folder itself. how can i do this?".
Answer
Preventing users from deleting items in SharePoint is a common issue. The recycle bin in SharePoint 2010 helps prevent the permanent deletion of files, folders, and sites, but you still need administrative assistance sometimes to restore the item. Ideally, the user's security permissions should be configured to restrict their access so they don’t even have the option to delete. You could break the security inheritance on the folder and change the permissions so that certain users cannot delete the folder, but the files in the folder will inherit the authorization permissions. You could also break the inheritance of each file in the folder, but that would be time consuming and hard to maintain when new files are added. You could probably create a workflow to give each added file the correct permissions, but all the unique permissions would get messy to maintain in the future.
To prevent any item from being deleted in a list or a site I would use an event handler if security permissions will not due. Event handlers are a compiled module of custom managed code that responds when specific SharePoint triggering events take place. In our case, we would want attach our event handler to the list and wait until the list fires an ItemDeleting event. An ItemDeleting event will run your custom code just before it starts deleting the folder. In your code you want to stop SharePoint from executing the rest of the SharePoint deletion code by cancelling the event.
Below are the instructions on how to create an event handler to stop a folder from being deleted:
- Start Microsoft Visual Studio 2010.
- On the File menu, point to New, and then click Project.
- In Project Types, under C#, select Event Receiver.
- In the SharePoint Customization Wizard under What local site do you want to user for debugging?, type the address to the site that contains the document library (ex: http://intranet.contoso.com/hr/).
- In the SharePoint Customization Wizard, choose Deploy as a sandboxed solution. Click Next.
- In the Choose Event Receiver Settings dialog, select List Item Events in the What type of event receiver do you want? dropdown.
- In the What item should be the event source? dropdown, choose Document Library.
- Choose the An item is being deleted option in the Handle the following events list. Click Finish.
- In the EventReceiver1 file that is created, insert the following code in the ItemDeleting method:
- In the solution explorer, delete the element.xml file because we do not need it for a single document library.
- In the solution explorer, click on the EventReceiver1 and view the folder properties.
- Under Feature Receiver in the Safe Control Entries properties, click on Collection and then the ... button.
- If there not a list item under Members on the Safe Control Entries screen, then click the Add button and then press the OK button to add a safe control entry for your DLL in the web application's web.config.
- In the solution explorer, right click on the Feature1 and click the Add Event Reciever menu item to create a event receiver cs file for your feature.
- In the Feature1.EventReceiver.cs file that was created, insert the following code in the FeatureActivated and FeatureDeactivating methods:
- Now that your event handler will be attached to your list programmatically, press F5 to compile and deploy the solution.
- Navigate to your document library list and select an item in the list. Click the Delete Item button on the Server ribbon.
- Your error message should appear and the folder will not be deleted.
public override void ItemDeleting(SPItemEventProperties properties)
{
//A Try Catch statement to capture any unexpected errors
try
{
//Check to make sure the list item we are looking at is a folder
if (properties.ListItem.Folder != null)
{
//Get folder object
SPFolder folder = properties.ListItem.Folder;
//Check folder name to make sure we have the correct folder
if (folder.Name == "Name of your folder")
{
//Cancel the delete event with an error message
properties.Status = SPEventReceiverStatus.CancelWithError;
//Create an error message so the user knows why the folder can't be deleted
properties.ErrorMessage = "This folder is restricted from being deleted.";
}
}
}
catch (Exception e)
{
//Create an error message so you know in the event logs what happened and where the error occurred.
throw new Exception("Restrict Folder Deletion Event Handler: Exception: [" + e.ToString() + "].");
}
}
//Define variables
string listName = "YourListName";
string receiverName = "Event Receiver Name";
string assemblyFullName = "EventReceiverProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=94de0004b6e3fcc5";
string assemblyClassName = "EventReceiverProject1.EventReceiver1";
int sequenceNumber = 2001;
string receiverData = "Data";
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
//A Try Catch statement to capture any unexpected errors
try
{
//Get current SharePoint site the feature was activated on
using (SPWeb web = (SPWeb)properties.Feature.Parent)
{
//Get List
SPList list = web.Lists[listName];
//Get event handlers for the list
SPEventReceiverDefinitionCollection eventReceivers = list.EventReceivers;
//Create the event handler definition object
SPEventReceiverDefinition eventReceiver = eventReceivers.Add();
//Set event handler properties
eventReceiver.Name = receiverName;
eventReceiver.Assembly = assemblyFullName;
eventReceiver.Class = assemblyClassName;
eventReceiver.SequenceNumber = sequenceNumber;
eventReceiver.Data = receiverData;
eventReceiver.Type = SPEventReceiverType.ItemDeleting;
//Create the event handler definition object with data
eventReceiver.Update();
//Update List
list.Update();
}
}
catch (Exception e)
{
//Create an error message so you know in the event logs what happened and where the error occurred.
throw new Exception("Event Handler Feature: Exception: [" + e.ToString() + "].");
}
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
//A Try Catch statement to capture any unexpected errors
try
{
//Get current SharePoint site the feature was deactivated on
using (SPWeb web = (SPWeb)properties.Feature.Parent)
{
//Get List
SPList list = web.Lists[listName];
//Get event handlers for the list
SPEventReceiverDefinitionCollection eventReceivers = list.EventReceivers;
//Define new Guid variable from the eventReceiver ID
Guid eventReceiverID = new Guid();
//Search through all the event handlers in the list
foreach (SPEventReceiverDefinition eventReceiver in eventReceivers)
{
//If the event handler matches our event handler name
if (eventReceiver.Name == receiverName)
{
//Save the event handler guid
eventReceiverID = eventReceiver.Id;
}
}
//If a guid is found for the event handler
if (eventReceiverID != null)
{
//Get the event handler for the event hander collection of the list
SPEventReceiverDefinition eventReceiver = eventReceivers[eventReceiverID];
//Delete the eventReceiver reference
eventReceiver.Delete();
//Update the list
list.Update();
}
}
}
catch (Exception e)
{
//Create an error message so you know in the event logs what happened and where the error occurred.
throw new Exception("Event Handler Feature: Exception: [" + e.ToString() + "].");
}
}
For more information on event handlers visit Events in SharePoint Foundation 2010, Using Event Receivers in SharePoint Foundation 2010 (Part 1 of 2), and Using Event Receivers in SharePoint Foundation 2010 (Part 2 of 2).
A Microsoft SharePoint 2010 FileNet Connector Question
Question
An anonymous visitor asked "I heard that the Microsoft SharePoint connector doesn’t work with SharePoint 2010. Are there any other connectors out there for FileNet and SharePoint 2010?".
Answer
You are indeed correct. Microsoft’s “Microsoft Enterprise Search Indexing Connector 2008 for IBM FileNet” does not work with SharePoint 2010 due its 64-bit architecture. In fact, the connector does not work for SharePoint 2007 64-bit environments as well. You can read more about know issues with the Microsoft Enterprise Search Indexing Connector 2008 for IBM FileNet at http://office.microsoft.com/download/afile.aspx?AssetID=AM102769721033.
All is not lost. There are two alternative connectors for you to try. IBM has a connector called “IBM Content Collector for Microsoft SharePoint” that supports WSS 3.0, SharePoint 2007, and SharePoint 2010. Since SharePoint 2010 only comes with a 64-bit architecture this mean that this connector should work for SharePoint 2007 64-bit environments as well. As the IBM’s website states, their connector:
- Collects and archive content from Microsoft SharePoint document libraries, wikis, and blogs; collects and archive SharePoint documents into Content Manager Enterprise Edition as well as FileNet Content Manager.
- Enables common rules and policies from a common administration console - across all content including Content Collector for eMail and Content Collector for File Systems
- Classifies documents and content using metadata, rules or Classification Module
- Optionally maintains original document properties in Microsoft SharePoint libraries when replacing collected content with a shortcut and automatically removes shortcut documents from Microsoft SharePoint once those documents have been deleted from Content Manager Enterprise Edition or FileNet Content Manager.
- Optionally maintains Microsoft SharePoint security settings when storing collected information in Content Manager Enterprise Edition as well as FileNet Content Manager.
- Dynamically declares collected content as a record using Enterprise Records
- Adds agility to the ability to respond to litigation, investigations, audit and information inquiries using eDiscovery Manager and eDiscovery Analyzer
The second connector for you to explore is called “Longitude FileNet Connector for SharePoint and FAST Search” that is offered by BA Insight. As the BA Insight’s website states, their connector:
- delivers a feature that allows organizations to replicate content from any source repository into a SharePoint site, SharePoint list or SharePoint document library. The replication preserves the integrity of the source data, and allows administrators to apply appropriate governance over legacy content via SharePoint.
- enables the instant, fully-formatted preview of any and all content returned in a search, regardless of its file-format or source location. Full hit-highlighting and a dynamic graphical hit-map make assessing the relevance of these search results swift and efficient, while a fully-integrated, Silverlight-driven workspace empowers knowledge workers to act upon relevant search results with speed and precision.
- maps users, groups, and role-based identities and security schemas from any non-Active Directory based system, and also optionally enables real-time security checking to ensure rigorous adherence to all permission and access protocols.
- maintains a calculated-change log that securely monitors activity on connected systems. By leveraging this index, connected systems are prevented from being over-burdened by repeated search queries and full-crawls, thereby ensuring optimal performance and real-time accuracy of search results.
- can quickly merge and link metadata from multiple systems based on common keys to create a single, data rich record.
- enables 'simulated' crawls, which provides the administrator the ability to test the impact of any configuration change, and see the result as the simulated crawls runs.
For more information about IBM's Content Collector for Microsoft SharePoint visit http://www-01.ibm.com/software/data/content-management/content-collector-sharepoint/. For more information about BA Insight's Longitude FileNet Connector for SharePoint and FAST Search visit http://www.bainsight.com/sharepoint-ibm-filenet-connector/Pages/features.aspx and http://www.bainsight.com/sharepoint-fast-search-connectors/Pages/features.aspx.
I hope that I was able to provide you with some options to investigate. If you come across any additional connectors or solutions for SharePoint 2010 integration with FileNet please let me know in the comments below.
A SharePoint Owstimer.exe & .NET Runtime Question
Question
An anonymous visitor asked "Does owstimer.exe host a .NET runtime (Common Language Runtime)?".
Answer
The short answer is yes. The SharePoint Timer Service (owstimer.exe) is a Windows service. Services in Windows must be created in a Windows Service application project or another .NET Framework–enabled project that creates an .exe file when built and inherits from the ServiceBase class. The owstimer.exe was likely compiled using managed as an .exe assembly unmanaged code that runs outside the Common Language Runtime (CLR), but has code that starts the CLR automatically by using the mscoree.dll when the .exe is executed.
For more information about Windows services visit Introduction to Windows Service Applications.
For more information about hosting the Common Language Runtime visit Hosting the Common Language Runtime.
For more information about SharePoint’s owstimer.exe visit SharePoint 2010 Architectures Overview and Creating Custom Timer Jobs.
Thank you for your question and please feel free to follow up with any additional questions you may have about the SharePoint Timer Service.
~The 14 folder
Migrating Workflows to SharePoint 2010 Question
Question
An anonymous visitor asked "Is it possible to migrate running workflows (built on SPD 2007 or VS 2008) when migrating 2007 farm to 2010? I tested on a very simple SPD workflow and it worked, but can we take it for granted for any kind of workflow...?".
Answer
This is a very interesting question anonymous visitor. It sounds like you are doing your homework before doing your migration which is great. I think the best way to answer your question is to briefly speak about how workflows work. The following summarizes how workflows are executed from start to finish:
- A person or process initiates some action that causes the workflow to begin. In SharePoint 2007, workflows can be:
- Started on demand by a user by using the SharePoint user interface.
- Started or resumed in response to the On Item Created event for an item in a list or document library.
- Started or resumed in response to the On Item Changed event for an item in a list or document library.
- Started or resumed programmatically through the SharePoint object model.
- Started programmatically through the Workflow Web service.
- Once the workflow begins a process is created to execute tasks or actions in the workflow code. Not all workflows use the same hosting process.
- Workflows started from the SharePoint user interface use the W3wp.exe process that is specific to the IIS Web application the workflow was initiate from.
- If the workflow uses DelayActivity code or has a noncatastrophic error when the workflow instance begins then the Owstimer.exe server process is the host process. The Owstimer.exe is the SharePoint timer service process and is used in this context to start workflows when DelayActivity code is used or to try executing a failing workflow again at a later time.
- When an external application (such as a console application, Web service, or Windows Communication Foundation service) creates items programmatically through the SharePoint object model, the process running the code becomes the workflow host.
- The workflow determines what action needs to perform next and executes the code.
- If the workflow needs to wait for a response before it can continue, then the SharePoint event handlers tell the Windows Workflow Foundation Runtime Engine to put the workflow to sleep using the SQL workflow persistence service.
- When a workflow becomes idle the Windows Workflow Foundation Runtime Engine calls the SQL workflow persistence service to save the workflow state into the content database of your SharePoint website.
- The SQL workflow persistence service assigns correlation tokens for the workflow and to each task as that the workflow engine can use unique identifiers to map events and actions to the correct workflow object. Next, the SQL workflow persistence serializes the workflow object turning into a binary string, and then saves it with a unique Workflow Instance ID to the SharePoint content database. This process is called dehydration.
- Once the workflow object is safely stored within the database the memory used to run the workflow is released and the workflow is considered to be put to sleep.
- When SharePoint receives a response to carry out the next action from ones of its event handlers, the Windows Workflow Foundation Runtime Engine wakes up the sleeping workflow using the SQL workflow persistence service. When the new response data and the data from the store workflow object the workflow can run the code to perform the remaining actions.
- When a user or system respond to a workflow action, the unique Workflow Instance ID is passed to the Windows Workflow Foundation Runtime Engine and SQL workflow persistence service finds the workflow object in the SharePoint web application’s content database.
- When the Windows Workflow Foundation Runtime Engine retrieves and deserializes the workflow object from the database, it performs many checks to ensure that the workflow object is mapped to the correct response. The checks ensure the workflow DLL has the correct namespaces, entities, and correlation tokens. The process of retrieving the workflow object is called hydration.
- Once the workflow object is successfully retrieved and passed all its checks the workflow is awake and is able to execute the rest of the action code.
- Steps 3 to 5 are repeated for each action as necessary until the workflow is complete. Once the workflow is complete, the workflow status is updated and the workflow memory and hosting process are released.
To answer your question there are ways that workflows might not make it through the migration process. The following are situations you should consider before migrating your SharePoint 2007 workflows to SharePoint 2010:
- A person or process initiates some action that causes the workflow to begin as a migration occurs: Workflows that are executing code are processing data in the memory of the server. If you begin a migration while the workflow is still in memory it is possible for the information and the workflow instance to be lost. Before starting your migration it is wise to make sure that your SharePoint sites are not able to be accessed by users. This ensures that no new workflow instances are initiated and any workflows that were running are hopefully completed or sleeping within the SharePoint web application content database.
- Identify any custom workflows that use DelayActivity code: The DelayActivity code delays an activate workflow from executing. If a workflow becomes completely idle during the delay and the UnloadOnIdle method is set to true, then the workflow may be unloaded from memory, put to sleep, and then reloaded into memory when the specified delay time expires. If the UnloadOnIdle method is set false then the workflow will remain in the server's memory and may be lost during a migration process. You want to ensure no new workflow instances are initiated and any workflow that were running are hopefully completed or sleeping within the SharePoint web application content database.
- Make sure any external applications do not start workflows during the migration process: If you have external applications in your company interacting with SharePoint you want ensure that no new workflow instances are initiated. The workflow instance could be in memory and could be lost. Again the best strategy is to limit access to the SharePoint environment.
- Ensure all custom workflow code are working correctly before the migration: If your workflow is not working correctly then the Owstimer.exe server process might trying to reactive the workflow action repeatedly. Especially if you are moving content databases to another SharePoint 2010 farm, this workflow instance could get lost. Make sure custom workflow code is in working order by checking the event and SharePoint logs on your server. Once the code is corrected the workflow will either finish or become idle and be saved to the content database.
- Run the pre-upgrade checker to look for potential issues: The pre-upgrade checker reports missing customizations and issues with orphaned sites, and more, so that you can address these issues before you perform your upgrade. The pre-upgrade checker also checks your workflows for the following issues:
- 956447: The ModifiedWorkflowActionsFile rule in Pre-Upgrade Checker can warn that the default declarative workflow actions file has been modified
- 956448: The CustomWorkflowActionsFiles rule in Pre-Upgrade Checker in Windows SharePoint Services 3.0 Service Pack 2 can warn that custom .ACTIONS files exist in the farm
- 956449: The ModifiedWebConfigWorkflowAuthorizedTypes rule in Pre-Upgrade Checker for Windows SharePoint Services 3.0 Service Pack 2 can warn that Web.config files contain modified authorized types for workflow
If the pre-upgrade checker is not run and the issues not corrected it is possible that your workflow will not work correctly. For more information about the pre-upgrade checker that comes with Office SharePoint Server 2007 with Service Pack 2 visit TechNet's Run the pre-upgrade checker article.
- Check to see if the Workflow Auto Cleanup timer has been disabled: If your Workflow Auto Cleanup timer job is disabled in your Office SharePoint Server 2007 environment, make sure that you disable this timer job in your new environment also. If this timer job is enabled in the new environment and disabled in the previous version environment, you might lose workflow associations when you upgrade. For more information about this timer job visit Disable preservation of workflow history.
If you are using out-of-the-box SharePoint workflows do not worry too much. Microsoft developers know how to handle their own solutions and migrate them forward correctly. You will notice in the web.config files of the SharePoint 2010 virtual directories that there are redirect statements so that if code is looking for the SharePoint 2007 DLLs they are redirected to the SharePoint 2010 workflow DLLs. The following are web.config entries for redirecting workflow DLL versions:
<dependentAssembly>
<assemblyIdentity name="Microsoft.SharePoint.WorkflowActions" culture="neutral" />
<bindingRedirect oldVersion="12.0.0.0" newVersion="14.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Extensions" />
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0" />
</dependentAssembly>
<dependentAssembly xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity name="Microsoft.Office.Workflow.Routing" culture="neutral" />
<bindingRedirect oldVersion="12.0.0.0" newVersion="14.0.0.0" />
</dependentAssembly>
<dependentAssembly xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity name="Microsoft.Office.Workflow.Tasks" culture="neutral" />
<bindingRedirect oldVersion="12.0.0.0" newVersion="14.0.0.0" />
</dependentAssembly>
<dependentAssembly xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity name="Microsoft.Office.Workflow.Feature" culture="neutral" />
<bindingRedirect oldVersion="12.0.0.0" newVersion="14.0.0.0" />
</dependentAssembly>
These DLLs likely have code for the old SharePoint 2007 workflow actions and also the new SharePoint 2010 workflow actions. By having two sets of code the old workflow actions can finish correctly and then any new workflows going forward will use the new SharePoint 2010 workflow actions.
When it comes to your custom workflow code make sure all the code is copied on the SharePoint 2010 environment and that any web.config or app.config settings are already in place. When the websites are finished being migrated you want everything to be in place so that workflows can complete their jobs.
If you are moving between farms remember that you want to make sure that your workflows are either completed or sleeping in the content database of your site. Any workflows in memory have the highest risk of getting lost or not finishing as the processes will not be active in your new farm.
I hope I have answered your question and gave you some things to think about. Thank you for submitting your question and good luck on your SharePoint 2007 to 2010 migration. Please feel free to send any additional questions you may have.
For more information about SharePoint workflows visit Workflows in SharePoint Server 2010, Workflows in SharePoint Foundation, Cutting Edge: Windows Workflow Foundation - Part 1, Cutting Edge: Windows Workflow Foundation - Part 2, Developing Workflows in VS: Part 1 - Workflow Objects and A Crash Course on Mechanics, Improvements in SharePoint 2010: Workflow, Developing Workflow Solutions with SharePoint Server 2007 and Windows Workflow Foundation, WF Scenarios Guidance: SharePoint and Workflow, Workflow Scalability and Performance in Windows SharePoint Services 3.0, Microsoft SharePoint Team Blog workflow posts, Understanding the Lifecycle of a Workflow, Channel 9 Workflow Videos, Best Practices For Windows Workflow Foundation Apps, Creating Custom Workflows for Windows SharePoint Services and Office SharePoint Server, Versioning long running workfows, and Site Collection Backups and Workflow Portability in SharePoint 2010.
SharePoint 2010 Planning Resources Question
Question
An anonymous visitor asked "Did Microsoft release a project plan for SP2010 ? If so could you direct me to where I can download?".
Answer
Planning for SharePoint 2010 can be difficult and find the right documentation to help you can even be harder to find. With SharePoint 2010, Microsoft has been pretty good about producing documentation. You will not find one document that explains start to finish how to go about your project. How to implemented SharePoint 2010 is different for every company and its needs. The following are five general stages that every company should go through to properly plan and execute their SharePoint environment:
- Evaluation: This stage involves installing a version of SharePoint 2010 to use and explore. You want to make sure that SharePoint is the right fit for your company and understand how it can be applied to help meet your strategy goals.
- Planning and Architecture: This stage involves creating the blueprints of how your SharePoint 2010 environment will be built, configured, and maintained. Planning and architecture is often over looked or simplified because companies have immediately needs they want to satisfy. I cannot express how important it is to properly plan your SharePoint environment. If you do not spend the time up front you will surely spend more time and money in the end when your environment crashes, has very poor performance, or has become too unwieldy to maintain.
- Configuration and Development: This stage involves building your SharePoint environment based on the documents produced from the planning and architecture stage. You want to have a good idea of the best practices you should follow while developing customizations to ensure long term scalability and maintenance. You should always have a development, staging, and production environment. Everything that is built by developers should be thoroughly tested in the staging environment before being deployed to the production environment.
- Deployment: This stage involves preparing and moving your code and configurations to your production environment. This can involve deployment of code, training of users, and content migration.
- Support and Maintenance: This stage involves administration of the infrastructure. You will want a back up and disaster discovery plan in place. Additionally you will want to schedules monthly outages to apply major code customization, software updates, and performance enhancements.
In case you have not evaluated SharePoint 2010 you should know that you can download a trail version of the software from the TechNet evaluation center that is good for 180 days. If you are thinking about running a virtualized environment you can download a demo Hyper-V image from the Microsoft Download Center that can be also used for 180 days and includes Microsoft Office Communication Server 2007 R2, Microsoft Visual Studio 2010, Microsoft SharePoint Server 2010 Enterprise Edition, Microsoft Office Web Applications, Microsoft FAST Search for SharePoint 2010, Microsoft Project Server 2010, Microsoft Office Professional Plus 2010, Microsoft Visio 2010, Microsoft Project 2010, and Microsoft Office Communicator 2007 R2. Please visit the http://www.the14folder.com for more information on SharePoint 2010 Editions, Hardware Requirements for SharePoint 2010, and Software Requirements for SharePoint 2010.
As for your question it sounds like you would like to begin stage 2. You should begin by downloading the Planning guide for Microsoft SharePoint Server 2010 or the Planning guide for Microsoft SharePoint Foundation 2010 from the Microsoft Download Center. These documents provide a lot of useful information and guidelines on how to lead a team through the planning stage of a SharePoint 2010 deployment. Microsoft’s TechNet website also has a whole section devoted to planning and architecture at http://technet.microsoft.com/en-ca/library/cc261834.aspx. The TechNet website includes planning worksheets and technical diagrams that you will find handy. The Microsoft Download Center also has guides, worksheets, and white papers on SharePoint 2010 that provide a lot of useful information. Additionally, at www.the14folder.com I have a section in my right side of the screen with links completely devoted to resources for SharePoint 2010 planning that you may find interesting.
You should definitely do your own research, however I would also recommend talking to a SharePoint consulting firm in your area. SharePoint is a big product and good consultants can help you avoid common pit fall that they have learned the hard way through experience. To find a SharePoint consulting firm in your area please visit the SharePoint partner finder.
Thank you for asking your question and I hope my response has helped you. I plan to talk more about this particular topic in greater detail in future posts. Please feel free to ask any additional questions you may have. Good luck!
~The 14 Folder
