Monday, February 9, 2009

Defending against XSS attacks in Freemarker

While Freemarker is quite rich in features, it seems to lack support for programmatically declaring HTML-escaping the default behavior for property access. You need to either add a ?html to every access or wrap every single template into this:


<#escape x as x?html>
... your template code ...
</#escape>


This really has to be done on every file, including those being included such as macro definitions.

Both approaches rely on people remembering to do the right thing, and I don't trust anyone that much, particularly not myself. So instead I decided to add this bit of wrapper code programmatically in the code that loads the template. I took the idea from a posting on the freemarker-user mailing list. Instead of using the normal ClassTemplateLoader, I now do this:


final TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), templatePath){
@Override
public Reader getReader(Object templateSource, String encoding) throws IOException {
return new WrappingReader(super.getReader(templateSource, encoding), "<#escape x as x?html>", "");
}
};
configuration.setTemplateLoader(templateLoader);


This uses the following class:


package domain.your.util;

import java.io.IOException;
import java.io.Reader;
import java.util.logging.Level;
import java.util.logging.Logger;

public class WrappingReader extends Reader {

private final Reader originalReader;
private final char[] prologue;
private final char[] epilogue;
private int pos = 0;
private int firstEpilogueChar = -1;
private boolean closed = false;

public WrappingReader(Reader originalReader, char[] prologue, char[] epilogue, Object lock) {
super(lock);
this.originalReader = originalReader;
this.prologue = prologue;
this.epilogue = epilogue;
}

public WrappingReader(Reader originalReader, char[] prologue, char[] epilogue) {
this.originalReader = originalReader;
this.prologue = prologue;
this.epilogue = epilogue;
}

public WrappingReader(Reader originalReader, String prologue, String epilogue, Object lock) {
super(lock);
this.originalReader = originalReader;
this.prologue = prologue.toCharArray();
this.epilogue = epilogue.toCharArray();
}

public WrappingReader(Reader originalReader, String prologue, String epilogue) {
this.originalReader = originalReader;
this.prologue = prologue.toCharArray();
this.epilogue = epilogue.toCharArray();
}

@Override
public int read(char[] cbuf, int off, int len) throws IOException {
if (closed) {
throw new IOException("Reader has been closed already");
}
int oldPos = pos;
Logger.getLogger(getClass().getName()).log(Level.FINE, String.format("Reading %d characters from position %d", len, pos));
if (pos < this.prologue.length) {
final int toCopy = Math.min(this.prologue.length - pos, len);
Logger.getLogger(getClass().getName()).log(Level.FINE, String.format("Copying %d characters from prologue", toCopy));
System.arraycopy(this.prologue, pos, cbuf, off, toCopy);
pos += toCopy;
if (toCopy == len) {
Logger.getLogger(getClass().getName()).log(Level.FINE, "Copied from prologue only");
return len;
}
}
if (firstEpilogueChar == -1) {
final int copiedSoFar = pos - oldPos;
final int read = originalReader.read(cbuf, off + copiedSoFar, len - copiedSoFar);
Logger.getLogger(getClass().getName()).log(Level.FINE, String.format("Got %d characters from delegate", read));
if (read != -1) {
pos += read;
if (pos - oldPos == len) {
Logger.getLogger(getClass().getName()).log(Level.FINE, "We do not reach epilogue");
return len;
}
}
firstEpilogueChar = pos;
}
final int copiedSoFar = pos - oldPos;
final int epiloguePos = pos - firstEpilogueChar;
final int toCopy = Math.min(this.epilogue.length - epiloguePos, len - copiedSoFar);
if((toCopy <= 0) && (copiedSoFar == 0)) {
return -1;
}
Logger.getLogger(getClass().getName()).log(Level.FINE, String.format("Copying %d characters from epilogue", toCopy));
System.arraycopy(this.epilogue, epiloguePos, cbuf, off + copiedSoFar, toCopy);
pos += toCopy;
Logger.getLogger(getClass().getName()).log(Level.FINE, String.format("Copied %d characters, now at position %d", pos-oldPos, pos));
return pos - oldPos;
}

@Override
public void close() throws IOException {
originalReader.close();
closed = true;
}
}


Note that this means that in some cases you might need to escape the escaping, which Freemarker allows with the <#noescape> directive. You also can't use template configuration via the <#ftl> directive anymore, since that would need to be before the <#escape>. Since I never felt the urge to use it, I don't care.

82 comments:

Elizabeth J. Neal said...

hi was just seeing if you minded a comment. i like your website and the thme you picked is super. I will be back. Pflegezusatzversicherung

saranya said...

Nice post. By reading your blog, i get inspired and this provides some useful information. Thank you for posting this exclusive post for our vision. 
python training Course in chennai
python training in Bangalore
Python training institute in bangalore

jai said...

Well somehow I got to read lots of articles on your blog. It’s amazing how interesting it is for me to visit you very often.
Data Science training in Chennai
Data science training in Bangalore
Data science training in pune
Data science online training
Data Science Interview questions and answers
Data Science Tutorial

jeeva said...

I appreciate your efforts because it conveys the message of what you are trying to say. It's a great skill to make even the person who doesn't know about the subject could able to understand the subject . Your blogs are understandable and also elaborately described. I hope to read more and more interesting articles from your blog.
rpa training in bangalore
best rpa training in bangalore
rpa training in pune | rpa course in bangalore
rpa training in chennai

rohini said...

Awesome article. It is so detailed and well formatted that i enjoyed reading it as well as get some new information too.
Best Devops Training in pune
Devops Training in Bangalore
Microsoft azure training in Bangalore
Power bi training in Chennai

diya shivanya said...

This is good information and really helpful for the people who need information about this.
Blockchain Training in Chennai
Blockchain Training Institutes in Chennai
german classes
Best IELTS Coaching in Chennai
learn Japanese in Chennai
Best Spoken English Class in Chennai
Blockchain Training in OMR
Blockchain Training in Porur 

Tech News said...

Good Article
devops training in bangalore
hadoop training in bangalore
iot training in bangalore
machine learning training in bangalore
uipath training in bangalore

Bala said...

Very valuable post...! This information shared is helpful to improve my knowledge skill. Thank you...!
Oracle Training in Chennai
Oracle Certification in Chennai
Tableau Training in Chennai
Oracle DBA Training in Chennai
Linux Training in Chennai
Advanced Excel Training in Chennai
Unix Training in Chennai
Power BI Training in Chennai
Oracle Training in Tambaram
Oracle Training in Thiruvanmiyur

sasi said...

I have to agree with everything in this post. Thanks for useful sharing information.
PHP Training in Chennai
PHP Training in bangalore
php training in coimbatore
PHP Course in Chennai
php Course in madurai
PHP Training Institute in Chennai
php training institute in bangalore
dot net training institutes in bangalore

Anna Schafer said...

This type of message always inspiring and I prefer to read quality content, so happy to find good place to many here in the post, the writing is just great, thanks for the post. Homepage

Herbert M. Reed said...

Thanks for the nice blog. It was very useful for me. I'm happy I found this blog. Thank you for sharing with us,I too always learn something new from your post. read this article

Data science training in mumbai said...

Data Science is the future of Artificial Intelligence. Therefore, it is very important to understand what is Data Science and how can it add value to your business.
Data Science Training in Mumbai which includes classroom and online training. Along with Classroom training, we also conduct online training using state-of-the-art technologies to ensure the wonderful experience of online interactive learning. Data Science Training

Durai Moorthy said...

Nice blog, this blog provide the more information. Thank you so much for sharing with us.
aws Training in Bangalore
python Training in Bangalore
hadoop Training in Bangalore
angular js Training in Bangalore
bigdata analytics Training in Bangalore
python Training in Bangalore
aws Training in Bangalore

Rajesh Anbu said...

Really nice post. Thank you for sharing amazing information.
aws Training in Bangalore
python Training in Bangalore
hadoop Training in Bangalore
angular js Training in Bangalore
bigdata analytics Training in Bangalore
python Training in Bangalore
aws Training in Bangalore

shalini said...
This comment has been removed by the author.
shalini said...

I got some clear information from this blog.. Thanks for taking a time to share this blog...
AWS Training in Chennai
AWS Training in Bangalore
AWS Training in Coimbatore
AWS Training in Hyderabad
AWS Training Institutes in Bangalore
AWS Training in BTM
AWS Course in Bangalore
AWS Training Institutes in Bangalore
Spoken English Classes in Bangalore
Data Science Courses in Bangalore

datasciencecourse said...

I am impressed by the information that you have on this blog. It shows how well you understand this subject.

data science course

nisha said...

Valuable Post.

Data Science Training Course In Chennai | Data Science Training Course In Anna Nagar | Data Science Training Course In OMR | Data Science Training Course In Porur | Data Science Training Course In Tambaram | Data Science Training Course In Velachery

rocky said...

very informative content in your blog.
Python Training in Chennai | Certification | Online Training Course | Python Training in Bangalore | Certification | Online Training Course | Python Training in Hyderabad | Certification | Online Training Course | Python Training in Coimbatore | Certification | Online Training Course | Python Training in Online | Python Certification Training Course

devi said...

Such a very useful article. Very interesting to read this article.I would like to thank you for the efforts you had made for writing this awesome article.Great Article. Thank you for sharing! Really an awesome post for every one.
Data Science Training In Chennai | Certification | Data Science Courses in Chennai | Data Science Training In Bangalore | Certification | Data Science Courses in Bangalore | Data Science Training In Hyderabad | Certification | Data Science Courses in hyderabad | Data Science Training In Coimbatore | Certification | Data Science Courses in Coimbatore | Data Science Training | Certification | Data Science Online Training Course

Aishu said...

The blog gives more information about the training and career, its useful to enhance my skills and knowledge.
IELTS training in chennai

German Classes in Chennai

GRE Coaching Classes in Chennai

TOEFL Coaching in Chennai

spoken english classes in chennai | Communication training

EXCELR said...

Thanks for sharing great information. I like your blog and highly recommendData Science Training in Hyderabad

Jayalakshmi said...

You have done a good research on this topic.
Great Work.
hadoop training in chennai

hadoop training in tambaram

salesforce training in chennai

salesforce training in tambaram

c and c plus plus course in chennai

c and c plus plus course in tambaram

machine learning training in chennai

machine learning training in tambaram

jeni said...

Wow, amazing weblog format! How lengthy have you been running a blog for? you make running a blog look easy. The total glance of your website is wonderful, let alone the content!

angular js training in chennai

angular js training in velachery

full stack training in chennai

full stack training in velachery

php training in chennai

php training in velachery

photoshop training in chennai

photoshop training in velachery

shiny said...

This is good information and really helpful for the people who need information about this.



hadoop training in chennai

hadoop training in annanagar

salesforce training in chennai

salesforce training in annanagar

c and c plus plus course in chennai

c and c plus plus course in annanagar

machine learning training in chennai

machine learning training in annanagar

datasciencecourse said...

Really nice and interesting post. I was looking for this kind of information and enjoyed reading this one. Keep posting. Thanks for sharing.

Simple Linear Regression

Correlation vs covariance

KNN Algorithm

hema said...
This comment has been removed by the author.
hema said...

It was good explanation and wonderful content. Keep posting..https://www.learnovita.com/web-designing-training-in-chennai

Web design Training in Chennai

Web design Training in Velachery

Web design Training in Tambaram

Web design Training in Porur

Web design Training in Omr
Web design Training in Annanagar

technology said...

The evaluation of the test is that if you communicate to an artificial intelligence and along the process you forget to remember that it is actually a computing system and not a person, then the system passes the test data science course in india

Huongkv said...

Mua vé tại Aivivu, tham khảo

thông tin chuyến bay từ singapore về hà nội

vé máy bay từ vinh đến sài gòn

vé máy bay cần thơ ra hà nội

vietnam airlines nha trang

vé máy bay hồ chí minh quy nhơn

Edison hope said...


Very interesting blog. A lot of the blogs I visit nowadays don't really provide anything that I'm interested in, but I'm definitely interested in this one Turkish e Visa is an electronic visa Turkey that allows entry into Turkey. Once available, eligible foreign will be able to complete the online application process without visiting an embassy or consulate.

Eliza Beth said...

Wow, ich kann sagen, dass dies ein weiterer großartiger Artikel ist, wie von diesem Blog erwartet. hyazinthe pflege

Mallela said...

Thanks for posting the best information and the blog.data science course in Lucknow

Tom said...

Thank you The foreign visitors need to apply for evisa kenya online. That offers them fast and secure visa services. You also can check the al information regarding to visa here to get in the Kenya.

Eliaz Beth said...

Es ist eine großartige Website.. Das Design sieht sehr gut aus.. Weiter so!. Saunen und Bäder in Ihrer Nähe

James said...

Thanks for sharing this information. Foreign travelers who want a tourist visa India can now apply for a visa online.

isabella said...

Thanks for all you do. I like the website themes and layout, you are posting amazing blogs.... (Overseas Citizenship Of India Services) OCI card application online process. You can apply for an OCI card online and you can read all the info related to OCI(Overseas Citizenship Of India Services) card via the Indian visa website.

Data Science said...

Extremely overall quite fascinating post. I was searching for this sort of data and delighted in perusing this one.
Continue posting. A debt of gratitude is in order for sharing.
data scientist course in warangal

Unknown said...

I am really bad at remembering to pin articles I liked or were helpful
but I do have a board started.
Pakistani Drama Website

Unknown said...

As what is good for the gander is good for the goose, why not let good old Ephraim Inoni benefit from this
very same largesse? His account published a few days ago should pay off his debt without much loss of sleep.
SEO Firm Chicago
Digital Evrima

Unknown said...

Thanks a lot for this awesome post.
lederjacke damen
leather jacket

Unknown said...

Keep up the good work. I’ll be coming back lots.
wedding photography packages
wedding photography

Anonymous said...

Great man. Nice to read your helpful blog . Saudi Arabia tourism is very popular. Saudi Arabia visa tourist Is one of most demanding travel visas in the world . Saudi Arabia is a very good place to visit . Al Ula is one of the best-known destinations in Saudi Arabia .It Also included in the top 20 most visited countries in the world.

Noah Ava said...

I am sure this article has impressed all internet users, it is a really great article.. You can come to India but you will need a visa. You can apply online visa for India. You can read all the info about Indian visas via our website.

Links For You said...

It might maintain to come into the dispensation into it and prepare the music to run. It gives you full convenience for data from one records site. Rekordbox Crack

jahanzaib33 said...

Happy Birthday To My Wife. You dazzle me. I am so happy we get to share this crazy, beautiful life together. I love you.Happy Birthday To Wife

Silent Girl said...

The Internet has known us huge opportunities for being more organized, for socializing easily. This priceless threat data give us unbelievable insight into what’s occurrence at the present. Malwarebytes License Key

Mudassara Shahzad said...



Thanks for letting me know about this great post. I'm glad to have found this article.
Propellerhead

saipdf said...

Nice post thanks for sharing
Sai Satcharitra Pdf
Sai Satcharitra Telugu Pdf
Sai Satcharitra Tamil Pdf

Henry Evelyn said...

EU Transforms Schengen Visa Application Process to Fully Digital Platform , making it easier and faster for travellers to apply for visas. The new system, called the European Travel Information and Authorization System (ETIAS), will allow travellers to apply for visas online, submit supporting documents digitally and receive electronic visas via email. This new system is designed to streamline the application process and reduce wait times.

Rupesh Kumar said...

very interesting to read this article.I would like to thank you for the efforts you had made for writing this awesome article. Looking for the best English speaking course in Riyadh? Enhance your language skills with Ziyyara’s tailored online English classes in Saudi Arabia.
For more info visit Spoken English Classes in Saudi Arabia or Call +971505593798

MNK said...

Interesting article!

Regards,
BroadMind - IELTS coaching in Chennai

alex said...

Your blog post is a literary gem! The eloquence of your prose and the depth of your insights create an immersive reading experience. The way you navigate complex topics with clarity and finesse is truly admirable. Each word feels purposeful, inviting readers to reflect and engage. Looking forward to more enlightening posts that continue to blend intellect with an engaging narrative. I want to share some information with you Securing a Turkish visa for Indians is typically uncomplicated. The process involves submitting necessary documents such as a valid passport, completed application form, flight itinerary, and hotel reservation. Adequate preparation ensures a hassle-free experience, making the question is Turkish visa easy for Indians? affirmative, encouraging individuals to embark on a seamless journey to explore Turkey's cultural wonders.

Phineas said...

This article is a real treasure trove! It grabbed my attention right away. Your talent for simplifying complex ideas is truly noteworthy. I can't wait to try out these strategies for myself. Keep up the superb work—I'll definitely be back for more insightful content like this. Wondering about the Ethiopian transit visa cost? Look no further! Our user-friendly service offers a hassle-free visa application process with transparent pricing. Whether you're stopping over for business or exploration, our competitive rates ensure your transit experience is seamless and stress-free. Say goodbye to uncertainty and hello to convenience with our efficient Ethiopian transit visa service. Let us help you navigate your layover in Ethiopia with ease.

Brian said...


In this blog, each word shines brightly, akin to precious gems, crafting a treasure trove of insight and knowledge. The captivating writing style and invaluable information serve as a compass on an enlightening journey. Is Kenya eTA the same as a visa? Yes, a Kenya eTA (Electronic Travel Authorization) serves as an electronic visa. It grants travelers permission to enter Kenya for specific purposes, such as tourism or business, for a designated period, similar to a traditional visa.

alex said...
This comment has been removed by the author.
alex said...

This captivating blog post offers a distinctive perspective on a subject often sidelined in discussions. The author's eloquent prose and profound insights resonate deeply, encouraging introspection and sparking meaningful interactions. Permit me to provide you with some pertinent information, Acquiring a Turkey visa for Afghanistan entails certain expenses, which are subject to fluctuation. While the Turkey visa for Afghanistan price is a crucial factor, it's essential to stay updated on the latest fees.

Phineas said...

Your blog post was fantastic! Your fresh insights and clear explanations simplify complex topics. Real-world examples enhance the content and add depth. Thanks for sharing this valuable information! I'm eager to read more of your work—keep it coming! I'd love to hear your thoughts on related subjects! Complete your visa application form for Cameroon with ease. The online form simplifies the process by guiding you through each step. Submit the necessary details and documents to secure your entry into Cameroon. Start your adventure and experience the natural beauty and vibrant culture of this amazing destination!

Alexender said...

Outstanding job! Your blog post is a breath of fresh air in the world of online content. You have a unique ability to simplify complex topics without sacrificing depth. Your writing flows seamlessly, keeping readers hooked from the first sentence to the last. Absolutely! US passport holders must obtain a visa before traveling to Saudi Arabia. It's a crucial step in ensuring a seamless entry into the country. To answer the question, 'Do US passport holders need a visa for Saudi Arabia?'—yes, they do. Remember to check the specific visa requirements and start the application process well in advance to avoid any delays in your travel plans.

Edison hope said...

After reading this, I found it really enlightening. I appreciate you taking the time and effort to put this information together. I once again find myself spending way too much time both reading and commenting, but it was still worthwhile! The Botswana Business eVisa facilitates entry for business purposes, requiring an application, passport validity, invitation letter, and proof of accommodation. Processing times vary, typically requiring 5-7 working days.

Micheal said...

What a fantastic blog post! You broke down complex ideas into simple, easy-to-understand points brilliantly. The real-life examples you shared helped illustrate your arguments and kept me hooked. There's something I'd like to share with you. Curious about what is the visa process for Tanzania You can apply online or at the Tanzanian. You'll need a valid passport, a completed application form, a passport-sized photo, and payment of the visa fee. Processing usually takes a few days, so plan accordingly.

Data Science said...

This article on XSS protection in Freemarker demonstrates the importance of secure coding practices when dealing with template engines, similar to the meticulous approach needed in data analysis. Just as escaping HTML properly can prevent security vulnerabilities, IIM SKILLS' Data Science Courses in Kansas provide a structured pathway to mastering data handling, ensuring accuracy and security in data-driven projects. These courses teach critical skills in data management and analysis, crucial for delivering secure and efficient solutions. Data Science Courses in Kansas

Bhumi DM said...

I appreciate the examples you provided. Looking forward to more valuable content!

Data Science Courses in Brisbane

Tannu said...

Thanks for discussing how to defend against XSS attacks in Freemarker! Your insights into best practices, such as proper escaping and validation, are essential for developers looking to enhance the security of their applications. This resource is crucial for anyone working with Freemarker to ensure safe user input handling. Great job raising awareness about web security!
Data science Courses in hamburg

Data Science said...

Freemarker templates, which helps defend against XSS vulnerabilities. By wrapping the templates with escape directives at the loading stage, you mitigate reliance on developers to consistently apply manual escapes. The WrappingReader class adds prologue and epilogue to each template, ensuring comprehensive coverage and boosting security. This proactive method is especially useful for teams working on large-scale projects where consistency and security are critical. Data science courses in Gurgaon

Bhumi IIM Skills said...

Fantastic article! It’s refreshing to see such thoughtful analysis on this subject. Looking forward to more!
Data science courses in Dubai

Sadhvi said...

This is a really clever approach to defending against XSS attacks in Freemarker templates by programmatically ensuring that HTML escaping is always applied. Data science courses in Visakhapatnam

Data Analytics Courses In Ontario said...

"Such a well-researched article! If you’re in Brighton, the Data Science courses in Brighton offer fantastic opportunities to enhance your skills and dive deeper into the world of data science. Highly recommend checking it out."

NEHA PATHARE said...

"Thank you for helping me understand session-level model attributes!"

Rachana said...

Thanks for sharing this insightful approach! Wrapping Freemarker templates programmatically for HTML escaping is a smart solution to enforce XSS safety consistently. The code example and explanation make it easy to understand and implement—very helpful for developers working with Freemarker!
Data science courses in Gujarat





Data Analytics Courses In Ontario said...

"Amazing content! Anyone looking to dive deeper into data science should definitely explore the Data Science courses in Kochi. It's an excellent way to gain expertise and stand out in the field."

NEHA PATHARE said...

"Well said!"
Data science course in mumbai.

IIM Skills Data Science said...

"Great post! It's essential to address XSS vulnerabilities early on in web development, and the techniques you described for defending against them are very practical.
Data science Courses in Canada

P. Zaheer Khan said...

Fantastic write-up! The balance of security best practices and Freemarker-specific tips is exactly what developers need to protect their applications from XSS vulnerabilities.
Data science Courses in Sydney

kriti sharma said...

This post is a valuable resource for developers looking to protect their web applications from XSS attacks. I like the practical tips you provided, such as sanitizing input and using Content Security Policies. It's essential to stay vigilant against security threats, and posts like this help spread awareness
Data science courses in Glasgow

Abar Singh said...

This article provides a detailed overview of defending against XSS attacks, an essential read for developers concerned about cybersecurity. The practical insights and real-world examples shared here make it highly informative. Thanks for breaking down a complex topic so well!

Data science courses in france

Neelkbh said...

This is a smart approach to enhance security in Freemarker by programmatically enforcing HTML escaping across templates. It eliminates the risk of human error while ensuring consistent protection against XSS attacks. A useful strategy for any project prioritizing security!

Data science Courses in City of Westminster

Neel KBH
kbhneel@gmail.com

Shikhaiimskills said...

Defending against XSS (Cross-Site Scripting) attacks in Freemarker involves implementing proper input validation and output encoding. It has built-in escape functions to sanitize data before rendering it in templates. Additionally, validate user inputs on the server side and adhere to the principle of least privilege. Keeping libraries updated ensures you're protected against known vulnerabilities, bolstering your application's security against XSS threats.
Data science Courses in Berlin

iim skills Diksha said...

This post demonstrates an elegant approach to programmatically enforce HTML escaping in Freemarker templates by wrapping template loading with a custom reader. While effective in reducing reliance on manual intervention, it imposes limitations like disabling <#ftl> configuration and requiring <#noescape> for specific cases. This tradeoff simplifies security management at the cost of flexibility in template authoring.
Data science Courses in Ireland

Brian said...

You have a knack for taking complex concepts and presenting them in a way that feels effortless to understand. I also appreciate how you included actionable steps—it makes the content practical and useful. To Sri Lanka tourist visa apply online . Complete the application form with personal details, travel information, and passport data. Ensure you meet the necessary requirements. Upon approval, the visa is emailed to you, allowing smooth entry to Sri Lanka.

carry john said...

Great content! The insights shared are both practical and thoughtful. I loved how you broke down complex ideas into simple, understandable points. This post is not only informative but also engaging—definitely a great read for those looking to expand their knowledge. Madagascar visa requirements are simple for most travelers. To apply for an eVisa, you’ll need a valid passport with at least six months of validity, a recent passport-sized photo, and proof of accommodation in Madagascar. The process is done entirely online, making it easy and convenient. Ensure that all your details are accurate to avoid delays in processing. Once approved, your eVisa will allow you to explore Madagascar’s unique wildlife and beautiful landscapes without any hassle.

Anjali said...

"Thank you for helping me understand session-level model attributes!"
Data Analytics Courses In Chennai